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

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

Issue 1074313002: speedup haircubics (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 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
« no previous file with comments | « src/core/SkGeometry.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
2 /* 1 /*
3 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
4 * 3 *
5 * 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
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9
10 #include "SkScan.h" 8 #include "SkScan.h"
11 #include "SkBlitter.h" 9 #include "SkBlitter.h"
12 #include "SkRasterClip.h" 10 #include "SkRasterClip.h"
13 #include "SkFDot6.h" 11 #include "SkFDot6.h"
14 #include "SkLineClipper.h" 12 #include "SkLineClipper.h"
15 13
14 //#define SK_SUPPORT_LEGACY_HAIRCUBIC
15
16 static void horiline(int x, int stopx, SkFixed fy, SkFixed dy, 16 static void horiline(int x, int stopx, SkFixed fy, SkFixed dy,
17 SkBlitter* blitter) { 17 SkBlitter* blitter) {
18 SkASSERT(x < stopx); 18 SkASSERT(x < stopx);
19 19
20 do { 20 do {
21 blitter->blitH(x, fy >> 16, 1); 21 blitter->blitH(x, fy >> 16, 1);
22 fy += dy; 22 fy += dy;
23 } while (++x < stopx); 23 } while (++x < stopx);
24 } 24 }
25 25
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 blitter->blitRect(r.fLeft, r.fTop + 1, 1, height - 2); // left 186 blitter->blitRect(r.fLeft, r.fTop + 1, 1, height - 2); // left
187 blitter->blitRect(r.fRight - 1, r.fTop + 1, 1, height - 2); // right 187 blitter->blitRect(r.fRight - 1, r.fTop + 1, 1, height - 2); // right
188 blitter->blitH(r.fLeft, r.fBottom - 1, width); // bottom 188 blitter->blitH(r.fLeft, r.fBottom - 1, width); // bottom
189 } 189 }
190 190
191 /////////////////////////////////////////////////////////////////////////////// 191 ///////////////////////////////////////////////////////////////////////////////
192 192
193 #include "SkPath.h" 193 #include "SkPath.h"
194 #include "SkGeometry.h" 194 #include "SkGeometry.h"
195 195
196 #define kMaxCubicSubdivideLevel 6
197 #define kMaxQuadSubdivideLevel 5
198
196 static int compute_int_quad_dist(const SkPoint pts[3]) { 199 static int compute_int_quad_dist(const SkPoint pts[3]) {
197 // compute the vector between the control point ([1]) and the middle of the 200 // compute the vector between the control point ([1]) and the middle of the
198 // line connecting the start and end ([0] and [2]) 201 // line connecting the start and end ([0] and [2])
199 SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX; 202 SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX;
200 SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY; 203 SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY;
201 // we want everyone to be positive 204 // we want everyone to be positive
202 dx = SkScalarAbs(dx); 205 dx = SkScalarAbs(dx);
203 dy = SkScalarAbs(dy); 206 dy = SkScalarAbs(dy);
204 // convert to whole pixel values (use ceiling to be conservative) 207 // convert to whole pixel values (use ceiling to be conservative)
205 int idx = SkScalarCeilToInt(dx); 208 int idx = SkScalarCeilToInt(dx);
(...skipping 13 matching lines...) Expand all
219 222
220 SkChopQuadAtHalf(pts, tmp); 223 SkChopQuadAtHalf(pts, tmp);
221 hairquad(tmp, clip, blitter, level - 1, lineproc); 224 hairquad(tmp, clip, blitter, level - 1, lineproc);
222 hairquad(&tmp[2], clip, blitter, level - 1, lineproc); 225 hairquad(&tmp[2], clip, blitter, level - 1, lineproc);
223 } else { 226 } else {
224 SkPoint tmp[] = { pts[0], pts[2] }; 227 SkPoint tmp[] = { pts[0], pts[2] };
225 lineproc(tmp, 2, clip, blitter); 228 lineproc(tmp, 2, clip, blitter);
226 } 229 }
227 } 230 }
228 231
229 static void haircubic(const SkPoint pts[4], const SkRegion* clip, 232 #ifndef SK_SUPPORT_LEGACY_HAIRCUBIC
233 static inline Sk2s abs(const Sk2s& value) {
234 return Sk2s::Max(value, -value);
235 }
236
237 static inline SkScalar max_component(const Sk2s& value) {
238 SkScalar components[2];
239 value.store(components);
240 return SkTMax(components[0], components[1]);
241 }
242
243 static inline int compute_cubic_segs(const SkPoint pts[4]) {
244 Sk2s p0 = from_point(pts[0]);
245 Sk2s p1 = from_point(pts[1]);
246 Sk2s p2 = from_point(pts[2]);
247 Sk2s p3 = from_point(pts[3]);
248
249 const Sk2s oneThird(1.0f / 3.0f);
250 const Sk2s twoThird(2.0f / 3.0f);
251
252 Sk2s p13 = oneThird * p3 + twoThird * p0;
253 Sk2s p23 = oneThird * p0 + twoThird * p3;
254
255 SkScalar diff = max_component(Sk2s::Max(abs(p1 - p13), abs(p2 - p23)));
256 SkScalar tol = SK_Scalar1 / 8;
257
258 for (int i = 0; i < kMaxCubicSubdivideLevel; ++i) {
259 if (diff < tol) {
260 return 1 << i;
261 }
262 tol *= 4;
263 }
264 return 1 << kMaxCubicSubdivideLevel;
265 }
266
267 static bool lt_90(SkPoint p0, SkPoint pivot, SkPoint p2) {
268 return SkVector::DotProduct(p0 - pivot, p2 - pivot) >= 0;
269 }
270
271 // The off-curve points are "inside" the limits of the on-curve pts
272 static bool quick_cubic_niceness_check(const SkPoint pts[4]) {
273 return lt_90(pts[1], pts[0], pts[3]) &&
274 lt_90(pts[2], pts[0], pts[3]) &&
275 lt_90(pts[1], pts[3], pts[0]) &&
276 lt_90(pts[2], pts[3], pts[0]);
277 }
278
279 static void hair_cubic(const SkPoint pts[4], const SkRegion* clip, SkBlitter* bl itter,
280 LineProc lineproc) {
281 const int nLines = compute_cubic_segs(pts);
282 SkASSERT(nLines > 0);
283 if (1 == nLines) {
284 lineproc(pts[0], pts[3], clip, blitter);
285 return;
286 }
287
288 SkPoint coeff[4];
289 SkCubicToPoly(pts, coeff);
290
291 const SkScalar deltaT = SK_Scalar1 / nLines;
292 SkScalar currT = deltaT;
293
294 SkPoint startPt = pts[0];
295 // to ensure we exactly end at the last cubic pt, we don't rely on the stepp er
296 // which could accumulate error in currT += deltaT...
297 for (int i = 0; i < nLines - 1; ++i) {
298 SkPoint endPt = SkEvalCubicPolyAt(coeff, currT);
299 lineproc(startPt, endPt, clip, blitter);
300 startPt = endPt;
301 currT += deltaT;
302 }
303 lineproc(startPt, pts[3], clip, blitter);
304 }
305 #endif
306
307 static inline void haircubic(const SkPoint pts[4], const SkRegion* clip,
230 SkBlitter* blitter, int level, SkScan::HairRgnProc linepro c) { 308 SkBlitter* blitter, int level, SkScan::HairRgnProc linepro c) {
309 #ifdef SK_SUPPORT_LEGACY_HAIRCUBIC
231 if (level > 0) { 310 if (level > 0) {
232 SkPoint tmp[7]; 311 SkPoint tmp[7];
233 312
234 SkChopCubicAt(pts, tmp, SK_Scalar1/2); 313 SkChopCubicAt(pts, tmp, SK_Scalar1/2);
235 haircubic(tmp, clip, blitter, level - 1, lineproc); 314 haircubic(tmp, clip, blitter, level - 1, lineproc);
236 haircubic(&tmp[3], clip, blitter, level - 1, lineproc); 315 haircubic(&tmp[3], clip, blitter, level - 1, lineproc);
237 } else { 316 } else {
238 SkPoint tmp[] = { pts[0], pts[3] }; 317 SkPoint tmp[] = { pts[0], pts[3] };
239 lineproc(tmp, 2, clip, blitter); 318 lineproc(tmp, 2, clip, blitter);
240 } 319 }
320 #else
321 if (quick_cubic_niceness_check(pts)) {
322 hair_cubic(pts, clip, blitter, lineproc);
323 } else {
324 SkPoint tmp[13];
325 SkScalar tValues[3];
326
327 int count = SkChopCubicAtMaxCurvature(pts, tmp, tValues);
328 for (int i = 0; i < count; i++) {
329 hair_cubic(&tmp[i * 3], clip, blitter, lineproc);
330 }
331 }
332 #endif
241 } 333 }
242 334
243 #define kMaxCubicSubdivideLevel 6
244 #define kMaxQuadSubdivideLevel 5
245
246 static int compute_quad_level(const SkPoint pts[3]) { 335 static int compute_quad_level(const SkPoint pts[3]) {
247 int d = compute_int_quad_dist(pts); 336 int d = compute_int_quad_dist(pts);
248 /* quadratics approach the line connecting their start and end points 337 /* quadratics approach the line connecting their start and end points
249 4x closer with each subdivision, so we compute the number of 338 4x closer with each subdivision, so we compute the number of
250 subdivisions to be the minimum need to get that distance to be less 339 subdivisions to be the minimum need to get that distance to be less
251 than a pixel. 340 than a pixel.
252 */ 341 */
253 int level = (33 - SkCLZ(d)) >> 1; 342 int level = (33 - SkCLZ(d)) >> 1;
254 // sanity check on level (from the previous version) 343 // sanity check on level (from the previous version)
255 if (level > kMaxQuadSubdivideLevel) { 344 if (level > kMaxQuadSubdivideLevel) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 const SkScalar tol = SK_Scalar1 / 4; 393 const SkScalar tol = SK_Scalar1 / 4;
305 const SkPoint* quadPts = converter.computeQuads(pts, 394 const SkPoint* quadPts = converter.computeQuads(pts,
306 iter.conicWeight(), tol); 395 iter.conicWeight(), tol);
307 for (int i = 0; i < converter.countQuads(); ++i) { 396 for (int i = 0; i < converter.countQuads(); ++i) {
308 int level = compute_quad_level(quadPts); 397 int level = compute_quad_level(quadPts);
309 hairquad(quadPts, clip, blitter, level, lineproc); 398 hairquad(quadPts, clip, blitter, level, lineproc);
310 quadPts += 2; 399 quadPts += 2;
311 } 400 }
312 break; 401 break;
313 } 402 }
314 case SkPath::kCubic_Verb: 403 case SkPath::kCubic_Verb: {
315 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ; 404 haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc) ;
316 break; 405 } break;
317 case SkPath::kClose_Verb: 406 case SkPath::kClose_Verb:
318 break; 407 break;
319 case SkPath::kDone_Verb: 408 case SkPath::kDone_Verb:
320 break; 409 break;
321 } 410 }
322 } 411 }
323 } 412 }
324 413
325 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) { 414 void SkScan::HairPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* b litter) {
326 hair_path(path, clip, blitter, SkScan::HairLineRgn); 415 hair_path(path, clip, blitter, SkScan::HairLineRgn);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 489
401 SkAAClipBlitterWrapper wrap; 490 SkAAClipBlitterWrapper wrap;
402 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) { 491 if (!clip.quickContains(r.roundOut().makeOutset(1, 1))) {
403 wrap.init(clip, blitter); 492 wrap.init(clip, blitter);
404 blitter = wrap.getBlitter(); 493 blitter = wrap.getBlitter();
405 clipRgn = &wrap.getRgn(); 494 clipRgn = &wrap.getRgn();
406 } 495 }
407 AntiHairLineRgn(pts, count, clipRgn, blitter); 496 AntiHairLineRgn(pts, count, clipRgn, blitter);
408 } 497 }
409 } 498 }
OLDNEW
« no previous file with comments | « src/core/SkGeometry.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698