Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: src/gpu/effects/GrDashingEffect.cpp

Issue 326103002: Use vertex attributes for dash effect in gpu (Closed) Base URL: https://skia.googlesource.com/skia.git@dashPlumb2
Patch Set: Format changes Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/GrDashingEffect.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11
12 #include "effects/GrVertexEffect.h"
10 #include "gl/GrGLEffect.h" 13 #include "gl/GrGLEffect.h"
14 #include "gl/GrGLVertexEffect.h"
11 #include "gl/GrGLSL.h" 15 #include "gl/GrGLSL.h"
12 #include "GrContext.h" 16 #include "GrContext.h"
13 #include "GrCoordTransform.h" 17 #include "GrCoordTransform.h"
18 #include "GrDrawTarget.h"
14 #include "GrDrawTargetCaps.h" 19 #include "GrDrawTargetCaps.h"
15 #include "GrEffect.h" 20 #include "GrEffect.h"
21 #include "GrGpu.h"
22 #include "GrStrokeInfo.h"
16 #include "GrTBackendEffectFactory.h" 23 #include "GrTBackendEffectFactory.h"
17 #include "SkGr.h" 24 #include "SkGr.h"
18 25
19 /////////////////////////////////////////////////////////////////////////////// 26 ///////////////////////////////////////////////////////////////////////////////
20 27
28 // Returns whether or not the gpu can fast path the dash line effect.
29 static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeI nfo,
30 const GrDrawTarget& target, const SkMatrix& viewM atrix) {
31 if (target.getDrawState().getRenderTarget()->isMultisampled()) {
32 return false;
33 }
34
35 // Pts must be either horizontal or vertical in src space
36 if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) {
37 return false;
38 }
39
40 // May be able to relax this to include skew. As of not cannot do perspectiv e
bsalomon 2014/06/11 13:24:44 not->now?
41 // because of the non uniform scaling of bloating a rect
42 if (!viewMatrix.preservesRightAngles()) {
43 return false;
44 }
45
46 if (!strokeInfo.isDashed() || 2 != strokeInfo.dashCount()) {
47 return false;
48 }
49
50 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
51 // Current we do don't handle Round or Square cap dashes
52 if (SkPaint::kRound_Cap == cap) {
53 return false;
54 }
55
56 return true;
57 }
58
59 namespace {
60
61 struct DashLineVertex {
62 SkPoint fPos;
63 SkPoint fDashPos;
64 };
65
66 extern const GrVertexAttrib gDashLineVertexAttribs[] = {
67 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing },
68 { kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBindin g },
69 };
70
71 };
21 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale, 72 static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale,
22 const SkMatrix& viewMatrix, const SkPoint pts[2]) { 73 const SkMatrix& viewMatrix, const SkPoint pts[2]) {
23 SkVector vecSrc = pts[1] - pts[0]; 74 SkVector vecSrc = pts[1] - pts[0];
24 SkScalar magSrc = vecSrc.length(); 75 SkScalar magSrc = vecSrc.length();
25 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0; 76 SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0;
26 vecSrc.scale(invSrc); 77 vecSrc.scale(invSrc);
27 78
28 SkVector vecSrcPerp; 79 SkVector vecSrcPerp;
29 vecSrc.rotateCW(&vecSrcPerp); 80 vecSrc.rotateCW(&vecSrcPerp);
30 viewMatrix.mapVectors(&vecSrc, 1); 81 viewMatrix.mapVectors(&vecSrc, 1);
(...skipping 24 matching lines...) Expand all
55 // Assumes phase < sum of all intervals 106 // Assumes phase < sum of all intervals
56 static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) { 107 static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) {
57 SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]); 108 SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]);
58 if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) { 109 if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) {
59 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; 110 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
60 return srcIntervalLen - info.fPhase; 111 return srcIntervalLen - info.fPhase;
61 } 112 }
62 return 0; 113 return 0;
63 } 114 }
64 115
65 static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk Point pts[2], SkScalar* endingInt) { 116 static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const Sk Point pts[2],
117 SkScalar phase, SkScalar* endingInt) {
66 if (pts[1].fX <= pts[0].fX) { 118 if (pts[1].fX <= pts[0].fX) {
67 return 0; 119 return 0;
68 } 120 }
69 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1]; 121 SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
70 SkScalar totalLen = pts[1].fX - pts[0].fX; 122 SkScalar totalLen = pts[1].fX - pts[0].fX;
71 SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen); 123 SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen);
72 SkScalar numFullIntervals = SkScalarFloorToScalar(temp); 124 SkScalar numFullIntervals = SkScalarFloorToScalar(temp);
73 *endingInt = totalLen - numFullIntervals * srcIntervalLen + info.fPhase; 125 *endingInt = totalLen - numFullIntervals * srcIntervalLen + phase;
74 temp = SkScalarDiv(*endingInt, srcIntervalLen); 126 temp = SkScalarDiv(*endingInt, srcIntervalLen);
75 *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen; 127 *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen;
76 if (0 == *endingInt) { 128 if (0 == *endingInt) {
77 *endingInt = srcIntervalLen; 129 *endingInt = srcIntervalLen;
78 } 130 }
79 if (*endingInt > info.fIntervals[0]) { 131 if (*endingInt > info.fIntervals[0]) {
80 if (0 == info.fIntervals[0]) { 132 if (0 == info.fIntervals[0]) {
81 *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps) 133 *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps)
82 } 134 }
83 return *endingInt - info.fIntervals[0]; 135 return *endingInt - info.fIntervals[0];
84 } 136 }
85 return 0; 137 return 0;
86 } 138 }
87 139
88 140 static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx , const SkMatrix& matrix,
89 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const SkPaint& paint, G rContext* context) { 141 SkScalar offset, SkScalar bloat, SkScalar len, SkScalar s troke) {
90 if (context->getRenderTarget()->isMultisampled()) { 142
143 SkScalar startDashX = offset - bloat;
144 SkScalar endDashX = offset + len + bloat;
145 SkScalar startDashY = -stroke - bloat;
146 SkScalar endDashY = stroke + bloat;
147 verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY);
148 verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY);
149 verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY);
150 verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY);
151
152 verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop);
153 verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom);
154 verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom);
155 verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop);
156
157 matrix.mapPoints(&verts[idx].fPos, 1);
bsalomon 2014/06/11 13:24:44 Not sure if it's clearer, but there is a mapPoints
158 matrix.mapPoints(&verts[idx + 1].fPos, 1);
159 matrix.mapPoints(&verts[idx + 2].fPos, 1);
160 matrix.mapPoints(&verts[idx + 3].fPos, 1);
161 }
162
163
164 bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
165 const GrStrokeInfo& strokeInfo, GrGpu* gpu,
166 GrDrawTarget* target, const SkMatrix& vm) {
167
168 if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) {
91 return false; 169 return false;
92 } 170 }
93 171
94 const SkMatrix& viewMatrix = context->getMatrix(); 172 const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
95 if (!viewMatrix.preservesRightAngles()) { 173
96 return false; 174 SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
97 } 175
98 176 SkScalar srcStrokeWidth = strokeInfo.getStrokeRec().getWidth();
99 const SkPathEffect* pe = paint.getPathEffect();
100 SkPathEffect::DashInfo info;
101 SkPathEffect::DashType dashType = pe->asADash(&info);
102 // Must be a dash effect with 2 intervals (1 on and 1 off)
103 if (SkPathEffect::kDash_DashType != dashType || 2 != info.fCount) {
104 return false;
105 }
106
107 SkPaint::Cap cap = paint.getStrokeCap();
108 // Current we do don't handle Round or Square cap dashes
109 if (SkPaint::kRound_Cap == cap) {
110 return false;
111 }
112
113 SkScalar srcStrokeWidth = paint.getStrokeWidth();
114
115 // Get all info about the dash effect
116 SkAutoTArray<SkScalar> intervals(info.fCount);
117 info.fIntervals = intervals.get();
118 pe->asADash(&info);
119 177
120 // the phase should be normalized to be [0, sum of all intervals) 178 // the phase should be normalized to be [0, sum of all intervals)
121 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv als[1]); 179 SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fInterv als[1]);
122 180
123 SkMatrix coordTrans; 181 SkScalar srcPhase = info.fPhase;
124 182
125 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[ 1].fX 183 // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[ 1].fX
126 SkMatrix srcRotInv; 184 SkMatrix srcRotInv;
127 SkPoint ptsRot[2]; 185 SkPoint ptsRot[2];
128 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) { 186 if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) {
129 align_to_x_axis(pts, &coordTrans, ptsRot); 187 SkMatrix rotMatrix;
130 if(!coordTrans.invert(&srcRotInv)) { 188 align_to_x_axis(pts, &rotMatrix, ptsRot);
189 if(!rotMatrix.invert(&srcRotInv)) {
190 GrPrintf("Failed to create invertible rotation matrix!\n");
131 return false; 191 return false;
132 } 192 }
133 } else { 193 } else {
134 coordTrans.reset();
135 srcRotInv.reset(); 194 srcRotInv.reset();
136 memcpy(ptsRot, pts, 2 * sizeof(SkPoint)); 195 memcpy(ptsRot, pts, 2 * sizeof(SkPoint));
137 } 196 }
138 197
139 GrPaint grPaint;
140 SkPaint2GrPaintShader(context, paint, true, &grPaint);
141
142 bool useAA = paint.isAntiAlias(); 198 bool useAA = paint.isAntiAlias();
143 199
144 // Scale corrections of intervals and stroke from view matrix 200 // Scale corrections of intervals and stroke from view matrix
145 SkScalar parallelScale; 201 SkScalar parallelScale;
146 SkScalar perpScale; 202 SkScalar perpScale;
147 calc_dash_scaling(&parallelScale, &perpScale, viewMatrix, ptsRot); 203 calc_dash_scaling(&parallelScale, &perpScale, vm, ptsRot);
148 204
149 bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth; 205 bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth;
150 206
151 // We always want to at least stroke out half a pixel on each side in device space 207 // We always want to at least stroke out half a pixel on each side in device space
152 // so 0.5f / perpScale gives us this min in src space 208 // so 0.5f / perpScale gives us this min in src space
153 SkScalar halfStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale); 209 SkScalar halfSrcStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale );
154 210
155 SkScalar xStroke; 211 SkScalar strokeAdj;
156 if (!hasCap) { 212 if (!hasCap) {
157 xStroke = 0.f; 213 strokeAdj = 0.f;
158 } else { 214 } else {
159 xStroke = halfStroke; 215 strokeAdj = halfSrcStroke;
160 } 216 }
161 217
218 SkScalar startAdj = 0;
219
220 SkMatrix combinedMatrix = srcRotInv;
221 combinedMatrix.postConcat(vm);
222
223 bool lineDone = false;
224 SkRect startRect;
225 bool hasStartRect = false;
162 // If we are using AA, check to see if we are drawing a partial dash at the start. If so 226 // If we are using AA, check to see if we are drawing a partial dash at the start. If so
163 // draw it separately here and adjust our start point accordingly 227 // draw it separately here and adjust our start point accordingly
164 if (useAA) { 228 if (useAA) {
165 if (info.fPhase > 0 && info.fPhase < info.fIntervals[0]) { 229 if (srcPhase > 0 && srcPhase < info.fIntervals[0]) {
166 SkPoint startPts[2]; 230 SkPoint startPts[2];
167 startPts[0] = ptsRot[0]; 231 startPts[0] = ptsRot[0];
168 startPts[1].fY = startPts[0].fY; 232 startPts[1].fY = startPts[0].fY;
169 startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - i nfo.fPhase, 233 startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - s rcPhase,
170 ptsRot[1].fX); 234 ptsRot[1].fX);
171 SkRect startRect;
172 startRect.set(startPts, 2); 235 startRect.set(startPts, 2);
173 startRect.outset(xStroke, halfStroke); 236 startRect.outset(strokeAdj, halfSrcStroke);
174 context->drawRect(grPaint, startRect, NULL, &srcRotInv); 237
175 238 hasStartRect = true;
176 ptsRot[0].fX += info.fIntervals[0] + info.fIntervals[1] - info.fPhas e; 239 startAdj = info.fIntervals[0] + info.fIntervals[1] - srcPhase;
177 info.fPhase = 0;
178 } 240 }
179 } 241 }
180 242
181 // adjustments for start and end of bounding rect so we only draw dash inter vals 243 // adjustments for start and end of bounding rect so we only draw dash inter vals
182 // contained in the original line segment. 244 // contained in the original line segment.
183 SkScalar startAdj = calc_start_adjustment(info); 245 startAdj += calc_start_adjustment(info);
246 if (startAdj != 0) {
247 ptsRot[0].fX += startAdj;
248 srcPhase = 0;
249 }
184 SkScalar endingInterval = 0; 250 SkScalar endingInterval = 0;
185 SkScalar endAdj = calc_end_adjustment(info, ptsRot, &endingInterval); 251 SkScalar endAdj = calc_end_adjustment(info, ptsRot, srcPhase, &endingInterva l);
186 if (ptsRot[0].fX + startAdj >= ptsRot[1].fX - endAdj) { 252 ptsRot[1].fX -= endAdj;
187 // Nothing left to draw so just return 253 if (ptsRot[0].fX >= ptsRot[1].fX) {
188 return true; 254 lineDone = true;
189 } 255 }
190 256
257 SkRect endRect;
258 bool hasEndRect = false;
191 // If we are using AA, check to see if we are drawing a partial dash at then end. If so 259 // If we are using AA, check to see if we are drawing a partial dash at then end. If so
192 // draw it separately here and adjust our end point accordingly 260 // draw it separately here and adjust our end point accordingly
193 if (useAA) { 261 if (useAA && !lineDone) {
194 // If we adjusted the end then we will not be drawing a partial dash at the end. 262 // If we adjusted the end then we will not be drawing a partial dash at the end.
195 // If we didn't adjust the end point then we just need to make sure the ending 263 // If we didn't adjust the end point then we just need to make sure the ending
196 // dash isn't a full dash 264 // dash isn't a full dash
197 if (0 == endAdj && endingInterval != info.fIntervals[0]) { 265 if (0 == endAdj && endingInterval != info.fIntervals[0]) {
198
199 SkPoint endPts[2]; 266 SkPoint endPts[2];
200 endPts[1] = ptsRot[1]; 267 endPts[1] = ptsRot[1];
201 endPts[0].fY = endPts[1].fY; 268 endPts[0].fY = endPts[1].fY;
202 endPts[0].fX = endPts[1].fX - endingInterval; 269 endPts[0].fX = endPts[1].fX - endingInterval;
203 270
204 SkRect endRect;
205 endRect.set(endPts, 2); 271 endRect.set(endPts, 2);
206 endRect.outset(xStroke, halfStroke); 272 endRect.outset(strokeAdj, halfSrcStroke);
207 context->drawRect(grPaint, endRect, NULL, &srcRotInv); 273
208 274 hasEndRect = true;
209 ptsRot[1].fX -= endingInterval + info.fIntervals[1]; 275 endAdj = endingInterval + info.fIntervals[1];
276
277 ptsRot[1].fX -= endAdj;
210 if (ptsRot[0].fX >= ptsRot[1].fX) { 278 if (ptsRot[0].fX >= ptsRot[1].fX) {
211 // Nothing left to draw so just return 279 lineDone = true;
212 return true;
213 } 280 }
214 } 281 }
215 } 282 }
216 coordTrans.postConcat(viewMatrix); 283
217 284 if (startAdj != 0) {
218 SkPoint devicePts[2]; 285 srcPhase = 0;
219 viewMatrix.mapPoints(devicePts, ptsRot, 2); 286 }
220 287
221 info.fIntervals[0] *= parallelScale; 288 // Change the dashing info from src space into device space
222 info.fIntervals[1] *= parallelScale; 289 SkScalar devIntervals[2];
223 info.fPhase *= parallelScale; 290 devIntervals[0] = info.fIntervals[0] * parallelScale;
291 devIntervals[1] = info.fIntervals[1] * parallelScale;
292 SkScalar devPhase = srcPhase * parallelScale;
224 SkScalar strokeWidth = srcStrokeWidth * perpScale; 293 SkScalar strokeWidth = srcStrokeWidth * perpScale;
225 294
226 if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) { 295 if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) {
227 strokeWidth = 1.f; 296 strokeWidth = 1.f;
228 } 297 }
229 298
230 // Set up coordTransform for device space transforms 299 SkScalar halfDevStroke = strokeWidth * 0.5f;
231 // We rotate the dashed line such that it is horizontal with the start point at smaller x
232 // then we translate the start point to the origin
233 if (devicePts[0].fY != devicePts[1].fY || devicePts[0].fX > devicePts[1].fX) {
234 SkMatrix rot;
235 align_to_x_axis(devicePts, &rot);
236 coordTrans.postConcat(rot);
237 }
238 coordTrans.postTranslate(-devicePts[0].fX, -devicePts[0].fY);
239 coordTrans.postTranslate(info.fIntervals[1] * 0.5f + info.fPhase, 0);
240 300
241 if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) { 301 if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) {
242 // add cap to on interveal and remove from off interval 302 // add cap to on interveal and remove from off interval
243 info.fIntervals[0] += strokeWidth; 303 devIntervals[0] += strokeWidth;
244 info.fIntervals[1] -= strokeWidth; 304 devIntervals[1] -= strokeWidth;
245 } 305 }
246 306 SkScalar startOffset = devIntervals[1] * 0.5 + devPhase;
247 if (info.fIntervals[1] > 0.f) { 307
308 SkScalar bloatX = useAA ? 0.5f / parallelScale : 0.f;
309 SkScalar bloatY = useAA ? 0.5f / perpScale : 0.f;
310
311 SkScalar devBloat = useAA ? 0.5f : 0.f;
312
313 GrDrawState* drawState = target->drawState();
314 if (devIntervals[1] <= 0.f) {
315 if (useAA) {
316 // Case when we end up drawing a solid AA rect
317 GrAARectRenderer* aaRectRenderer = SkNEW(GrAARectRenderer);
bsalomon 2014/06/11 13:24:44 Hmm... it seems a bit expensive to cons up an obje
318 ptsRot[0].fX -= hasStartRect ? startAdj : 0;
319 ptsRot[1].fX += hasEndRect ? endAdj : 0;
320 SkRect rect;
321 rect.set(ptsRot, 2);
322 rect.outset(strokeAdj, halfSrcStroke);
323 SkRect devRect;
324 combinedMatrix.mapRect(&devRect, rect);
325 aaRectRenderer->fillAARect(gpu, target, rect, combinedMatrix, devRec t, false);
326 aaRectRenderer->unref();
327 return true;
328 }
329 } else {
330 SkPathEffect::DashInfo devInfo;
331 devInfo.fPhase = devPhase;
332 devInfo.fCount = 2;
333 devInfo.fIntervals = devIntervals;
248 GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType : 334 GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType :
249 kFillBW_GrEffectEdgeType; 335 kFillBW_GrEffectEdgeType;
250 grPaint.addCoverageEffect( 336 drawState->addCoverageEffect(
251 GrDashingEffect::Create(edgeType, info, coordTrans, strokeWidth))->u nref(); 337 GrDashingEffect::Create(edgeType, devInfo, strokeWidth), 1)->unref() ;
252 grPaint.setAntiAlias(false); 338 }
253 } 339
254 340 // Set up the vertex data for the line and start/end dashes
255 SkRect rect; 341 drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLine VertexAttribs));
256 bool bloat = useAA && info.fIntervals[1] > 0.f; 342
257 SkScalar bloatX = bloat ? 0.5f / parallelScale : 0.f; 343 int totalRectCnt = 0;
258 SkScalar bloatY = bloat ? 0.5f / perpScale : 0.f; 344
259 ptsRot[0].fX += startAdj; 345 totalRectCnt += !lineDone ? 1 : 0;
260 ptsRot[1].fX -= endAdj; 346 totalRectCnt += hasStartRect ? 1 : 0;
261 if (!hasCap) { 347 totalRectCnt += hasEndRect ? 1 : 0;
262 xStroke = 0.f; 348
263 } else { 349 GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0);
264 xStroke = halfStroke; 350 if (!geo.succeeded()) {
265 } 351 GrPrintf("Failed to get space for vertices!\n");
266 rect.set(ptsRot, 2); 352 return false;
267 rect.outset(bloatX + xStroke, bloatY + halfStroke); 353 }
268 context->drawRect(grPaint, rect, NULL, &srcRotInv); 354
269 355 DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices());
356
357 int curVIdx = 0;
358
359 // Draw interior part of dashed line
360 if (!lineDone) {
361 SkPoint devicePts[2];
362 vm.mapPoints(devicePts, ptsRot, 2);
363 SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
364 if (hasCap) {
365 lineLength += 2.f * halfDevStroke;
366 }
367
368 SkRect bounds;
369 bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY);
370 bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke);
371 setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, d evBloat,
372 lineLength, halfDevStroke);
373 curVIdx += 4;
374 }
375
376 if (hasStartRect) {
377 SkASSERT(useAA); // so that we know bloatX and bloatY have been set
378 startRect.outset(bloatX, bloatY);
379 setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset , devBloat,
380 devIntervals[0], halfDevStroke);
381 curVIdx += 4;
382 }
383
384 if (hasEndRect) {
385 SkASSERT(useAA); // so that we know bloatX and bloatY have been set
386 endRect.outset(bloatX, bloatY);
387 setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat,
388 devIntervals[0], halfDevStroke);
389 }
390
391 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
392 target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6) ;
393 target->resetIndexSource();
270 return true; 394 return true;
271 } 395 }
272 396
273 ////////////////////////////////////////////////////////////////////////////// 397 //////////////////////////////////////////////////////////////////////////////
274 398
275 class GLDashingLineEffect; 399 class GLDashingLineEffect;
276 400
277 class DashingLineEffect : public GrEffect { 401 class DashingLineEffect : public GrVertexEffect {
278 public: 402 public:
279 typedef SkPathEffect::DashInfo DashInfo; 403 typedef SkPathEffect::DashInfo DashInfo;
280 404
281 /** 405 /**
282 * The effect calculates the coverage for the case of a horizontal line in d evice space. 406 * The effect calculates the coverage for the case of a horizontal line in d evice space.
283 * The matrix that is passed in should be able to convert a line in source s pace to a 407 * The matrix that is passed in should be able to convert a line in source s pace to a
284 * horizontal line in device space. Additionally, the coord transform matrix should translate 408 * horizontal line in device space. Additionally, the coord transform matrix should translate
285 * the the start of line to origin, and the shift it along the positive x-ax is by the phase 409 * the the start of line to origin, and the shift it along the positive x-ax is by the phase
286 * and half the off interval. 410 * and half the off interval.
287 */ 411 */
288 static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info, 412 static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info,
289 const SkMatrix& matrix, SkScalar strokeWidth); 413 SkScalar strokeWidth);
290 414
291 virtual ~DashingLineEffect(); 415 virtual ~DashingLineEffect();
292 416
293 static const char* Name() { return "DashingEffect"; } 417 static const char* Name() { return "DashingEffect"; }
294 418
295 GrEffectEdgeType getEdgeType() const { return fEdgeType; } 419 GrEffectEdgeType getEdgeType() const { return fEdgeType; }
296 420
297 const SkRect& getRect() const { return fRect; } 421 const SkRect& getRect() const { return fRect; }
298 422
299 SkScalar getIntervalLength() const { return fIntervalLength; } 423 SkScalar getIntervalLength() const { return fIntervalLength; }
300 424
301 typedef GLDashingLineEffect GLEffect; 425 typedef GLDashingLineEffect GLEffect;
302 426
303 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; 427 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
304 428
305 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 429 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
306 430
307 private: 431 private:
308 DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, const SkM atrix& matrix, 432 DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, SkScalar strokeWidth);
309 SkScalar strokeWidth);
310 433
311 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; 434 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
312 435
313 GrEffectEdgeType fEdgeType; 436 GrEffectEdgeType fEdgeType;
314 GrCoordTransform fCoordTransform;
315 SkRect fRect; 437 SkRect fRect;
316 SkScalar fIntervalLength; 438 SkScalar fIntervalLength;
317 439
318 GR_DECLARE_EFFECT_TEST; 440 GR_DECLARE_EFFECT_TEST;
319 441
320 typedef GrEffect INHERITED; 442 typedef GrEffect INHERITED;
321 }; 443 };
322 444
323 ////////////////////////////////////////////////////////////////////////////// 445 //////////////////////////////////////////////////////////////////////////////
324 446
325 class GLDashingLineEffect : public GrGLEffect { 447 class GLDashingLineEffect : public GrGLVertexEffect {
326 public: 448 public:
327 GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&); 449 GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
328 450
329 virtual void emitCode(GrGLShaderBuilder* builder, 451 virtual void emitCode(GrGLFullShaderBuilder* builder,
330 const GrDrawEffect& drawEffect, 452 const GrDrawEffect& drawEffect,
331 EffectKey key, 453 EffectKey key,
332 const char* outputColor, 454 const char* outputColor,
333 const char* inputColor, 455 const char* inputColor,
334 const TransformedCoordsArray&, 456 const TransformedCoordsArray&,
335 const TextureSamplerArray&) SK_OVERRIDE; 457 const TextureSamplerArray&) SK_OVERRIDE;
336 458
337 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 459 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
338 460
339 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; 461 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
340 462
341 private: 463 private:
342 GrGLUniformManager::UniformHandle fRectUniform; 464 GrGLUniformManager::UniformHandle fRectUniform;
343 GrGLUniformManager::UniformHandle fIntervalUniform; 465 GrGLUniformManager::UniformHandle fIntervalUniform;
344 SkRect fPrevRect; 466 SkRect fPrevRect;
345 SkScalar fPrevIntervalLength; 467 SkScalar fPrevIntervalLength;
346 typedef GrGLEffect INHERITED; 468 typedef GrGLVertexEffect INHERITED;
347 }; 469 };
348 470
349 GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory, 471 GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory,
350 const GrDrawEffect& drawEffect) 472 const GrDrawEffect& drawEffect)
351 : INHERITED (factory) { 473 : INHERITED (factory) {
352 fPrevRect.fLeft = SK_ScalarNaN; 474 fPrevRect.fLeft = SK_ScalarNaN;
353 fPrevIntervalLength = SK_ScalarMax; 475 fPrevIntervalLength = SK_ScalarMax;
354 476
355 } 477 }
356 478
357 void GLDashingLineEffect::emitCode(GrGLShaderBuilder* builder, 479 void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder,
358 const GrDrawEffect& drawEffect, 480 const GrDrawEffect& drawEffect,
359 EffectKey key, 481 EffectKey key,
360 const char* outputColor, 482 const char* outputColor,
361 const char* inputColor, 483 const char* inputColor,
362 const TransformedCoordsArray& coords, 484 const TransformedCoordsArray&,
363 const TextureSamplerArray& samplers) { 485 const TextureSamplerArray& samplers) {
364 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); 486 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
365 const char *rectName; 487 const char *rectName;
366 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot tom - 0.5), 488 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bot tom - 0.5),
367 // respectively. 489 // respectively.
368 fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 490 fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
369 kVec4f_GrSLType, 491 kVec4f_GrSLType,
370 "rect", 492 "rect",
371 &rectName); 493 &rectName);
372 const char *intervalName; 494 const char *intervalName;
373 // The interval uniform's refers to the total length of the interval (on + o ff) 495 // The interval uniform's refers to the total length of the interval (on + o ff)
374 fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty, 496 fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty,
375 kFloat_GrSLType, 497 kFloat_GrSLType,
376 "interval", 498 "interval",
377 &intervalName); 499 &intervalName);
500
501 const char *vsCoordName, *fsCoordName;
502 builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
503 const SkString* attr0Name =
504 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
505 builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
506
378 // transforms all points so that we can compare them to our test rect 507 // transforms all points so that we can compare them to our test rect
379 builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n ", 508 builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n ",
380 coords[0].c_str(), coords[0].c_str(), intervalName, i ntervalName); 509 fsCoordName, fsCoordName, intervalName, intervalName) ;
381 builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", coords[0].c_str()); 510 builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
382 if (GrEffectEdgeTypeIsAA(de.getEdgeType())) { 511 if (GrEffectEdgeTypeIsAA(de.getEdgeType())) {
383 // The amount of coverage removed in x and y by the edges is computed as a pair of negative 512 // The amount of coverage removed in x and y by the edges is computed as a pair of negative
384 // numbers, xSub and ySub. 513 // numbers, xSub and ySub.
385 builder->fsCodeAppend("\t\tfloat xSub, ySub;\n"); 514 builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
386 builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n" , rectName); 515 builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n" , rectName);
387 builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n ", rectName); 516 builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n ", rectName);
388 builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n" , rectName); 517 builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n" , rectName);
389 builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n ", rectName); 518 builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n ", rectName);
390 // Now compute coverage in x and y and multiply them to get the fraction of the pixel 519 // Now compute coverage in x and y and multiply them to get the fraction of the pixel
391 // covered. 520 // covered.
(...skipping 23 matching lines...) Expand all
415 544
416 GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect , 545 GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect ,
417 const GrGLCaps&) { 546 const GrGLCaps&) {
418 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>(); 547 const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
419 return de.getEdgeType(); 548 return de.getEdgeType();
420 } 549 }
421 550
422 ////////////////////////////////////////////////////////////////////////////// 551 //////////////////////////////////////////////////////////////////////////////
423 552
424 GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo & info, 553 GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo & info,
425 const SkMatrix& matrix, SkScalar strokeWidt h) { 554 SkScalar strokeWidth) {
426 if (info.fCount != 2) { 555 if (info.fCount != 2) {
427 return NULL; 556 return NULL;
428 } 557 }
429 558
430 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect, 559 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect,
431 (edgeType, info, matrix, s trokeWidth)))); 560 (edgeType, info, strokeWid th))));
432 } 561 }
433 562
434 DashingLineEffect::~DashingLineEffect() {} 563 DashingLineEffect::~DashingLineEffect() {}
435 564
436 void DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* val idFlags) const { 565 void DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* val idFlags) const {
437 *validFlags = 0; 566 *validFlags = 0;
438 } 567 }
439 568
440 const GrBackendEffectFactory& DashingLineEffect::getFactory() const { 569 const GrBackendEffectFactory& DashingLineEffect::getFactory() const {
441 return GrTBackendEffectFactory<DashingLineEffect>::getInstance(); 570 return GrTBackendEffectFactory<DashingLineEffect>::getInstance();
442 } 571 }
443 572
444 DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, 573 DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info,
445 const SkMatrix& matrix, SkScalar strokeWidth) 574 SkScalar strokeWidth)
446 : fEdgeType(edgeType) 575 : fEdgeType(edgeType) {
447 , fCoordTransform(kLocal_GrCoordSet, matrix) {
448 SkScalar onLen = info.fIntervals[0]; 576 SkScalar onLen = info.fIntervals[0];
449 SkScalar offLen = info.fIntervals[1]; 577 SkScalar offLen = info.fIntervals[1];
450 SkScalar halfOffLen = SkScalarHalf(offLen); 578 SkScalar halfOffLen = SkScalarHalf(offLen);
451 SkScalar halfStroke = SkScalarHalf(strokeWidth); 579 SkScalar halfStroke = SkScalarHalf(strokeWidth);
452 fIntervalLength = onLen + offLen; 580 fIntervalLength = onLen + offLen;
453 fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke); 581 fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke);
454 582
455 addCoordTransform(&fCoordTransform); 583 this->addVertexAttrib(kVec2f_GrSLType);
456 } 584 }
457 585
458 bool DashingLineEffect::onIsEqual(const GrEffect& other) const { 586 bool DashingLineEffect::onIsEqual(const GrEffect& other) const {
459 const DashingLineEffect& de = CastEffect<DashingLineEffect>(other); 587 const DashingLineEffect& de = CastEffect<DashingLineEffect>(other);
460 return (fEdgeType == de.fEdgeType && 588 return (fEdgeType == de.fEdgeType &&
461 fCoordTransform == de.fCoordTransform &&
462 fRect == de.fRect && 589 fRect == de.fRect &&
463 fIntervalLength == de.fIntervalLength); 590 fIntervalLength == de.fIntervalLength);
464 } 591 }
465 592
466 GR_DEFINE_EFFECT_TEST(DashingLineEffect); 593 GR_DEFINE_EFFECT_TEST(DashingLineEffect);
467 594
468 GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random, 595 GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random,
469 GrContext*, 596 GrContext*,
470 const GrDrawTargetCaps& caps, 597 const GrDrawTargetCaps& caps,
471 GrTexture*[]) { 598 GrTexture*[]) {
472 GrEffectRef* effect; 599 GrEffectRef* effect;
473 SkMatrix m;
474 m.reset();
475 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessT han( 600 GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessT han(
476 kGrEffectEdgeTypeCnt)); 601 kGrEffectEdgeTypeCnt));
477 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f); 602 SkScalar strokeWidth = random->nextRangeScalar(0, 100.f);
478 DashInfo info; 603 DashInfo info;
479 info.fCount = 2; 604 info.fCount = 2;
480 SkAutoTArray<SkScalar> intervals(info.fCount); 605 SkAutoTArray<SkScalar> intervals(info.fCount);
481 info.fIntervals = intervals.get(); 606 info.fIntervals = intervals.get();
482 info.fIntervals[0] = random->nextRangeScalar(0, 10.f); 607 info.fIntervals[0] = random->nextRangeScalar(0, 10.f);
483 info.fIntervals[1] = random->nextRangeScalar(0, 10.f); 608 info.fIntervals[1] = random->nextRangeScalar(0, 10.f);
484 info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fInterval s[1]); 609 info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fInterval s[1]);
485 610
486 effect = DashingLineEffect::Create(edgeType, info, m, strokeWidth); 611 effect = DashingLineEffect::Create(edgeType, info, strokeWidth);
487 return effect; 612 return effect;
488 } 613 }
489 614
490 ////////////////////////////////////////////////////////////////////////////// 615 //////////////////////////////////////////////////////////////////////////////
491 616
492 GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffe ct::DashInfo& info, 617 GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffe ct::DashInfo& info,
493 const SkMatrix& matrix, SkScalar strokeWidt h) { 618 SkScalar strokeWidth) {
494 return DashingLineEffect::Create(edgeType, info, matrix, strokeWidth); 619 return DashingLineEffect::Create(edgeType, info, strokeWidth);
495 } 620 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrDashingEffect.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698