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