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

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

Issue 18258005: Add implicit hairline conic rendering to GPU (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 5 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 | Annotate | Revision Log
« src/core/SkGeometry.cpp ('K') | « src/gpu/GrAAHairLinePathRenderer.h ('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 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "GrAAHairLinePathRenderer.h" 9 #include "GrAAHairLinePathRenderer.h"
10 10
(...skipping 12 matching lines...) Expand all
23 #include "gl/GrGLEffect.h" 23 #include "gl/GrGLEffect.h"
24 #include "gl/GrGLSL.h" 24 #include "gl/GrGLSL.h"
25 25
26 namespace { 26 namespace {
27 // quadratics are rendered as 5-sided polys in order to bound the 27 // quadratics are rendered as 5-sided polys in order to bound the
28 // AA stroke around the center-curve. See comments in push_quad_index_buffer and 28 // AA stroke around the center-curve. See comments in push_quad_index_buffer and
29 // bloat_quad. 29 // bloat_quad.
30 static const int kVertsPerQuad = 5; 30 static const int kVertsPerQuad = 5;
31 static const int kIdxsPerQuad = 9; 31 static const int kIdxsPerQuad = 9;
32 32
33 static const int kVertsPerConic = 5;
34 static const int kIdxsPerConic = 9;
35
33 static const int kVertsPerLineSeg = 4; 36 static const int kVertsPerLineSeg = 4;
34 static const int kIdxsPerLineSeg = 6; 37 static const int kIdxsPerLineSeg = 6;
35 38
36 static const int kNumQuadsInIdxBuffer = 256; 39 static const int kNumQuadsInIdxBuffer = 256;
37 static const size_t kQuadIdxSBufize = kIdxsPerQuad * 40 static const size_t kQuadIdxSBufize = kIdxsPerQuad *
38 sizeof(uint16_t) * 41 sizeof(uint16_t) *
39 kNumQuadsInIdxBuffer; 42 kNumQuadsInIdxBuffer;
43 static const int kNumConicsInIdxBuffer = 256;
44 static const size_t kConicIdxSBufize = kIdxsPerConic *
45 sizeof(uint16_t) *
46 kNumConicsInIdxBuffer;
40 47
41 bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) { 48 bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
42 uint16_t* data = (uint16_t*) qIdxBuffer->lock(); 49 uint16_t* data = (uint16_t*) qIdxBuffer->lock();
43 bool tempData = NULL == data; 50 bool tempData = NULL == data;
44 if (tempData) { 51 if (tempData) {
45 data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad); 52 data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad);
46 } 53 }
47 for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) { 54 for (int i = 0; i < kNumQuadsInIdxBuffer; ++i) {
48 55
49 // Each quadratic is rendered as a five sided polygon. This poly bounds 56 // Each quadratic is rendered as a five sided polygon. This poly bounds
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 if (NULL == lIdxBuffer) { 93 if (NULL == lIdxBuffer) {
87 return NULL; 94 return NULL;
88 } 95 }
89 GrGpu* gpu = context->getGpu(); 96 GrGpu* gpu = context->getGpu();
90 GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false); 97 GrIndexBuffer* qIdxBuf = gpu->createIndexBuffer(kQuadIdxSBufize, false);
91 SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf); 98 SkAutoTUnref<GrIndexBuffer> qIdxBuffer(qIdxBuf);
92 if (NULL == qIdxBuf || 99 if (NULL == qIdxBuf ||
93 !push_quad_index_data(qIdxBuf)) { 100 !push_quad_index_data(qIdxBuf)) {
94 return NULL; 101 return NULL;
95 } 102 }
103 GrIndexBuffer* cIdxBuf = gpu->createIndexBuffer(kConicIdxSBufize, false);
104 if (NULL == cIdxBuf ||
105 !push_quad_index_data(cIdxBuf)) {
bsalomon 2013/07/10 15:14:36 can't we just use one idx buffer then?
egdaniel 2013/07/10 20:34:18 I'm assuming you mean for the quad and conic corre
106 return NULL;
107 }
96 return SkNEW_ARGS(GrAAHairLinePathRenderer, 108 return SkNEW_ARGS(GrAAHairLinePathRenderer,
97 (context, lIdxBuffer, qIdxBuf)); 109 (context, lIdxBuffer, qIdxBuf, cIdxBuf));
98 } 110 }
99 111
100 GrAAHairLinePathRenderer::GrAAHairLinePathRenderer( 112 GrAAHairLinePathRenderer::GrAAHairLinePathRenderer(
101 const GrContext* context, 113 const GrContext* context,
102 const GrIndexBuffer* linesIndexBuffer, 114 const GrIndexBuffer* linesIndexBuffer,
103 const GrIndexBuffer* quadsIndexBuffer) { 115 const GrIndexBuffer* quadsIndexBuffer,
116 const GrIndexBuffer* conicIndexBuffer) {
104 fLinesIndexBuffer = linesIndexBuffer; 117 fLinesIndexBuffer = linesIndexBuffer;
105 linesIndexBuffer->ref(); 118 linesIndexBuffer->ref();
106 fQuadsIndexBuffer = quadsIndexBuffer; 119 fQuadsIndexBuffer = quadsIndexBuffer;
107 quadsIndexBuffer->ref(); 120 quadsIndexBuffer->ref();
121 fConicsIndexBuffer = conicIndexBuffer;
122 conicIndexBuffer->ref();
108 } 123 }
109 124
110 GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() { 125 GrAAHairLinePathRenderer::~GrAAHairLinePathRenderer() {
111 fLinesIndexBuffer->unref(); 126 fLinesIndexBuffer->unref();
112 fQuadsIndexBuffer->unref(); 127 fQuadsIndexBuffer->unref();
128 fConicsIndexBuffer->unref();
113 } 129 }
114 130
115 namespace { 131 namespace {
116 132
117 typedef SkTArray<SkPoint, true> PtArray; 133 typedef SkTArray<SkPoint, true> PtArray;
118 #define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true> 134 #define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
119 typedef SkTArray<int, true> IntArray; 135 typedef SkTArray<int, true> IntArray;
136 typedef SkTArray<float, true> FloatArray;
120 137
121 // Takes 178th time of logf on Z600 / VC2010 138 // Takes 178th time of logf on Z600 / VC2010
122 int get_float_exp(float x) { 139 int get_float_exp(float x) {
123 GR_STATIC_ASSERT(sizeof(int) == sizeof(float)); 140 GR_STATIC_ASSERT(sizeof(int) == sizeof(float));
124 #if GR_DEBUG 141 #if GR_DEBUG
125 static bool tested; 142 static bool tested;
126 if (!tested) { 143 if (!tested) {
127 tested = true; 144 tested = true;
128 GrAssert(get_float_exp(0.25f) == -2); 145 GrAssert(get_float_exp(0.25f) == -2);
129 GrAssert(get_float_exp(0.3f) == -2); 146 GrAssert(get_float_exp(0.3f) == -2);
130 GrAssert(get_float_exp(0.5f) == -1); 147 GrAssert(get_float_exp(0.5f) == -1);
131 GrAssert(get_float_exp(1.f) == 0); 148 GrAssert(get_float_exp(1.f) == 0);
132 GrAssert(get_float_exp(2.f) == 1); 149 GrAssert(get_float_exp(2.f) == 1);
133 GrAssert(get_float_exp(2.5f) == 1); 150 GrAssert(get_float_exp(2.5f) == 1);
134 GrAssert(get_float_exp(8.f) == 3); 151 GrAssert(get_float_exp(8.f) == 3);
135 GrAssert(get_float_exp(100.f) == 6); 152 GrAssert(get_float_exp(100.f) == 6);
136 GrAssert(get_float_exp(1000.f) == 9); 153 GrAssert(get_float_exp(1000.f) == 9);
137 GrAssert(get_float_exp(1024.f) == 10); 154 GrAssert(get_float_exp(1024.f) == 10);
138 GrAssert(get_float_exp(3000000.f) == 21); 155 GrAssert(get_float_exp(3000000.f) == 21);
139 } 156 }
140 #endif 157 #endif
141 const int* iptr = (const int*)&x; 158 const int* iptr = (const int*)&x;
142 return (((*iptr) & 0x7f800000) >> 23) - 127; 159 return (((*iptr) & 0x7f800000) >> 23) - 127;
143 } 160 }
144 161
162
163 // returns 0 if quad/conic is degen or close to it
164 // in this case approx the path with lines
165 // otherwise returns 1
166 int is_degen_quad_conic(const SkPoint p[3]) {
bsalomon 2013/07/10 15:14:36 quad_or_conic?
167
168 static const SkScalar gDegenerateToLineTol = SK_Scalar1;
169 static const SkScalar gDegenerateToLineTolSqd =
170 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
171
172 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
173 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
174 return 1;
175 }
176
177 SkScalar dsqd = p[1].distanceToLineBetweenSqd(p[0], p[2]);
178 if (dsqd < gDegenerateToLineTolSqd) {
179 return 1;
180 }
181
182 if (p[2].distanceToLineBetweenSqd(p[1], p[0]) < gDegenerateToLineTolSqd) {
183 return 1;
184 }
185 return 0;
186 }
187
145 // we subdivide the quads to avoid huge overfill 188 // we subdivide the quads to avoid huge overfill
146 // if it returns -1 then should be drawn as lines 189 // if it returns -1 then should be drawn as lines
147 int num_quad_subdivs(const SkPoint p[3]) { 190 int num_quad_subdivs(const SkPoint p[3]) {
148 static const SkScalar gDegenerateToLineTol = SK_Scalar1; 191 static const SkScalar gDegenerateToLineTol = SK_Scalar1;
149 static const SkScalar gDegenerateToLineTolSqd = 192 static const SkScalar gDegenerateToLineTolSqd =
150 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 193 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
151 194
152 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 195 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
153 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 196 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
154 return -1; 197 return -1;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 * Quads are recorded in device space unless m contains 243 * Quads are recorded in device space unless m contains
201 * perspective, then in they are in src space. We do this because we will 244 * perspective, then in they are in src space. We do this because we will
202 * subdivide large quads to reduce over-fill. This subdivision has to be 245 * subdivide large quads to reduce over-fill. This subdivision has to be
203 * performed before applying the perspective matrix. 246 * performed before applying the perspective matrix.
204 */ 247 */
205 int generate_lines_and_quads(const SkPath& path, 248 int generate_lines_and_quads(const SkPath& path,
206 const SkMatrix& m, 249 const SkMatrix& m,
207 const GrIRect& devClipBounds, 250 const GrIRect& devClipBounds,
208 PtArray* lines, 251 PtArray* lines,
209 PtArray* quads, 252 PtArray* quads,
210 IntArray* quadSubdivCnts) { 253 PtArray* conics,
254 IntArray* quadSubdivCnts,
255 FloatArray* conicWeights) {
211 SkPath::Iter iter(path, false); 256 SkPath::Iter iter(path, false);
212 257
213 int totalQuadCount = 0; 258 int totalQuadCount = 0;
214 GrRect bounds; 259 GrRect bounds;
215 GrIRect ibounds; 260 GrIRect ibounds;
216 261
217 bool persp = m.hasPerspective(); 262 bool persp = m.hasPerspective();
218 263
219 for (;;) { 264 for (;;) {
220 GrPoint pathPts[4]; 265 GrPoint pathPts[4];
221 GrPoint devPts[4]; 266 GrPoint devPts[4];
222 SkPath::Verb verb = iter.next(pathPts); 267 SkPath::Verb verb = iter.next(pathPts);
223 switch (verb) { 268 switch (verb) {
224 case SkPath::kConic_Verb: 269 case SkPath::kConic_Verb: {
225 SkASSERT(0); 270 SkScalar t = SkGetTQuadAtMaxCurvature(pathPts);
bsalomon 2013/07/10 15:14:36 maybe this whole bit up to the for should be added
271 int conicCnt = 1;
272 SkConic dst[2];
273 if (t == 0)
274 {
bsalomon 2013/07/10 15:14:36 move {s up to prev line
275 dst[0].set(pathPts, iter.conicWeight());
276 }
277 else
278 {
279 SkConic conic;
280 conic.set(pathPts, iter.conicWeight());
281 conic.chopAt(t, dst);
282 conicCnt = 2;
283 }
284 for (int i = 0; i < conicCnt; ++i) {
285 SkPoint* chopPnts = dst[i].fPts;
286 m.mapPoints(devPts, chopPnts, 3);
287 bounds.setBounds(devPts, 3);
288 bounds.outset(SK_Scalar1, SK_Scalar1);
289 bounds.roundOut(&ibounds);
290 if (SkIRect::Intersects(devClipBounds, ibounds)) {
291 if (is_degen_quad_conic(devPts)) {
292 SkPoint* pts = lines->push_back_n(4);
293 pts[0] = devPts[0];
294 pts[1] = devPts[1];
295 pts[2] = devPts[1];
296 pts[3] = devPts[2];
297 } else {
298 // when in perspective keep conics in src space ???
bsalomon 2013/07/10 15:14:36 should test this... but yes. The later chopping th
299 SkPoint* cPts = persp ? chopPnts : devPts;
300 SkPoint* pts = conics->push_back_n(3);
301 pts[0] = cPts[0];
302 pts[1] = cPts[1];
303 pts[2] = cPts[2];
304 conicWeights->push_back() = dst[i].fW;
305 }
306 }
307 }
308 }
226 break; 309 break;
227 case SkPath::kMove_Verb: 310 case SkPath::kMove_Verb:
228 break; 311 break;
229 case SkPath::kLine_Verb: 312 case SkPath::kLine_Verb:
230 m.mapPoints(devPts, pathPts, 2); 313 m.mapPoints(devPts, pathPts, 2);
231 bounds.setBounds(devPts, 2); 314 bounds.setBounds(devPts, 2);
232 bounds.outset(SK_Scalar1, SK_Scalar1); 315 bounds.outset(SK_Scalar1, SK_Scalar1);
233 bounds.roundOut(&ibounds); 316 bounds.roundOut(&ibounds);
234 if (SkIRect::Intersects(devClipBounds, ibounds)) { 317 if (SkIRect::Intersects(devClipBounds, ibounds)) {
235 SkPoint* pts = lines->push_back_n(2); 318 SkPoint* pts = lines->push_back_n(2);
236 pts[0] = devPts[0]; 319 pts[0] = devPts[0];
237 pts[1] = devPts[1]; 320 pts[1] = devPts[1];
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 424 }
342 425
343 struct Vertex { 426 struct Vertex {
344 GrPoint fPos; 427 GrPoint fPos;
345 union { 428 union {
346 struct { 429 struct {
347 SkScalar fA; 430 SkScalar fA;
348 SkScalar fB; 431 SkScalar fB;
349 SkScalar fC; 432 SkScalar fC;
350 } fLine; 433 } fLine;
434 struct {
435 SkScalar fA;
436 SkScalar fB;
437 SkScalar fC;
438 SkScalar fD;
439 SkScalar fE;
440 SkScalar fF;
441 } fConic;
351 GrVec fQuadCoord; 442 GrVec fQuadCoord;
352 struct { 443 struct {
353 SkScalar fBogus[4]; 444 SkScalar fBogus[6];
354 }; 445 };
355 }; 446 };
356 }; 447 };
357 GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint)); 448
449 GR_STATIC_ASSERT(sizeof(Vertex) == 4 * sizeof(GrPoint));
358 450
359 void intersect_lines(const SkPoint& ptA, const SkVector& normA, 451 void intersect_lines(const SkPoint& ptA, const SkVector& normA,
360 const SkPoint& ptB, const SkVector& normB, 452 const SkPoint& ptB, const SkVector& normB,
361 SkPoint* result) { 453 SkPoint* result) {
362 454
363 SkScalar lineAW = -normA.dot(ptA); 455 SkScalar lineAW = -normA.dot(ptA);
364 SkScalar lineBW = -normB.dot(ptB); 456 SkScalar lineBW = -normB.dot(ptB);
365 457
366 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 458 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
367 SkScalarMul(normA.fY, normB.fX); 459 SkScalarMul(normA.fY, normB.fX);
368 wInv = SkScalarInvert(wInv); 460 wInv = SkScalarInvert(wInv);
369 461
370 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); 462 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY);
371 result->fX = SkScalarMul(result->fX, wInv); 463 result->fX = SkScalarMul(result->fX, wInv);
372 464
373 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); 465 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW);
374 result->fY = SkScalarMul(result->fY, wInv); 466 result->fY = SkScalarMul(result->fY, wInv);
375 } 467 }
376 468
377 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, 469 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 // include it. 539 // include it.
448 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 540 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
449 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); 541 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY);
450 542
451 if (toSrc) { 543 if (toSrc) {
452 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad ); 544 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad );
453 } 545 }
454 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 546 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts);
455 } 547 }
456 548
549
550 // Input Parametric:
551 // 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)
552 // Output Implicit:
553 // Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
554 // A = 4w^2*(y0-y1)(y1-y2)-(y0-y2)^2
555 // B = 4w^2*((x0-x1)(y2-y1)+(x1-x2)(y1-y0)) + 2(x0-x2)(y0-y2)
556 // C = 4w^2(x0-x1)(x1-x2) - (x0-x2)^2
557 // D = 4w^2((x0y1-x1y0)(y1-y2)+(x1y2-x2y1)(y0-y1)) + 2(y2-y0)(x0y2-x2y0)
558 // E = 4w^2((y0x1-y1x0)(x1-x2)+(y1x2-y2x1)(x0-x1)) + 2(x2-x0)(y0x2-y2x0)
559 // F = 4w^2(x1y2-x2y1)(x0y1-x1y0) - (x2y0-x0y2)^2
560
561 void set_conic_coeffs(const SkPoint p[3], Vertex verts[kVertsPerConic], const fl oat weight) {
562 const float ww4 = 4 * weight * weight;
563 const float x0Mx1 = p[0].fX - p[1].fX;
564 const float x1Mx2 = p[1].fX - p[2].fX;
565 const float x0Mx2 = p[0].fX - p[2].fX;
566 const float y0My1 = p[0].fY - p[1].fY;
567 const float y1My2 = p[1].fY - p[2].fY;
568 const float y0My2 = p[0].fY - p[2].fY;
569 const float x0y1Mx1y0 = p[0].fX*p[1].fY - p[1].fX*p[0].fY;
570 const float x1y2Mx2y1 = p[1].fX*p[2].fY - p[2].fX*p[1].fY;
571 const float x0y2Mx2y0 = p[0].fX*p[2].fY - p[2].fX*p[0].fY;
572 const float a = ww4 * y0My1 * y1My2 - y0My2 * y0My2;
573 const float b = -ww4 * (x0Mx1 * y1My2 + x1Mx2 * y0My1) + 2 * x0Mx2 * y0My2;
574 const float c = ww4 * x0Mx1 * x1Mx2 - x0Mx2 * x0Mx2;
575 const float d = ww4 * (x0y1Mx1y0 * y1My2 + x1y2Mx2y1 * y0My1) - 2 * y0My2 * x0y2Mx2y0;
576 const float e = -ww4 * (x0y1Mx1y0 * x1Mx2 + x1y2Mx2y1 * x0Mx1) + 2 * x0Mx2 * x0y2Mx2y0;
577 const float f = ww4 * x1y2Mx2y1 * x0y1Mx1y0 - x0y2Mx2y0 * x0y2Mx2y0;
578
579 for (int i = 0; i < kVertsPerConic; ++i) {
580 verts[i].fConic.fA = a/f;
581 verts[i].fConic.fB = b/f;
582 verts[i].fConic.fC = c/f;
583 verts[i].fConic.fD = d/f;
584 verts[i].fConic.fE = e/f;
585 verts[i].fConic.fF = f/f;
586 }
587 }
588
589 void add_conics(const SkPoint p[3],
590 float weight,
591 const SkMatrix* toDevice,
592 const SkMatrix* toSrc,
593 Vertex** vert,
594 SkRect* devBounds) {
595 bloat_quad(p, toDevice, toSrc, *vert, devBounds);
596 set_conic_coeffs(p, *vert, weight);
597 *vert += kVertsPerConic;
598 }
599
457 void add_quads(const SkPoint p[3], 600 void add_quads(const SkPoint p[3],
458 int subdiv, 601 int subdiv,
459 const SkMatrix* toDevice, 602 const SkMatrix* toDevice,
460 const SkMatrix* toSrc, 603 const SkMatrix* toSrc,
461 Vertex** vert, 604 Vertex** vert,
462 SkRect* devBounds) { 605 SkRect* devBounds) {
463 GrAssert(subdiv >= 0); 606 GrAssert(subdiv >= 0);
464 if (subdiv) { 607 if (subdiv) {
465 SkPoint newP[5]; 608 SkPoint newP[5];
466 SkChopQuadAtHalf(p, newP); 609 SkChopQuadAtHalf(p, newP);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax); 651 (*vert)[1].fPos.set(SK_ScalarMax, SK_ScalarMax);
509 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 652 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax);
510 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 653 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax);
511 } 654 }
512 655
513 *vert += kVertsPerLineSeg; 656 *vert += kVertsPerLineSeg;
514 } 657 }
515 658
516 } 659 }
517 660
661 /**
662 * The output of this effect is a hairline edge for conics.
663 * Conics specified by implicit equation Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0.
664 * A, B, C, D are the first vec4 of vertex attributes and
665 * E and F are the vec2 attached to 2nd vertex attrribute.
666 * Coverage is max(0, 1-distance).
667 */
668 class HairConicEdgeEffect : public GrEffect {
669 public:
670
671 static GrEffectRef* Create() {
672 GR_CREATE_STATIC_EFFECT(gHairConicEdgeEffect, HairConicEdgeEffect, ());
673 gHairConicEdgeEffect->ref();
674 return gHairConicEdgeEffect;
675 }
676
677 virtual ~HairConicEdgeEffect() {}
678
679 static const char* Name() { return "HairConicEdge"; }
680
681 virtual void getConstantColorComponents(GrColor* color,
682 uint32_t* validFlags) const SK_OVERR IDE {
683 *validFlags = 0;
684 }
685
686 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
687 return GrTBackendEffectFactory<HairConicEdgeEffect>::getInstance();
688 }
689
690 class GLEffect : public GrGLEffect {
691 public:
692 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
693 : INHERITED (factory) {}
694
695 virtual void emitCode(GrGLShaderBuilder* builder,
696 const GrDrawEffect& drawEffect,
697 EffectKey key,
698 const char* outputColor,
699 const char* inputColor,
700 const TextureSamplerArray& samplers) SK_OVERRIDE {
701 const char *vsCoeffABCDName, *fsCoeffABCDName;
702 const char *vsCoeffEFName, *fsCoeffEFName;
703
704 SkAssertResult(builder->enableFeature(
705 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
706 builder->addVarying(kVec4f_GrSLType, "ConicCoeffsABCD",
707 &vsCoeffABCDName, &fsCoeffABCDName);
708 const SkString* attr0Name =
709 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
710 builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffABCDName, attr0Name->c _str());
711
712 builder->addVarying(kVec2f_GrSLType, "ConicCoeffsEF",
713 &vsCoeffEFName, &fsCoeffEFName);
714 const SkString* attr1Name =
715 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[1]);
716 builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffEFName, attr1Name->c_s tr());
717
718 // Based on Gustavson 2006: "Beyond the Pixel: towards infinite reso lution textures"
719 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
720
721 builder->fsCodeAppendf("\t\tvec3 uv1 = vec3(%s.xy, 1);\n", builder-> fragmentPosition());
722 builder->fsCodeAppend("\t\tvec3 u2uvv2 = uv1.xxy * uv1.xyy;\n");
723 builder->fsCodeAppendf("\t\tvec3 ABC = %s.xyz;\n", fsCoeffABCDName);
724 builder->fsCodeAppendf("\t\tvec3 DEF = vec3(%s.w, %s.xy);\n",
725 fsCoeffABCDName, fsCoeffEFName);
726
727 builder->fsCodeAppend("\t\tfloat dfdx = dot(uv1,vec3(2.0*ABC.x,ABC.y ,DEF.x));\n");
728 builder->fsCodeAppend("\t\tfloat dfdy = dot(uv1,vec3(ABC.y, 2.0*ABC. z,DEF.y));\n");
729 builder->fsCodeAppend("\t\tfloat gF = dfdx*dfdx + dfdy*dfdy;\n");
730 builder->fsCodeAppend("\t\tedgeAlpha = dot(ABC,u2uvv2) + dot(DEF,uv1 );\n");
731 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / gF );\n");
732 builder->fsCodeAppend("\t\tedgeAlpha = max((1.0 - edgeAlpha), 0.0);\ n");
733 // Add line below for smooth cubic ramp
734 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2 .0*edgeAlpha);\n");
735
736 SkString modulate;
737 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
738 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
739
740 }
741
742 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
743 return 0x0;
744 }
745
746 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
747
748 private:
749 typedef GrGLEffect INHERITED;
750 };
751
752 private:
753 HairConicEdgeEffect() {
754 this->addVertexAttrib(kVec4f_GrSLType);
755 this->addVertexAttrib(kVec2f_GrSLType);
756 this->setWillReadFragmentPosition();
757 }
758
759 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
760 return true;
761 }
762
763 GR_DECLARE_EFFECT_TEST;
764
765 typedef GrEffect INHERITED;
766 };
767
768 GR_DEFINE_EFFECT_TEST(HairConicEdgeEffect);
769
770 GrEffectRef* HairConicEdgeEffect::TestCreate(SkMWCRandom* random,
771 GrContext*,
772 const GrDrawTargetCaps& caps,
773 GrTexture*[]) {
774 return HairConicEdgeEffect::Create();
775 }
518 /////////////////////////////////////////////////////////////////////////////// 776 ///////////////////////////////////////////////////////////////////////////////
519 777
520 /** 778 /**
521 * The output of this effect is a hairline edge for quadratics. 779 * The output of this effect is a hairline edge for quadratics.
522 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 780 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
523 * two components of the vertex attribute. Uses unsigned distance. 781 * two components of the vertex attribute. Uses unsigned distance.
524 * Coverage is min(0, 1-distance). 3rd & 4th component unused. 782 * Coverage is min(0, 1-distance). 3rd & 4th component unused.
525 * Requires shader derivative instruction support. 783 * Requires shader derivative instruction support.
526 */ 784 */
527 class HairQuadEdgeEffect : public GrEffect { 785 class HairQuadEdgeEffect : public GrEffect {
(...skipping 28 matching lines...) Expand all
556 EffectKey key, 814 EffectKey key,
557 const char* outputColor, 815 const char* outputColor,
558 const char* inputColor, 816 const char* inputColor,
559 const TextureSamplerArray& samplers) SK_OVERRIDE { 817 const TextureSamplerArray& samplers) SK_OVERRIDE {
560 const char *vsName, *fsName; 818 const char *vsName, *fsName;
561 const SkString* attrName = 819 const SkString* attrName =
562 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); 820 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
563 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 821 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
564 822
565 SkAssertResult(builder->enableFeature( 823 SkAssertResult(builder->enableFeature(
566 GrGLShaderBuilder::kStandardDeriva tives_GLSLFeature)); 824 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
567 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam e); 825 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsNam e);
568 826
569 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName); 827 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
570 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName); 828 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
571 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx. y,\n" 829 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx. y,\n"
572 "\t\t 2.0*%s.x*duvdy.x - duvdy. y);\n", 830 "\t\t 2.0*%s.x*duvdy.x - duvdy. y);\n",
573 fsName, fsName); 831 fsName, fsName);
574 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa me, fsName, 832 builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsNa me, fsName,
575 fsName); 833 fsName);
576 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do t(gF, gF));\n"); 834 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / do t(gF, gF));\n");
(...skipping 30 matching lines...) Expand all
607 typedef GrEffect INHERITED; 865 typedef GrEffect INHERITED;
608 }; 866 };
609 867
610 GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect); 868 GR_DEFINE_EFFECT_TEST(HairQuadEdgeEffect);
611 869
612 GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random, 870 GrEffectRef* HairQuadEdgeEffect::TestCreate(SkMWCRandom* random,
613 GrContext*, 871 GrContext*,
614 const GrDrawTargetCaps& caps, 872 const GrDrawTargetCaps& caps,
615 GrTexture*[]) { 873 GrTexture*[]) {
616 // Doesn't work without derivative instructions. 874 // Doesn't work without derivative instructions.
617 return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL; } 875 return caps.shaderDerivativeSupport() ? HairQuadEdgeEffect::Create() : NULL;
876 }
618 877
619 /////////////////////////////////////////////////////////////////////////////// 878 ///////////////////////////////////////////////////////////////////////////////
620 879
621 /** 880 /**
622 * The output of this effect is a 1-pixel wide line. 881 * The output of this effect is a 1-pixel wide line.
623 * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component u nused. 882 * Input is 2D implicit device coord line eq (a*x + b*y +c = 0). 4th component u nused.
624 */ 883 */
625 class HairLineEdgeEffect : public GrEffect { 884 class HairLineEdgeEffect : public GrEffect {
626 public: 885 public:
627 886
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 /////////////////////////////////////////////////////////////////////////////// 969 ///////////////////////////////////////////////////////////////////////////////
711 970
712 namespace { 971 namespace {
713 972
714 // position + edge 973 // position + edge
715 extern const GrVertexAttrib gHairlineAttribs[] = { 974 extern const GrVertexAttrib gHairlineAttribs[] = {
716 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing}, 975 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing},
717 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g} 976 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g}
718 }; 977 };
719 978
979 // Conic
980 // position + ABCD + EF
981 extern const GrVertexAttrib gConicVertexAttribs[] = {
982 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing },
983 { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g },
984 { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBindin g }
985 };
720 }; 986 };
721 987
722 bool GrAAHairLinePathRenderer::createGeom( 988 bool GrAAHairLinePathRenderer::createGeom(
723 const SkPath& path, 989 const SkPath& path,
724 GrDrawTarget* target, 990 GrDrawTarget* target,
725 int* lineCnt, 991 int* lineCnt,
726 int* quadCnt, 992 int* quadCnt,
993 int* conicCnt,
727 GrDrawTarget::AutoReleaseGeometry* arg, 994 GrDrawTarget::AutoReleaseGeometry* arg,
728 SkRect* devBounds) { 995 SkRect* devBounds) {
729 GrDrawState* drawState = target->drawState(); 996 GrDrawState* drawState = target->drawState();
730 int rtHeight = drawState->getRenderTarget()->height(); 997 int rtHeight = drawState->getRenderTarget()->height();
731 998
732 GrIRect devClipBounds; 999 GrIRect devClipBounds;
733 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devC lipBounds); 1000 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), &devC lipBounds);
734 1001
735 SkMatrix viewM = drawState->getViewMatrix(); 1002 SkMatrix viewM = drawState->getViewMatrix();
736 1003
737 // All the vertices that we compute are within 1 of path control points with the exception of 1004 // All the vertices that we compute are within 1 of path control points with the exception of
738 // one of the bounding vertices for each quad. The add_quads() function will update the bounds 1005 // one of the bounding vertices for each quad. The add_quads() function will update the bounds
739 // for each quad added. 1006 // for each quad added.
740 *devBounds = path.getBounds(); 1007 *devBounds = path.getBounds();
741 viewM.mapRect(devBounds); 1008 viewM.mapRect(devBounds);
742 devBounds->outset(SK_Scalar1, SK_Scalar1); 1009 devBounds->outset(SK_Scalar1, SK_Scalar1);
743 1010
744 PREALLOC_PTARRAY(128) lines; 1011 PREALLOC_PTARRAY(128) lines;
745 PREALLOC_PTARRAY(128) quads; 1012 PREALLOC_PTARRAY(128) quads;
1013 PREALLOC_PTARRAY(128) conics;
746 IntArray qSubdivs; 1014 IntArray qSubdivs;
1015 FloatArray cWeights;
747 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 1016 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds,
748 &lines, &quads, &qSubdivs); 1017 &lines, &quads, &conics, &qSubdivs, &cWe ights);
749 1018
750 *lineCnt = lines.count() / 2; 1019 *lineCnt = lines.count() / 2;
751 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; 1020 *conicCnt = conics.count() / 3;
1021 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt +
1022 kVertsPerConic * *conicCnt;
752 1023
753 target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHair lineAttribs)); 1024 target->drawState()->setVertexAttribs<gConicVertexAttribs>(SK_ARRAY_COUNT(gC onicVertexAttribs));
754 GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 1025 GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
755 1026
756 if (!arg->set(target, vertCnt, 0)) { 1027 if (!arg->set(target, vertCnt, 0)) {
757 return false; 1028 return false;
758 } 1029 }
759 1030
760 Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 1031 Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices());
761 1032
762 const SkMatrix* toDevice = NULL; 1033 const SkMatrix* toDevice = NULL;
763 const SkMatrix* toSrc = NULL; 1034 const SkMatrix* toSrc = NULL;
764 SkMatrix ivm; 1035 SkMatrix ivm;
765 1036
766 if (viewM.hasPerspective()) { 1037 if (viewM.hasPerspective()) {
767 if (viewM.invert(&ivm)) { 1038 if (viewM.invert(&ivm)) {
768 toDevice = &viewM; 1039 toDevice = &viewM;
769 toSrc = &ivm; 1040 toSrc = &ivm;
770 } 1041 }
771 } 1042 }
772 1043
773 for (int i = 0; i < *lineCnt; ++i) { 1044 for (int i = 0; i < *lineCnt; ++i) {
774 add_line(&lines[2*i], rtHeight, toSrc, &verts); 1045 add_line(&lines[2*i], rtHeight, toSrc, &verts);
775 } 1046 }
776 1047
777 int unsubdivQuadCnt = quads.count() / 3; 1048 int unsubdivQuadCnt = quads.count() / 3;
778 for (int i = 0; i < unsubdivQuadCnt; ++i) { 1049 for (int i = 0; i < unsubdivQuadCnt; ++i) {
779 GrAssert(qSubdivs[i] >= 0); 1050 GrAssert(qSubdivs[i] >= 0);
780 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); 1051 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds);
781 } 1052 }
782 1053
1054 // Start Conics
1055 for (int i = 0; i < *conicCnt; ++i) {
1056 add_conics(&conics[3*i], cWeights[i], toDevice, toSrc, &verts, devBounds );
1057 }
783 return true; 1058 return true;
784 } 1059 }
785 1060
786 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 1061 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
787 const SkStrokeRec& stroke, 1062 const SkStrokeRec& stroke,
788 const GrDrawTarget* target, 1063 const GrDrawTarget* target,
789 bool antiAlias) const { 1064 bool antiAlias) const {
790 if (!stroke.isHairlineStyle() || !antiAlias) { 1065 if (!stroke.isHairlineStyle() || !antiAlias) {
791 return false; 1066 return false;
792 } 1067 }
793 1068
794 static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 1069 static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
795 SkPath::kQuad_SegmentMask; 1070 SkPath::kQuad_SegmentMask;
796 if (!target->caps()->shaderDerivativeSupport() && 1071 if (!target->caps()->shaderDerivativeSupport() &&
797 (gReqDerivMask & path.getSegmentMasks())) { 1072 (gReqDerivMask & path.getSegmentMasks())) {
798 return false; 1073 return false;
799 } 1074 }
800 return true; 1075 return true;
801 } 1076 }
802 1077
803 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 1078 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
804 const SkStrokeRec&, 1079 const SkStrokeRec&,
805 GrDrawTarget* target, 1080 GrDrawTarget* target,
806 bool antiAlias) { 1081 bool antiAlias) {
807 1082
808 int lineCnt; 1083 int lineCnt;
809 int quadCnt; 1084 int quadCnt;
1085 int conicCnt;
810 GrDrawTarget::AutoReleaseGeometry arg; 1086 GrDrawTarget::AutoReleaseGeometry arg;
811 SkRect devBounds; 1087 SkRect devBounds;
812 1088
813 if (!this->createGeom(path, 1089 if (!this->createGeom(path,
814 target, 1090 target,
815 &lineCnt, 1091 &lineCnt,
816 &quadCnt, 1092 &quadCnt,
1093 &conicCnt,
817 &arg, 1094 &arg,
818 &devBounds)) { 1095 &devBounds)) {
819 return false; 1096 return false;
820 } 1097 }
821 1098
822 GrDrawTarget::AutoStateRestore asr; 1099 GrDrawTarget::AutoStateRestore asr;
823 1100
824 // createGeom transforms the geometry to device space when the matrix does n ot have 1101 // createGeom transforms the geometry to device space when the matrix does n ot have
825 // perspective. 1102 // perspective.
826 if (target->getDrawState().getViewMatrix().hasPerspective()) { 1103 if (target->getDrawState().getViewMatrix().hasPerspective()) {
827 asr.set(target, GrDrawTarget::kPreserve_ASRInit); 1104 asr.set(target, GrDrawTarget::kPreserve_ASRInit);
828 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) { 1105 } else if (!asr.setIdentity(target, GrDrawTarget::kPreserve_ASRInit)) {
829 return false; 1106 return false;
830 } 1107 }
831 GrDrawState* drawState = target->drawState(); 1108 GrDrawState* drawState = target->drawState();
832 1109
833 // TODO: See whether rendering lines as degenerate quads improves perf 1110 // TODO: See whether rendering lines as degenerate quads improves perf
834 // when we have a mix 1111 // when we have a mix
835 1112
836 enum { 1113 enum {
837 // the edge effects share this stage with glyph rendering 1114 // the edge effects share this stage with glyph rendering
838 // (kGlyphMaskStage in GrTextContext) && SW path rendering 1115 // (kGlyphMaskStage in GrTextContext) && SW path rendering
839 // (kPathMaskStage in GrSWMaskHelper) 1116 // (kPathMaskStage in GrSWMaskHelper)
840 kEdgeEffectStage = GrPaint::kTotalStages, 1117 kEdgeEffectStage = GrPaint::kTotalStages,
841 }; 1118 };
842 static const int kEdgeAttrIndex = 1; 1119 static const int kEdgeAttrIndex = 1;
843 1120
844 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); 1121 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create();
845 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); 1122 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create();
1123 GrEffectRef* hairConicEffect = HairConicEdgeEffect::Create();
846 1124
847 // Check devBounds 1125 // Check devBounds
848 #if GR_DEBUG 1126 #if GR_DEBUG
849 SkRect tolDevBounds = devBounds; 1127 SkRect tolDevBounds = devBounds;
850 tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); 1128 tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000);
851 SkRect actualBounds; 1129 SkRect actualBounds;
852 Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices()); 1130 Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices());
853 int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt; 1131 int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt + kVertsPe rConic * conicCnt;
854 bool first = true; 1132 bool first = true;
855 for (int i = 0; i < vCount; ++i) { 1133 for (int i = 0; i < vCount; ++i) {
856 SkPoint pos = verts[i].fPos; 1134 SkPoint pos = verts[i].fPos;
857 // This is a hack to workaround the fact that we move some degenerate se gments offscreen. 1135 // This is a hack to workaround the fact that we move some degenerate se gments offscreen.
858 if (SK_ScalarMax == pos.fX) { 1136 if (SK_ScalarMax == pos.fX) {
859 continue; 1137 continue;
860 } 1138 }
861 drawState->getViewMatrix().mapPoints(&pos, 1); 1139 drawState->getViewMatrix().mapPoints(&pos, 1);
862 if (first) { 1140 if (first) {
863 actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); 1141 actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY);
(...skipping 18 matching lines...) Expand all
882 target->drawIndexed(kTriangles_GrPrimitiveType, 1160 target->drawIndexed(kTriangles_GrPrimitiveType,
883 kVertsPerLineSeg*lines, // startV 1161 kVertsPerLineSeg*lines, // startV
884 0, // startI 1162 0, // startI
885 kVertsPerLineSeg*n, // vCount 1163 kVertsPerLineSeg*n, // vCount
886 kIdxsPerLineSeg*n, 1164 kIdxsPerLineSeg*n,
887 &devBounds); // iCount 1165 &devBounds); // iCount
888 lines += n; 1166 lines += n;
889 } 1167 }
890 } 1168 }
891 1169
892 target->setIndexSourceToBuffer(fQuadsIndexBuffer); 1170 {
893 int quads = 0; 1171 GrDrawState::AutoRestoreEffects are(drawState);
894 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref(); 1172 target->setIndexSourceToBuffer(fQuadsIndexBuffer);
895 while (quads < quadCnt) { 1173 int quads = 0;
896 int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); 1174 drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
897 target->drawIndexed(kTriangles_GrPrimitiveType, 1175 while (quads < quadCnt) {
898 4 * lineCnt + kVertsPerQuad*quads, // startV 1176 int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
899 0, // startI 1177 target->drawIndexed(kTriangles_GrPrimitiveType,
900 kVertsPerQuad*n, // vCount 1178 kVertsPerLineSeg * lineCnt + kVertsPerQuad*quads , // startV
901 kIdxsPerQuad*n, // iCount 1179 0, // startI
902 &devBounds); 1180 kVertsPerQuad*n, // vCount
903 quads += n; 1181 kIdxsPerQuad*n, // iCount
1182 &devBounds);
1183 quads += n;
1184 }
1185 }
1186
1187 {
1188 GrDrawState::AutoRestoreEffects are(drawState);
1189 target->setIndexSourceToBuffer(fConicsIndexBuffer);
1190 int conics = 0;
1191 drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
1192 // drawState->addCoverageEffect(hairConicEffect, kEdgeAttrIndex)->unref( );
1193 while (conics < conicCnt) {
1194 int n = GrMin(conicCnt - conics, kNumConicsInIdxBuffer);
1195 target->drawIndexed(kTriangles_GrPrimitiveType,
1196 kVertsPerLineSeg*lineCnt + kVertsPerQuad*quadCnt +
1197 kVertsPerConic*conics, // startV
1198 0, // startI
1199 kVertsPerConic*n, // vCount
1200 kIdxsPerConic*n, // iCount
1201 &devBounds);
1202 conics += n;
1203 }
904 } 1204 }
905 target->resetIndexSource(); 1205 target->resetIndexSource();
906 1206
907 return true; 1207 return true;
908 } 1208 }
1209
OLDNEW
« src/core/SkGeometry.cpp ('K') | « src/gpu/GrAAHairLinePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698