msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 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 | |
Cary Clark | a4083c9 | 2017-09-15 11:59:23 -0400 | [diff] [blame] | 8 | #include "SkColorData.h" |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 9 | #include "SkColorSpace_A2B.h" |
msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 10 | #include "SkColorSpace_Base.h" |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 11 | #include "SkColorSpace_XYZ.h" |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 12 | #include "SkColorSpacePriv.h" |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 13 | #include "SkColorSpaceXform_A2B.h" |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 14 | #include "SkColorSpaceXform_Base.h" |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 15 | #include "SkColorSpaceXformPriv.h" |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 16 | #include "SkHalf.h" |
| 17 | #include "SkOpts.h" |
Mike Klein | 5e15961 | 2016-12-01 16:39:21 -0500 | [diff] [blame] | 18 | #include "SkPM4fPriv.h" |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 19 | #include "SkRasterPipeline.h" |
mtklein | ac41bac | 2016-07-08 06:33:16 -0700 | [diff] [blame] | 20 | #include "SkSRGB.h" |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 21 | #include "../jumper/SkJumper.h" |
msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 22 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 23 | static constexpr float sk_linear_from_2dot2[256] = { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 24 | 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, |
| 25 | 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, |
| 26 | 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, |
| 27 | 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, |
| 28 | 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, |
| 29 | 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, |
| 30 | 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, |
| 31 | 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, |
| 32 | 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, |
| 33 | 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, |
| 34 | 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, |
| 35 | 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, |
| 36 | 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, |
| 37 | 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, |
| 38 | 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, |
| 39 | 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, |
| 40 | 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, |
| 41 | 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, |
| 42 | 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, |
| 43 | 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, |
| 44 | 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, |
| 45 | 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, |
| 46 | 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, |
| 47 | 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, |
| 48 | 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, |
| 49 | 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, |
| 50 | 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, |
| 51 | 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, |
| 52 | 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, |
| 53 | 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, |
| 54 | 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, |
| 55 | 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, |
| 56 | 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, |
| 57 | 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, |
| 58 | 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, |
| 59 | 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, |
| 60 | 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, |
| 61 | 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, |
| 62 | 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, |
| 63 | 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, |
| 64 | 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, |
| 65 | 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, |
| 66 | 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, |
| 67 | 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, |
| 68 | 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, |
| 69 | 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, |
| 70 | 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, |
| 71 | 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, |
| 72 | 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, |
| 73 | 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, |
| 74 | 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, |
| 75 | 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, |
| 76 | 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, |
| 77 | 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, |
| 78 | 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, |
| 79 | 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, |
| 80 | 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, |
| 81 | 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, |
| 82 | 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, |
| 83 | 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, |
| 84 | 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, |
| 85 | 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, |
| 86 | 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, |
| 87 | 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, |
| 88 | }; |
| 89 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 90 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 91 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 92 | static void build_table_linear_from_gamma(float* outTable, float exponent) { |
| 93 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 94 | *outTable++ = powf(x, exponent); |
| 95 | } |
| 96 | } |
| 97 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 98 | // outTable is always 256 entries, inTable may be larger or smaller. |
| 99 | static void build_table_linear_from_gamma(float* outTable, const float* inTable, |
| 100 | int inTableSize) { |
| 101 | if (256 == inTableSize) { |
| 102 | memcpy(outTable, inTable, sizeof(float) * 256); |
| 103 | return; |
| 104 | } |
| 105 | |
| 106 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 107 | *outTable++ = interp_lut(x, inTable, inTableSize); |
| 108 | } |
| 109 | } |
| 110 | |
Matt Sarett | aa34f7e | 2016-11-09 18:14:47 -0500 | [diff] [blame] | 111 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 112 | static void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, |
| 113 | float d, float e, float f) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 114 | // Y = (aX + b)^g + e for X >= d |
| 115 | // Y = cX + f otherwise |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 116 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 117 | if (x >= d) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 118 | *outTable++ = clamp_0_1(powf(a * x + b, g) + e); |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 119 | } else { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 120 | *outTable++ = clamp_0_1(c * x + f); |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 126 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 127 | static const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize; |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 128 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 129 | static void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 130 | float toGammaExp = 1.0f / exponent; |
| 131 | |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 132 | for (int i = 0; i < kDstGammaTableSize; i++) { |
| 133 | float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 134 | outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); |
| 135 | } |
msarett | dc27a64 | 2016-06-06 12:02:31 -0700 | [diff] [blame] | 136 | } |
| 137 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 138 | static void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 139 | int inTableSize) { |
raftias | 197e311 | 2016-12-01 15:31:29 -0500 | [diff] [blame] | 140 | invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | static float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, |
| 144 | float f) { |
| 145 | // We need to take the inverse of the following piecewise function. |
| 146 | // Y = (aX + b)^g + c for X >= d |
| 147 | // Y = eX + f otherwise |
| 148 | |
| 149 | // Assume that the gamma function is continuous, or this won't make much sense anyway. |
| 150 | // Plug in |d| to the first equation to calculate the new piecewise interval. |
| 151 | // Then simply use the inverse of the original functions. |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 152 | float interval = c * d + f; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 153 | if (x < interval) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 154 | // X = (Y - F) / C |
| 155 | if (0.0f == c) { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 156 | // The gamma curve for this segment is constant, so the inverse is undefined. |
| 157 | // Since this is the lower segment, guess zero. |
| 158 | return 0.0f; |
| 159 | } |
| 160 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 161 | return (x - f) / c; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 162 | } |
| 163 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 164 | // X = ((Y - E)^(1 / G) - B) / A |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 165 | if (0.0f == a || 0.0f == g) { |
| 166 | // The gamma curve for this segment is constant, so the inverse is undefined. |
| 167 | // Since this is the upper segment, guess one. |
| 168 | return 1.0f; |
| 169 | } |
| 170 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 171 | return (powf(x - e, 1.0f / g) - b) / a; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 172 | } |
| 173 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 174 | static void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 175 | float b, float c, float d, float e, float f) { |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 176 | for (int i = 0; i < kDstGammaTableSize; i++) { |
| 177 | float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 178 | float y = inverse_parametric(x, g, a, b, c, d, e, f); |
| 179 | outTable[i] = clamp_normalized_float_to_byte(y); |
| 180 | } |
| 181 | } |
| 182 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 183 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 184 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 185 | template <typename T> |
| 186 | struct GammaFns { |
| 187 | const T* fSRGBTable; |
| 188 | const T* f2Dot2Table; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 189 | void (*fBuildFromValue)(T*, float); |
| 190 | void (*fBuildFromTable)(T*, const float*, int); |
| 191 | void (*fBuildFromParam)(T*, float, float, float, float, float, float, float); |
| 192 | }; |
| 193 | |
| 194 | static const GammaFns<float> kToLinear { |
| 195 | sk_linear_from_srgb, |
| 196 | sk_linear_from_2dot2, |
| 197 | &build_table_linear_from_gamma, |
| 198 | &build_table_linear_from_gamma, |
| 199 | &build_table_linear_from_gamma, |
| 200 | }; |
| 201 | |
| 202 | static const GammaFns<uint8_t> kFromLinear { |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 203 | nullptr, |
| 204 | nullptr, |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 205 | &build_table_linear_to_gamma, |
| 206 | &build_table_linear_to_gamma, |
| 207 | &build_table_linear_to_gamma, |
| 208 | }; |
| 209 | |
| 210 | // Build tables to transform src gamma to linear. |
| 211 | template <typename T> |
| 212 | static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 213 | const SkColorSpace_XYZ* space, const GammaFns<T>& fns, |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 214 | bool gammasAreMatching) |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 215 | { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 216 | switch (space->gammaNamed()) { |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 217 | case kSRGB_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 218 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; |
| 219 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 220 | case k2Dot2Curve_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 221 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table; |
| 222 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 223 | case kLinear_SkGammaNamed: |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 224 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 225 | break; |
| 226 | default: { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 227 | const SkGammas* gammas = space->gammas(); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 228 | SkASSERT(gammas); |
| 229 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 230 | auto build_table = [=](int i) { |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 231 | if (gammas->isNamed(i)) { |
| 232 | switch (gammas->data(i).fNamed) { |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 233 | case kSRGB_SkGammaNamed: |
Hal Canary | a8565e5 | 2017-06-19 12:43:28 -0400 | [diff] [blame] | 234 | (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], |
| 235 | gSRGB_TransferFn.fG, |
| 236 | gSRGB_TransferFn.fA, |
| 237 | gSRGB_TransferFn.fB, |
| 238 | gSRGB_TransferFn.fC, |
| 239 | gSRGB_TransferFn.fD, |
| 240 | gSRGB_TransferFn.fE, |
| 241 | gSRGB_TransferFn.fF); |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 242 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 243 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 244 | case k2Dot2Curve_SkGammaNamed: |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 245 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f); |
| 246 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 247 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 248 | case kLinear_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 249 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f); |
| 250 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 251 | break; |
| 252 | default: |
| 253 | SkASSERT(false); |
| 254 | break; |
| 255 | } |
| 256 | } else if (gammas->isValue(i)) { |
| 257 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], |
| 258 | gammas->data(i).fValue); |
| 259 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 260 | } else if (gammas->isTable(i)) { |
| 261 | (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i), |
| 262 | gammas->data(i).fTable.fSize); |
| 263 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 264 | } else { |
| 265 | SkASSERT(gammas->isParametric(i)); |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 266 | const SkColorSpaceTransferFn& params = gammas->params(i); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 267 | (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG, |
| 268 | params.fA, params.fB, params.fC, params.fD, params.fE, |
| 269 | params.fF); |
| 270 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 271 | } |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 272 | }; |
| 273 | |
| 274 | if (gammasAreMatching) { |
| 275 | build_table(0); |
| 276 | outGammaTables[1] = outGammaTables[0]; |
| 277 | outGammaTables[2] = outGammaTables[0]; |
| 278 | } else { |
| 279 | build_table(0); |
| 280 | build_table(1); |
| 281 | build_table(2); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 282 | } |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 283 | |
| 284 | break; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 285 | } |
| 286 | } |
| 287 | } |
| 288 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 289 | void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3], |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 290 | uint8_t* dstStorage, |
| 291 | const SkColorSpace_XYZ* space, |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 292 | bool gammasAreMatching) { |
| 293 | build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear, |
| 294 | gammasAreMatching); |
| 295 | } |
| 296 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 297 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 298 | |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 299 | std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace, |
| 300 | SkColorSpace* dstSpace) { |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 301 | return SkColorSpaceXform_Base::New(srcSpace, dstSpace, SkTransferFunctionBehavior::kRespect); |
| 302 | } |
| 303 | |
| 304 | std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New(SkColorSpace* srcSpace, |
| 305 | SkColorSpace* dstSpace, SkTransferFunctionBehavior premulBehavior) { |
| 306 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 307 | if (!srcSpace || !dstSpace) { |
| 308 | // Invalid input |
| 309 | return nullptr; |
| 310 | } |
| 311 | |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 312 | if (SkColorSpace_Base::Type::kA2B == as_CSB(dstSpace)->type()) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 313 | SkCSXformPrintf("A2B destinations not supported\n"); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 314 | return nullptr; |
| 315 | } |
| 316 | |
| 317 | if (SkColorSpace_Base::Type::kA2B == as_CSB(srcSpace)->type()) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 318 | SkColorSpace_A2B* src = static_cast<SkColorSpace_A2B*>(srcSpace); |
| 319 | SkColorSpace_XYZ* dst = static_cast<SkColorSpace_XYZ*>(dstSpace); |
| 320 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B(src, dst)); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 321 | } |
| 322 | SkColorSpace_XYZ* srcSpaceXYZ = static_cast<SkColorSpace_XYZ*>(srcSpace); |
| 323 | SkColorSpace_XYZ* dstSpaceXYZ = static_cast<SkColorSpace_XYZ*>(dstSpace); |
| 324 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 325 | ColorSpaceMatch csm = kNone_ColorSpaceMatch; |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 326 | SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); |
Matt Sarett | f388093 | 2017-03-24 10:06:03 -0400 | [diff] [blame] | 327 | if (SkColorSpace::Equals(srcSpace, dstSpace)) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 328 | srcToDst.setIdentity(); |
| 329 | csm = kFull_ColorSpaceMatch; |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 330 | } else { |
Brian Osman | bbf251b | 2016-10-19 14:56:07 -0400 | [diff] [blame] | 331 | if (srcSpaceXYZ->toXYZD50Hash() == dstSpaceXYZ->toXYZD50Hash()) { |
| 332 | SkASSERT(*srcSpaceXYZ->toXYZD50() == *dstSpaceXYZ->toXYZD50() && "Hash collision"); |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 333 | srcToDst.setIdentity(); |
| 334 | csm = kGamut_ColorSpaceMatch; |
Brian Osman | bbf251b | 2016-10-19 14:56:07 -0400 | [diff] [blame] | 335 | } else { |
| 336 | srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50()); |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 337 | } |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 338 | } |
| 339 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 340 | switch (csm) { |
| 341 | case kNone_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 342 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 343 | <kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 344 | case kGamut_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 345 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 346 | <kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 347 | case kFull_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 348 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 349 | <kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior)); |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 350 | default: |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 351 | SkASSERT(false); |
| 352 | return nullptr; |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 353 | } |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 357 | |
Mike Klein | e23e55e | 2017-06-13 17:44:51 -0400 | [diff] [blame] | 358 | static inline int num_tables(SkColorSpace_XYZ* space) { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 359 | switch (space->gammaNamed()) { |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 360 | case kSRGB_SkGammaNamed: |
| 361 | case k2Dot2Curve_SkGammaNamed: |
| 362 | case kLinear_SkGammaNamed: |
| 363 | return 0; |
| 364 | default: { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 365 | const SkGammas* gammas = space->gammas(); |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 366 | SkASSERT(gammas); |
| 367 | |
| 368 | bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && |
| 369 | (gammas->data(0) == gammas->data(1)) && |
| 370 | (gammas->type(0) == gammas->type(2)) && |
| 371 | (gammas->data(0) == gammas->data(2)); |
| 372 | |
| 373 | // It's likely that each component will have the same gamma. In this case, |
| 374 | // we only need to build one table. |
| 375 | return gammasAreMatching ? 1 : 3; |
| 376 | } |
| 377 | } |
| 378 | } |
| 379 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 380 | template <ColorSpaceMatch kCSM> |
| 381 | SkColorSpaceXform_XYZ<kCSM> |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 382 | ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst, |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 383 | SkColorSpace_XYZ* dstSpace, SkTransferFunctionBehavior premulBehavior) |
| 384 | : fPremulBehavior(premulBehavior) |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 385 | { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 386 | fSrcToDst[ 0] = srcToDst.get(0, 0); |
| 387 | fSrcToDst[ 1] = srcToDst.get(1, 0); |
| 388 | fSrcToDst[ 2] = srcToDst.get(2, 0); |
| 389 | fSrcToDst[ 3] = srcToDst.get(0, 1); |
| 390 | fSrcToDst[ 4] = srcToDst.get(1, 1); |
| 391 | fSrcToDst[ 5] = srcToDst.get(2, 1); |
| 392 | fSrcToDst[ 6] = srcToDst.get(0, 2); |
| 393 | fSrcToDst[ 7] = srcToDst.get(1, 2); |
| 394 | fSrcToDst[ 8] = srcToDst.get(2, 2); |
| 395 | fSrcToDst[ 9] = srcToDst.get(0, 3); |
| 396 | fSrcToDst[10] = srcToDst.get(1, 3); |
| 397 | fSrcToDst[11] = srcToDst.get(2, 3); |
| 398 | fSrcToDst[12] = 0.0f; |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 399 | |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 400 | const int numSrcTables = num_tables(srcSpace); |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 401 | const size_t srcEntries = numSrcTables * 256; |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 402 | const bool srcGammasAreMatching = (1 >= numSrcTables); |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 403 | fSrcStorage.reset(srcEntries); |
| 404 | build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear, |
| 405 | srcGammasAreMatching); |
| 406 | |
| 407 | const int numDstTables = num_tables(dstSpace); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 408 | dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 409 | |
| 410 | if (srcSpace->gammaIsLinear()) { |
| 411 | fSrcGamma = kLinear_SrcGamma; |
| 412 | } else if (kSRGB_SkGammaNamed == srcSpace->gammaNamed()) { |
| 413 | fSrcGamma = kSRGB_SrcGamma; |
| 414 | } else { |
| 415 | fSrcGamma = kTable_SrcGamma; |
| 416 | } |
| 417 | |
| 418 | switch (dstSpace->gammaNamed()) { |
| 419 | case kSRGB_SkGammaNamed: |
| 420 | fDstGamma = kSRGB_DstGamma; |
| 421 | break; |
| 422 | case k2Dot2Curve_SkGammaNamed: |
| 423 | fDstGamma = k2Dot2_DstGamma; |
| 424 | break; |
| 425 | case kLinear_SkGammaNamed: |
| 426 | fDstGamma = kLinear_DstGamma; |
| 427 | break; |
| 428 | default: |
| 429 | fDstGamma = kTable_DstGamma; |
| 430 | break; |
| 431 | } |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 432 | } |
| 433 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 434 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 435 | |
Mike Klein | 1f8796d | 2017-06-15 19:50:33 +0000 | [diff] [blame] | 436 | template <ColorSpaceMatch kCSM> |
Mike Klein | e23e55e | 2017-06-13 17:44:51 -0400 | [diff] [blame] | 437 | bool SkColorSpaceXform_XYZ<kCSM>::onApply(ColorFormat dstColorFormat, void* dst, |
| 438 | ColorFormat srcColorFormat, const void* src, |
| 439 | int len, SkAlphaType alphaType) const { |
| 440 | if (kFull_ColorSpaceMatch == kCSM && kPremul_SkAlphaType != alphaType) { |
| 441 | if ((kRGBA_8888_ColorFormat == dstColorFormat && |
| 442 | kRGBA_8888_ColorFormat == srcColorFormat) || |
| 443 | (kBGRA_8888_ColorFormat == dstColorFormat && |
| 444 | kBGRA_8888_ColorFormat == srcColorFormat)) |
| 445 | { |
| 446 | memcpy(dst, src, len * sizeof(uint32_t)); |
| 447 | return true; |
| 448 | } |
| 449 | |
| 450 | if ((kRGBA_8888_ColorFormat == dstColorFormat && |
| 451 | kBGRA_8888_ColorFormat == srcColorFormat) || |
| 452 | (kBGRA_8888_ColorFormat == dstColorFormat && |
| 453 | kRGBA_8888_ColorFormat == srcColorFormat)) |
| 454 | { |
| 455 | SkOpts::RGBA_to_BGRA((uint32_t*)dst, src, len); |
| 456 | return true; |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 457 | } |
| 458 | } |
| 459 | |
Mike Klein | e23e55e | 2017-06-13 17:44:51 -0400 | [diff] [blame] | 460 | return this->applyPipeline(dstColorFormat, dst, srcColorFormat, src, len, alphaType); |
msarett | 9ce3a54 | 2016-07-15 13:54:38 -0700 | [diff] [blame] | 461 | } |
msarett | 9dc6cf6 | 2016-08-23 17:53:06 -0700 | [diff] [blame] | 462 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 463 | bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, |
| 464 | const void* src, int len, SkAlphaType alphaType) const { |
| 465 | return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcColorFormat, src, len, |
| 466 | alphaType); |
| 467 | } |
| 468 | |
Mike Reed | edf8a76 | 2017-05-22 13:41:36 -0400 | [diff] [blame] | 469 | bool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst, |
| 470 | SkColorSpace* srcCS, ColorFormat srcFormat, const void* src, |
| 471 | int count, AlphaOp op) { |
| 472 | SkAlphaType at; |
| 473 | switch (op) { |
| 474 | case kPreserve_AlphaOp: at = kUnpremul_SkAlphaType; break; |
| 475 | case kPremul_AlphaOp: at = kPremul_SkAlphaType; break; |
| 476 | case kSrcIsOpaque_AlphaOp: at = kOpaque_SkAlphaType; break; |
| 477 | } |
| 478 | return New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, count, at); |
| 479 | } |
| 480 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 481 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 482 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 483 | template <ColorSpaceMatch kCSM> |
| 484 | bool SkColorSpaceXform_XYZ<kCSM> |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 485 | ::applyPipeline(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, |
| 486 | const void* src, int len, SkAlphaType alphaType) const { |
Mike Klein | b24704d | 2017-05-24 07:53:00 -0400 | [diff] [blame] | 487 | SkRasterPipeline_<256> pipeline; |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 488 | |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 489 | SkJumper_MemoryCtx src_ctx = { (void*)src, 0 }, |
| 490 | dst_ctx = { (void*)dst, 0 }; |
| 491 | |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 492 | LoadTablesContext loadTables; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 493 | switch (srcColorFormat) { |
| 494 | case kRGBA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 495 | if (kLinear_SrcGamma == fSrcGamma) { |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 496 | pipeline.append(SkRasterPipeline::load_8888, &src_ctx); |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 497 | } else { |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 498 | loadTables.fSrc = src; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 499 | loadTables.fR = fSrcGammaTables[0]; |
| 500 | loadTables.fG = fSrcGammaTables[1]; |
| 501 | loadTables.fB = fSrcGammaTables[2]; |
| 502 | pipeline.append(SkRasterPipeline::load_tables, &loadTables); |
| 503 | } |
| 504 | |
| 505 | break; |
| 506 | case kBGRA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 507 | if (kLinear_SrcGamma == fSrcGamma) { |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 508 | pipeline.append(SkRasterPipeline::load_bgra, &src_ctx); |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 509 | } else { |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 510 | loadTables.fSrc = src; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 511 | loadTables.fR = fSrcGammaTables[2]; |
| 512 | loadTables.fG = fSrcGammaTables[1]; |
| 513 | loadTables.fB = fSrcGammaTables[0]; |
| 514 | pipeline.append(SkRasterPipeline::load_tables, &loadTables); |
Mike Klein | c2d2076 | 2017-06-27 19:53:21 -0400 | [diff] [blame] | 515 | pipeline.append(SkRasterPipeline::swap_rb); |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 516 | } |
| 517 | |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 518 | break; |
Brian Osman | b1168a7 | 2017-03-20 14:21:18 -0400 | [diff] [blame] | 519 | case kRGBA_F16_ColorFormat: |
| 520 | if (kLinear_SrcGamma != fSrcGamma) { |
| 521 | return false; |
| 522 | } |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 523 | pipeline.append(SkRasterPipeline::load_f16, &src_ctx); |
Brian Osman | b1168a7 | 2017-03-20 14:21:18 -0400 | [diff] [blame] | 524 | break; |
Matt Sarett | 4c55027 | 2017-03-20 19:06:18 -0400 | [diff] [blame] | 525 | case kRGBA_F32_ColorFormat: |
| 526 | if (kLinear_SrcGamma != fSrcGamma) { |
| 527 | return false; |
| 528 | } |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 529 | pipeline.append(SkRasterPipeline::load_f32, &src_ctx); |
Matt Sarett | 4c55027 | 2017-03-20 19:06:18 -0400 | [diff] [blame] | 530 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 531 | case kRGBA_U16_BE_ColorFormat: |
| 532 | switch (fSrcGamma) { |
| 533 | case kLinear_SrcGamma: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 534 | pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 535 | break; |
| 536 | case kSRGB_SrcGamma: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 537 | pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 538 | pipeline.append_from_srgb(kUnpremul_SkAlphaType); |
| 539 | break; |
| 540 | case kTable_SrcGamma: |
| 541 | loadTables.fSrc = src; |
| 542 | loadTables.fR = fSrcGammaTables[0]; |
| 543 | loadTables.fG = fSrcGammaTables[1]; |
| 544 | loadTables.fB = fSrcGammaTables[2]; |
| 545 | pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables); |
| 546 | break; |
| 547 | } |
| 548 | break; |
Matt Sarett | 5bee0b6 | 2017-01-19 12:04:32 -0500 | [diff] [blame] | 549 | case kRGB_U16_BE_ColorFormat: |
| 550 | switch (fSrcGamma) { |
| 551 | case kLinear_SrcGamma: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 552 | pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx); |
Matt Sarett | 5bee0b6 | 2017-01-19 12:04:32 -0500 | [diff] [blame] | 553 | break; |
| 554 | case kSRGB_SrcGamma: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 555 | pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx); |
Matt Sarett | 5bee0b6 | 2017-01-19 12:04:32 -0500 | [diff] [blame] | 556 | pipeline.append_from_srgb(kUnpremul_SkAlphaType); |
| 557 | break; |
| 558 | case kTable_SrcGamma: |
| 559 | loadTables.fSrc = src; |
| 560 | loadTables.fR = fSrcGammaTables[0]; |
| 561 | loadTables.fG = fSrcGammaTables[1]; |
| 562 | loadTables.fB = fSrcGammaTables[2]; |
| 563 | pipeline.append(SkRasterPipeline::load_tables_rgb_u16_be, &loadTables); |
| 564 | break; |
| 565 | } |
| 566 | break; |
Matt Sarett | 3725f0a | 2017-03-28 14:34:20 -0400 | [diff] [blame] | 567 | default: |
| 568 | return false; |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 569 | } |
| 570 | |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 571 | if (kNone_ColorSpaceMatch == kCSM) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 572 | pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 573 | |
Matt Sarett | eeb3cb1 | 2017-03-29 20:00:18 -0400 | [diff] [blame] | 574 | if (kRGBA_F16_ColorFormat != dstColorFormat && |
| 575 | kRGBA_F32_ColorFormat != dstColorFormat) |
Matt Sarett | 8f7a9a9 | 2017-03-29 17:12:26 -0400 | [diff] [blame] | 576 | { |
Mike Klein | 5e15961 | 2016-12-01 16:39:21 -0500 | [diff] [blame] | 577 | bool need_clamp_0, need_clamp_1; |
| 578 | analyze_3x4_matrix(fSrcToDst, &need_clamp_0, &need_clamp_1); |
| 579 | |
| 580 | if (need_clamp_0) { pipeline.append(SkRasterPipeline::clamp_0); } |
| 581 | if (need_clamp_1) { pipeline.append(SkRasterPipeline::clamp_1); } |
| 582 | } |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 583 | } |
| 584 | |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 585 | if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kRespect == fPremulBehavior) |
| 586 | { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 587 | pipeline.append(SkRasterPipeline::premul); |
| 588 | } |
| 589 | |
Matt Sarett | e522f4c | 2017-02-22 13:02:31 -0500 | [diff] [blame] | 590 | TablesContext tables; |
Mike Klein | a07e430 | 2017-08-09 13:51:35 -0400 | [diff] [blame] | 591 | float to_2dot2 = 1/2.2f; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 592 | switch (fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 593 | case kSRGB_DstGamma: |
| 594 | pipeline.append(SkRasterPipeline::to_srgb); |
| 595 | break; |
| 596 | case k2Dot2_DstGamma: |
Mike Klein | a07e430 | 2017-08-09 13:51:35 -0400 | [diff] [blame] | 597 | pipeline.append(SkRasterPipeline::gamma, &to_2dot2); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 598 | break; |
Matt Sarett | e522f4c | 2017-02-22 13:02:31 -0500 | [diff] [blame] | 599 | case kTable_DstGamma: |
| 600 | tables.fR = fDstGammaTables[0]; |
| 601 | tables.fG = fDstGammaTables[1]; |
| 602 | tables.fB = fDstGammaTables[2]; |
| 603 | tables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize; |
| 604 | pipeline.append(SkRasterPipeline::byte_tables_rgb, &tables); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 605 | default: |
| 606 | break; |
| 607 | } |
| 608 | |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 609 | if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kIgnore == fPremulBehavior) |
| 610 | { |
Matt Sarett | e522f4c | 2017-02-22 13:02:31 -0500 | [diff] [blame] | 611 | pipeline.append(SkRasterPipeline::premul); |
| 612 | } |
| 613 | |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 614 | switch (dstColorFormat) { |
| 615 | case kRGBA_8888_ColorFormat: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 616 | pipeline.append(SkRasterPipeline::store_8888, &dst_ctx); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 617 | break; |
| 618 | case kBGRA_8888_ColorFormat: |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 619 | pipeline.append(SkRasterPipeline::store_bgra, &dst_ctx); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 620 | break; |
| 621 | case kRGBA_F16_ColorFormat: |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 622 | if (kLinear_DstGamma != fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 623 | return false; |
| 624 | } |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 625 | pipeline.append(SkRasterPipeline::store_f16, &dst_ctx); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 626 | break; |
| 627 | case kRGBA_F32_ColorFormat: |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 628 | if (kLinear_DstGamma != fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 629 | return false; |
| 630 | } |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 631 | pipeline.append(SkRasterPipeline::store_f32, &dst_ctx); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 632 | break; |
Matt Sarett | 3725f0a | 2017-03-28 14:34:20 -0400 | [diff] [blame] | 633 | case kBGR_565_ColorFormat: |
| 634 | if (kOpaque_SkAlphaType != alphaType) { |
| 635 | return false; |
| 636 | } |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 637 | pipeline.append(SkRasterPipeline::store_565, &dst_ctx); |
Matt Sarett | 3725f0a | 2017-03-28 14:34:20 -0400 | [diff] [blame] | 638 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 639 | default: |
| 640 | return false; |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 641 | } |
| 642 | |
Mike Klein | 45c16fa | 2017-07-18 18:15:13 -0400 | [diff] [blame] | 643 | pipeline.run(0,0, len,1); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 644 | return true; |
| 645 | } |
| 646 | |
| 647 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 648 | |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 649 | std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) { |
Matt Sarett | cf3f234 | 2017-03-23 15:32:25 -0400 | [diff] [blame] | 650 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ<kNone_ColorSpaceMatch> |
| 651 | (space, SkMatrix::I(), space, SkTransferFunctionBehavior::kRespect)); |
msarett | 9dc6cf6 | 2016-08-23 17:53:06 -0700 | [diff] [blame] | 652 | } |