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

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