Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: src/core/SkColorSpaceXform.cpp

Issue 2046013002: Optimize color xforms with 2.2 gammas for SSE2 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkColorPriv.h" 8 #include "SkColorPriv.h"
9 #include "SkColorSpace_Base.h" 9 #include "SkColorSpace_Base.h"
10 #include "SkColorSpaceXform.h" 10 #include "SkColorSpaceXform.h"
11 #include "SkOpts.h"
11 12
12 static inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& s rcToXYZ, 13 static inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& s rcToXYZ,
13 const SkMatrix44& dstToXYZ) { 14 const SkMatrix44& dstToXYZ) {
14 if (!dstToXYZ.invert(srcToDst)) { 15 if (!dstToXYZ.invert(srcToDst)) {
15 return false; 16 return false;
16 } 17 }
17 18
18 srcToDst->postConcat(srcToXYZ); 19 srcToDst->postConcat(srcToXYZ);
19 return true; 20 return true;
20 } 21 }
21 22
22 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa ce>& srcSpace, 23 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa ce>& srcSpace,
23 const sk_sp<SkColorSpa ce>& dstSpace) { 24 const sk_sp<SkColorSpa ce>& dstSpace) {
24 if (!srcSpace || !dstSpace) { 25 if (!srcSpace || !dstSpace) {
25 // Invalid input 26 // Invalid input
26 return nullptr; 27 return nullptr;
27 } 28 }
28 29
29 if (as_CSB(srcSpace)->colorLUT() || as_CSB(dstSpace)->colorLUT()) { 30 if (as_CSB(srcSpace)->colorLUT() || as_CSB(dstSpace)->colorLUT()) {
30 // Unimplemented 31 // Unimplemented
31 return nullptr; 32 return nullptr;
32 } 33 }
33 34
34 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); 35 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
35 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { 36 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) {
36 return nullptr; 37 return nullptr;
37 } 38 }
38 39
39 if (as_CSB(srcSpace)->gammas()->isValues() && as_CSB(dstSpace)->gammas()->is Values()) { 40 if (SkColorSpace::k2Dot2Curve_GammaNamed == srcSpace->gammaNamed() &&
40 float srcGammas[3]; 41 SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed())
41 float dstGammas[3]; 42 {
42 srcGammas[0] = as_CSB(srcSpace)->gammas()->fRed.fValue; 43 return std::unique_ptr<SkColorSpaceXform>(new Sk2Dot2Xform(srcToDst));
43 srcGammas[1] = as_CSB(srcSpace)->gammas()->fGreen.fValue;
44 srcGammas[2] = as_CSB(srcSpace)->gammas()->fBlue.fValue;
45 dstGammas[0] = 1.0f / as_CSB(dstSpace)->gammas()->fRed.fValue;
46 dstGammas[1] = 1.0f / as_CSB(dstSpace)->gammas()->fGreen.fValue;
47 dstGammas[2] = 1.0f / as_CSB(dstSpace)->gammas()->fBlue.fValue;
48
49 return std::unique_ptr<SkColorSpaceXform>(
50 new SkGammaByValueXform(srcGammas, srcToDst, dstGammas));
51 } 44 }
52 45
53 return std::unique_ptr<SkColorSpaceXform>( 46 return std::unique_ptr<SkColorSpaceXform>(
54 new SkDefaultXform(as_CSB(srcSpace)->gammas(), srcToDst, as_CSB(dstS pace)->gammas())); 47 new SkDefaultXform(as_CSB(srcSpace)->gammas(), srcToDst, as_CSB(dstS pace)->gammas()));
55 } 48 }
56 49
57 //////////////////////////////////////////////////////////////////////////////// /////////////////// 50 //////////////////////////////////////////////////////////////////////////////// ///////////////////
58 51
52 Sk2Dot2Xform::Sk2Dot2Xform(const SkMatrix44& srcToDst)
53 {
54 // Build row major 4x4 matrix:
55 // rX gX bX 0
56 // rY gY bY 0
57 // rZ gZ bZ 0
58 // rQ gQ bQ 0
59 fSrcToDst[0] = srcToDst.getFloat(0, 0);
60 fSrcToDst[1] = srcToDst.getFloat(0, 1);
61 fSrcToDst[2] = srcToDst.getFloat(0, 2);
62 fSrcToDst[3] = 0.0f;
63 fSrcToDst[4] = srcToDst.getFloat(1, 0);
64 fSrcToDst[5] = srcToDst.getFloat(1, 1);
65 fSrcToDst[6] = srcToDst.getFloat(1, 2);
66 fSrcToDst[7] = 0.0f;
67 fSrcToDst[8] = srcToDst.getFloat(2, 0);
68 fSrcToDst[9] = srcToDst.getFloat(2, 1);
69 fSrcToDst[10] = srcToDst.getFloat(2, 2);
70 fSrcToDst[11] = 0.0f;
71 fSrcToDst[12] = srcToDst.getFloat(3, 0);
72 fSrcToDst[13] = srcToDst.getFloat(3, 1);
73 fSrcToDst[14] = srcToDst.getFloat(3, 2);
74 fSrcToDst[15] = 0.0f;
75 }
76
77 void Sk2Dot2Xform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const {
78 SkOpts::color_xform_2Dot2_RGBA_to_8888(dst, src, len, fSrcToDst);
79 }
80
81 //////////////////////////////////////////////////////////////////////////////// ///////////////////
82
59 static inline float byte_to_float(uint8_t v) { 83 static inline float byte_to_float(uint8_t v) {
60 return ((float) v) * (1.0f / 255.0f); 84 return ((float) v) * (1.0f / 255.0f);
61 } 85 }
62 86
63 static inline uint8_t clamp_float_to_byte(float v) { 87 // Expand range from 0-1 to 0-255, then convert.
88 static inline uint8_t clamp_normalized_float_to_byte(float v) {
64 v = v * 255.0f; 89 v = v * 255.0f;
65 if (v > 255.0f) { 90 if (v >= 254.5f) {
66 return 255; 91 return 255;
67 } else if (v <= 0.0f) { 92 } else if (v < 0.5f) {
68 return 0; 93 return 0;
69 } else { 94 } else {
70 return (uint8_t) (v + 0.5f); 95 return (uint8_t) (v + 0.5f);
71 } 96 }
72 } 97 }
73 98
74 //////////////////////////////////////////////////////////////////////////////// ///////////////////
75
76 SkGammaByValueXform::SkGammaByValueXform(float srcGammas[3], const SkMatrix44& s rcToDst,
77 float dstGammas[3])
78 : fSrcToDst(srcToDst)
79 {
80 memcpy(fSrcGammas, srcGammas, 3 * sizeof(float));
81 memcpy(fDstGammas, dstGammas, 3 * sizeof(float));
82 }
83
84 void SkGammaByValueXform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, ui nt32_t len) const {
85 while (len-- > 0) {
86 float srcFloats[3];
87 srcFloats[0] = byte_to_float((*src >> 0) & 0xFF);
88 srcFloats[1] = byte_to_float((*src >> 8) & 0xFF);
89 srcFloats[2] = byte_to_float((*src >> 16) & 0xFF);
90
91 // Convert to linear.
92 srcFloats[0] = pow(srcFloats[0], fSrcGammas[0]);
93 srcFloats[1] = pow(srcFloats[1], fSrcGammas[1]);
94 srcFloats[2] = pow(srcFloats[2], fSrcGammas[2]);
95
96 // Convert to dst gamut.
97 float dstFloats[3];
98 dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) +
99 srcFloats[1] * fSrcToDst.getFloat(1, 0) +
100 srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFl oat(3, 0);
101 dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) +
102 srcFloats[1] * fSrcToDst.getFloat(1, 1) +
103 srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFl oat(3, 1);
104 dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) +
105 srcFloats[1] * fSrcToDst.getFloat(1, 2) +
106 srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFl oat(3, 2);
107
108 // Convert to dst gamma.
109 dstFloats[0] = pow(dstFloats[0], fDstGammas[0]);
110 dstFloats[1] = pow(dstFloats[1], fDstGammas[1]);
111 dstFloats[2] = pow(dstFloats[2], fDstGammas[2]);
112
113 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF),
114 clamp_float_to_byte(dstFloats[0]),
115 clamp_float_to_byte(dstFloats[1]),
116 clamp_float_to_byte(dstFloats[2]));
117
118 dst++;
119 src++;
120 }
121 }
122
123 //////////////////////////////////////////////////////////////////////////////// ///////////////////
124
125 // Interpolating lookup in a variably sized table. 99 // Interpolating lookup in a variably sized table.
126 static inline float interp_lut(uint8_t byte, float* table, size_t tableSize) { 100 static inline float interp_lut(uint8_t byte, float* table, size_t tableSize) {
127 float index = byte_to_float(byte) * (tableSize - 1); 101 float index = byte_to_float(byte) * (tableSize - 1);
128 float diff = index - sk_float_floor2int(index); 102 float diff = index - sk_float_floor2int(index);
129 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + 103 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) +
130 table[(int) sk_float_ceil2int(index)] * diff; 104 table[(int) sk_float_ceil2int(index)] * diff;
131 } 105 }
132 106
133 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill 107 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill
134 // have strange results when the table is non-increasing. But any sane gamma 108 // have strange results when the table is non-increasing. But any sane gamma
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 dstFloats[i] = 0.0f; 228 dstFloats[i] = 0.0f;
255 } else { 229 } else {
256 dstFloats[i] = (pow(dstFloats[i] - gamma.fC, 1.0f / gamm a.fG) - gamma.fB) 230 dstFloats[i] = (pow(dstFloats[i] - gamma.fC, 1.0f / gamm a.fG) - gamma.fB)
257 / gamma.fA; 231 / gamma.fA;
258 } 232 }
259 } 233 }
260 } 234 }
261 } 235 }
262 236
263 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF), 237 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF),
264 clamp_float_to_byte(dstFloats[0]), 238 clamp_normalized_float_to_byte(dstFloats[0]),
265 clamp_float_to_byte(dstFloats[1]), 239 clamp_normalized_float_to_byte(dstFloats[1]),
266 clamp_float_to_byte(dstFloats[2])); 240 clamp_normalized_float_to_byte(dstFloats[2])) ;
267 241
268 dst++; 242 dst++;
269 src++; 243 src++;
270 } 244 }
271 } 245 }
OLDNEW
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698