| 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 |