OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "GrDashingEffect.h" | 8 #include "GrDashingEffect.h" |
9 | 9 |
10 #include "../GrAARectRenderer.h" | 10 #include "../GrAARectRenderer.h" |
11 | 11 |
12 #include "GrGeometryProcessor.h" | 12 #include "GrGeometryProcessor.h" |
13 #include "gl/builders/GrGLProgramBuilder.h" | |
14 #include "gl/GrGLProcessor.h" | |
15 #include "gl/GrGLGeometryProcessor.h" | |
16 #include "gl/GrGLSL.h" | |
17 #include "GrContext.h" | 13 #include "GrContext.h" |
18 #include "GrCoordTransform.h" | 14 #include "GrCoordTransform.h" |
| 15 #include "GrDefaultGeoProcFactory.h" |
19 #include "GrDrawTarget.h" | 16 #include "GrDrawTarget.h" |
20 #include "GrDrawTargetCaps.h" | 17 #include "GrDrawTargetCaps.h" |
21 #include "GrInvariantOutput.h" | 18 #include "GrInvariantOutput.h" |
22 #include "GrProcessor.h" | 19 #include "GrProcessor.h" |
23 #include "GrGpu.h" | |
24 #include "GrStrokeInfo.h" | 20 #include "GrStrokeInfo.h" |
25 #include "GrTBackendProcessorFactory.h" | 21 #include "GrTBackendProcessorFactory.h" |
26 #include "SkGr.h" | 22 #include "SkGr.h" |
| 23 #include "gl/GrGLGeometryProcessor.h" |
| 24 #include "gl/GrGLProcessor.h" |
| 25 #include "gl/GrGLSL.h" |
| 26 #include "gl/builders/GrGLProgramBuilder.h" |
27 | 27 |
28 /////////////////////////////////////////////////////////////////////////////// | 28 /////////////////////////////////////////////////////////////////////////////// |
29 | 29 |
30 // Returns whether or not the gpu can fast path the dash line effect. | 30 // Returns whether or not the gpu can fast path the dash line effect. |
31 static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeI
nfo, | 31 static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeI
nfo, |
32 const GrDrawTarget& target, const SkMatrix& viewM
atrix) { | 32 const GrDrawTarget& target, const SkMatrix& viewM
atrix) { |
33 if (target.getDrawState().getRenderTarget()->isMultisampled()) { | 33 if (target.getDrawState().getRenderTarget()->isMultisampled()) { |
34 return false; | 34 return false; |
35 } | 35 } |
36 | 36 |
(...skipping 26 matching lines...) Expand all Loading... |
63 return true; | 63 return true; |
64 } | 64 } |
65 | 65 |
66 namespace { | 66 namespace { |
67 | 67 |
68 struct DashLineVertex { | 68 struct DashLineVertex { |
69 SkPoint fPos; | 69 SkPoint fPos; |
70 SkPoint fDashPos; | 70 SkPoint fDashPos; |
71 }; | 71 }; |
72 | 72 |
73 extern const GrVertexAttrib gDashLineNoAAVertexAttribs[] = { | |
74 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing } | |
75 }; | |
76 | |
77 extern const GrVertexAttrib gDashLineVertexAttribs[] = { | 73 extern const GrVertexAttrib gDashLineVertexAttribs[] = { |
78 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing }, | 74 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind
ing }, |
79 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding }, | 75 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexA
ttribBinding }, |
80 }; | 76 }; |
81 | 77 |
82 }; | 78 }; |
83 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, | 79 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, |
84 const SkMatrix& viewMatrix, const SkPoint pts[2]) { | 80 const SkMatrix& viewMatrix, const SkPoint pts[2]) { |
85 SkVector vecSrc = pts[1] - pts[0]; | 81 SkVector vecSrc = pts[1] - pts[0]; |
86 SkScalar magSrc = vecSrc.length(); | 82 SkScalar magSrc = vecSrc.length(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 if (0 == info.fIntervals[0]) { | 139 if (0 == info.fIntervals[0]) { |
144 *endingInt -= 0.01f; // make sure we capture the last zero size pnt
(used if has caps) | 140 *endingInt -= 0.01f; // make sure we capture the last zero size pnt
(used if has caps) |
145 } | 141 } |
146 return *endingInt - info.fIntervals[0]; | 142 return *endingInt - info.fIntervals[0]; |
147 } | 143 } |
148 return 0; | 144 return 0; |
149 } | 145 } |
150 | 146 |
151 static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx
, const SkMatrix& matrix, | 147 static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx
, const SkMatrix& matrix, |
152 SkScalar offset, SkScalar bloat, SkScalar len, SkScalar s
troke) { | 148 SkScalar offset, SkScalar bloat, SkScalar len, SkScalar s
troke) { |
153 | |
154 SkScalar startDashX = offset - bloat; | 149 SkScalar startDashX = offset - bloat; |
155 SkScalar endDashX = offset + len + bloat; | 150 SkScalar endDashX = offset + len + bloat; |
156 SkScalar startDashY = -stroke - bloat; | 151 SkScalar startDashY = -stroke - bloat; |
157 SkScalar endDashY = stroke + bloat; | 152 SkScalar endDashY = stroke + bloat; |
158 verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY); | 153 verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY); |
159 verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); | 154 verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY); |
160 verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); | 155 verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY); |
161 verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); | 156 verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY); |
162 | |
163 verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); | 157 verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop); |
164 verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); | 158 verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom); |
165 verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); | 159 verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom); |
166 verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); | 160 verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop); |
167 | |
168 matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4); | 161 matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4); |
169 } | 162 } |
170 | 163 |
| 164 static void setup_dashed_rect_pos(const SkRect& rect, int idx, const SkMatrix& m
atrix, |
| 165 SkPoint* verts) { |
| 166 verts[idx] = SkPoint::Make(rect.fLeft, rect.fTop); |
| 167 verts[idx + 1] = SkPoint::Make(rect.fLeft, rect.fBottom); |
| 168 verts[idx + 2] = SkPoint::Make(rect.fRight, rect.fBottom); |
| 169 verts[idx + 3] = SkPoint::Make(rect.fRight, rect.fTop); |
| 170 matrix.mapPoints(&verts[idx], 4); |
| 171 } |
171 | 172 |
172 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint, | 173 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint, |
173 const GrStrokeInfo& strokeInfo, GrGpu* gpu, | 174 const GrStrokeInfo& strokeInfo, GrGpu* gpu, |
174 GrDrawTarget* target, const SkMatrix& vm) { | 175 GrDrawTarget* target, const SkMatrix& vm) { |
175 | 176 |
176 if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) { | 177 if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) { |
177 return false; | 178 return false; |
178 } | 179 } |
179 | 180 |
180 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); | 181 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo(); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 lineDone = true; | 334 lineDone = true; |
334 | 335 |
335 SkPoint devicePts[2]; | 336 SkPoint devicePts[2]; |
336 vm.mapPoints(devicePts, ptsRot, 2); | 337 vm.mapPoints(devicePts, ptsRot, 2); |
337 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); | 338 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); |
338 if (hasCap) { | 339 if (hasCap) { |
339 lineLength += 2.f * halfDevStroke; | 340 lineLength += 2.f * halfDevStroke; |
340 } | 341 } |
341 devIntervals[0] = lineLength; | 342 devIntervals[0] = lineLength; |
342 } | 343 } |
343 if (devIntervals[1] > 0.f || useAA) { | 344 bool fullDash = devIntervals[1] > 0.f || useAA; |
| 345 if (fullDash) { |
344 SkPathEffect::DashInfo devInfo; | 346 SkPathEffect::DashInfo devInfo; |
345 devInfo.fPhase = devPhase; | 347 devInfo.fPhase = devPhase; |
346 devInfo.fCount = 2; | 348 devInfo.fCount = 2; |
347 devInfo.fIntervals = devIntervals; | 349 devInfo.fIntervals = devIntervals; |
348 GrPrimitiveEdgeType edgeType= useAA ? kFillAA_GrProcessorEdgeType : | 350 GrPrimitiveEdgeType edgeType= useAA ? kFillAA_GrProcessorEdgeType : |
349 kFillBW_GrProcessorEdgeType; | 351 kFillBW_GrProcessorEdgeType; |
350 bool isRoundCap = SkPaint::kRound_Cap == cap; | 352 bool isRoundCap = SkPaint::kRound_Cap == cap; |
351 GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_
DashCap : | 353 GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_
DashCap : |
352 GrDashingEffect::kNonRou
nd_DashCap; | 354 GrDashingEffect::kNonRou
nd_DashCap; |
353 drawState->setGeometryProcessor( | 355 drawState->setGeometryProcessor( |
354 GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType)
)->unref(); | 356 GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType)
)->unref(); |
355 | 357 |
356 // Set up the vertex data for the line and start/end dashes | 358 // Set up the vertex data for the line and start/end dashes |
357 drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDash
LineVertexAttribs), | 359 drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDash
LineVertexAttribs), |
358 sizeof(DashLineVerte
x)); | 360 sizeof(DashLineVerte
x)); |
359 } else { | 361 } else { |
360 // Set up the vertex data for the line and start/end dashes | 362 // Set up the vertex data for the line and start/end dashes |
361 drawState->setVertexAttribs<gDashLineNoAAVertexAttribs>( | 363 drawState->setGeometryProcessor( |
362 SK_ARRAY_COUNT(gDashLineNoAAVertexAttribs), sizeof(DashLineVerte
x)); | 364 GrDefaultGeoProcFactory::CreateAndSetAttribs( |
| 365 drawState, |
| 366 GrDefaultGeoProcFactory::kPosition_GPType))->unref(); |
363 } | 367 } |
364 | 368 |
365 int totalRectCnt = 0; | 369 int totalRectCnt = 0; |
366 | 370 |
367 totalRectCnt += !lineDone ? 1 : 0; | 371 totalRectCnt += !lineDone ? 1 : 0; |
368 totalRectCnt += hasStartRect ? 1 : 0; | 372 totalRectCnt += hasStartRect ? 1 : 0; |
369 totalRectCnt += hasEndRect ? 1 : 0; | 373 totalRectCnt += hasEndRect ? 1 : 0; |
370 | 374 |
371 GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0); | 375 GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0); |
372 if (!geo.succeeded()) { | 376 if (!geo.succeeded()) { |
373 SkDebugf("Failed to get space for vertices!\n"); | 377 SkDebugf("Failed to get space for vertices!\n"); |
374 return false; | 378 return false; |
375 } | 379 } |
376 | 380 |
377 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices()); | |
378 | |
379 int curVIdx = 0; | 381 int curVIdx = 0; |
380 | 382 |
381 if (SkPaint::kRound_Cap == cap && 0 != srcStrokeWidth) { | 383 if (SkPaint::kRound_Cap == cap && 0 != srcStrokeWidth) { |
382 // need to adjust this for round caps to correctly set the dashPos attri
b on vertices | 384 // need to adjust this for round caps to correctly set the dashPos attri
b on vertices |
383 startOffset -= halfDevStroke; | 385 startOffset -= halfDevStroke; |
384 } | 386 } |
385 | 387 |
386 // Draw interior part of dashed line | 388 // Draw interior part of dashed line |
387 if (!lineDone) { | 389 if (!lineDone) { |
388 SkPoint devicePts[2]; | 390 SkPoint devicePts[2]; |
389 vm.mapPoints(devicePts, ptsRot, 2); | 391 vm.mapPoints(devicePts, ptsRot, 2); |
390 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); | 392 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]); |
391 if (hasCap) { | 393 if (hasCap) { |
392 lineLength += 2.f * halfDevStroke; | 394 lineLength += 2.f * halfDevStroke; |
393 } | 395 } |
394 | 396 |
395 SkRect bounds; | 397 SkRect bounds; |
396 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); | 398 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY); |
397 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); | 399 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke); |
398 setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, d
evBloat, | 400 if (fullDash) { |
399 lineLength, halfDevStroke); | 401 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic
es()); |
| 402 setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffse
t, devBloat, |
| 403 lineLength, halfDevStroke); |
| 404 } else { |
| 405 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
| 406 setup_dashed_rect_pos(bounds, curVIdx, combinedMatrix, verts); |
| 407 } |
400 curVIdx += 4; | 408 curVIdx += 4; |
401 } | 409 } |
402 | 410 |
403 if (hasStartRect) { | 411 if (hasStartRect) { |
404 SkASSERT(useAA); // so that we know bloatX and bloatY have been set | 412 SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
405 startRect.outset(bloatX, bloatY); | 413 startRect.outset(bloatX, bloatY); |
406 setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset
, devBloat, | 414 if (fullDash) { |
407 devIntervals[0], halfDevStroke); | 415 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic
es()); |
| 416 setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOf
fset, devBloat, |
| 417 devIntervals[0], halfDevStroke); |
| 418 } else { |
| 419 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
| 420 setup_dashed_rect_pos(startRect, curVIdx, combinedMatrix, verts); |
| 421 } |
| 422 |
408 curVIdx += 4; | 423 curVIdx += 4; |
409 } | 424 } |
410 | 425 |
411 if (hasEndRect) { | 426 if (hasEndRect) { |
412 SkASSERT(useAA); // so that we know bloatX and bloatY have been set | 427 SkASSERT(useAA); // so that we know bloatX and bloatY have been set |
413 endRect.outset(bloatX, bloatY); | 428 endRect.outset(bloatX, bloatY); |
414 setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset,
devBloat, | 429 if (fullDash) { |
415 devIntervals[0], halfDevStroke); | 430 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertic
es()); |
| 431 setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffs
et, devBloat, |
| 432 devIntervals[0], halfDevStroke); |
| 433 } else { |
| 434 SkPoint* verts = reinterpret_cast<SkPoint*>(geo.vertices()); |
| 435 setup_dashed_rect_pos(endRect, curVIdx, combinedMatrix, verts); |
| 436 } |
| 437 |
416 } | 438 } |
417 | 439 |
418 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); | 440 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); |
419 target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6)
; | 441 target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6)
; |
420 target->resetIndexSource(); | 442 target->resetIndexSource(); |
421 return true; | 443 return true; |
422 } | 444 } |
423 | 445 |
424 ////////////////////////////////////////////////////////////////////////////// | 446 ////////////////////////////////////////////////////////////////////////////// |
425 | 447 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 switch (cap) { | 872 switch (cap) { |
851 case GrDashingEffect::kRound_DashCap: | 873 case GrDashingEffect::kRound_DashCap: |
852 return DashingCircleEffect::Create(edgeType, info, SkScalarHalf(stro
keWidth)); | 874 return DashingCircleEffect::Create(edgeType, info, SkScalarHalf(stro
keWidth)); |
853 case GrDashingEffect::kNonRound_DashCap: | 875 case GrDashingEffect::kNonRound_DashCap: |
854 return DashingLineEffect::Create(edgeType, info, strokeWidth); | 876 return DashingLineEffect::Create(edgeType, info, strokeWidth); |
855 default: | 877 default: |
856 SkFAIL("Unexpected dashed cap."); | 878 SkFAIL("Unexpected dashed cap."); |
857 } | 879 } |
858 return NULL; | 880 return NULL; |
859 } | 881 } |
OLD | NEW |