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

Side by Side Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 1116943004: Move instanced index buffer creation to flush time (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: static inline instead of inline static, because consistency Created 5 years, 7 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 2011 Google Inc. 2 * Copyright 2011 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 "GrAAHairLinePathRenderer.h" 8 #include "GrAAHairLinePathRenderer.h"
9 9
10 #include "GrBatch.h" 10 #include "GrBatch.h"
11 #include "GrBatchTarget.h" 11 #include "GrBatchTarget.h"
12 #include "GrBufferAllocPool.h" 12 #include "GrBufferAllocPool.h"
13 #include "GrContext.h" 13 #include "GrContext.h"
14 #include "GrDefaultGeoProcFactory.h" 14 #include "GrDefaultGeoProcFactory.h"
15 #include "GrDrawTargetCaps.h" 15 #include "GrDrawTargetCaps.h"
16 #include "GrGpu.h"
17 #include "GrIndexBuffer.h" 16 #include "GrIndexBuffer.h"
18 #include "GrPathUtils.h" 17 #include "GrPathUtils.h"
19 #include "GrPipelineBuilder.h" 18 #include "GrPipelineBuilder.h"
20 #include "GrProcessor.h" 19 #include "GrProcessor.h"
20 #include "GrResourceProvider.h"
21 #include "GrVertexBuffer.h" 21 #include "GrVertexBuffer.h"
22 #include "SkGeometry.h" 22 #include "SkGeometry.h"
23 #include "SkStroke.h" 23 #include "SkStroke.h"
24 #include "SkTemplates.h" 24 #include "SkTemplates.h"
25 25
26 #include "effects/GrBezierEffect.h" 26 #include "effects/GrBezierEffect.h"
27 27
28 #define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
29
28 // quadratics are rendered as 5-sided polys in order to bound the 30 // quadratics are rendered as 5-sided polys in order to bound the
29 // AA stroke around the center-curve. See comments in push_quad_index_buffer and 31 // AA stroke around the center-curve. See comments in push_quad_index_buffer and
30 // bloat_quad. Quadratics and conics share an index buffer 32 // bloat_quad. Quadratics and conics share an index buffer
31 33
32 // lines are rendered as: 34 // lines are rendered as:
33 // *______________* 35 // *______________*
34 // |\ -_______ /| 36 // |\ -_______ /|
35 // | \ \ / | 37 // | \ \ / |
36 // | *--------* | 38 // | *--------* |
37 // | / ______/ \ | 39 // | / ______/ \ |
(...skipping 15 matching lines...) Expand all
53 // specified by these 9 indices: 55 // specified by these 9 indices:
54 static const uint16_t kQuadIdxBufPattern[] = { 56 static const uint16_t kQuadIdxBufPattern[] = {
55 0, 1, 2, 57 0, 1, 2,
56 2, 4, 3, 58 2, 4, 3,
57 1, 4, 2 59 1, 4, 2
58 }; 60 };
59 61
60 static const int kIdxsPerQuad = SK_ARRAY_COUNT(kQuadIdxBufPattern); 62 static const int kIdxsPerQuad = SK_ARRAY_COUNT(kQuadIdxBufPattern);
61 static const int kQuadNumVertices = 5; 63 static const int kQuadNumVertices = 5;
62 static const int kQuadsNumInIdxBuffer = 256; 64 static const int kQuadsNumInIdxBuffer = 256;
65 GR_DECLARE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);
66
67 static const GrIndexBuffer* ref_quads_index_buffer(GrResourceProvider* resourceP rovider) {
68 GR_DEFINE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey);
69 return resourceProvider->refOrCreateInstancedIndexBuffer(
70 kQuadIdxBufPattern, kIdxsPerQuad, kQuadsNumInIdxBuffer, kQuadNumVertices ,
71 gQuadsIndexBufferKey);
72 }
63 73
64 74
65 // Each line segment is rendered as two quads and two triangles. 75 // Each line segment is rendered as two quads and two triangles.
66 // p0 and p1 have alpha = 1 while all other points have alpha = 0. 76 // p0 and p1 have alpha = 1 while all other points have alpha = 0.
67 // The four external points are offset 1 pixel perpendicular to the 77 // The four external points are offset 1 pixel perpendicular to the
68 // line and half a pixel parallel to the line. 78 // line and half a pixel parallel to the line.
69 // 79 //
70 // p4 p5 80 // p4 p5
71 // p0 p1 81 // p0 p1
72 // p2 p3 82 // p2 p3
73 // 83 //
74 // Each is drawn as six triangles specified by these 18 indices: 84 // Each is drawn as six triangles specified by these 18 indices:
75 85
76 static const uint16_t kLineSegIdxBufPattern[] = { 86 static const uint16_t kLineSegIdxBufPattern[] = {
77 0, 1, 3, 87 0, 1, 3,
78 0, 3, 2, 88 0, 3, 2,
79 0, 4, 5, 89 0, 4, 5,
80 0, 5, 1, 90 0, 5, 1,
81 0, 2, 4, 91 0, 2, 4,
82 1, 5, 3 92 1, 5, 3
83 }; 93 };
84 94
85 static const int kIdxsPerLineSeg = SK_ARRAY_COUNT(kLineSegIdxBufPattern); 95 static const int kIdxsPerLineSeg = SK_ARRAY_COUNT(kLineSegIdxBufPattern);
86 static const int kLineSegNumVertices = 6; 96 static const int kLineSegNumVertices = 6;
87 static const int kLineSegsNumInIdxBuffer = 256; 97 static const int kLineSegsNumInIdxBuffer = 256;
88 98
89 GrPathRenderer* GrAAHairLinePathRenderer::Create(GrContext* context) { 99 GR_DECLARE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);
90 GrGpu* gpu = context->getGpu(); 100
91 GrIndexBuffer* qIdxBuf = gpu->createInstancedIndexBuffer(kQuadIdxBufPattern, 101 static const GrIndexBuffer* ref_lines_index_buffer(GrResourceProvider* resourceP rovider) {
92 kIdxsPerQuad, 102 GR_DEFINE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey);
93 kQuadsNumInIdxBuffe r, 103 return resourceProvider->refOrCreateInstancedIndexBuffer(
94 kQuadNumVertices); 104 kLineSegIdxBufPattern, kIdxsPerLineSeg, kLineSegsNumInIdxBuffer, kLineS egNumVertices,
95 SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 105 gLinesIndexBufferKey);
96 GrIndexBuffer* lIdxBuf = gpu->createInstancedIndexBuffer(kLineSegIdxBufPatte rn,
97 kIdxsPerLineSeg,
98 kLineSegsNumInIdxBu ffer,
99 kLineSegNumVertices );
100 SkAutoTUnref<GrIndexBuffer> lIdxBuffer(lIdxBuf);
101 return SkNEW_ARGS(GrAAHairLinePathRenderer,
102 (context, lIdxBuf, qIdxBuf));
103 } 106 }
104 107
105 GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
106 const GrContext* context,
107 const GrIndexBuffer* linesIndexBuffer,
108 const GrIndexBuffer* quadsIndexBuffer) {
109 fLinesIndexBuffer = linesIndexBuffer;
110 linesIndexBuffer->ref();
111 fQuadsIndexBuffer = quadsIndexBuffer;
112 quadsIndexBuffer->ref();
113 }
114
115 GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
116 fLinesIndexBuffer->unref();
117 fQuadsIndexBuffer->unref();
118 }
119
120 namespace {
121
122 #define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
123
124 // Takes 178th time of logf on Z600 / VC2010 108 // Takes 178th time of logf on Z600 / VC2010
125 int get_float_exp(float x) { 109 static int get_float_exp(float x) {
126 GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 110 GR_STATIC_ASSERT(sizeof(int) == sizeof(float));
127 #ifdef SK_DEBUG 111 #ifdef SK_DEBUG
128 static bool tested; 112 static bool tested;
129 if (!tested) { 113 if (!tested) {
130 tested = true; 114 tested = true;
131 SkASSERT(get_float_exp(0.25f) == -2); 115 SkASSERT(get_float_exp(0.25f) == -2);
132 SkASSERT(get_float_exp(0.3f) == -2); 116 SkASSERT(get_float_exp(0.3f) == -2);
133 SkASSERT(get_float_exp(0.5f) == -1); 117 SkASSERT(get_float_exp(0.5f) == -1);
134 SkASSERT(get_float_exp(1.f) == 0); 118 SkASSERT(get_float_exp(1.f) == 0);
135 SkASSERT(get_float_exp(2.f) == 1); 119 SkASSERT(get_float_exp(2.f) == 1);
136 SkASSERT(get_float_exp(2.5f) == 1); 120 SkASSERT(get_float_exp(2.5f) == 1);
137 SkASSERT(get_float_exp(8.f) == 3); 121 SkASSERT(get_float_exp(8.f) == 3);
138 SkASSERT(get_float_exp(100.f) == 6); 122 SkASSERT(get_float_exp(100.f) == 6);
139 SkASSERT(get_float_exp(1000.f) == 9); 123 SkASSERT(get_float_exp(1000.f) == 9);
140 SkASSERT(get_float_exp(1024.f) == 10); 124 SkASSERT(get_float_exp(1024.f) == 10);
141 SkASSERT(get_float_exp(3000000.f) == 21); 125 SkASSERT(get_float_exp(3000000.f) == 21);
142 } 126 }
143 #endif 127 #endif
144 const int* iptr = (const int*)&x; 128 const int* iptr = (const int*)&x;
145 return (((*iptr) & 0x7f800000) >> 23) - 127; 129 return (((*iptr) & 0x7f800000) >> 23) - 127;
146 } 130 }
147 131
148 // Uses the max curvature function for quads to estimate 132 // Uses the max curvature function for quads to estimate
149 // where to chop the conic. If the max curvature is not 133 // where to chop the conic. If the max curvature is not
150 // found along the curve segment it will return 1 and 134 // found along the curve segment it will return 1 and
151 // dst[0] is the original conic. If it returns 2 the dst[0] 135 // dst[0] is the original conic. If it returns 2 the dst[0]
152 // and dst[1] are the two new conics. 136 // and dst[1] are the two new conics.
153 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 137 static int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weig ht) {
154 SkScalar t = SkFindQuadMaxCurvature(src); 138 SkScalar t = SkFindQuadMaxCurvature(src);
155 if (t == 0) { 139 if (t == 0) {
156 if (dst) { 140 if (dst) {
157 dst[0].set(src, weight); 141 dst[0].set(src, weight);
158 } 142 }
159 return 1; 143 return 1;
160 } else { 144 } else {
161 if (dst) { 145 if (dst) {
162 SkConic conic; 146 SkConic conic;
163 conic.set(src, weight); 147 conic.set(src, weight);
164 conic.chopAt(t, dst); 148 conic.chopAt(t, dst);
165 } 149 }
166 return 2; 150 return 2;
167 } 151 }
168 } 152 }
169 153
170 // Calls split_conic on the entire conic and then once more on each subsection. 154 // Calls split_conic on the entire conic and then once more on each subsection.
171 // Most cases will result in either 1 conic (chop point is not within t range) 155 // Most cases will result in either 1 conic (chop point is not within t range)
172 // or 3 points (split once and then one subsection is split again). 156 // or 3 points (split once and then one subsection is split again).
173 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 157 static int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weigh t) {
174 SkConic dstTemp[2]; 158 SkConic dstTemp[2];
175 int conicCnt = split_conic(src, dstTemp, weight); 159 int conicCnt = split_conic(src, dstTemp, weight);
176 if (2 == conicCnt) { 160 if (2 == conicCnt) {
177 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW); 161 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
178 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dst Temp[1].fW); 162 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dst Temp[1].fW);
179 } else { 163 } else {
180 dst[0] = dstTemp[0]; 164 dst[0] = dstTemp[0];
181 } 165 }
182 return conicCnt; 166 return conicCnt;
183 } 167 }
184 168
185 // returns 0 if quad/conic is degen or close to it 169 // returns 0 if quad/conic is degen or close to it
186 // in this case approx the path with lines 170 // in this case approx the path with lines
187 // otherwise returns 1 171 // otherwise returns 1
188 int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) { 172 static int is_degen_quad_or_conic(const SkPoint p[3], SkScalar* dsqd) {
189 static const SkScalar gDegenerateToLineTol = SK_Scalar1; 173 static const SkScalar gDegenerateToLineTol = SK_Scalar1;
190 static const SkScalar gDegenerateToLineTolSqd = 174 static const SkScalar gDegenerateToLineTolSqd =
191 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 175 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
192 176
193 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 177 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
194 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 178 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
195 return 1; 179 return 1;
196 } 180 }
197 181
198 *dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]); 182 *dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]);
199 if (*dsqd < gDegenerateToLineTolSqd) { 183 if (*dsqd < gDegenerateToLineTolSqd) {
200 return 1; 184 return 1;
201 } 185 }
202 186
203 if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) { 187 if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) {
204 return 1; 188 return 1;
205 } 189 }
206 return 0; 190 return 0;
207 } 191 }
208 192
209 int is_degen_quad_or_conic(const SkPoint p[3]) { 193 static int is_degen_quad_or_conic(const SkPoint p[3]) {
210 SkScalar dsqd; 194 SkScalar dsqd;
211 return is_degen_quad_or_conic(p, &dsqd); 195 return is_degen_quad_or_conic(p, &dsqd);
212 } 196 }
213 197
214 // we subdivide the quads to avoid huge overfill 198 // we subdivide the quads to avoid huge overfill
215 // if it returns -1 then should be drawn as lines 199 // if it returns -1 then should be drawn as lines
216 int num_quad_subdivs(const SkPoint p[3]) { 200 static int num_quad_subdivs(const SkPoint p[3]) {
217 SkScalar dsqd; 201 SkScalar dsqd;
218 if (is_degen_quad_or_conic(p, &dsqd)) { 202 if (is_degen_quad_or_conic(p, &dsqd)) {
219 return -1; 203 return -1;
220 } 204 }
221 205
222 // tolerance of triangle height in pixels 206 // tolerance of triangle height in pixels
223 // tuned on windows Quadro FX 380 / Z600 207 // tuned on windows Quadro FX 380 / Z600
224 // trade off of fill vs cpu time on verts 208 // trade off of fill vs cpu time on verts
225 // maybe different when do this using gpu (geo or tess shaders) 209 // maybe different when do this using gpu (geo or tess shaders)
226 static const SkScalar gSubdivTol = 175 * SK_Scalar1; 210 static const SkScalar gSubdivTol = 175 * SK_Scalar1;
(...skipping 15 matching lines...) Expand all
242 226
243 /** 227 /**
244 * Generates the lines and quads to be rendered. Lines are always recorded in 228 * Generates the lines and quads to be rendered. Lines are always recorded in
245 * device space. We will do a device space bloat to account for the 1pixel 229 * device space. We will do a device space bloat to account for the 1pixel
246 * thickness. 230 * thickness.
247 * Quads are recorded in device space unless m contains 231 * Quads are recorded in device space unless m contains
248 * perspective, then in they are in src space. We do this because we will 232 * perspective, then in they are in src space. We do this because we will
249 * subdivide large quads to reduce over-fill. This subdivision has to be 233 * subdivide large quads to reduce over-fill. This subdivision has to be
250 * performed before applying the perspective matrix. 234 * performed before applying the perspective matrix.
251 */ 235 */
252 int gather_lines_and_quads(const SkPath& path, 236 static int gather_lines_and_quads(const SkPath& path,
253 const SkMatrix& m, 237 const SkMatrix& m,
254 const SkIRect& devClipBounds, 238 const SkIRect& devClipBounds,
255 GrAAHairLinePathRenderer::PtArray* lines, 239 GrAAHairLinePathRenderer::PtArray* lines,
256 GrAAHairLinePathRenderer::PtArray* quads, 240 GrAAHairLinePathRenderer::PtArray* quads,
257 GrAAHairLinePathRenderer::PtArray* conics, 241 GrAAHairLinePathRenderer::PtArray* conics,
258 GrAAHairLinePathRenderer::IntArray* quadSubdivCnts, 242 GrAAHairLinePathRenderer::IntArray* quadSubdiv Cnts,
259 GrAAHairLinePathRenderer::FloatArray* conicWeights) { 243 GrAAHairLinePathRenderer::FloatArray* conicWei ghts) {
260 SkPath::Iter iter(path, false); 244 SkPath::Iter iter(path, false);
261 245
262 int totalQuadCount = 0; 246 int totalQuadCount = 0;
263 SkRect bounds; 247 SkRect bounds;
264 SkIRect ibounds; 248 SkIRect ibounds;
265 249
266 bool persp = m.hasPerspective(); 250 bool persp = m.hasPerspective();
267 251
268 for (;;) { 252 for (;;) {
269 SkPoint pathPts[4]; 253 SkPoint pathPts[4];
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 } fConic; 417 } fConic;
434 SkVector fQuadCoord; 418 SkVector fQuadCoord;
435 struct { 419 struct {
436 SkScalar fBogus[4]; 420 SkScalar fBogus[4];
437 }; 421 };
438 }; 422 };
439 }; 423 };
440 424
441 GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint)); 425 GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint));
442 426
443 void intersect_lines(const SkPoint& ptA, const SkVector& normA, 427 static void intersect_lines(const SkPoint& ptA, const SkVector& normA,
444 const SkPoint& ptB, const SkVector& normB, 428 const SkPoint& ptB, const SkVector& normB,
445 SkPoint* result) { 429 SkPoint* result) {
446 430
447 SkScalar lineAW = -normA.dot(ptA); 431 SkScalar lineAW = -normA.dot(ptA);
448 SkScalar lineBW = -normB.dot(ptB); 432 SkScalar lineBW = -normB.dot(ptB);
449 433
450 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 434 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
451 SkScalarMul(normA.fY, normB.fX); 435 SkScalarMul(normA.fY, normB.fX);
452 wInv = SkScalarInvert(wInv); 436 wInv = SkScalarInvert(wInv);
453 437
454 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 438 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY);
455 result->fX = SkScalarMul(result->fX, wInv); 439 result->fX = SkScalarMul(result->fX, wInv);
456 440
457 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 441 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW);
458 result->fY = SkScalarMul(result->fY, wInv); 442 result->fY = SkScalarMul(result->fY, wInv);
459 } 443 }
460 444
461 void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertices]) { 445 static void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kQuadNumVertic es]) {
462 // this should be in the src space, not dev coords, when we have perspective 446 // this should be in the src space, not dev coords, when we have perspective
463 GrPathUtils::QuadUVMatrix DevToUV(qpts); 447 GrPathUtils::QuadUVMatrix DevToUV(qpts);
464 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts ); 448 DevToUV.apply<kQuadNumVertices, sizeof(BezierVertex), sizeof(SkPoint)>(verts );
465 } 449 }
466 450
467 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 451 static void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
468 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertices]) { 452 const SkMatrix* toSrc, BezierVertex verts[kQuadNumVertice s]) {
469 SkASSERT(!toDevice == !toSrc); 453 SkASSERT(!toDevice == !toSrc);
470 // original quad is specified by tri a,b,c 454 // original quad is specified by tri a,b,c
471 SkPoint a = qpts[0]; 455 SkPoint a = qpts[0];
472 SkPoint b = qpts[1]; 456 SkPoint b = qpts[1];
473 SkPoint c = qpts[2]; 457 SkPoint c = qpts[2];
474 458
475 if (toDevice) { 459 if (toDevice) {
476 toDevice->mapPoints(&a, 1); 460 toDevice->mapPoints(&a, 1);
477 toDevice->mapPoints(&b, 1); 461 toDevice->mapPoints(&b, 1);
478 toDevice->mapPoints(&c, 1); 462 toDevice->mapPoints(&c, 1);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 } 520 }
537 } 521 }
538 522
539 // Equations based off of Loop-Blinn Quadratic GPU Rendering 523 // Equations based off of Loop-Blinn Quadratic GPU Rendering
540 // Input Parametric: 524 // Input Parametric:
541 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) 525 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2)
542 // Output Implicit: 526 // Output Implicit:
543 // f(x, y, w) = f(P) = K^2 - LM 527 // f(x, y, w) = f(P) = K^2 - LM
544 // K = dot(k, P), L = dot(l, P), M = dot(m, P) 528 // K = dot(k, P), L = dot(l, P), M = dot(m, P)
545 // k, l, m are calculated in function GrPathUtils::getConicKLM 529 // k, l, m are calculated in function GrPathUtils::getConicKLM
546 void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVertices], 530 static void set_conic_coeffs(const SkPoint p[3], BezierVertex verts[kQuadNumVert ices],
547 const SkScalar weight) { 531 const SkScalar weight) {
548 SkScalar klm[9]; 532 SkScalar klm[9];
549 533
550 GrPathUtils::getConicKLM(p, weight, klm); 534 GrPathUtils::getConicKLM(p, weight, klm);
551 535
552 for (int i = 0; i < kQuadNumVertices; ++i) { 536 for (int i = 0; i < kQuadNumVertices; ++i) {
553 const SkPoint pnt = verts[i].fPos; 537 const SkPoint pnt = verts[i].fPos;
554 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2]; 538 verts[i].fConic.fK = pnt.fX * klm[0] + pnt.fY * klm[1] + klm[2];
555 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5]; 539 verts[i].fConic.fL = pnt.fX * klm[3] + pnt.fY * klm[4] + klm[5];
556 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8]; 540 verts[i].fConic.fM = pnt.fX * klm[6] + pnt.fY * klm[7] + klm[8];
557 } 541 }
558 } 542 }
559 543
560 void add_conics(const SkPoint p[3], 544 static void add_conics(const SkPoint p[3],
561 const SkScalar weight, 545 const SkScalar weight,
562 const SkMatrix* toDevice, 546 const SkMatrix* toDevice,
563 const SkMatrix* toSrc, 547 const SkMatrix* toSrc,
564 BezierVertex** vert) { 548 BezierVertex** vert) {
565 bloat_quad(p, toDevice, toSrc, *vert); 549 bloat_quad(p, toDevice, toSrc, *vert);
566 set_conic_coeffs(p, *vert, weight); 550 set_conic_coeffs(p, *vert, weight);
567 *vert += kQuadNumVertices; 551 *vert += kQuadNumVertices;
568 } 552 }
569 553
570 void add_quads(const SkPoint p[3], 554 static void add_quads(const SkPoint p[3],
571 int subdiv, 555 int subdiv,
572 const SkMatrix* toDevice, 556 const SkMatrix* toDevice,
573 const SkMatrix* toSrc, 557 const SkMatrix* toSrc,
574 BezierVertex** vert) { 558 BezierVertex** vert) {
575 SkASSERT(subdiv >= 0); 559 SkASSERT(subdiv >= 0);
576 if (subdiv) { 560 if (subdiv) {
577 SkPoint newP[5]; 561 SkPoint newP[5];
578 SkChopQuadAtHalf(p, newP); 562 SkChopQuadAtHalf(p, newP);
579 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); 563 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert);
580 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); 564 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert);
581 } else { 565 } else {
582 bloat_quad(p, toDevice, toSrc, *vert); 566 bloat_quad(p, toDevice, toSrc, *vert);
583 set_uv_quad(p, *vert); 567 set_uv_quad(p, *vert);
584 *vert += kQuadNumVertices; 568 *vert += kQuadNumVertices;
585 } 569 }
586 } 570 }
587 571
588 void add_line(const SkPoint p[2], 572 static void add_line(const SkPoint p[2],
589 const SkMatrix* toSrc, 573 const SkMatrix* toSrc,
590 uint8_t coverage, 574 uint8_t coverage,
591 LineVertex** vert) { 575 LineVertex** vert) {
592 const SkPoint& a = p[0]; 576 const SkPoint& a = p[0];
593 const SkPoint& b = p[1]; 577 const SkPoint& b = p[1];
594 578
595 SkVector ortho, vec = b; 579 SkVector ortho, vec = b;
596 vec -= a; 580 vec -= a;
597 581
598 if (vec.setLength(SK_ScalarHalf)) { 582 if (vec.setLength(SK_ScalarHalf)) {
599 // Create a vector orthogonal to 'vec' and of unit length 583 // Create a vector orthogonal to 'vec' and of unit length
600 ortho.fX = 2.0f * vec.fY; 584 ortho.fX = 2.0f * vec.fY;
601 ortho.fY = -2.0f * vec.fX; 585 ortho.fY = -2.0f * vec.fX;
(...skipping 21 matching lines...) Expand all
623 } else { 607 } else {
624 // just make it degenerate and likely offscreen 608 // just make it degenerate and likely offscreen
625 for (int i = 0; i < kLineSegNumVertices; ++i) { 609 for (int i = 0; i < kLineSegNumVertices; ++i) {
626 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax); 610 (*vert)[i].fPos.set(SK_ScalarMax, SK_ScalarMax);
627 } 611 }
628 } 612 }
629 613
630 *vert += kLineSegNumVertices; 614 *vert += kLineSegNumVertices;
631 } 615 }
632 616
633 }
634
635 /////////////////////////////////////////////////////////////////////////////// 617 ///////////////////////////////////////////////////////////////////////////////
636 618
637 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, 619 bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target,
638 const GrPipelineBuilder* pipelineBuil der, 620 const GrPipelineBuilder* pipelineBuil der,
639 const SkMatrix& viewMatrix, 621 const SkMatrix& viewMatrix,
640 const SkPath& path, 622 const SkPath& path,
641 const GrStrokeInfo& stroke, 623 const GrStrokeInfo& stroke,
642 bool antiAlias) const { 624 bool antiAlias) const {
643 if (!antiAlias) { 625 if (!antiAlias) {
644 return false; 626 return false;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 class AAHairlineBatch : public GrBatch { 677 class AAHairlineBatch : public GrBatch {
696 public: 678 public:
697 struct Geometry { 679 struct Geometry {
698 GrColor fColor; 680 GrColor fColor;
699 uint8_t fCoverage; 681 uint8_t fCoverage;
700 SkMatrix fViewMatrix; 682 SkMatrix fViewMatrix;
701 SkPath fPath; 683 SkPath fPath;
702 SkIRect fDevClipBounds; 684 SkIRect fDevClipBounds;
703 }; 685 };
704 686
705 // TODO Batch itself should not hold on to index buffers. Instead, these sh ould live in the 687 static GrBatch* Create(const Geometry& geometry) {
706 // cache. 688 return SkNEW_ARGS(AAHairlineBatch, (geometry));
707 static GrBatch* Create(const Geometry& geometry, const GrIndexBuffer* linesI ndexBuffer,
708 const GrIndexBuffer* quadsIndexBuffer) {
709 return SkNEW_ARGS(AAHairlineBatch, (geometry, linesIndexBuffer, quadsInd exBuffer));
710 } 689 }
711 690
712 const char* name() const override { return "AAHairlineBatch"; } 691 const char* name() const override { return "AAHairlineBatch"; }
713 692
714 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 693 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
715 // When this is called on a batch, there is only one geometry bundle 694 // When this is called on a batch, there is only one geometry bundle
716 out->setKnownFourComponents(fGeoData[0].fColor); 695 out->setKnownFourComponents(fGeoData[0].fColor);
717 } 696 }
718 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { 697 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
719 out->setUnknownSingleComponent(); 698 out->setUnknownSingleComponent();
(...skipping 17 matching lines...) Expand all
737 716
738 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override; 717 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override;
739 718
740 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } 719 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
741 720
742 private: 721 private:
743 typedef SkTArray<SkPoint, true> PtArray; 722 typedef SkTArray<SkPoint, true> PtArray;
744 typedef SkTArray<int, true> IntArray; 723 typedef SkTArray<int, true> IntArray;
745 typedef SkTArray<float, true> FloatArray; 724 typedef SkTArray<float, true> FloatArray;
746 725
747 AAHairlineBatch(const Geometry& geometry, const GrIndexBuffer* linesIndexBuf fer, 726 AAHairlineBatch(const Geometry& geometry) {
748 const GrIndexBuffer* quadsIndexBuffer)
749 : fLinesIndexBuffer(linesIndexBuffer)
750 , fQuadsIndexBuffer(quadsIndexBuffer) {
751 SkASSERT(linesIndexBuffer && quadsIndexBuffer);
752 this->initClassID<AAHairlineBatch>(); 727 this->initClassID<AAHairlineBatch>();
753 fGeoData.push_back(geometry); 728 fGeoData.push_back(geometry);
754 729
755 // compute bounds 730 // compute bounds
756 fBounds = geometry.fPath.getBounds(); 731 fBounds = geometry.fPath.getBounds();
757 geometry.fViewMatrix.mapRect(&fBounds); 732 geometry.fViewMatrix.mapRect(&fBounds);
758 } 733 }
759 734
760 bool onCombineIfPossible(GrBatch* t) override { 735 bool onCombineIfPossible(GrBatch* t) override {
761 AAHairlineBatch* that = t->cast<AAHairlineBatch>(); 736 AAHairlineBatch* that = t->cast<AAHairlineBatch>();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 GrColor fColor; 775 GrColor fColor;
801 uint8_t fCoverage; 776 uint8_t fCoverage;
802 SkRect fDevBounds; 777 SkRect fDevBounds;
803 bool fUsesLocalCoords; 778 bool fUsesLocalCoords;
804 bool fColorIgnored; 779 bool fColorIgnored;
805 bool fCoverageIgnored; 780 bool fCoverageIgnored;
806 }; 781 };
807 782
808 BatchTracker fBatch; 783 BatchTracker fBatch;
809 SkSTArray<1, Geometry, true> fGeoData; 784 SkSTArray<1, Geometry, true> fGeoData;
810 const GrIndexBuffer* fLinesIndexBuffer;
811 const GrIndexBuffer* fQuadsIndexBuffer;
812 }; 785 };
813 786
814 void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel ine* pipeline) { 787 void AAHairlineBatch::generateGeometry(GrBatchTarget* batchTarget, const GrPipel ine* pipeline) {
815 // Setup the viewmatrix and localmatrix for the GrGeometryProcessor. 788 // Setup the viewmatrix and localmatrix for the GrGeometryProcessor.
816 SkMatrix invert; 789 SkMatrix invert;
817 if (!this->viewMatrix().invert(&invert)) { 790 if (!this->viewMatrix().invert(&invert)) {
818 return; 791 return;
819 } 792 }
820 793
821 // we will transform to identity space if the viewmatrix does not have persp ective 794 // we will transform to identity space if the viewmatrix does not have persp ective
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 const Geometry& args = fGeoData[i]; 845 const Geometry& args = fGeoData[i];
873 quadCount += gather_lines_and_quads(args.fPath, args.fViewMatrix, args.f DevClipBounds, 846 quadCount += gather_lines_and_quads(args.fPath, args.fViewMatrix, args.f DevClipBounds,
874 &lines, &quads, &conics, &qSubdivs, &cWeights); 847 &lines, &quads, &conics, &qSubdivs, &cWeights);
875 } 848 }
876 849
877 int lineCount = lines.count() / 2; 850 int lineCount = lines.count() / 2;
878 int conicCount = conics.count() / 3; 851 int conicCount = conics.count() / 3;
879 852
880 // do lines first 853 // do lines first
881 if (lineCount) { 854 if (lineCount) {
855 SkAutoTUnref<const GrIndexBuffer> linesIndexBuffer(
856 ref_lines_index_buffer(batchTarget->resourceProvider()));
robertphillips 2015/05/04 13:16:00 Check if this fails ? We seem to do it every where
bsalomon 2015/05/04 15:01:09 Done.
882 batchTarget->initDraw(lineGP, pipeline); 857 batchTarget->initDraw(lineGP, pipeline);
883 858
884 // TODO remove this when batch is everywhere 859 // TODO remove this when batch is everywhere
885 GrPipelineInfo init; 860 GrPipelineInfo init;
886 init.fColorIgnored = fBatch.fColorIgnored; 861 init.fColorIgnored = fBatch.fColorIgnored;
887 init.fOverrideColor = GrColor_ILLEGAL; 862 init.fOverrideColor = GrColor_ILLEGAL;
888 init.fCoverageIgnored = fBatch.fCoverageIgnored; 863 init.fCoverageIgnored = fBatch.fCoverageIgnored;
889 init.fUsesLocalCoords = this->usesLocalCoords(); 864 init.fUsesLocalCoords = this->usesLocalCoords();
890 lineGP->initBatchTracker(batchTarget->currentBatchTracker(), init); 865 lineGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
891 866
(...skipping 15 matching lines...) Expand all
907 SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex)); 882 SkASSERT(lineGP->getVertexStride() == sizeof(LineVertex));
908 883
909 LineVertex* verts = reinterpret_cast<LineVertex*>(vertices); 884 LineVertex* verts = reinterpret_cast<LineVertex*>(vertices);
910 for (int i = 0; i < lineCount; ++i) { 885 for (int i = 0; i < lineCount; ++i) {
911 add_line(&lines[2*i], toSrc, this->coverage(), &verts); 886 add_line(&lines[2*i], toSrc, this->coverage(), &verts);
912 } 887 }
913 888
914 { 889 {
915 GrDrawTarget::DrawInfo info; 890 GrDrawTarget::DrawInfo info;
916 info.setVertexBuffer(vertexBuffer); 891 info.setVertexBuffer(vertexBuffer);
917 info.setIndexBuffer(fLinesIndexBuffer); 892 info.setIndexBuffer(linesIndexBuffer);
918 info.setPrimitiveType(kTriangles_GrPrimitiveType); 893 info.setPrimitiveType(kTriangles_GrPrimitiveType);
919 info.setStartIndex(0); 894 info.setStartIndex(0);
920 895
921 int lines = 0; 896 int lines = 0;
922 while (lines < lineCount) { 897 while (lines < lineCount) {
923 int n = SkTMin(lineCount - lines, kLineSegsNumInIdxBuffer); 898 int n = SkTMin(lineCount - lines, kLineSegsNumInIdxBuffer);
924 899
925 info.setStartVertex(kLineSegNumVertices*lines + firstVertex); 900 info.setStartVertex(kLineSegNumVertices*lines + firstVertex);
926 info.setVertexCount(kLineSegNumVertices*n); 901 info.setVertexCount(kLineSegNumVertices*n);
927 info.setIndexCount(kIdxsPerLineSeg*n); 902 info.setIndexCount(kIdxsPerLineSeg*n);
928 batchTarget->draw(info); 903 batchTarget->draw(info);
929 904
930 lines += n; 905 lines += n;
931 } 906 }
932 } 907 }
933 } 908 }
934 909
935 if (quadCount || conicCount) { 910 if (quadCount || conicCount) {
936 const GrVertexBuffer* vertexBuffer; 911 const GrVertexBuffer* vertexBuffer;
937 int firstVertex; 912 int firstVertex;
938 913
914 SkAutoTUnref<const GrIndexBuffer> quadsIndexBuffer(
915 ref_quads_index_buffer(batchTarget->resourceProvider()));
916
939 size_t vertexStride = sizeof(BezierVertex); 917 size_t vertexStride = sizeof(BezierVertex);
940 int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * coni cCount; 918 int vertexCount = kQuadNumVertices * quadCount + kQuadNumVertices * coni cCount;
941 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride, 919 void *vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
942 vertexCount, 920 vertexCount,
943 &vertexBuffer, 921 &vertexBuffer,
944 &firstVertex); 922 &firstVertex);
945 923
946 if (!vertices) { 924 if (!vertices || !quadsIndexBuffer) {
947 SkDebugf("Could not allocate vertices\n"); 925 SkDebugf("Could not allocate vertices\n");
948 return; 926 return;
949 } 927 }
950 928
951 // Setup vertices 929 // Setup vertices
952 BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices); 930 BezierVertex* verts = reinterpret_cast<BezierVertex*>(vertices);
953 931
954 int unsubdivQuadCnt = quads.count() / 3; 932 int unsubdivQuadCnt = quads.count() / 3;
955 for (int i = 0; i < unsubdivQuadCnt; ++i) { 933 for (int i = 0; i < unsubdivQuadCnt; ++i) {
956 SkASSERT(qSubdivs[i] >= 0); 934 SkASSERT(qSubdivs[i] >= 0);
(...skipping 12 matching lines...) Expand all
969 GrPipelineInfo init; 947 GrPipelineInfo init;
970 init.fColorIgnored = fBatch.fColorIgnored; 948 init.fColorIgnored = fBatch.fColorIgnored;
971 init.fOverrideColor = GrColor_ILLEGAL; 949 init.fOverrideColor = GrColor_ILLEGAL;
972 init.fCoverageIgnored = fBatch.fCoverageIgnored; 950 init.fCoverageIgnored = fBatch.fCoverageIgnored;
973 init.fUsesLocalCoords = this->usesLocalCoords(); 951 init.fUsesLocalCoords = this->usesLocalCoords();
974 quadGP->initBatchTracker(batchTarget->currentBatchTracker(), init); 952 quadGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
975 953
976 { 954 {
977 GrDrawTarget::DrawInfo info; 955 GrDrawTarget::DrawInfo info;
978 info.setVertexBuffer(vertexBuffer); 956 info.setVertexBuffer(vertexBuffer);
979 info.setIndexBuffer(fQuadsIndexBuffer); 957 info.setIndexBuffer(quadsIndexBuffer);
980 info.setPrimitiveType(kTriangles_GrPrimitiveType); 958 info.setPrimitiveType(kTriangles_GrPrimitiveType);
981 info.setStartIndex(0); 959 info.setStartIndex(0);
982 960
983 int quads = 0; 961 int quads = 0;
984 while (quads < quadCount) { 962 while (quads < quadCount) {
985 int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer); 963 int n = SkTMin(quadCount - quads, kQuadsNumInIdxBuffer);
986 964
987 info.setStartVertex(kQuadNumVertices*quads + firstVertex); 965 info.setStartVertex(kQuadNumVertices*quads + firstVertex);
988 info.setVertexCount(kQuadNumVertices*n); 966 info.setVertexCount(kQuadNumVertices*n);
989 info.setIndexCount(kIdxsPerQuad*n); 967 info.setIndexCount(kIdxsPerQuad*n);
(...skipping 11 matching lines...) Expand all
1001 GrPipelineInfo init; 979 GrPipelineInfo init;
1002 init.fColorIgnored = fBatch.fColorIgnored; 980 init.fColorIgnored = fBatch.fColorIgnored;
1003 init.fOverrideColor = GrColor_ILLEGAL; 981 init.fOverrideColor = GrColor_ILLEGAL;
1004 init.fCoverageIgnored = fBatch.fCoverageIgnored; 982 init.fCoverageIgnored = fBatch.fCoverageIgnored;
1005 init.fUsesLocalCoords = this->usesLocalCoords(); 983 init.fUsesLocalCoords = this->usesLocalCoords();
1006 conicGP->initBatchTracker(batchTarget->currentBatchTracker(), init); 984 conicGP->initBatchTracker(batchTarget->currentBatchTracker(), init);
1007 985
1008 { 986 {
1009 GrDrawTarget::DrawInfo info; 987 GrDrawTarget::DrawInfo info;
1010 info.setVertexBuffer(vertexBuffer); 988 info.setVertexBuffer(vertexBuffer);
1011 info.setIndexBuffer(fQuadsIndexBuffer); 989 info.setIndexBuffer(quadsIndexBuffer);
1012 info.setPrimitiveType(kTriangles_GrPrimitiveType); 990 info.setPrimitiveType(kTriangles_GrPrimitiveType);
1013 info.setStartIndex(0); 991 info.setStartIndex(0);
1014 992
1015 int conics = 0; 993 int conics = 0;
1016 while (conics < conicCount) { 994 while (conics < conicCount) {
1017 int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer); 995 int n = SkTMin(conicCount - conics, kQuadsNumInIdxBuffer);
1018 996
1019 info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVertex); 997 info.setStartVertex(kQuadNumVertices*(quadCount + conics) + firstVertex);
1020 info.setVertexCount(kQuadNumVertices*n); 998 info.setVertexCount(kQuadNumVertices*n);
1021 info.setIndexCount(kIdxsPerQuad*n); 999 info.setIndexCount(kIdxsPerQuad*n);
1022 batchTarget->draw(info); 1000 batchTarget->draw(info);
1023 1001
1024 conics += n; 1002 conics += n;
1025 } 1003 }
1026 } 1004 }
1027 } 1005 }
1028 } 1006 }
1029 } 1007 }
1030 1008
1031 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 1009 bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target,
1032 GrPipelineBuilder* pipelineBuilder, 1010 GrPipelineBuilder* pipelineBuilder,
1033 GrColor color, 1011 GrColor color,
1034 const SkMatrix& viewMatrix, 1012 const SkMatrix& viewMatrix,
1035 const SkPath& path, 1013 const SkPath& path,
1036 const GrStrokeInfo& stroke, 1014 const GrStrokeInfo& stroke,
1037 bool) { 1015 bool) {
1038 if (!fLinesIndexBuffer || !fQuadsIndexBuffer) {
1039 SkDebugf("unable to allocate indices\n");
1040 return false;
1041 }
1042
1043 SkScalar hairlineCoverage; 1016 SkScalar hairlineCoverage;
1044 uint8_t newCoverage = 0xff; 1017 uint8_t newCoverage = 0xff;
1045 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { 1018 if (IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) {
1046 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); 1019 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
1047 } 1020 }
1048 1021
1049 SkIRect devClipBounds; 1022 SkIRect devClipBounds;
1050 pipelineBuilder->clip().getConservativeBounds(pipelineBuilder->getRenderTarg et(), 1023 pipelineBuilder->clip().getConservativeBounds(pipelineBuilder->getRenderTarg et(),
1051 &devClipBounds); 1024 &devClipBounds);
1052 1025
1053 AAHairlineBatch::Geometry geometry; 1026 AAHairlineBatch::Geometry geometry;
1054 geometry.fColor = color; 1027 geometry.fColor = color;
1055 geometry.fCoverage = newCoverage; 1028 geometry.fCoverage = newCoverage;
1056 geometry.fViewMatrix = viewMatrix; 1029 geometry.fViewMatrix = viewMatrix;
1057 geometry.fPath = path; 1030 geometry.fPath = path;
1058 geometry.fDevClipBounds = devClipBounds; 1031 geometry.fDevClipBounds = devClipBounds;
1059 1032
1060 SkAutoTUnref<GrBatch> batch(AAHairlineBatch::Create(geometry, fLinesIndexBuf fer, 1033 SkAutoTUnref<GrBatch> batch(AAHairlineBatch::Create(geometry));
1061 fQuadsIndexBuffer));
1062 target->drawBatch(pipelineBuilder, batch); 1034 target->drawBatch(pipelineBuilder, batch);
1063 1035
1064 return true; 1036 return true;
1065 } 1037 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698