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