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