19876ac5b3016e5353c072378ac1545a0a2270757msarett/* 29876ac5b3016e5353c072378ac1545a0a2270757msarett * Copyright 2016 Google Inc. 39876ac5b3016e5353c072378ac1545a0a2270757msarett * 49876ac5b3016e5353c072378ac1545a0a2270757msarett * Use of this source code is governed by a BSD-style license that can be 59876ac5b3016e5353c072378ac1545a0a2270757msarett * found in the LICENSE file. 69876ac5b3016e5353c072378ac1545a0a2270757msarett */ 79876ac5b3016e5353c072378ac1545a0a2270757msarett 8a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h" 9200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkColorSpacePriv.h" 1098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpaceXformPriv.h" 112563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXform_A2B.h" 1231d097e865f266c8398f45114e4c75c0dfdef058msarett#include "SkColorSpaceXform_Base.h" 1398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpace_A2B.h" 1498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpace_XYZ.h" 15200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkHalf.h" 1698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkMakeUnique.h" 17200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkOpts.h" 185e15961fa77281540a80ac0d036fefe071c11574Mike Klein#include "SkPM4fPriv.h" 19f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#include "SkRasterPipeline.h" 20ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h" 2145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein#include "../jumper/SkJumper.h" 229876ac5b3016e5353c072378ac1545a0a2270757msarett 236006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = { 24b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, 25b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, 26b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, 27b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, 28b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, 29b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, 30b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, 31b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, 32b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, 33b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, 34b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, 35b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, 36b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, 37b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, 38b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, 39b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, 40b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, 41b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, 42b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, 43b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, 44b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, 45b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, 46b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, 47b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, 48b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, 49b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, 50b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, 51b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, 52b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, 53b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, 54b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, 55b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, 56b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, 57b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, 58b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, 59b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, 60b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, 61b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, 62b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, 63b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, 64b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, 65b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, 66b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, 67b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, 68b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, 69b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, 70b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, 71b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, 72b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, 73b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, 74b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, 75b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, 76b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, 77b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, 78b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, 79b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, 80b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, 81b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, 82b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, 83b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, 84b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, 85b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, 86b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, 87b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, 88b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 89b39067696ad08a26bbe49b71a71f0546dc42a075msarett 906006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 916006f678e78af7b6f67a454cd4bc213048983f9dmsarett 9215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) { 9315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 9415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = powf(x, exponent); 9515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 9615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 9715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 9815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// outTable is always 256 entries, inTable may be larger or smaller. 9915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable, 10015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett int inTableSize) { 10115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett if (256 == inTableSize) { 10215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett memcpy(outTable, inTable, sizeof(float) * 256); 10315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett return; 10415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 10515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 10615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 10715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = interp_lut(x, inTable, inTableSize); 10815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 10915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 11015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 111aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett 11215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, 11315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett float d, float e, float f) { 1142410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett // Y = (aX + b)^g + e for X >= d 1152410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett // Y = cX + f otherwise 11615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 11715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett if (x >= d) { 1182410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett *outTable++ = clamp_0_1(powf(a * x + b, g) + e); 11915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } else { 1202410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett *outTable++ = clamp_0_1(c * x + f); 12115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 12215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 12315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 12415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 12515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 12615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 127f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettstatic const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize; 1283418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett 1291b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { 130b39067696ad08a26bbe49b71a71f0546dc42a075msarett float toGammaExp = 1.0f / exponent; 131b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett for (int i = 0; i < kDstGammaTableSize; i++) { 1333418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); 134b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); 135b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 136dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 137dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 1381b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, 139b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 140197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize); 141b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 142dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 143b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, 144b39067696ad08a26bbe49b71a71f0546dc42a075msarett float f) { 145b39067696ad08a26bbe49b71a71f0546dc42a075msarett // We need to take the inverse of the following piecewise function. 1460cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein // Y = (aX + b)^g + e for X >= d 1470cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein // Y = cX + f otherwise 148b39067696ad08a26bbe49b71a71f0546dc42a075msarett 149b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Assume that the gamma function is continuous, or this won't make much sense anyway. 1500cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein // Plug in |d| to the second equation to calculate the new piecewise interval. 151b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Then simply use the inverse of the original functions. 1522410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett float interval = c * d + f; 153b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x < interval) { 1542410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett // X = (Y - F) / C 1552410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett if (0.0f == c) { 156b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 157b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the lower segment, guess zero. 158b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 159b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 160b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1612410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett return (x - f) / c; 162b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 163b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1642410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett // X = ((Y - E)^(1 / G) - B) / A 165b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == a || 0.0f == g) { 166b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 167b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the upper segment, guess one. 168b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 169b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 170b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1712410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett return (powf(x - e, 1.0f / g) - b) / a; 172b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 173b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1741b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, 175b39067696ad08a26bbe49b71a71f0546dc42a075msarett float b, float c, float d, float e, float f) { 1763418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett for (int i = 0; i < kDstGammaTableSize; i++) { 1773418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); 178b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_parametric(x, g, a, b, c, d, e, f); 179b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 180b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 181b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 182b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1836006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 1846006f678e78af7b6f67a454cd4bc213048983f9dmsarett 1851b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 1861b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns { 1871b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* fSRGBTable; 1881b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* f2Dot2Table; 1891b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromValue)(T*, float); 1901b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromTable)(T*, const float*, int); 1911b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromParam)(T*, float, float, float, float, float, float, float); 1921b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 1931b93bd1e6eba3d14593490e4e24a34546638c8damsarett 1941b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear { 1951b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_srgb, 1961b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_2dot2, 1971b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 1981b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 1991b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 2001b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 2011b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2021b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear { 20355bcc8e0af3415601b3d62252a0d579fbe87c85amsarett nullptr, 20455bcc8e0af3415601b3d62252a0d579fbe87c85amsarett nullptr, 2051b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2061b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2071b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2081b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 2091b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2101b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear. 2111b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 2121b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, 2139488833428e83c93a7e6002f4d056084fb57112fraftias const SkColorSpace_XYZ* space, const GammaFns<T>& fns, 214f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett bool gammasAreMatching) 2154be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett{ 2169488833428e83c93a7e6002f4d056084fb57112fraftias switch (space->gammaNamed()) { 217600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 2181b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; 2191b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 220600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 2211b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table; 2221b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 223600c737b64eae2c7379442ae2c852853cce3a278msarett case kLinear_SkGammaNamed: 2248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; 2251b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2261b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: { 2279488833428e83c93a7e6002f4d056084fb57112fraftias const SkGammas* gammas = space->gammas(); 2281b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas); 2291b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2307bbda991af353fbe6b34132132d211d23a3dba8cmsarett auto build_table = [=](int i) { 2311b93bd1e6eba3d14593490e4e24a34546638c8damsarett if (gammas->isNamed(i)) { 2321b93bd1e6eba3d14593490e4e24a34546638c8damsarett switch (gammas->data(i).fNamed) { 233600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 234a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], 235a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fG, 236a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fA, 237a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fB, 238a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fC, 239a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fD, 240a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fE, 241a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary gSRGB_TransferFn.fF); 24255bcc8e0af3415601b3d62252a0d579fbe87c85amsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2431b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 244600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 24555bcc8e0af3415601b3d62252a0d579fbe87c85amsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f); 24655bcc8e0af3415601b3d62252a0d579fbe87c85amsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2471b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 248600c737b64eae2c7379442ae2c852853cce3a278msarett case kLinear_SkGammaNamed: 2491b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f); 2501b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2511b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2521b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: 2531b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(false); 2541b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2551b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2561b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isValue(i)) { 2571b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2581b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fValue); 2591b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2601b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isTable(i)) { 2611b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i), 2621b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fTable.fSize); 2631b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2641b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else { 2651b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas->isParametric(i)); 266df44fc5f2bb282557df291e20dbd26c070533aa6Matt Sarett const SkColorSpaceTransferFn& params = gammas->params(i); 2671b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG, 2681b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fA, params.fB, params.fC, params.fD, params.fE, 2691b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fF); 2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2711b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2727bbda991af353fbe6b34132132d211d23a3dba8cmsarett }; 2737bbda991af353fbe6b34132132d211d23a3dba8cmsarett 2747bbda991af353fbe6b34132132d211d23a3dba8cmsarett if (gammasAreMatching) { 2757bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(0); 2767bbda991af353fbe6b34132132d211d23a3dba8cmsarett outGammaTables[1] = outGammaTables[0]; 2777bbda991af353fbe6b34132132d211d23a3dba8cmsarett outGammaTables[2] = outGammaTables[0]; 2787bbda991af353fbe6b34132132d211d23a3dba8cmsarett } else { 2797bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(0); 2807bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(1); 2817bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(2); 2821b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2837bbda991af353fbe6b34132132d211d23a3dba8cmsarett 2847bbda991af353fbe6b34132132d211d23a3dba8cmsarett break; 2851b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2861b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2871b93bd1e6eba3d14593490e4e24a34546638c8damsarett} 2881b93bd1e6eba3d14593490e4e24a34546638c8damsarett 289f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettvoid SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3], 2909488833428e83c93a7e6002f4d056084fb57112fraftias uint8_t* dstStorage, 2919488833428e83c93a7e6002f4d056084fb57112fraftias const SkColorSpace_XYZ* space, 292f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett bool gammasAreMatching) { 293f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear, 294f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett gammasAreMatching); 295f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett} 296f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett 2971b93bd1e6eba3d14593490e4e24a34546638c8damsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 2981b93bd1e6eba3d14593490e4e24a34546638c8damsarett 29998156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* src, 30098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkColorSpace* dst) { 30198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein return SkColorSpaceXform_Base::New(src, dst, SkTransferFunctionBehavior::kRespect); 302cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett} 303cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett 30498156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New( 30598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkColorSpace* src, 30698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkColorSpace* dst, 30798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkTransferFunctionBehavior premulBehavior) { 308cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett 30998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein if (!src || !dst) { 3106006f678e78af7b6f67a454cd4bc213048983f9dmsarett // Invalid input 3116006f678e78af7b6f67a454cd4bc213048983f9dmsarett return nullptr; 3126006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 3136006f678e78af7b6f67a454cd4bc213048983f9dmsarett 314333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein if (!dst->toXYZD50()) { 315333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein SkCSXformPrintf("only XYZ destinations supported\n"); 3169488833428e83c93a7e6002f4d056084fb57112fraftias return nullptr; 3179488833428e83c93a7e6002f4d056084fb57112fraftias } 3189488833428e83c93a7e6002f4d056084fb57112fraftias 319333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein if (src->toXYZD50()) { 320333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein return skstd::make_unique<SkColorSpaceXform_XYZ>(static_cast<SkColorSpace_XYZ*>(src), 321333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein static_cast<SkColorSpace_XYZ*>(dst), 322333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein premulBehavior); 3236006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 324333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein return skstd::make_unique<SkColorSpaceXform_A2B>(static_cast<SkColorSpace_A2B*>(src), 325333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein static_cast<SkColorSpace_XYZ*>(dst)); 3266006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 3276006f678e78af7b6f67a454cd4bc213048983f9dmsarett 3286006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 3296006f678e78af7b6f67a454cd4bc213048983f9dmsarett 330e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Kleinstatic inline int num_tables(SkColorSpace_XYZ* space) { 3319488833428e83c93a7e6002f4d056084fb57112fraftias switch (space->gammaNamed()) { 3327bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kSRGB_SkGammaNamed: 3337bbda991af353fbe6b34132132d211d23a3dba8cmsarett case k2Dot2Curve_SkGammaNamed: 3347bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kLinear_SkGammaNamed: 3357bbda991af353fbe6b34132132d211d23a3dba8cmsarett return 0; 3367bbda991af353fbe6b34132132d211d23a3dba8cmsarett default: { 3379488833428e83c93a7e6002f4d056084fb57112fraftias const SkGammas* gammas = space->gammas(); 3387bbda991af353fbe6b34132132d211d23a3dba8cmsarett SkASSERT(gammas); 3397bbda991af353fbe6b34132132d211d23a3dba8cmsarett 3407bbda991af353fbe6b34132132d211d23a3dba8cmsarett // It's likely that each component will have the same gamma. In this case, 3417bbda991af353fbe6b34132132d211d23a3dba8cmsarett // we only need to build one table. 34205d7416b371fe1db9faef5a3623e54e109977c2cMike Klein return gammas->allChannelsSame() ? 1 : 3; 3437bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 3447bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 3457bbda991af353fbe6b34132132d211d23a3dba8cmsarett} 3467bbda991af353fbe6b34132132d211d23a3dba8cmsarett 34798156c4592d98b7ee50dfb47bf64efe8660b14adMike KleinSkColorSpaceXform_XYZ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* src, 34898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkColorSpace_XYZ* dst, 34998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkTransferFunctionBehavior premulBehavior) 350cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett : fPremulBehavior(premulBehavior) 3513418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{ 35298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein fColorSpacesAreIdentical = SkColorSpace::Equals(src, dst); 35398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein 35498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkMatrix44 srcToDst(SkMatrix44::kIdentity_Constructor); 35598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein if (!fColorSpacesAreIdentical && *src->toXYZD50() != *dst->toXYZD50()) { 35698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein srcToDst.setConcat(*dst->fromXYZD50(), *src->toXYZD50()); 35798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein } 35898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein 35926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 0] = srcToDst.get(0, 0); 36026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 1] = srcToDst.get(1, 0); 36126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 2] = srcToDst.get(2, 0); 36226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 3] = srcToDst.get(0, 1); 36326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 4] = srcToDst.get(1, 1); 36426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 5] = srcToDst.get(2, 1); 36526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 6] = srcToDst.get(0, 2); 36626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 7] = srcToDst.get(1, 2); 36726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 8] = srcToDst.get(2, 2); 36826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[ 9] = srcToDst.get(0, 3); 36926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[10] = srcToDst.get(1, 3); 37026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett fSrcToDst[11] = srcToDst.get(2, 3); 37198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein fSrcToDstIsIdentity = srcToDst.isIdentity(); 3727bbda991af353fbe6b34132132d211d23a3dba8cmsarett 37398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein const int numSrcTables = num_tables(src); 374f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett const size_t srcEntries = numSrcTables * 256; 3757bbda991af353fbe6b34132132d211d23a3dba8cmsarett const bool srcGammasAreMatching = (1 >= numSrcTables); 376f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett fSrcStorage.reset(srcEntries); 37798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, src, kToLinear, 378f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett srcGammasAreMatching); 379f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett 38098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein const int numDstTables = num_tables(dst); 38198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein dst->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables); 382379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett 38398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein if (src->gammaIsLinear()) { 384379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fSrcGamma = kLinear_SrcGamma; 38598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein } else if (kSRGB_SkGammaNamed == src->gammaNamed()) { 386379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fSrcGamma = kSRGB_SrcGamma; 387379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett } else { 388379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fSrcGamma = kTable_SrcGamma; 389379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett } 390379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett 39198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein switch (dst->gammaNamed()) { 392379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kSRGB_SkGammaNamed: 393379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fDstGamma = kSRGB_DstGamma; 394379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 395379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case k2Dot2Curve_SkGammaNamed: 396379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fDstGamma = k2Dot2_DstGamma; 397379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 398379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kLinear_SkGammaNamed: 399379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fDstGamma = kLinear_DstGamma; 400379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 401379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett default: 402379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett fDstGamma = kTable_DstGamma; 403379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 404379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett } 4053418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett} 406dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 4077bbda991af353fbe6b34132132d211d23a3dba8cmsarett 40898156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform_XYZ::onApply(ColorFormat dstColorFormat, void* dst, 40998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein ColorFormat srcColorFormat, const void* src, 41098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein int len, SkAlphaType alphaType) const { 41198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein if (fColorSpacesAreIdentical && kPremul_SkAlphaType != alphaType) { 412e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein if ((kRGBA_8888_ColorFormat == dstColorFormat && 413e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein kRGBA_8888_ColorFormat == srcColorFormat) || 414e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein (kBGRA_8888_ColorFormat == dstColorFormat && 415e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein kBGRA_8888_ColorFormat == srcColorFormat)) 416e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein { 417e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein memcpy(dst, src, len * sizeof(uint32_t)); 418e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein return true; 41958564425e5acb5911cc3719f9c1e39190cc829b8Mike Klein } 42026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett 421e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein if ((kRGBA_8888_ColorFormat == dstColorFormat && 422e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein kBGRA_8888_ColorFormat == srcColorFormat) || 423e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein (kBGRA_8888_ColorFormat == dstColorFormat && 424e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein kRGBA_8888_ColorFormat == srcColorFormat)) 425e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein { 426e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein SkOpts::RGBA_to_BGRA((uint32_t*)dst, src, len); 427e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein return true; 428e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein } 4291f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein } 4301f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein 431b24704d35f67f5b460be9c92794892e06adceb46Mike Klein SkRasterPipeline_<256> pipeline; 432f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 43345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein SkJumper_MemoryCtx src_ctx = { (void*)src, 0 }, 43445c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein dst_ctx = { (void*)dst, 0 }; 43545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein 43626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett LoadTablesContext loadTables; 43726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett switch (srcColorFormat) { 43826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett case kRGBA_8888_ColorFormat: 439379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett if (kLinear_SrcGamma == fSrcGamma) { 44045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_8888, &src_ctx); 44126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett } else { 442379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fSrc = src; 44326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fR = fSrcGammaTables[0]; 44426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fG = fSrcGammaTables[1]; 44526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fB = fSrcGammaTables[2]; 44626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett pipeline.append(SkRasterPipeline::load_tables, &loadTables); 447f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 448f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 44926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett break; 45026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett case kBGRA_8888_ColorFormat: 451379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett if (kLinear_SrcGamma == fSrcGamma) { 45245c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_bgra, &src_ctx); 45326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett } else { 454379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fSrc = src; 45526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fR = fSrcGammaTables[2]; 45626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fG = fSrcGammaTables[1]; 45726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett loadTables.fB = fSrcGammaTables[0]; 45826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett pipeline.append(SkRasterPipeline::load_tables, &loadTables); 459c2d207603edbbd3809d5144fe4a048a2ad774910Mike Klein pipeline.append(SkRasterPipeline::swap_rb); 460f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 461f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 46226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett break; 463b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman case kRGBA_F16_ColorFormat: 464b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman if (kLinear_SrcGamma != fSrcGamma) { 465b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman return false; 466b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman } 46745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_f16, &src_ctx); 468b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman break; 4694c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett case kRGBA_F32_ColorFormat: 4704c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett if (kLinear_SrcGamma != fSrcGamma) { 4714c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett return false; 4724c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett } 47345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_f32, &src_ctx); 4744c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett break; 475379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kRGBA_U16_BE_ColorFormat: 476379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett switch (fSrcGamma) { 477379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kLinear_SrcGamma: 47845c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx); 479379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 480379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kSRGB_SrcGamma: 48145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx); 482f1f1162273b382db99f8609e5bbfff24f5594821Mike Klein pipeline.append(SkRasterPipeline::from_srgb); 483379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 484379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kTable_SrcGamma: 485379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fSrc = src; 486379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fR = fSrcGammaTables[0]; 487379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fG = fSrcGammaTables[1]; 488379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett loadTables.fB = fSrcGammaTables[2]; 489379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables); 490379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 491379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett } 492379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 4935bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kRGB_U16_BE_ColorFormat: 4945bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett switch (fSrcGamma) { 4955bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kLinear_SrcGamma: 49645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx); 4975bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 4985bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kSRGB_SrcGamma: 49945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx); 500f1f1162273b382db99f8609e5bbfff24f5594821Mike Klein pipeline.append(SkRasterPipeline::from_srgb); 5015bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 5025bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kTable_SrcGamma: 5035bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett loadTables.fSrc = src; 5045bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett loadTables.fR = fSrcGammaTables[0]; 5055bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett loadTables.fG = fSrcGammaTables[1]; 5065bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett loadTables.fB = fSrcGammaTables[2]; 5075bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett pipeline.append(SkRasterPipeline::load_tables_rgb_u16_be, &loadTables); 5085bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 5095bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett } 5105bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 5113725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett default: 5123725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett return false; 513f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 514f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 51598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein if (!fSrcToDstIsIdentity) { 516f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst); 517f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 518eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett if (kRGBA_F16_ColorFormat != dstColorFormat && 519eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett kRGBA_F32_ColorFormat != dstColorFormat) 5208f7a9a9bfb51a00082bde7eb6b04515b935a588fMatt Sarett { 5215e15961fa77281540a80ac0d036fefe071c11574Mike Klein bool need_clamp_0, need_clamp_1; 5225e15961fa77281540a80ac0d036fefe071c11574Mike Klein analyze_3x4_matrix(fSrcToDst, &need_clamp_0, &need_clamp_1); 5235e15961fa77281540a80ac0d036fefe071c11574Mike Klein 5245e15961fa77281540a80ac0d036fefe071c11574Mike Klein if (need_clamp_0) { pipeline.append(SkRasterPipeline::clamp_0); } 5255e15961fa77281540a80ac0d036fefe071c11574Mike Klein if (need_clamp_1) { pipeline.append(SkRasterPipeline::clamp_1); } 5265e15961fa77281540a80ac0d036fefe071c11574Mike Klein } 527f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 528f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 529cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kRespect == fPremulBehavior) 530cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett { 531f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett pipeline.append(SkRasterPipeline::premul); 532f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 533f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 534e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett TablesContext tables; 535a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein float to_2dot2 = 1/2.2f; 536379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett switch (fDstGamma) { 537f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case kSRGB_DstGamma: 538f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett pipeline.append(SkRasterPipeline::to_srgb); 539f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 540f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case k2Dot2_DstGamma: 541a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein pipeline.append(SkRasterPipeline::gamma, &to_2dot2); 542f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 543e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett case kTable_DstGamma: 544e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett tables.fR = fDstGammaTables[0]; 545e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett tables.fG = fDstGammaTables[1]; 546e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett tables.fB = fDstGammaTables[2]; 547e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett tables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize; 548e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett pipeline.append(SkRasterPipeline::byte_tables_rgb, &tables); 549f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett default: 550f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 551f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 552f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 553cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kIgnore == fPremulBehavior) 554cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett { 555e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett pipeline.append(SkRasterPipeline::premul); 556e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett } 557e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett 558f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett switch (dstColorFormat) { 559f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case kRGBA_8888_ColorFormat: 56045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_8888, &dst_ctx); 561f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 562f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case kBGRA_8888_ColorFormat: 56345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_bgra, &dst_ctx); 564f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 565f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case kRGBA_F16_ColorFormat: 566cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett if (kLinear_DstGamma != fDstGamma) { 567f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett return false; 568f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 56945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_f16, &dst_ctx); 570f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 571f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett case kRGBA_F32_ColorFormat: 572cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett if (kLinear_DstGamma != fDstGamma) { 573f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett return false; 574f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 57545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_f32, &dst_ctx); 576f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett break; 5773725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett case kBGR_565_ColorFormat: 5783725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett if (kOpaque_SkAlphaType != alphaType) { 5793725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett return false; 5803725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett } 58145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_565, &dst_ctx); 5823725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett break; 583379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett default: 584379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett return false; 585f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett } 58645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.run(0,0, len,1); 587f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett return true; 588f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett} 589f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett 5909488833428e83c93a7e6002f4d056084fb57112fraftiasstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) { 59198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein auto xform = skstd::make_unique<SkColorSpaceXform_XYZ>(space, space, 59298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkTransferFunctionBehavior::kRespect); 59398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein xform->pretendNotToBeIdentityForTesting(); 59498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein return std::move(xform); 59598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein} 59698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein 59798156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, 59898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein ColorFormat srcColorFormat, const void* src, 59998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein int len, SkAlphaType alphaType) const { 60098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, 60198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein srcColorFormat, src, 60298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein len, alphaType); 60398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein} 60498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein 60598156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst, 60698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkColorSpace* srcCS, ColorFormat srcFormat, const void* src, 60798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein int len, AlphaOp op) { 60898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein SkAlphaType at; 60998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein switch (op) { 61098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein case kPreserve_AlphaOp: at = kUnpremul_SkAlphaType; break; 61198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein case kPremul_AlphaOp: at = kPremul_SkAlphaType; break; 61298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein case kSrcIsOpaque_AlphaOp: at = kOpaque_SkAlphaType; break; 61398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein } 61498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein return New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, len, at); 6159dc6cf6b8833d36c29a23d2519989b069745fcd5msarett} 616