SkPM4fPriv.h revision c789b61167dd98efc3c3bfcf9673eef24c2e57f4
1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkPM4fPriv_DEFINED 9#define SkPM4fPriv_DEFINED 10 11#include "SkColorPriv.h" 12#include "SkColorSpace.h" 13#include "SkColorSpace_Base.h" 14#include "SkFixedAlloc.h" 15#include "SkPM4f.h" 16#include "SkRasterPipeline.h" 17#include "SkSRGB.h" 18 19static inline Sk4f set_alpha(const Sk4f& px, float alpha) { 20 return { px[0], px[1], px[2], alpha }; 21} 22 23static inline float get_alpha(const Sk4f& px) { 24 return px[3]; 25} 26 27 28static inline Sk4f Sk4f_fromL32(uint32_t px) { 29 return SkNx_cast<float>(Sk4b::Load(&px)) * (1/255.0f); 30} 31 32static inline Sk4f Sk4f_fromS32(uint32_t px) { 33 return { sk_linear_from_srgb[(px >> 0) & 0xff], 34 sk_linear_from_srgb[(px >> 8) & 0xff], 35 sk_linear_from_srgb[(px >> 16) & 0xff], 36 (1/255.0f) * (px >> 24) }; 37} 38 39static inline uint32_t Sk4f_toL32(const Sk4f& px) { 40 uint32_t l32; 41 SkNx_cast<uint8_t>(Sk4f_round(px * 255.0f)).store(&l32); 42 return l32; 43} 44 45static inline uint32_t Sk4f_toS32(const Sk4f& px) { 46 Sk4i rgb = sk_linear_to_srgb(px), 47 srgb = { rgb[0], rgb[1], rgb[2], (int)(255.0f * px[3] + 0.5f) }; 48 49 uint32_t s32; 50 SkNx_cast<uint8_t>(srgb).store(&s32); 51 return s32; 52} 53 54 55// SkColor handling: 56// SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swizzles r and b to 57// produce the needed (r, g, b, a) ordering. 58static inline Sk4f Sk4f_from_SkColor(SkColor color) { 59 return swizzle_rb(Sk4f_fromS32(color)); 60} 61 62static inline void assert_unit(float x) { 63 SkASSERT(0 <= x && x <= 1); 64} 65 66static inline float exact_srgb_to_linear(float srgb) { 67 assert_unit(srgb); 68 float linear; 69 if (srgb <= 0.04045) { 70 linear = srgb / 12.92f; 71 } else { 72 linear = powf((srgb + 0.055f) / 1.055f, 2.4f); 73 } 74 assert_unit(linear); 75 return linear; 76} 77 78 79// N.B. scratch_matrix_3x4 must live at least as long as p. 80static inline bool append_gamut_transform(SkRasterPipeline* p, float scratch_matrix_3x4[12], 81 SkColorSpace* src, SkColorSpace* dst) { 82 if (src == dst) { return true; } 83 if (!dst) { return true; } // Legacy modes intentionally ignore color gamut. 84 if (!src) { return true; } // A null src color space means linear gamma, dst gamut. 85 86 auto toXYZ = as_CSB(src)-> toXYZD50(), 87 fromXYZ = as_CSB(dst)->fromXYZD50(); 88 if (!toXYZ || !fromXYZ) { return false; } // Unsupported color space type. 89 90 if (as_CSB(src)->toXYZD50Hash() == as_CSB(dst)->toXYZD50Hash()) { return true; } 91 92 SkMatrix44 m44(*fromXYZ, *toXYZ); 93 94 // Convert from 4x4 to (column-major) 3x4. 95 auto ptr = scratch_matrix_3x4; 96 *ptr++ = m44.get(0,0); *ptr++ = m44.get(1,0); *ptr++ = m44.get(2,0); 97 *ptr++ = m44.get(0,1); *ptr++ = m44.get(1,1); *ptr++ = m44.get(2,1); 98 *ptr++ = m44.get(0,2); *ptr++ = m44.get(1,2); *ptr++ = m44.get(2,2); 99 *ptr++ = m44.get(0,3); *ptr++ = m44.get(1,3); *ptr++ = m44.get(2,3); 100 101 p->append(SkRasterPipeline::matrix_3x4, scratch_matrix_3x4); 102 // TODO: detect whether we can skip the clamps? 103 p->append(SkRasterPipeline::clamp_0); 104 p->append(SkRasterPipeline::clamp_a); 105 return true; 106} 107 108static inline bool append_gamut_transform(SkRasterPipeline* p, SkFallbackAlloc* scratch, 109 SkColorSpace* src, SkColorSpace* dst) { 110 struct matrix_3x4 { float arr[12]; }; 111 return append_gamut_transform(p, scratch->make<matrix_3x4>()->arr, src, dst); 112} 113 114static inline SkColor4f SkColor4f_from_SkColor(SkColor color, SkColorSpace* dst) { 115 SkColor4f color4f; 116 if (dst) { 117 // sRGB gamma, sRGB gamut. 118 color4f = SkColor4f::FromColor(color); 119 void* color4f_ptr = &color4f; 120 121 float scratch_matrix_3x4[12]; 122 123 SkRasterPipeline p; 124 p.append(SkRasterPipeline::constant_color, color4f_ptr); 125 append_gamut_transform(&p, scratch_matrix_3x4, 126 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).get(), dst); 127 p.append(SkRasterPipeline::store_f32, &color4f_ptr); 128 129 p.run(0,0,1); 130 } else { 131 // Linear gamma, dst gamut. 132 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&color)) * (1/255.0f)).store(&color4f); 133 } 134 return color4f; 135} 136 137static inline SkPM4f SkPM4f_from_SkColor(SkColor color, SkColorSpace* dst) { 138 return SkColor4f_from_SkColor(color, dst).premul(); 139} 140 141#endif 142