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

Side by Side Diff: src/effects/gradients/SkTwoPointConicalGradient.cpp

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fCachedLocalMatrix Created 6 years, 8 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
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 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 "SkTwoPointConicalGradient.h" 8 #include "SkTwoPointConicalGradient.h"
9 9
10 #include "SkTwoPointConicalGradient_gpu.h" 10 #include "SkTwoPointConicalGradient_gpu.h"
11 11
12 struct TwoPtRadialContext {
13 const TwoPtRadial& fRec;
14 float fRelX, fRelY;
15 const float fIncX, fIncY;
16 float fB;
17 const float fDB;
18
19 TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
20 SkScalar dfx, SkScalar dfy);
21 SkFixed nextT();
22 };
23
12 static int valid_divide(float numer, float denom, float* ratio) { 24 static int valid_divide(float numer, float denom, float* ratio) {
13 SkASSERT(ratio); 25 SkASSERT(ratio);
14 if (0 == denom) { 26 if (0 == denom) {
15 return 0; 27 return 0;
16 } 28 }
17 *ratio = numer / denom; 29 *ratio = numer / denom;
18 return 1; 30 return 1;
19 } 31 }
20 32
21 // Return the number of distinct real roots, and write them into roots[] in 33 // Return the number of distinct real roots, and write them into roots[] in
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; 82 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
71 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; 83 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY;
72 fRadius = SkScalarToFloat(rad0); 84 fRadius = SkScalarToFloat(rad0);
73 fDRadius = SkScalarToFloat(rad1) - fRadius; 85 fDRadius = SkScalarToFloat(rad1) - fRadius;
74 86
75 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); 87 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
76 fRadius2 = sqr(fRadius); 88 fRadius2 = sqr(fRadius);
77 fRDR = fRadius * fDRadius; 89 fRDR = fRadius * fDRadius;
78 } 90 }
79 91
80 void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) { 92 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc alar fy,
81 fRelX = SkScalarToFloat(fx) - fCenterX; 93 SkScalar dfx, SkScalar dfy)
82 fRelY = SkScalarToFloat(fy) - fCenterY; 94 : fRec(rec)
83 fIncX = SkScalarToFloat(dfx); 95 , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
84 fIncY = SkScalarToFloat(dfy); 96 , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
85 fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR); 97 , fIncX(SkScalarToFloat(dfx))
86 fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY); 98 , fIncY(SkScalarToFloat(dfy))
87 } 99 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
100 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
88 101
89 SkFixed TwoPtRadial::nextT() { 102 SkFixed TwoPtRadialContext::nextT() {
90 float roots[2]; 103 float roots[2];
91 104
92 float C = sqr(fRelX) + sqr(fRelY) - fRadius2; 105 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
93 int countRoots = find_quad_roots(fA, fB, C, roots); 106 int countRoots = find_quad_roots(fRec.fA, fB, C, roots);
94 107
95 fRelX += fIncX; 108 fRelX += fIncX;
96 fRelY += fIncY; 109 fRelY += fIncY;
97 fB += fDB; 110 fB += fDB;
98 111
99 if (0 == countRoots) { 112 if (0 == countRoots) {
100 return kDontDrawT; 113 return TwoPtRadial::kDontDrawT;
101 } 114 }
102 115
103 // Prefer the bigger t value if both give a radius(t) > 0 116 // Prefer the bigger t value if both give a radius(t) > 0
104 // find_quad_roots returns the values sorted, so we start with the last 117 // find_quad_roots returns the values sorted, so we start with the last
105 float t = roots[countRoots - 1]; 118 float t = roots[countRoots - 1];
106 float r = lerp(fRadius, fDRadius, t); 119 float r = lerp(fRec.fRadius, fRec.fDRadius, t);
107 if (r <= 0) { 120 if (r <= 0) {
108 t = roots[0]; // might be the same as roots[countRoots-1] 121 t = roots[0]; // might be the same as roots[countRoots-1]
109 r = lerp(fRadius, fDRadius, t); 122 r = lerp(fRec.fRadius, fRec.fDRadius, t);
110 if (r <= 0) { 123 if (r <= 0) {
111 return kDontDrawT; 124 return TwoPtRadial::kDontDrawT;
112 } 125 }
113 } 126 }
114 return SkFloatToFixed(t); 127 return SkFloatToFixed(t);
115 } 128 }
116 129
117 typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, 130 typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
118 const SkPMColor* cache, int toggle, int coun t); 131 const SkPMColor* cache, int toggle, int coun t);
119 132
120 static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 133 static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
121 const SkPMColor* SK_RESTRICT cache, int toggle, 134 const SkPMColor* SK_RESTRICT cache, int toggle,
122 int count) { 135 int count) {
123 for (; count > 0; --count) { 136 for (; count > 0; --count) {
124 SkFixed t = rec->nextT(); 137 SkFixed t = rec->nextT();
125 if (TwoPtRadial::DontDrawT(t)) { 138 if (TwoPtRadial::DontDrawT(t)) {
126 *dstC++ = 0; 139 *dstC++ = 0;
127 } else { 140 } else {
128 SkFixed index = SkClampMax(t, 0xFFFF); 141 SkFixed index = SkClampMax(t, 0xFFFF);
129 SkASSERT(index <= 0xFFFF); 142 SkASSERT(index <= 0xFFFF);
130 *dstC++ = cache[toggle + 143 *dstC++ = cache[toggle +
131 (index >> SkGradientShaderBase::kCache32Shift)]; 144 (index >> SkGradientShaderBase::kCache32Shift)];
132 } 145 }
133 toggle = next_dither_toggle(toggle); 146 toggle = next_dither_toggle(toggle);
134 } 147 }
135 } 148 }
136 149
137 static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 150 static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC ,
138 const SkPMColor* SK_RESTRICT cache, int toggle, 151 const SkPMColor* SK_RESTRICT cache, int toggle,
139 int count) { 152 int count) {
140 for (; count > 0; --count) { 153 for (; count > 0; --count) {
141 SkFixed t = rec->nextT(); 154 SkFixed t = rec->nextT();
142 if (TwoPtRadial::DontDrawT(t)) { 155 if (TwoPtRadial::DontDrawT(t)) {
143 *dstC++ = 0; 156 *dstC++ = 0;
144 } else { 157 } else {
145 SkFixed index = repeat_tileproc(t); 158 SkFixed index = repeat_tileproc(t);
146 SkASSERT(index <= 0xFFFF); 159 SkASSERT(index <= 0xFFFF);
147 *dstC++ = cache[toggle + 160 *dstC++ = cache[toggle +
148 (index >> SkGradientShaderBase::kCache32Shift)]; 161 (index >> SkGradientShaderBase::kCache32Shift)];
149 } 162 }
150 toggle = next_dither_toggle(toggle); 163 toggle = next_dither_toggle(toggle);
151 } 164 }
152 } 165 }
153 166
154 static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 167 static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC ,
155 const SkPMColor* SK_RESTRICT cache, int toggle, 168 const SkPMColor* SK_RESTRICT cache, int toggle,
156 int count) { 169 int count) {
157 for (; count > 0; --count) { 170 for (; count > 0; --count) {
158 SkFixed t = rec->nextT(); 171 SkFixed t = rec->nextT();
159 if (TwoPtRadial::DontDrawT(t)) { 172 if (TwoPtRadial::DontDrawT(t)) {
160 *dstC++ = 0; 173 *dstC++ = 0;
161 } else { 174 } else {
162 SkFixed index = mirror_tileproc(t); 175 SkFixed index = mirror_tileproc(t);
163 SkASSERT(index <= 0xFFFF); 176 SkASSERT(index <= 0xFFFF);
164 *dstC++ = cache[toggle + 177 *dstC++ = cache[toggle +
(...skipping 24 matching lines...) Expand all
189 this->init(); 202 this->init();
190 } 203 }
191 204
192 bool SkTwoPointConicalGradient::isOpaque() const { 205 bool SkTwoPointConicalGradient::isOpaque() const {
193 // Because areas outside the cone are left untouched, we cannot treat the 206 // Because areas outside the cone are left untouched, we cannot treat the
194 // shader as opaque even if the gradient itself is opaque. 207 // shader as opaque even if the gradient itself is opaque.
195 // TODO(junov): Compute whether the cone fills the plane crbug.com/222380 208 // TODO(junov): Compute whether the cone fills the plane crbug.com/222380
196 return false; 209 return false;
197 } 210 }
198 211
199 void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, 212 size_t SkTwoPointConicalGradient::contextSize() const {
200 int count) { 213 return sizeof(TwoPointConicalGradientContext);
214 }
215
216 SkShader::Context* SkTwoPointConicalGradient::createContext(
217 const SkBitmap& device, const SkPaint& paint,
218 const SkMatrix& matrix, void* storage) const {
219 if (!this->validContext(device, paint, matrix)) {
220 return NULL;
221 }
222
223 return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext,
224 (*this, device, paint, matrix));
225 }
226
227 SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradie ntContext(
228 const SkTwoPointConicalGradient& shader, const SkBitmap& device,
229 const SkPaint& paint, const SkMatrix& matrix)
230 : INHERITED(shader, device, paint, matrix)
231 {
232 // we don't have a span16 proc
233 fFlags &= ~kHasSpan16_Flag;
234
235 // in general, we might discard based on computed-radius, so clear
236 // this flag (todo: sometimes we can detect that we never discard...)
237 fFlags &= ~kOpaqueAlpha_Flag;
238 }
239
240 void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
241 int x, int y, SkPMColor* dstCParam, int count) {
242 const SkTwoPointConicalGradient& twoPointConicalGradient =
243 static_cast<const SkTwoPointConicalGradient&>(fShader);
244
201 int toggle = init_dither_toggle(x, y); 245 int toggle = init_dither_toggle(x, y);
202 246
203 SkASSERT(count > 0); 247 SkASSERT(count > 0);
204 248
205 SkPMColor* SK_RESTRICT dstC = dstCParam; 249 SkPMColor* SK_RESTRICT dstC = dstCParam;
206 250
207 SkMatrix::MapXYProc dstProc = fDstToIndexProc; 251 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
208 252
209 const SkPMColor* SK_RESTRICT cache = this->getCache32(); 253 const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
210 254
211 TwoPointConicalProc shadeProc = twopoint_repeat; 255 TwoPointConicalProc shadeProc = twopoint_repeat;
212 if (SkShader::kClamp_TileMode == fTileMode) { 256 if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
213 shadeProc = twopoint_clamp; 257 shadeProc = twopoint_clamp;
214 } else if (SkShader::kMirror_TileMode == fTileMode) { 258 } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
215 shadeProc = twopoint_mirror; 259 shadeProc = twopoint_mirror;
216 } else { 260 } else {
217 SkASSERT(SkShader::kRepeat_TileMode == fTileMode); 261 SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode );
218 } 262 }
219 263
220 if (fDstToIndexClass != kPerspective_MatrixClass) { 264 if (fDstToIndexClass != kPerspective_MatrixClass) {
221 SkPoint srcPt; 265 SkPoint srcPt;
222 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 266 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
223 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 267 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
224 SkScalar dx, fx = srcPt.fX; 268 SkScalar dx, fx = srcPt.fX;
225 SkScalar dy, fy = srcPt.fY; 269 SkScalar dy, fy = srcPt.fY;
226 270
227 if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 271 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
228 SkFixed fixedX, fixedY; 272 SkFixed fixedX, fixedY;
229 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY); 273 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
230 dx = SkFixedToScalar(fixedX); 274 dx = SkFixedToScalar(fixedX);
231 dy = SkFixedToScalar(fixedY); 275 dy = SkFixedToScalar(fixedY);
232 } else { 276 } else {
233 SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 277 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
234 dx = fDstToIndex.getScaleX(); 278 dx = fDstToIndex.getScaleX();
235 dy = fDstToIndex.getSkewY(); 279 dy = fDstToIndex.getSkewY();
236 } 280 }
237 281
238 fRec.setup(fx, fy, dx, dy); 282 TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
239 (*shadeProc)(&fRec, dstC, cache, toggle, count); 283 (*shadeProc)(&rec, dstC, cache, toggle, count);
240 } else { // perspective case 284 } else { // perspective case
241 SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf; 285 SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
242 SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf; 286 SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
243 for (; count > 0; --count) { 287 for (; count > 0; --count) {
244 SkPoint srcPt; 288 SkPoint srcPt;
245 dstProc(fDstToIndex, dstX, dstY, &srcPt); 289 dstProc(fDstToIndex, dstX, dstY, &srcPt);
246 fRec.setup(srcPt.fX, srcPt.fY, 0, 0); 290 TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt .fY, 0, 0);
247 (*shadeProc)(&fRec, dstC, cache, toggle, 1); 291 (*shadeProc)(&rec, dstC, cache, toggle, 1);
248 292
249 dstX += SK_Scalar1; 293 dstX += SK_Scalar1;
250 toggle = next_dither_toggle(toggle); 294 toggle = next_dither_toggle(toggle);
251 dstC += 1; 295 dstC += 1;
252 } 296 }
253 } 297 }
254 } 298 }
255 299
256 bool SkTwoPointConicalGradient::setContext(const SkBitmap& device,
257 const SkPaint& paint,
258 const SkMatrix& matrix) {
259 if (!this->INHERITED::setContext(device, paint, matrix)) {
260 return false;
261 }
262
263 // we don't have a span16 proc
264 fFlags &= ~kHasSpan16_Flag;
265
266 // in general, we might discard based on computed-radius, so clear
267 // this flag (todo: sometimes we can detect that we never discard...)
268 fFlags &= ~kOpaqueAlpha_Flag;
269
270 return true;
271 }
272
273 SkShader::BitmapType SkTwoPointConicalGradient::asABitmap( 300 SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
274 SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const { 301 SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
275 SkPoint diff = fCenter2 - fCenter1; 302 SkPoint diff = fCenter2 - fCenter1;
276 SkScalar diffLen = 0; 303 SkScalar diffLen = 0;
277 304
278 if (bitmap) { 305 if (bitmap) {
279 this->getGradientTableBitmap(bitmap); 306 this->getGradientTableBitmap(bitmap);
280 } 307 }
281 if (matrix) { 308 if (matrix) {
282 diffLen = diff.length(); 309 diffLen = diff.length();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 str->appendScalar(fCenter2.fY); 393 str->appendScalar(fCenter2.fY);
367 str->append(") radius2: "); 394 str->append(") radius2: ");
368 str->appendScalar(fRadius2); 395 str->appendScalar(fRadius2);
369 str->append(" "); 396 str->append(" ");
370 397
371 this->INHERITED::toString(str); 398 this->INHERITED::toString(str);
372 399
373 str->append(")"); 400 str->append(")");
374 } 401 }
375 #endif 402 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698