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