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

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

Powered by Google App Engine
This is Rietveld 408576698