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

Side by Side Diff: src/gpu/GrRectRenderer.cpp

Issue 2230513004: Re-adding analytical GeoProc for rectangles (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Created 4 years, 4 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/GrRectRenderer.h ('K') | « src/gpu/GrRectRenderer.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
(Empty)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrRectRenderer.h"
9
10 #include "GrBatchFlushState.h"
11 #include "GrBatchTest.h"
12 #include "GrGeometryProcessor.h"
13 #include "GrInvariantOutput.h"
14 #include "GrProcessor.h"
15 #include "GrResourceProvider.h"
16 #include "SkRRect.h"
17 #include "SkStrokeRec.h"
18 #include "batches/GrVertexBatch.h"
19 #include "glsl/GrGLSLFragmentShaderBuilder.h"
20 #include "glsl/GrGLSLGeometryProcessor.h"
21 #include "glsl/GrGLSLProgramDataManager.h"
22 #include "glsl/GrGLSLVarying.h"
23 #include "glsl/GrGLSLVertexShaderBuilder.h"
24 #include "glsl/GrGLSLUniformHandler.h"
25 #include "glsl/GrGLSLUtil.h"
26
27 namespace {
28
29 struct RectVertex {
30 SkPoint fPos;
31 GrColor fColor;
32 SkPoint fCenter;
33 SkVector fDownDir;
34 SkScalar fHalfWidth;
35 SkScalar fHalfHeight;
36 };
37
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////
41
42 /**
43 * The output of this effect is the input color and coverage for an arbitrarily oriented rect. The
44 * rect is specified as:
45 * Center of the rect
46 * Unit vector point down the height of the rect
47 * Half width + 0.5
48 * Half height + 0.5
49 * The center and vector are stored in a vec4 varying ("RectEdge") with the
50 * center in the xy components and the vector in the zw components.
51 * The munged width and height are stored in a vec2 varying ("WidthHeight")
52 * with the width in x and the height in y.
53 */
54 class RectGeometryProcessor : public GrGeometryProcessor {
55 public:
56 RectGeometryProcessor(const SkMatrix& localMatrix) : fLocalMatrix(localMatri x){
57 this->initClassID<RectGeometryProcessor>();
58 fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_G rVertexAttribType,
59 kHigh_GrSLPrecision));
60 fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrV ertexAttribType));
61 fInRectEdge = &this->addVertexAttrib(Attribute("inRectEdge", kVec4f_G rVertexAttribType));
62 fInWidthHeight = &this->addVertexAttrib(Attribute("inWidthHeight",
63 kVec2f_GrVertexAttribT ype));
64 }
65
66 bool implementsDistanceVector() const override { return true; };
67
68 const Attribute* inPosition() const { return fInPosition; }
69 const Attribute* inColor() const { return fInColor; }
70 const Attribute* inRectEdge() const { return fInRectEdge; }
71 const Attribute* inWidthHeight() const { return fInWidthHeight; }
72
73 const SkMatrix& localMatrix() const { return fLocalMatrix; }
74
75 virtual ~RectGeometryProcessor() {}
76
77 const char* name() const override { return "RectEdge"; }
78
79 class GLSLProcessor : public GrGLSLGeometryProcessor {
80 public:
81 GLSLProcessor() {}
82
83 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
84 const RectGeometryProcessor& rgp = args.fGP.cast<RectGeometryProcess or>();
85 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
86 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
87 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
88
89 // emit attributes
90 varyingHandler->emitAttributes(rgp);
91
92 // setup the varying for the position
93 GrGLSLVertToFrag positionVary(kVec2f_GrSLType);
94 varyingHandler->addVarying("Position", &positionVary);
95 vertBuilder->codeAppendf("%s = %s;", positionVary.vsOut(), rgp.inPos ition()->fName);
96
97 // setup the varying for the center point and the unit vector that p oints down the
98 // height of the rect
99 GrGLSLVertToFrag rectEdgeVary(kVec4f_GrSLType);
100 varyingHandler->addVarying("RectEdge", &rectEdgeVary);
101 vertBuilder->codeAppendf("%s = %s;", rectEdgeVary.vsOut(), rgp.inRec tEdge()->fName);
102
103 // setup the varying for the width/2+.5 and height/2+.5
104 GrGLSLVertToFrag widthHeightVary(kVec2f_GrSLType);
105 varyingHandler->addVarying("WidthHeight", &widthHeightVary);
106 vertBuilder->codeAppendf("%s = %s;", widthHeightVary.vsOut(), rgp.in WidthHeight()->fName);
egdaniel 2016/08/12 17:37:06 100 chars
dvonbeck 2016/08/12 18:29:48 Done.
107
108 GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
109
110 // setup pass through color
111 varyingHandler->addPassThroughAttribute(rgp.inColor(), args.fOutputC olor);
112
113 // Setup position
114 this->setupPosition(vertBuilder, gpArgs, rgp.inPosition()->fName);
115
116 // emit transforms
117 this->emitTransforms(vertBuilder,
118 varyingHandler,
119 uniformHandler,
120 gpArgs->fPositionVar,
121 rgp.inPosition()->fName,
122 rgp.localMatrix(),
123 args.fTransformsIn,
124 args.fTransformsOut);
125
126 // TODO: compute all these offsets, spans, and scales in the VS
127 fragBuilder->codeAppendf("float insetW = min(1.0, %s.x) - 0.5;", wid thHeightVary.fsIn());
egdaniel 2016/08/12 17:37:06 100 chars
dvonbeck 2016/08/12 18:29:48 Done.
128 fragBuilder->codeAppendf("float insetH = min(1.0, %s.y) - 0.5;", wid thHeightVary.fsIn());
129 fragBuilder->codeAppend("float outset = 0.5;");
130 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0 ). For rects
131 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
132 fragBuilder->codeAppend("float spanW = insetW + outset;");
133 fragBuilder->codeAppend("float spanH = insetH + outset;");
134 // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
135 // value of coverage that is used. In other words it is the coverage that is
136 // used in the interior of the rect after the ramp.
137 fragBuilder->codeAppend("float scaleW = min(1.0, 2.0*insetW/spanW);" );
138 fragBuilder->codeAppend("float scaleH = min(1.0, 2.0*insetH/spanH);" );
139 // Compute the coverage for the rect's width
140 fragBuilder->codeAppendf("vec2 offset = %s.xy - %s.xy;",
141 positionVary.fsIn(), rectEdgeVary.fsIn());
142 fragBuilder->codeAppendf("float perpDot = abs(offset.x * %s.w - offs et.y * %s.z);",
143 rectEdgeVary.fsIn(), rectEdgeVary.fsIn());
144
145 if (args.fDistanceVectorName) {
146 fragBuilder->codeAppendf("float widthDistance = %s.x - perpDot;" ,
147 widthHeightVary.fsIn());
148 }
149
150 fragBuilder->codeAppendf(
151 "float coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1. 0);",
152 widthHeightVary.fsIn());
153 // Compute the coverage for the rect's height and merge with the wid th
154 fragBuilder->codeAppendf("perpDot = abs(dot(offset, %s.zw));",
155 rectEdgeVary.fsIn());
156
157 if (args.fDistanceVectorName) {
158 fragBuilder->codeAppendf("float heightDistance = %s.y - perpDot; ",
159 widthHeightVary.fsIn());
160 }
161
162 fragBuilder->codeAppendf(
163 "coverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);",
164 widthHeightVary.fsIn());
165
166 fragBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverag e);
167
168 if (args.fDistanceVectorName) {
169 fragBuilder->codeAppend( "// Calculating distance vector\n");
170 fragBuilder->codeAppend( "vec2 dvAxis;");
171 fragBuilder->codeAppend( "float dvLength;");
172
173 fragBuilder->codeAppend( "if (heightDistance < widthDistance) {" );
174 fragBuilder->codeAppendf(" dvAxis = %s.zw;", rectEdgeVary.fsI n());
175 fragBuilder->codeAppend( " dvLength = heightDistance;");
176 fragBuilder->codeAppend( "} else {");
177 fragBuilder->codeAppendf(" dvAxis = vec2(-%s.w, %s.z);",
178 rectEdgeVary.fsIn(), rectEdgeVary.fsIn( ));
179 fragBuilder->codeAppend( " dvLength = widthDistance;");
180 fragBuilder->codeAppend( "}");
181
182 fragBuilder->codeAppend( "float dvSign = sign(dot(offset, dvAxis ));");
183 fragBuilder->codeAppendf("%s = vec3(dvSign * dvAxis, dvLength);" ,
184 args.fDistanceVectorName);
185
186 }
187 }
188
189 static void GenKey(const GrGeometryProcessor& gp,
190 const GrGLSLCaps&,
191 GrProcessorKeyBuilder* b) {
192 b->add32(0x0);
193 }
194
195 void setData(const GrGLSLProgramDataManager& pdman,
196 const GrPrimitiveProcessor& gp) override {}
197
198 void setTransformData(const GrPrimitiveProcessor& primProc,
199 const GrGLSLProgramDataManager& pdman,
200 int index,
201 const SkTArray<const GrCoordTransform*, true>& tra nsforms) override {
202 this->setTransformDataHelper<RectGeometryProcessor>(primProc, pdman, index, transforms);
203 }
204
205 private:
206 typedef GrGLSLGeometryProcessor INHERITED;
207 };
208
209 void getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override {
210 GLSLProcessor::GenKey(*this, caps, b);
211 }
212
213 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const overri de {
214 return new GLSLProcessor();
215 }
216
217 private:
218 SkMatrix fLocalMatrix;
219
220 const Attribute* fInPosition;
221 const Attribute* fInColor;
222 const Attribute* fInRectEdge;
223 const Attribute* fInWidthHeight;
224
225 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
226
227 typedef GrGeometryProcessor INHERITED;
228 };
229
230 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(RectGeometryProcessor);
231
232 sk_sp<GrGeometryProcessor> RectGeometryProcessor::TestCreate(GrProcessorTestData * d) {
233 return sk_sp<GrGeometryProcessor>(
234 new RectGeometryProcessor(GrTest::TestMatrix(d->fRandom)));
235 }
236
237 ///////////////////////////////////////////////////////////////////////////////
238
239 class AnalyticRectBatch : public GrVertexBatch {
240 public:
241 DEFINE_BATCH_CLASS_ID
242
243 AnalyticRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& r ect,
244 const SkRect& croppedRect, const SkRect& bounds)
245 : INHERITED(ClassID())
246 , fViewMatrixIfUsingLocalCoords(viewMatrix) {
247 SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
248 viewMatrix.mapPoints(&center, 1);
249 SkScalar halfWidth = viewMatrix.mapRadius(SkScalarHalf(rect.width()));
250 SkScalar halfHeight = viewMatrix.mapRadius(SkScalarHalf(rect.height()));
251 SkVector downDir = viewMatrix.mapVector(0.0f, 1.0f);
252 downDir.normalize();
253
254 SkRect deviceSpaceCroppedRect = croppedRect;
255 viewMatrix.mapRect(&deviceSpaceCroppedRect);
256
257 fGeoData.emplace_back(Geometry {color, center, downDir, halfWidth, halfH eight,
258 deviceSpaceCroppedRect});
259
260 this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
261 }
262
263 const char* name() const override { return "AnalyticRectBatch"; }
264
265 SkString dumpInfo() const override {
266 SkString string;
267 for (int i = 0; i < fGeoData.count(); ++i) {
268 string.appendf("Color: 0x%08x Rect [C:(%.2f, %.2f) D:<%.2f,%.3f> W/2 :%.2f H/2:%.2f]\n",
269 fGeoData[i].fColor,
270 fGeoData[i].fCenter.x(), fGeoData[i].fCenter.y(),
271 fGeoData[i].fDownDir.x(), fGeoData[i].fDownDir.y(),
272 fGeoData[i].fHalfWidth,
273 fGeoData[i].fHalfHeight);
274 }
275 string.append(INHERITED::dumpInfo());
276 return string;
277 }
278
279 void computePipelineOptimizations(GrInitInvariantOutput* color,
280 GrInitInvariantOutput* coverage,
281 GrBatchToXPOverrides* overrides) const ove rride {
282 // When this is called on a batch, there is only one geometry bundle
283 color->setKnownFourComponents(fGeoData[0].fColor);
284 coverage->setUnknownSingleComponent();
285 }
286
287 private:
288 void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
289 // Handle any overrides that affect our GP.
290 overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
291 if (!overrides.readsLocalCoords()) {
292 fViewMatrixIfUsingLocalCoords.reset();
293 }
294 }
295
296 void onPrepareDraws(Target* target) const override {
297 SkMatrix localMatrix;
298 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) {
299 return;
300 }
301
302 // Setup geometry processor
303 SkAutoTUnref<GrGeometryProcessor> gp(new RectGeometryProcessor(localMatr ix));
304
305 int instanceCount = fGeoData.count();
306 size_t vertexStride = gp->getVertexStride();
307 SkASSERT(vertexStride == sizeof(RectVertex));
308 QuadHelper helper;
309 RectVertex* verts = reinterpret_cast<RectVertex*>(helper.init(target, ve rtexStride,
310 instanceCo unt));
311 if (!verts) {
312 return;
313 }
314
315 for (int i = 0; i < instanceCount; i++) {
316 const Geometry& geom = fGeoData[i];
317
318 GrColor color = geom.fColor;
319 SkPoint center = geom.fCenter;
320 SkVector downDir = geom.fDownDir;
321 SkScalar halfWidth = geom.fHalfWidth;
322 SkScalar halfHeight = geom.fHalfHeight;
323 SkRect croppedRect = geom.fCroppedRect;
324
325 SkVector rightDir;
326 downDir.rotateCCW(&rightDir);
327
328 verts[0].fPos = {croppedRect.fLeft, croppedRect.fTop};
329 verts[0].fColor = color;
330 verts[0].fCenter = center;
331 verts[0].fDownDir = downDir;
332 verts[0].fHalfWidth = halfWidth;
333 verts[0].fHalfHeight = halfHeight;
334
335 verts[1].fPos = {croppedRect.fRight, croppedRect.fTop};
336 verts[1].fColor = color;
337 verts[1].fCenter = center;
338 verts[1].fDownDir = downDir;
339 verts[1].fHalfWidth = halfWidth;
340 verts[1].fHalfHeight = halfHeight;
341
342 verts[2].fPos = {croppedRect.fRight, croppedRect.fBottom};
343 verts[2].fColor = color;
344 verts[2].fCenter = center;
345 verts[2].fDownDir = downDir;
346 verts[2].fHalfWidth = halfWidth;
347 verts[2].fHalfHeight = halfHeight;
348
349 verts[3].fPos = {croppedRect.fLeft, croppedRect.fBottom};
350 verts[3].fColor = color;
351 verts[3].fCenter = center;
352 verts[3].fDownDir = downDir;
353 verts[3].fHalfWidth = halfWidth;
354 verts[3].fHalfHeight = halfHeight;
355
356 verts += kVerticesPerQuad;
357 }
358 helper.recordDraw(target, gp);
359 }
360
361 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
362 AnalyticRectBatch* that = t->cast<AnalyticRectBatch>();
363 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
364 that->bounds(), caps)) {
365 return false;
366 }
367
368 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) {
369 return false;
370 }
371
372 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
373 this->joinBounds(*that);
374 return true;
375 }
376
377 struct Geometry {
378 GrColor fColor;
379 SkPoint fCenter;
380 SkVector fDownDir;
381 SkScalar fHalfWidth;
382 SkScalar fHalfHeight;
383 SkRect fCroppedRect;
384 };
385
386 SkMatrix fViewMatrixIfUsingLocalCoords;
387 SkSTArray<1, Geometry, true> fGeoData;
388
389 typedef GrVertexBatch INHERITED;
390 };
391
392 GrDrawBatch* GrRectRenderer::CreateAnalyticRectBatch(GrColor color,
393 const SkMatrix& viewMatrix,
394 const SkRect& rect,
395 const SkRect& croppedRect,
396 const SkRect& bounds) {
397 return new AnalyticRectBatch(color, viewMatrix, rect, croppedRect, bounds);
398 }
399
400 #ifdef GR_TEST_UTILS
401
402 DRAW_BATCH_TEST_DEFINE(AnalyticRectBatch) {
403 SkMatrix viewMatrix = GrTest::TestMatrix(random);
404 GrColor color = GrRandomColor(random);
405 SkRect rect = GrTest::TestSquare(random);
406 SkRect croppedRect = GrTest::TestSquare(random);
407 SkRect bounds = GrTest::TestSquare(random);
408 return new AnalyticRectBatch(color, viewMatrix, rect, croppedRect, bounds);
409 }
410
411 #endif
OLDNEW
« src/gpu/GrRectRenderer.h ('K') | « src/gpu/GrRectRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698