blob: 1a144d9b7591b19f0e0ce3aa4bed289105e6696e [file] [log] [blame]
robertphillips@google.comf6747b02012-06-12 00:32:28 +00001/*
2 * Copyright 2012 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 "GrAARectRenderer.h"
robertphillips@google.comf6747b02012-06-12 00:32:28 +00009#include "GrGpu.h"
joshualitt47bb3822014-10-07 16:43:25 -070010#include "gl/builders/GrGLProgramBuilder.h"
joshualittb0a8a372014-09-23 09:50:21 -070011#include "gl/GrGLProcessor.h"
joshualitt249af152014-09-15 11:41:13 -070012#include "gl/GrGLGeometryProcessor.h"
joshualittb0a8a372014-09-23 09:50:21 -070013#include "GrTBackendProcessorFactory.h"
robertphillips@google.com908aed82013-05-28 13:16:20 +000014#include "SkColorPriv.h"
joshualittb0a8a372014-09-23 09:50:21 -070015#include "GrGeometryProcessor.h"
robertphillips@google.comf6747b02012-06-12 00:32:28 +000016
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000017///////////////////////////////////////////////////////////////////////////////
18class GrGLAlignedRectEffect;
19
20// Axis Aligned special case
joshualitt249af152014-09-15 11:41:13 -070021class GrAlignedRectEffect : public GrGeometryProcessor {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000022public:
joshualittb0a8a372014-09-23 09:50:21 -070023 static GrGeometryProcessor* Create() {
24 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gAlignedRectEffect, GrAlignedRectEffect, ());
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000025 gAlignedRectEffect->ref();
26 return gAlignedRectEffect;
27 }
28
29 virtual ~GrAlignedRectEffect() {}
30
31 static const char* Name() { return "AlignedRectEdge"; }
32
joshualitt249af152014-09-15 11:41:13 -070033 const GrShaderVar& inRect() const { return fInRect; }
34
joshualittb0a8a372014-09-23 09:50:21 -070035 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE {
36 return GrTBackendGeometryProcessorFactory<GrAlignedRectEffect>::getInstance();
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000037 }
38
joshualittb0a8a372014-09-23 09:50:21 -070039 class GLProcessor : public GrGLGeometryProcessor {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000040 public:
joshualittb0a8a372014-09-23 09:50:21 -070041 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000042 : INHERITED (factory) {}
43
joshualitt47bb3822014-10-07 16:43:25 -070044 virtual void emitCode(GrGLGPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070045 const GrGeometryProcessor& geometryProcessor,
46 const GrProcessorKey& key,
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000047 const char* outputColor,
48 const char* inputColor,
bsalomon@google.com77af6802013-10-02 13:04:56 +000049 const TransformedCoordsArray&,
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000050 const TextureSamplerArray& samplers) SK_OVERRIDE {
51 // setup the varying for the Axis aligned rect effect
52 // xy -> interpolated offset
53 // zw -> w/2+0.5, h/2+0.5
54 const char *vsRectName, *fsRectName;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +000055 builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000056
joshualittb0a8a372014-09-23 09:50:21 -070057 const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
joshualitt47bb3822014-10-07 16:43:25 -070058 GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
joshualitt249af152014-09-15 11:41:13 -070059 vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
joshualitt30ba4362014-08-21 20:18:45 -070060
joshualitt47bb3822014-10-07 16:43:25 -070061 GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
commit-bot@chromium.org99e0d082013-06-14 14:58:50 +000062 // TODO: compute all these offsets, spans, and scales in the VS
joshualitt30ba4362014-08-21 20:18:45 -070063 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
64 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
65 fsBuilder->codeAppend("\tfloat outset = 0.5;\n");
commit-bot@chromium.org99e0d082013-06-14 14:58:50 +000066 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
67 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
joshualitt30ba4362014-08-21 20:18:45 -070068 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n");
69 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n");
commit-bot@chromium.org99e0d082013-06-14 14:58:50 +000070 // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
71 // value of coverage that is used. In other words it is the coverage that is
72 // used in the interior of the rect after the ramp.
joshualitt30ba4362014-08-21 20:18:45 -070073 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n");
74 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n");
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000075
76 // Compute the coverage for the rect's width
joshualitt30ba4362014-08-21 20:18:45 -070077 fsBuilder->codeAppendf(
commit-bot@chromium.org99e0d082013-06-14 14:58:50 +000078 "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", fsRectName,
79 fsRectName);
80 // Compute the coverage for the rect's height and merge with the width
joshualitt30ba4362014-08-21 20:18:45 -070081 fsBuilder->codeAppendf(
egdaniel@google.comf1d7de72013-06-14 19:25:53 +000082 "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n",
83 fsRectName, fsRectName);
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000084
commit-bot@chromium.org824c3462013-10-10 06:30:18 +000085
joshualitt30ba4362014-08-21 20:18:45 -070086 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000087 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000088 }
89
joshualittb0a8a372014-09-23 09:50:21 -070090 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000091
joshualittb0a8a372014-09-23 09:50:21 -070092 virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {}
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000093
94 private:
joshualitt249af152014-09-15 11:41:13 -070095 typedef GrGLGeometryProcessor INHERITED;
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +000096 };
97
98
99private:
joshualitt249af152014-09-15 11:41:13 -0700100 GrAlignedRectEffect()
101 : fInRect(this->addVertexAttrib(GrShaderVar("inRect",
102 kVec4f_GrSLType,
103 GrShaderVar::kAttribute_TypeModifier))) {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000104 }
105
joshualitt249af152014-09-15 11:41:13 -0700106 const GrShaderVar& fInRect;
107
joshualittb0a8a372014-09-23 09:50:21 -0700108 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000109
egdaniel1a8ecdf2014-10-03 06:24:12 -0700110 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE {
egdanielccb2e382014-10-13 12:53:46 -0700111 inout->mulByUnknownAlpha();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700112 }
113
joshualittb0a8a372014-09-23 09:50:21 -0700114 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000115
joshualitt249af152014-09-15 11:41:13 -0700116 typedef GrGeometryProcessor INHERITED;
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000117};
118
119
joshualittb0a8a372014-09-23 09:50:21 -0700120GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrAlignedRectEffect);
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000121
joshualittb0a8a372014-09-23 09:50:21 -0700122GrGeometryProcessor* GrAlignedRectEffect::TestCreate(SkRandom* random,
123 GrContext* context,
124 const GrDrawTargetCaps&,
125 GrTexture* textures[]) {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000126 return GrAlignedRectEffect::Create();
127}
128
129///////////////////////////////////////////////////////////////////////////////
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000130class GrGLRectEffect;
131
132/**
skia.committer@gmail.com07d3a652013-04-10 07:01:15 +0000133 * The output of this effect is a modulation of the input color and coverage
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000134 * for an arbitrarily oriented rect. The rect is specified as:
135 * Center of the rect
136 * Unit vector point down the height of the rect
137 * Half width + 0.5
138 * Half height + 0.5
139 * The center and vector are stored in a vec4 varying ("RectEdge") with the
140 * center in the xy components and the vector in the zw components.
141 * The munged width and height are stored in a vec2 varying ("WidthHeight")
142 * with the width in x and the height in y.
143 */
joshualitt249af152014-09-15 11:41:13 -0700144
145class GrRectEffect : public GrGeometryProcessor {
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000146public:
joshualittb0a8a372014-09-23 09:50:21 -0700147 static GrGeometryProcessor* Create() {
148 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gRectEffect, GrRectEffect, ());
bsalomon@google.comd42aca32013-04-23 15:37:27 +0000149 gRectEffect->ref();
150 return gRectEffect;
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000151 }
152
153 virtual ~GrRectEffect() {}
154
155 static const char* Name() { return "RectEdge"; }
156
joshualitt249af152014-09-15 11:41:13 -0700157 const GrShaderVar& inRectEdge() const { return fInRectEdge; }
158 const GrShaderVar& inWidthHeight() const { return fInWidthHeight; }
159
joshualittb0a8a372014-09-23 09:50:21 -0700160 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE {
161 return GrTBackendGeometryProcessorFactory<GrRectEffect>::getInstance();
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000162 }
163
joshualittb0a8a372014-09-23 09:50:21 -0700164 class GLProcessor : public GrGLGeometryProcessor {
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000165 public:
joshualittb0a8a372014-09-23 09:50:21 -0700166 GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000167 : INHERITED (factory) {}
168
joshualitt47bb3822014-10-07 16:43:25 -0700169 virtual void emitCode(GrGLGPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700170 const GrGeometryProcessor& geometryProcessor,
171 const GrProcessorKey& key,
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000172 const char* outputColor,
173 const char* inputColor,
bsalomon@google.com77af6802013-10-02 13:04:56 +0000174 const TransformedCoordsArray&,
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000175 const TextureSamplerArray& samplers) SK_OVERRIDE {
176 // setup the varying for the center point and the unit vector
177 // that points down the height of the rect
178 const char *vsRectEdgeName, *fsRectEdgeName;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000179 builder->addVarying(kVec4f_GrSLType, "RectEdge",
180 &vsRectEdgeName, &fsRectEdgeName);
joshualitt30ba4362014-08-21 20:18:45 -0700181
joshualittb0a8a372014-09-23 09:50:21 -0700182 const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
joshualitt47bb3822014-10-07 16:43:25 -0700183 GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
joshualitt249af152014-09-15 11:41:13 -0700184 vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000185
186 // setup the varying for width/2+.5 and height/2+.5
187 const char *vsWidthHeightName, *fsWidthHeightName;
commit-bot@chromium.org261dc562013-10-04 15:42:56 +0000188 builder->addVarying(kVec2f_GrSLType, "WidthHeight",
189 &vsWidthHeightName, &fsWidthHeightName);
joshualitt249af152014-09-15 11:41:13 -0700190 vsBuilder->codeAppendf("%s = %s;",
191 vsWidthHeightName,
192 rectEffect.inWidthHeight().c_str());
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000193
joshualitt47bb3822014-10-07 16:43:25 -0700194 GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
egdaniel@google.comf1d7de72013-06-14 19:25:53 +0000195 // TODO: compute all these offsets, spans, and scales in the VS
joshualitt30ba4362014-08-21 20:18:45 -0700196 fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
197 fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
198 fsBuilder->codeAppend("\tfloat outset = 0.5;\n");
egdaniel@google.comf1d7de72013-06-14 19:25:53 +0000199 // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
200 // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
joshualitt30ba4362014-08-21 20:18:45 -0700201 fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n");
202 fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n");
egdaniel@google.comf1d7de72013-06-14 19:25:53 +0000203 // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
204 // value of coverage that is used. In other words it is the coverage that is
205 // used in the interior of the rect after the ramp.
joshualitt30ba4362014-08-21 20:18:45 -0700206 fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n");
207 fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n");
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000208
209 // Compute the coverage for the rect's width
joshualitt30ba4362014-08-21 20:18:45 -0700210 fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n",
211 fsBuilder->fragmentPosition(), fsRectEdgeName);
212 fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n",
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000213 fsRectEdgeName, fsRectEdgeName);
joshualitt30ba4362014-08-21 20:18:45 -0700214 fsBuilder->codeAppendf(
egdaniel@google.comf1d7de72013-06-14 19:25:53 +0000215 "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n",
216 fsWidthHeightName);
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000217
218 // Compute the coverage for the rect's height and merge with the width
joshualitt30ba4362014-08-21 20:18:45 -0700219 fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n",
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000220 fsRectEdgeName);
joshualitt30ba4362014-08-21 20:18:45 -0700221 fsBuilder->codeAppendf(
egdaniel@google.comf1d7de72013-06-14 19:25:53 +0000222 "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n",
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000223 fsWidthHeightName);
224
commit-bot@chromium.org824c3462013-10-10 06:30:18 +0000225
joshualitt30ba4362014-08-21 20:18:45 -0700226 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000227 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000228 }
229
joshualittb0a8a372014-09-23 09:50:21 -0700230 static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000231
joshualittb0a8a372014-09-23 09:50:21 -0700232 virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {}
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000233
234 private:
joshualitt249af152014-09-15 11:41:13 -0700235 typedef GrGLGeometryProcessor INHERITED;
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000236 };
237
238
joshualitt249af152014-09-15 11:41:13 -0700239
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000240private:
joshualitt249af152014-09-15 11:41:13 -0700241 GrRectEffect()
242 : fInRectEdge(this->addVertexAttrib(GrShaderVar("inRectEdge",
243 kVec4f_GrSLType,
244 GrShaderVar::kAttribute_TypeModifier)))
245 , fInWidthHeight(this->addVertexAttrib(
246 GrShaderVar("inWidthHeight",
247 kVec2f_GrSLType,
248 GrShaderVar::kAttribute_TypeModifier))) {
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +0000249 this->setWillReadFragmentPosition();
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000250 }
251
joshualittb0a8a372014-09-23 09:50:21 -0700252 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000253
egdaniel1a8ecdf2014-10-03 06:24:12 -0700254 virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE {
egdanielccb2e382014-10-13 12:53:46 -0700255 inout->mulByUnknownAlpha();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700256 }
257
joshualitt249af152014-09-15 11:41:13 -0700258 const GrShaderVar& fInRectEdge;
259 const GrShaderVar& fInWidthHeight;
260
joshualittb0a8a372014-09-23 09:50:21 -0700261 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000262
joshualitt249af152014-09-15 11:41:13 -0700263 typedef GrGeometryProcessor INHERITED;
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000264};
265
266
joshualittb0a8a372014-09-23 09:50:21 -0700267GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRectEffect);
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000268
joshualittb0a8a372014-09-23 09:50:21 -0700269GrGeometryProcessor* GrRectEffect::TestCreate(SkRandom* random,
270 GrContext* context,
271 const GrDrawTargetCaps&,
272 GrTexture* textures[]) {
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000273 return GrRectEffect::Create();
274}
275
276///////////////////////////////////////////////////////////////////////////////
277
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000278namespace {
bsalomon9c0822a2014-08-11 11:07:48 -0700279extern const GrVertexAttrib gAARectAttribs[] = {
280 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
281 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
282 {kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
robertphillips@google.com42903302013-04-20 12:26:07 +0000283};
284
bsalomonc30aaa02014-08-13 07:15:29 -0700285// Should the coverage be multiplied into the color attrib or use a separate attrib.
286enum CoverageAttribType {
287 kUseColor_CoverageAttribType,
288 kUseCoverage_CoverageAttribType,
289};
290}
291
292static CoverageAttribType set_rect_attribs(GrDrawState* drawState) {
293 if (drawState->canTweakAlphaForCoverage()) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700294 drawState->setVertexAttribs<gAARectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor));
bsalomonc30aaa02014-08-13 07:15:29 -0700295 return kUseColor_CoverageAttribType;
296 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700297 drawState->setVertexAttribs<gAARectAttribs>(3, sizeof(SkPoint) + 2 * sizeof(SkColor));
bsalomonc30aaa02014-08-13 07:15:29 -0700298 return kUseCoverage_CoverageAttribType;
299 }
300}
301
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000302static void set_inset_fan(SkPoint* pts, size_t stride,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000303 const SkRect& r, SkScalar dx, SkScalar dy) {
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000304 pts->setRectFan(r.fLeft + dx, r.fTop + dy,
305 r.fRight - dx, r.fBottom - dy, stride);
306}
307
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000308void GrAARectRenderer::reset() {
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000309 SkSafeSetNull(fAAFillRectIndexBuffer);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000310 SkSafeSetNull(fAAMiterStrokeRectIndexBuffer);
311 SkSafeSetNull(fAABevelStrokeRectIndexBuffer);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000312}
313
robertphillips@google.com6d067302012-12-18 21:47:47 +0000314static const uint16_t gFillAARectIdx[] = {
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000315 0, 1, 5, 5, 4, 0,
316 1, 2, 6, 6, 5, 1,
317 2, 3, 7, 7, 6, 2,
318 3, 0, 4, 4, 7, 3,
319 4, 5, 6, 6, 7, 4,
320};
321
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000322static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx);
robertphillips@google.com6d067302012-12-18 21:47:47 +0000323static const int kVertsPerAAFillRect = 8;
324static const int kNumAAFillRectsInIndexBuffer = 256;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000325
326GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
robertphillips@google.com6d067302012-12-18 21:47:47 +0000327 static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect *
328 sizeof(uint16_t) *
329 kNumAAFillRectsInIndexBuffer;
330
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000331 if (NULL == fAAFillRectIndexBuffer) {
robertphillips@google.com6d067302012-12-18 21:47:47 +0000332 fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
bsalomon49f085d2014-09-05 13:34:00 -0700333 if (fAAFillRectIndexBuffer) {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000334 uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->map();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000335 bool useTempData = (NULL == data);
336 if (useTempData) {
337 data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect);
338 }
339 for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) {
340 // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around
341 // the inner rect (for AA) and 2 for the inner rect.
342 int baseIdx = i * kIndicesPerAAFillRect;
343 uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect);
344 for (int j = 0; j < kIndicesPerAAFillRect; ++j) {
345 data[baseIdx+j] = baseVert + gFillAARectIdx[j];
346 }
347 }
348 if (useTempData) {
349 if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000350 SkFAIL("Can't get AA Fill Rect indices into buffer!");
robertphillips@google.com6d067302012-12-18 21:47:47 +0000351 }
352 SkDELETE_ARRAY(data);
353 } else {
commit-bot@chromium.org8341eb72014-05-07 20:51:05 +0000354 fAAFillRectIndexBuffer->unmap();
robertphillips@google.com6d067302012-12-18 21:47:47 +0000355 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000356 }
357 }
robertphillips@google.com6d067302012-12-18 21:47:47 +0000358
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000359 return fAAFillRectIndexBuffer;
360}
361
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000362static const uint16_t gMiterStrokeAARectIdx[] = {
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000363 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
364 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
365 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
366 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
367
368 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
369 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
370 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
371 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
372
373 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
374 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
375 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
376 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
377};
378
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000379/**
380 * As in miter-stroke, index = a + b, and a is the current index, b is the shift
381 * from the first index. The index layout:
382 * outer AA line: 0~3, 4~7
383 * outer edge: 8~11, 12~15
384 * inner edge: 16~19
385 * inner AA line: 20~23
386 * Following comes a bevel-stroke rect and its indices:
387 *
388 * 4 7
skia.committer@gmail.com26144182013-11-07 07:02:19 +0000389 * *********************************
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000390 * * ______________________________ *
391 * * / 12 15 \ *
392 * * / \ *
393 * 0 * |8 16_____________________19 11 | * 3
394 * * | | | | *
395 * * | | **************** | | *
396 * * | | * 20 23 * | | *
397 * * | | * * | | *
398 * * | | * 21 22 * | | *
399 * * | | **************** | | *
400 * * | |____________________| | *
401 * 1 * |9 17 18 10| * 2
skia.committer@gmail.com26144182013-11-07 07:02:19 +0000402 * * \ / *
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000403 * * \13 __________________________14/ *
404 * * *
skia.committer@gmail.com26144182013-11-07 07:02:19 +0000405 * **********************************
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000406 * 5 6
407 */
408static const uint16_t gBevelStrokeAARectIdx[] = {
409 // Draw outer AA, from outer AA line to outer edge, shift is 0.
410 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
411 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
412 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
413 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
414 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
415 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
416 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
417 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
418
419 // Draw the stroke, from outer edge to inner edge, shift is 8.
420 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
421 1 + 8, 5 + 8, 9 + 8,
422 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
423 6 + 8, 2 + 8, 10 + 8,
424 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
425 3 + 8, 7 + 8, 11 + 8,
426 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
427 4 + 8, 0 + 8, 8 + 8,
428
429 // Draw the inner AA, from inner edge to inner AA line, shift is 16.
430 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
431 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
432 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
433 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
434};
435
436int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000437 return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) :
438 SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000439}
440
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000441GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) {
442 if (miterStroke) {
443 if (NULL == fAAMiterStrokeRectIndexBuffer) {
444 fAAMiterStrokeRectIndexBuffer =
445 gpu->createIndexBuffer(sizeof(gMiterStrokeAARectIdx), false);
bsalomon49f085d2014-09-05 13:34:00 -0700446 if (fAAMiterStrokeRectIndexBuffer) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000447#ifdef SK_DEBUG
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000448 bool updated =
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000449#endif
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000450 fAAMiterStrokeRectIndexBuffer->updateData(gMiterStrokeAARectIdx,
451 sizeof(gMiterStrokeAARectIdx));
452 GR_DEBUGASSERT(updated);
453 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000454 }
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000455 return fAAMiterStrokeRectIndexBuffer;
456 } else {
457 if (NULL == fAABevelStrokeRectIndexBuffer) {
458 fAABevelStrokeRectIndexBuffer =
459 gpu->createIndexBuffer(sizeof(gBevelStrokeAARectIdx), false);
bsalomon49f085d2014-09-05 13:34:00 -0700460 if (fAABevelStrokeRectIndexBuffer) {
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000461#ifdef SK_DEBUG
462 bool updated =
463#endif
464 fAABevelStrokeRectIndexBuffer->updateData(gBevelStrokeAARectIdx,
465 sizeof(gBevelStrokeAARectIdx));
466 GR_DEBUGASSERT(updated);
467 }
468 }
469 return fAABevelStrokeRectIndexBuffer;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000470 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000471}
472
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000473void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
474 GrDrawTarget* target,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000475 const SkRect& rect,
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000476 const SkMatrix& combinedMatrix,
bsalomon9c0822a2014-08-11 11:07:48 -0700477 const SkRect& devRect) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000478 GrDrawState* drawState = target->drawState();
479
bsalomon9c0822a2014-08-11 11:07:48 -0700480 GrColor color = drawState->getColor();
481
bsalomonc30aaa02014-08-13 07:15:29 -0700482 CoverageAttribType covAttribType = set_rect_attribs(drawState);
483 if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) {
bsalomon9c0822a2014-08-11 11:07:48 -0700484 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
485 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000486
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000487 GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000488 if (!geo.succeeded()) {
489 GrPrintf("Failed to get space for vertices!\n");
490 return;
491 }
robertphillips@google.com6d067302012-12-18 21:47:47 +0000492
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000493 GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
494 if (NULL == indexBuffer) {
495 GrPrintf("Failed to create index buffer!\n");
496 return;
497 }
498
499 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
egdaniel7b3d5ee2014-08-28 05:41:14 -0700500 size_t vstride = drawState->getVertexStride();
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000501
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000502 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700503 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vstride);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000504
robertphillips@google.com908aed82013-05-28 13:16:20 +0000505 SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
506 inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
507
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000508 if (combinedMatrix.rectStaysRect()) {
robertphillips@google.comafd1cba2013-05-14 19:47:47 +0000509 // Temporarily #if'ed out. We don't want to pass in the devRect but
510 // right now it is computed in GrContext::apply_aa_to_rect and we don't
511 // want to throw away the work
512#if 0
robertphillips@google.com91b71162013-05-10 14:09:54 +0000513 SkRect devRect;
514 combinedMatrix.mapRect(&devRect, rect);
robertphillips@google.comafd1cba2013-05-14 19:47:47 +0000515#endif
robertphillips@google.com91b71162013-05-10 14:09:54 +0000516
egdaniel7b3d5ee2014-08-28 05:41:14 -0700517 set_inset_fan(fan0Pos, vstride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
518 set_inset_fan(fan1Pos, vstride, devRect, inset, inset);
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000519 } else {
520 // compute transformed (1, 0) and (0, 1) vectors
521 SkVector vec[2] = {
522 { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
523 { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] }
524 };
525
526 vec[0].normalize();
527 vec[0].scale(SK_ScalarHalf);
528 vec[1].normalize();
529 vec[1].scale(SK_ScalarHalf);
530
robertphillips@google.com91b71162013-05-10 14:09:54 +0000531 // create the rotated rect
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000532 fan0Pos->setRectFan(rect.fLeft, rect.fTop,
egdaniel7b3d5ee2014-08-28 05:41:14 -0700533 rect.fRight, rect.fBottom, vstride);
534 combinedMatrix.mapPointsWithStride(fan0Pos, vstride, 4);
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000535
robertphillips@google.com91b71162013-05-10 14:09:54 +0000536 // Now create the inset points and then outset the original
537 // rotated points
538
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000539 // TL
egdaniel7b3d5ee2014-08-28 05:41:14 -0700540 *((SkPoint*)((intptr_t)fan1Pos + 0 * vstride)) =
541 *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) + vec[0] + vec[1];
542 *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) -= vec[0] + vec[1];
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000543 // BL
egdaniel7b3d5ee2014-08-28 05:41:14 -0700544 *((SkPoint*)((intptr_t)fan1Pos + 1 * vstride)) =
545 *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) + vec[0] - vec[1];
546 *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) -= vec[0] - vec[1];
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000547 // BR
egdaniel7b3d5ee2014-08-28 05:41:14 -0700548 *((SkPoint*)((intptr_t)fan1Pos + 2 * vstride)) =
549 *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) - vec[0] - vec[1];
550 *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) += vec[0] + vec[1];
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000551 // TR
egdaniel7b3d5ee2014-08-28 05:41:14 -0700552 *((SkPoint*)((intptr_t)fan1Pos + 3 * vstride)) =
553 *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) - vec[0] + vec[1];
554 *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) += vec[0] - vec[1];
robertphillips@google.com4b140b52013-05-02 17:13:13 +0000555 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000556
bsalomon9c0822a2014-08-11 11:07:48 -0700557 // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000558 verts += sizeof(SkPoint);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000559 for (int i = 0; i < 4; ++i) {
bsalomonc30aaa02014-08-13 07:15:29 -0700560 if (kUseCoverage_CoverageAttribType == covAttribType) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700561 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
562 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700563 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700564 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700565 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000566 }
567
robertphillips@google.com908aed82013-05-28 13:16:20 +0000568 int scale;
569 if (inset < SK_ScalarHalf) {
570 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
571 SkASSERT(scale >= 0 && scale <= 255);
572 } else {
573 scale = 0xff;
574 }
575
bsalomon9c0822a2014-08-11 11:07:48 -0700576 GrColor innerCoverage;
bsalomonc30aaa02014-08-13 07:15:29 -0700577 if (kUseCoverage_CoverageAttribType == covAttribType) {
578 innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
579 } else {
580 innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
581 }
egdaniel7b3d5ee2014-08-28 05:41:14 -0700582 verts += 4 * vstride;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000583 for (int i = 0; i < 4; ++i) {
bsalomonc30aaa02014-08-13 07:15:29 -0700584 if (kUseCoverage_CoverageAttribType == covAttribType) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700585 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
586 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage;
bsalomonc30aaa02014-08-13 07:15:29 -0700587 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700588 *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage;
bsalomonc30aaa02014-08-13 07:15:29 -0700589 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000590 }
591
592 target->setIndexSourceToBuffer(indexBuffer);
robertphillips@google.com6d067302012-12-18 21:47:47 +0000593 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
594 kVertsPerAAFillRect,
595 kIndicesPerAAFillRect);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000596 target->resetIndexSource();
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000597}
598
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000599namespace {
600
601// Rotated
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000602struct RectVertex {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000603 SkPoint fPos;
604 SkPoint fCenter;
605 SkPoint fDir;
606 SkPoint fWidthHeight;
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000607};
608
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000609// Rotated
robertphillips@google.com42903302013-04-20 12:26:07 +0000610extern const GrVertexAttrib gAARectVertexAttribs[] = {
611 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
joshualittb0a8a372014-09-23 09:50:21 -0700612 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding },
613 { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }
robertphillips@google.com42903302013-04-20 12:26:07 +0000614};
615
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000616// Axis Aligned
617struct AARectVertex {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000618 SkPoint fPos;
619 SkPoint fOffset;
620 SkPoint fWidthHeight;
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000621};
622
623// Axis Aligned
624extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
625 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
joshualittb0a8a372014-09-23 09:50:21 -0700626 { kVec4f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding },
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000627};
628
robertphillips@google.com42903302013-04-20 12:26:07 +0000629};
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000630
631void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
632 GrDrawTarget* target,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000633 const SkRect& rect,
robertphillips@google.com114eb9e2013-05-10 13:16:13 +0000634 const SkMatrix& combinedMatrix) {
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000635 GrDrawState* drawState = target->drawState();
636
637 SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
638 combinedMatrix.mapPoints(&center, 1);
639
640 // compute transformed (0, 1) vector
641 SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] };
642 dir.normalize();
643
644 // compute transformed (width, 0) and (0, height) vectors
645 SkVector vec[2] = {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000646 { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
647 { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] }
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000648 };
649
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000650 SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf;
651 SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700652 drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs),
653 sizeof(RectVertex));
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000654
655 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
656 if (!geo.succeeded()) {
657 GrPrintf("Failed to get space for vertices!\n");
658 return;
659 }
660
661 RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices());
662
joshualittb0a8a372014-09-23 09:50:21 -0700663 GrGeometryProcessor* gp = GrRectEffect::Create();
664 drawState->setGeometryProcessor(gp)->unref();
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000665
666 for (int i = 0; i < 4; ++i) {
667 verts[i].fCenter = center;
668 verts[i].fDir = dir;
669 verts[i].fWidthHeight.fX = newWidth;
670 verts[i].fWidthHeight.fY = newHeight;
671 }
672
robertphillips@google.com114eb9e2013-05-10 13:16:13 +0000673 SkRect devRect;
674 combinedMatrix.mapRect(&devRect, rect);
675
robertphillips@google.comdf3695e2013-04-09 14:01:44 +0000676 SkRect devBounds = {
677 devRect.fLeft - SK_ScalarHalf,
678 devRect.fTop - SK_ScalarHalf,
679 devRect.fRight + SK_ScalarHalf,
680 devRect.fBottom + SK_ScalarHalf
681 };
682
683 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
684 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
685 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
686 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
687
688 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
689 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
690 target->resetIndexSource();
691}
692
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000693void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
694 GrDrawTarget* target,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000695 const SkRect& rect,
robertphillips@google.com114eb9e2013-05-10 13:16:13 +0000696 const SkMatrix& combinedMatrix) {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000697 GrDrawState* drawState = target->drawState();
698 SkASSERT(combinedMatrix.rectStaysRect());
699
egdaniel7b3d5ee2014-08-28 05:41:14 -0700700 drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs),
701 sizeof(AARectVertex));
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000702
703 GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
704 if (!geo.succeeded()) {
705 GrPrintf("Failed to get space for vertices!\n");
706 return;
707 }
708
709 AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices());
710
joshualittb0a8a372014-09-23 09:50:21 -0700711 GrGeometryProcessor* gp = GrAlignedRectEffect::Create();
712 drawState->setGeometryProcessor(gp)->unref();
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000713
robertphillips@google.com114eb9e2013-05-10 13:16:13 +0000714 SkRect devRect;
715 combinedMatrix.mapRect(&devRect, rect);
716
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000717 SkRect devBounds = {
718 devRect.fLeft - SK_ScalarHalf,
719 devRect.fTop - SK_ScalarHalf,
720 devRect.fRight + SK_ScalarHalf,
721 devRect.fBottom + SK_ScalarHalf
722 };
723
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000724 SkPoint widthHeight = {
robertphillips@google.comb19cb7f2013-05-02 15:37:20 +0000725 SkScalarHalf(devRect.width()) + SK_ScalarHalf,
726 SkScalarHalf(devRect.height()) + SK_ScalarHalf
727 };
728
729 verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
730 verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY);
731 verts[0].fWidthHeight = widthHeight;
732
733 verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
734 verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY);
735 verts[1].fWidthHeight = widthHeight;
736
737 verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
738 verts[2].fOffset = widthHeight;
739 verts[2].fWidthHeight = widthHeight;
740
741 verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
742 verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY);
743 verts[3].fWidthHeight = widthHeight;
744
745 target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
746 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
747 target->resetIndexSource();
748}
749
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000750void GrAARectRenderer::strokeAARect(GrGpu* gpu,
bsalomon@google.come7249bd2012-08-16 15:28:54 +0000751 GrDrawTarget* target,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000752 const SkRect& rect,
robertphillips@google.com18136d12013-05-10 11:05:58 +0000753 const SkMatrix& combinedMatrix,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000754 const SkRect& devRect,
bsalomon9c0822a2014-08-11 11:07:48 -0700755 const SkStrokeRec& stroke) {
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000756 SkVector devStrokeSize;
egdanield58a0ba2014-06-11 10:30:05 -0700757 SkScalar width = stroke.getWidth();
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000758 if (width > 0) {
759 devStrokeSize.set(width, width);
760 combinedMatrix.mapVectors(&devStrokeSize, 1);
761 devStrokeSize.setAbs(devStrokeSize);
762 } else {
763 devStrokeSize.set(SK_Scalar1, SK_Scalar1);
764 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000765
robertphillips@google.com18136d12013-05-10 11:05:58 +0000766 const SkScalar dx = devStrokeSize.fX;
767 const SkScalar dy = devStrokeSize.fY;
bsalomon@google.com81712882012-11-01 17:12:34 +0000768 const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
769 const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000770
robertphillips@google.comafd1cba2013-05-14 19:47:47 +0000771 // Temporarily #if'ed out. We don't want to pass in the devRect but
772 // right now it is computed in GrContext::apply_aa_to_rect and we don't
773 // want to throw away the work
774#if 0
robertphillips@google.com18136d12013-05-10 11:05:58 +0000775 SkRect devRect;
776 combinedMatrix.mapRect(&devRect, rect);
robertphillips@google.comafd1cba2013-05-14 19:47:47 +0000777#endif
robertphillips@google.com18136d12013-05-10 11:05:58 +0000778
bsalomon@google.com81712882012-11-01 17:12:34 +0000779 SkScalar spare;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000780 {
bsalomon@google.com81712882012-11-01 17:12:34 +0000781 SkScalar w = devRect.width() - dx;
782 SkScalar h = devRect.height() - dy;
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000783 spare = SkTMin(w, h);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000784 }
785
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000786 SkRect devOutside(devRect);
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000787 devOutside.outset(rx, ry);
788
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000789 bool miterStroke = true;
yunchao.he2bff2302014-07-28 19:18:49 -0700790 // For hairlines, make bevel and round joins appear the same as mitered ones.
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000791 // small miter limit means right angles show bevel...
yunchao.he2bff2302014-07-28 19:18:49 -0700792 if ((width > 0) && (stroke.getJoin() != SkPaint::kMiter_Join ||
793 stroke.getMiter() < SK_ScalarSqrt2)) {
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000794 miterStroke = false;
795 }
796
797 if (spare <= 0 && miterStroke) {
bsalomon9c0822a2014-08-11 11:07:48 -0700798 this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000799 return;
800 }
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000801
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000802 SkRect devInside(devRect);
803 devInside.inset(rx, ry);
804
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000805 SkRect devOutsideAssist(devRect);
806
807 // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
808 // to draw the outer of the rect. Because there are 8 vertices on the outer
skia.committer@gmail.com26144182013-11-07 07:02:19 +0000809 // edge, while vertex number of inner edge is 4, the same as miter-stroke.
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000810 if (!miterStroke) {
811 devOutside.inset(0, ry);
812 devOutsideAssist.outset(0, ry);
813 }
814
bsalomon9c0822a2014-08-11 11:07:48 -0700815 this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, miterStroke);
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000816}
817
818void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
819 GrDrawTarget* target,
820 const SkRect& devOutside,
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000821 const SkRect& devOutsideAssist,
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000822 const SkRect& devInside,
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000823 bool miterStroke) {
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000824 GrDrawState* drawState = target->drawState();
825
bsalomonc30aaa02014-08-13 07:15:29 -0700826 CoverageAttribType covAttribType = set_rect_attribs(drawState);
bsalomon9c0822a2014-08-11 11:07:48 -0700827
828 GrColor color = drawState->getColor();
bsalomonc30aaa02014-08-13 07:15:29 -0700829 if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) {
bsalomon9c0822a2014-08-11 11:07:48 -0700830 drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
831 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000832
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000833 int innerVertexNum = 4;
834 int outerVertexNum = miterStroke ? 4 : 8;
835 int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
836
837 GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000838 if (!geo.succeeded()) {
839 GrPrintf("Failed to get space for vertices!\n");
840 return;
841 }
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000842 GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu, miterStroke);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000843 if (NULL == indexBuffer) {
844 GrPrintf("Failed to create index buffer!\n");
845 return;
846 }
847
848 intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
egdaniel7b3d5ee2014-08-28 05:41:14 -0700849 size_t vstride = drawState->getVertexStride();
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000850
bsalomon@google.come7249bd2012-08-16 15:28:54 +0000851 // We create vertices for four nested rectangles. There are two ramps from 0 to full
852 // coverage, one on the exterior of the stroke and the other on the interior.
853 // The following pointers refer to the four rects, from outermost to innermost.
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000854 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
egdaniel7b3d5ee2014-08-28 05:41:14 -0700855 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstride);
856 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vstride);
857 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000858
robertphillips@google.comc111ce22013-07-01 13:10:10 +0000859#ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
robertphillips@google.com353f0972013-06-28 17:57:06 +0000860 // TODO: this only really works if the X & Y margins are the same all around
861 // the rect
862 SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight);
863 inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
864 inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000865 if (miterStroke) {
866 inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom);
867 } else {
868 inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom);
869 }
robertphillips@google.com353f0972013-06-28 17:57:06 +0000870 SkASSERT(inset >= 0);
robertphillips@google.comc111ce22013-07-01 13:10:10 +0000871#else
872 SkScalar inset = SK_ScalarHalf;
873#endif
robertphillips@google.com353f0972013-06-28 17:57:06 +0000874
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000875 if (miterStroke) {
876 // outermost
egdaniel7b3d5ee2014-08-28 05:41:14 -0700877 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000878 // inner two
egdaniel7b3d5ee2014-08-28 05:41:14 -0700879 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset);
880 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000881 // innermost
egdaniel7b3d5ee2014-08-28 05:41:14 -0700882 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000883 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700884 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride);
885 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vstride);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000886 // outermost
egdaniel7b3d5ee2014-08-28 05:41:14 -0700887 set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
888 set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000889 // outer one of the inner two
egdaniel7b3d5ee2014-08-28 05:41:14 -0700890 set_inset_fan(fan1Pos, vstride, devOutside, inset, inset);
891 set_inset_fan(fan1AssistPos, vstride, devOutsideAssist, inset, inset);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000892 // inner one of the inner two
egdaniel7b3d5ee2014-08-28 05:41:14 -0700893 set_inset_fan(fan2Pos, vstride, devInside, -inset, -inset);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000894 // innermost
egdaniel7b3d5ee2014-08-28 05:41:14 -0700895 set_inset_fan(fan3Pos, vstride, devInside, SK_ScalarHalf, SK_ScalarHalf);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000896 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000897
bsalomon9c0822a2014-08-11 11:07:48 -0700898 // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
bsalomon@google.come7249bd2012-08-16 15:28:54 +0000899 // The outermost rect has 0 coverage
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000900 verts += sizeof(SkPoint);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000901 for (int i = 0; i < outerVertexNum; ++i) {
bsalomonc30aaa02014-08-13 07:15:29 -0700902 if (kUseCoverage_CoverageAttribType == covAttribType) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700903 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
904 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700905 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700906 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700907 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000908 }
909
bsalomon9c0822a2014-08-11 11:07:48 -0700910 // scale is the coverage for the the inner two rects.
robertphillips@google.com353f0972013-06-28 17:57:06 +0000911 int scale;
912 if (inset < SK_ScalarHalf) {
913 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
914 SkASSERT(scale >= 0 && scale <= 255);
915 } else {
916 scale = 0xff;
917 }
918
egdaniel7b3d5ee2014-08-28 05:41:14 -0700919 verts += outerVertexNum * vstride;
bsalomonc30aaa02014-08-13 07:15:29 -0700920 GrColor innerCoverage;
921 if (kUseCoverage_CoverageAttribType == covAttribType) {
922 innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
923 } else {
924 innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
925 }
926
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000927 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
bsalomonc30aaa02014-08-13 07:15:29 -0700928 if (kUseCoverage_CoverageAttribType == covAttribType) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700929 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
930 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage;
bsalomonc30aaa02014-08-13 07:15:29 -0700931 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700932 *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage;
bsalomonc30aaa02014-08-13 07:15:29 -0700933 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000934 }
935
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000936 // The innermost rect has 0 coverage
egdaniel7b3d5ee2014-08-28 05:41:14 -0700937 verts += (outerVertexNum + innerVertexNum) * vstride;
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000938 for (int i = 0; i < innerVertexNum; ++i) {
bsalomonc30aaa02014-08-13 07:15:29 -0700939 if (kUseCoverage_CoverageAttribType == covAttribType) {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700940 *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
941 *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700942 } else {
egdaniel7b3d5ee2014-08-28 05:41:14 -0700943 *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
bsalomonc30aaa02014-08-13 07:15:29 -0700944 }
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000945 }
946
947 target->setIndexSourceToBuffer(indexBuffer);
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000948 target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0,
949 totalVertexNum, aaStrokeRectIndexCount(miterStroke));
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000950}
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000951
952void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
953 GrDrawTarget* target,
954 const SkRect rects[2],
bsalomon9c0822a2014-08-11 11:07:48 -0700955 const SkMatrix& combinedMatrix) {
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000956 SkASSERT(combinedMatrix.rectStaysRect());
957 SkASSERT(!rects[1].isEmpty());
958
commit-bot@chromium.org6006d0f2013-11-06 10:08:21 +0000959 SkRect devOutside, devOutsideAssist, devInside;
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000960 combinedMatrix.mapRect(&devOutside, rects[0]);
961 // can't call mapRect for devInside since it calls sort
962 combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
963
964 if (devInside.isEmpty()) {
bsalomon9c0822a2014-08-11 11:07:48 -0700965 this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000966 return;
967 }
968
bsalomon9c0822a2014-08-11 11:07:48 -0700969 this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, true);
robertphillips@google.com83d1a682013-05-17 12:50:27 +0000970}