1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrAARectRenderer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,932 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "GrAARectRenderer.h" 1.12 +#include "GrGpu.h" 1.13 +#include "gl/GrGLEffect.h" 1.14 +#include "gl/GrGLVertexEffect.h" 1.15 +#include "GrTBackendEffectFactory.h" 1.16 +#include "SkColorPriv.h" 1.17 +#include "effects/GrVertexEffect.h" 1.18 + 1.19 +/////////////////////////////////////////////////////////////////////////////// 1.20 +class GrGLAlignedRectEffect; 1.21 + 1.22 +// Axis Aligned special case 1.23 +class GrAlignedRectEffect : public GrVertexEffect { 1.24 +public: 1.25 + static GrEffectRef* Create() { 1.26 + GR_CREATE_STATIC_EFFECT(gAlignedRectEffect, GrAlignedRectEffect, ()); 1.27 + gAlignedRectEffect->ref(); 1.28 + return gAlignedRectEffect; 1.29 + } 1.30 + 1.31 + virtual ~GrAlignedRectEffect() {} 1.32 + 1.33 + static const char* Name() { return "AlignedRectEdge"; } 1.34 + 1.35 + virtual void getConstantColorComponents(GrColor* color, 1.36 + uint32_t* validFlags) const SK_OVERRIDE { 1.37 + *validFlags = 0; 1.38 + } 1.39 + 1.40 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 1.41 + return GrTBackendEffectFactory<GrAlignedRectEffect>::getInstance(); 1.42 + } 1.43 + 1.44 + class GLEffect : public GrGLVertexEffect { 1.45 + public: 1.46 + GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 1.47 + : INHERITED (factory) {} 1.48 + 1.49 + virtual void emitCode(GrGLFullShaderBuilder* builder, 1.50 + const GrDrawEffect& drawEffect, 1.51 + EffectKey key, 1.52 + const char* outputColor, 1.53 + const char* inputColor, 1.54 + const TransformedCoordsArray&, 1.55 + const TextureSamplerArray& samplers) SK_OVERRIDE { 1.56 + // setup the varying for the Axis aligned rect effect 1.57 + // xy -> interpolated offset 1.58 + // zw -> w/2+0.5, h/2+0.5 1.59 + const char *vsRectName, *fsRectName; 1.60 + builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName); 1.61 + const SkString* attr0Name = 1.62 + builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 1.63 + builder->vsCodeAppendf("\t%s = %s;\n", vsRectName, attr0Name->c_str()); 1.64 + 1.65 + // TODO: compute all these offsets, spans, and scales in the VS 1.66 + builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName); 1.67 + builder->fsCodeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName); 1.68 + builder->fsCodeAppend("\tfloat outset = 0.5;\n"); 1.69 + // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects 1.70 + // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. 1.71 + builder->fsCodeAppend("\tfloat spanW = insetW + outset;\n"); 1.72 + builder->fsCodeAppend("\tfloat spanH = insetH + outset;\n"); 1.73 + // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum 1.74 + // value of coverage that is used. In other words it is the coverage that is 1.75 + // used in the interior of the rect after the ramp. 1.76 + builder->fsCodeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); 1.77 + builder->fsCodeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); 1.78 + 1.79 + // Compute the coverage for the rect's width 1.80 + builder->fsCodeAppendf( 1.81 + "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", fsRectName, 1.82 + fsRectName); 1.83 + // Compute the coverage for the rect's height and merge with the width 1.84 + builder->fsCodeAppendf( 1.85 + "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n", 1.86 + fsRectName, fsRectName); 1.87 + 1.88 + 1.89 + builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 1.90 + (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); 1.91 + } 1.92 + 1.93 + static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1.94 + return 0; 1.95 + } 1.96 + 1.97 + virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {} 1.98 + 1.99 + private: 1.100 + typedef GrGLVertexEffect INHERITED; 1.101 + }; 1.102 + 1.103 + 1.104 +private: 1.105 + GrAlignedRectEffect() : GrVertexEffect() { 1.106 + this->addVertexAttrib(kVec4f_GrSLType); 1.107 + } 1.108 + 1.109 + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; } 1.110 + 1.111 + GR_DECLARE_EFFECT_TEST; 1.112 + 1.113 + typedef GrVertexEffect INHERITED; 1.114 +}; 1.115 + 1.116 + 1.117 +GR_DEFINE_EFFECT_TEST(GrAlignedRectEffect); 1.118 + 1.119 +GrEffectRef* GrAlignedRectEffect::TestCreate(SkRandom* random, 1.120 + GrContext* context, 1.121 + const GrDrawTargetCaps&, 1.122 + GrTexture* textures[]) { 1.123 + return GrAlignedRectEffect::Create(); 1.124 +} 1.125 + 1.126 +/////////////////////////////////////////////////////////////////////////////// 1.127 +class GrGLRectEffect; 1.128 + 1.129 +/** 1.130 + * The output of this effect is a modulation of the input color and coverage 1.131 + * for an arbitrarily oriented rect. The rect is specified as: 1.132 + * Center of the rect 1.133 + * Unit vector point down the height of the rect 1.134 + * Half width + 0.5 1.135 + * Half height + 0.5 1.136 + * The center and vector are stored in a vec4 varying ("RectEdge") with the 1.137 + * center in the xy components and the vector in the zw components. 1.138 + * The munged width and height are stored in a vec2 varying ("WidthHeight") 1.139 + * with the width in x and the height in y. 1.140 + */ 1.141 +class GrRectEffect : public GrVertexEffect { 1.142 +public: 1.143 + static GrEffectRef* Create() { 1.144 + GR_CREATE_STATIC_EFFECT(gRectEffect, GrRectEffect, ()); 1.145 + gRectEffect->ref(); 1.146 + return gRectEffect; 1.147 + } 1.148 + 1.149 + virtual ~GrRectEffect() {} 1.150 + 1.151 + static const char* Name() { return "RectEdge"; } 1.152 + 1.153 + virtual void getConstantColorComponents(GrColor* color, 1.154 + uint32_t* validFlags) const SK_OVERRIDE { 1.155 + *validFlags = 0; 1.156 + } 1.157 + 1.158 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 1.159 + return GrTBackendEffectFactory<GrRectEffect>::getInstance(); 1.160 + } 1.161 + 1.162 + class GLEffect : public GrGLVertexEffect { 1.163 + public: 1.164 + GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 1.165 + : INHERITED (factory) {} 1.166 + 1.167 + virtual void emitCode(GrGLFullShaderBuilder* builder, 1.168 + const GrDrawEffect& drawEffect, 1.169 + EffectKey key, 1.170 + const char* outputColor, 1.171 + const char* inputColor, 1.172 + const TransformedCoordsArray&, 1.173 + const TextureSamplerArray& samplers) SK_OVERRIDE { 1.174 + // setup the varying for the center point and the unit vector 1.175 + // that points down the height of the rect 1.176 + const char *vsRectEdgeName, *fsRectEdgeName; 1.177 + builder->addVarying(kVec4f_GrSLType, "RectEdge", 1.178 + &vsRectEdgeName, &fsRectEdgeName); 1.179 + const SkString* attr0Name = 1.180 + builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 1.181 + builder->vsCodeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str()); 1.182 + 1.183 + // setup the varying for width/2+.5 and height/2+.5 1.184 + const char *vsWidthHeightName, *fsWidthHeightName; 1.185 + builder->addVarying(kVec2f_GrSLType, "WidthHeight", 1.186 + &vsWidthHeightName, &fsWidthHeightName); 1.187 + const SkString* attr1Name = 1.188 + builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); 1.189 + builder->vsCodeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str()); 1.190 + 1.191 + // TODO: compute all these offsets, spans, and scales in the VS 1.192 + builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName); 1.193 + builder->fsCodeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName); 1.194 + builder->fsCodeAppend("\tfloat outset = 0.5;\n"); 1.195 + // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects 1.196 + // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range. 1.197 + builder->fsCodeAppend("\tfloat spanW = insetW + outset;\n"); 1.198 + builder->fsCodeAppend("\tfloat spanH = insetH + outset;\n"); 1.199 + // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum 1.200 + // value of coverage that is used. In other words it is the coverage that is 1.201 + // used in the interior of the rect after the ramp. 1.202 + builder->fsCodeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n"); 1.203 + builder->fsCodeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n"); 1.204 + 1.205 + // Compute the coverage for the rect's width 1.206 + builder->fsCodeAppendf("\tvec2 offset = %s.xy - %s.xy;\n", 1.207 + builder->fragmentPosition(), fsRectEdgeName); 1.208 + builder->fsCodeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n", 1.209 + fsRectEdgeName, fsRectEdgeName); 1.210 + builder->fsCodeAppendf( 1.211 + "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n", 1.212 + fsWidthHeightName); 1.213 + 1.214 + // Compute the coverage for the rect's height and merge with the width 1.215 + builder->fsCodeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n", 1.216 + fsRectEdgeName); 1.217 + builder->fsCodeAppendf( 1.218 + "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n", 1.219 + fsWidthHeightName); 1.220 + 1.221 + 1.222 + builder->fsCodeAppendf("\t%s = %s;\n", outputColor, 1.223 + (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str()); 1.224 + } 1.225 + 1.226 + static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1.227 + return 0; 1.228 + } 1.229 + 1.230 + virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {} 1.231 + 1.232 + private: 1.233 + typedef GrGLVertexEffect INHERITED; 1.234 + }; 1.235 + 1.236 + 1.237 +private: 1.238 + GrRectEffect() : GrVertexEffect() { 1.239 + this->addVertexAttrib(kVec4f_GrSLType); 1.240 + this->addVertexAttrib(kVec2f_GrSLType); 1.241 + this->setWillReadFragmentPosition(); 1.242 + } 1.243 + 1.244 + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; } 1.245 + 1.246 + GR_DECLARE_EFFECT_TEST; 1.247 + 1.248 + typedef GrVertexEffect INHERITED; 1.249 +}; 1.250 + 1.251 + 1.252 +GR_DEFINE_EFFECT_TEST(GrRectEffect); 1.253 + 1.254 +GrEffectRef* GrRectEffect::TestCreate(SkRandom* random, 1.255 + GrContext* context, 1.256 + const GrDrawTargetCaps&, 1.257 + GrTexture* textures[]) { 1.258 + return GrRectEffect::Create(); 1.259 +} 1.260 + 1.261 +/////////////////////////////////////////////////////////////////////////////// 1.262 + 1.263 +namespace { 1.264 + 1.265 +extern const GrVertexAttrib gAARectCoverageAttribs[] = { 1.266 + {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 1.267 + {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding}, 1.268 +}; 1.269 + 1.270 +extern const GrVertexAttrib gAARectColorAttribs[] = { 1.271 + {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 1.272 + {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding}, 1.273 +}; 1.274 + 1.275 +static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) { 1.276 + if (useCoverage) { 1.277 + drawState->setVertexAttribs<gAARectCoverageAttribs>(SK_ARRAY_COUNT(gAARectCoverageAttribs)); 1.278 + } else { 1.279 + drawState->setVertexAttribs<gAARectColorAttribs>(SK_ARRAY_COUNT(gAARectColorAttribs)); 1.280 + } 1.281 +} 1.282 + 1.283 +static void set_inset_fan(GrPoint* pts, size_t stride, 1.284 + const SkRect& r, SkScalar dx, SkScalar dy) { 1.285 + pts->setRectFan(r.fLeft + dx, r.fTop + dy, 1.286 + r.fRight - dx, r.fBottom - dy, stride); 1.287 +} 1.288 + 1.289 +}; 1.290 + 1.291 +void GrAARectRenderer::reset() { 1.292 + SkSafeSetNull(fAAFillRectIndexBuffer); 1.293 + SkSafeSetNull(fAAMiterStrokeRectIndexBuffer); 1.294 + SkSafeSetNull(fAABevelStrokeRectIndexBuffer); 1.295 +} 1.296 + 1.297 +static const uint16_t gFillAARectIdx[] = { 1.298 + 0, 1, 5, 5, 4, 0, 1.299 + 1, 2, 6, 6, 5, 1, 1.300 + 2, 3, 7, 7, 6, 2, 1.301 + 3, 0, 4, 4, 7, 3, 1.302 + 4, 5, 6, 6, 7, 4, 1.303 +}; 1.304 + 1.305 +static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx); 1.306 +static const int kVertsPerAAFillRect = 8; 1.307 +static const int kNumAAFillRectsInIndexBuffer = 256; 1.308 + 1.309 +GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) { 1.310 + static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect * 1.311 + sizeof(uint16_t) * 1.312 + kNumAAFillRectsInIndexBuffer; 1.313 + 1.314 + if (NULL == fAAFillRectIndexBuffer) { 1.315 + fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false); 1.316 + if (NULL != fAAFillRectIndexBuffer) { 1.317 + uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock(); 1.318 + bool useTempData = (NULL == data); 1.319 + if (useTempData) { 1.320 + data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect); 1.321 + } 1.322 + for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) { 1.323 + // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around 1.324 + // the inner rect (for AA) and 2 for the inner rect. 1.325 + int baseIdx = i * kIndicesPerAAFillRect; 1.326 + uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect); 1.327 + for (int j = 0; j < kIndicesPerAAFillRect; ++j) { 1.328 + data[baseIdx+j] = baseVert + gFillAARectIdx[j]; 1.329 + } 1.330 + } 1.331 + if (useTempData) { 1.332 + if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) { 1.333 + GrCrash("Can't get AA Fill Rect indices into buffer!"); 1.334 + } 1.335 + SkDELETE_ARRAY(data); 1.336 + } else { 1.337 + fAAFillRectIndexBuffer->unlock(); 1.338 + } 1.339 + } 1.340 + } 1.341 + 1.342 + return fAAFillRectIndexBuffer; 1.343 +} 1.344 + 1.345 +static const uint16_t gMiterStrokeAARectIdx[] = { 1.346 + 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, 1.347 + 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, 1.348 + 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, 1.349 + 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, 1.350 + 1.351 + 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, 1.352 + 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, 1.353 + 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, 1.354 + 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, 1.355 + 1.356 + 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, 1.357 + 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, 1.358 + 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, 1.359 + 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, 1.360 +}; 1.361 + 1.362 +/** 1.363 + * As in miter-stroke, index = a + b, and a is the current index, b is the shift 1.364 + * from the first index. The index layout: 1.365 + * outer AA line: 0~3, 4~7 1.366 + * outer edge: 8~11, 12~15 1.367 + * inner edge: 16~19 1.368 + * inner AA line: 20~23 1.369 + * Following comes a bevel-stroke rect and its indices: 1.370 + * 1.371 + * 4 7 1.372 + * ********************************* 1.373 + * * ______________________________ * 1.374 + * * / 12 15 \ * 1.375 + * * / \ * 1.376 + * 0 * |8 16_____________________19 11 | * 3 1.377 + * * | | | | * 1.378 + * * | | **************** | | * 1.379 + * * | | * 20 23 * | | * 1.380 + * * | | * * | | * 1.381 + * * | | * 21 22 * | | * 1.382 + * * | | **************** | | * 1.383 + * * | |____________________| | * 1.384 + * 1 * |9 17 18 10| * 2 1.385 + * * \ / * 1.386 + * * \13 __________________________14/ * 1.387 + * * * 1.388 + * ********************************** 1.389 + * 5 6 1.390 + */ 1.391 +static const uint16_t gBevelStrokeAARectIdx[] = { 1.392 + // Draw outer AA, from outer AA line to outer edge, shift is 0. 1.393 + 0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0, 1.394 + 1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0, 1.395 + 5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0, 1.396 + 6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0, 1.397 + 2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0, 1.398 + 3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0, 1.399 + 7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0, 1.400 + 4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0, 1.401 + 1.402 + // Draw the stroke, from outer edge to inner edge, shift is 8. 1.403 + 0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8, 1.404 + 1 + 8, 5 + 8, 9 + 8, 1.405 + 5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8, 1.406 + 6 + 8, 2 + 8, 10 + 8, 1.407 + 2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8, 1.408 + 3 + 8, 7 + 8, 11 + 8, 1.409 + 7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8, 1.410 + 4 + 8, 0 + 8, 8 + 8, 1.411 + 1.412 + // Draw the inner AA, from inner edge to inner AA line, shift is 16. 1.413 + 0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16, 1.414 + 1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16, 1.415 + 2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16, 1.416 + 3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16, 1.417 +}; 1.418 + 1.419 +int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) { 1.420 + return miterStroke ? GR_ARRAY_COUNT(gMiterStrokeAARectIdx) : 1.421 + GR_ARRAY_COUNT(gBevelStrokeAARectIdx); 1.422 +} 1.423 + 1.424 +GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) { 1.425 + if (miterStroke) { 1.426 + if (NULL == fAAMiterStrokeRectIndexBuffer) { 1.427 + fAAMiterStrokeRectIndexBuffer = 1.428 + gpu->createIndexBuffer(sizeof(gMiterStrokeAARectIdx), false); 1.429 + if (NULL != fAAMiterStrokeRectIndexBuffer) { 1.430 +#ifdef SK_DEBUG 1.431 + bool updated = 1.432 +#endif 1.433 + fAAMiterStrokeRectIndexBuffer->updateData(gMiterStrokeAARectIdx, 1.434 + sizeof(gMiterStrokeAARectIdx)); 1.435 + GR_DEBUGASSERT(updated); 1.436 + } 1.437 + } 1.438 + return fAAMiterStrokeRectIndexBuffer; 1.439 + } else { 1.440 + if (NULL == fAABevelStrokeRectIndexBuffer) { 1.441 + fAABevelStrokeRectIndexBuffer = 1.442 + gpu->createIndexBuffer(sizeof(gBevelStrokeAARectIdx), false); 1.443 + if (NULL != fAABevelStrokeRectIndexBuffer) { 1.444 +#ifdef SK_DEBUG 1.445 + bool updated = 1.446 +#endif 1.447 + fAABevelStrokeRectIndexBuffer->updateData(gBevelStrokeAARectIdx, 1.448 + sizeof(gBevelStrokeAARectIdx)); 1.449 + GR_DEBUGASSERT(updated); 1.450 + } 1.451 + } 1.452 + return fAABevelStrokeRectIndexBuffer; 1.453 + } 1.454 +} 1.455 + 1.456 +void GrAARectRenderer::geometryFillAARect(GrGpu* gpu, 1.457 + GrDrawTarget* target, 1.458 + const SkRect& rect, 1.459 + const SkMatrix& combinedMatrix, 1.460 + const SkRect& devRect, 1.461 + bool useVertexCoverage) { 1.462 + GrDrawState* drawState = target->drawState(); 1.463 + 1.464 + set_aa_rect_vertex_attributes(drawState, useVertexCoverage); 1.465 + 1.466 + GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0); 1.467 + if (!geo.succeeded()) { 1.468 + GrPrintf("Failed to get space for vertices!\n"); 1.469 + return; 1.470 + } 1.471 + 1.472 + GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu); 1.473 + if (NULL == indexBuffer) { 1.474 + GrPrintf("Failed to create index buffer!\n"); 1.475 + return; 1.476 + } 1.477 + 1.478 + intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); 1.479 + size_t vsize = drawState->getVertexSize(); 1.480 + SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize); 1.481 + 1.482 + GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); 1.483 + GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); 1.484 + 1.485 + SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1); 1.486 + inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height()); 1.487 + 1.488 + if (combinedMatrix.rectStaysRect()) { 1.489 + // Temporarily #if'ed out. We don't want to pass in the devRect but 1.490 + // right now it is computed in GrContext::apply_aa_to_rect and we don't 1.491 + // want to throw away the work 1.492 +#if 0 1.493 + SkRect devRect; 1.494 + combinedMatrix.mapRect(&devRect, rect); 1.495 +#endif 1.496 + 1.497 + set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf); 1.498 + set_inset_fan(fan1Pos, vsize, devRect, inset, inset); 1.499 + } else { 1.500 + // compute transformed (1, 0) and (0, 1) vectors 1.501 + SkVector vec[2] = { 1.502 + { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, 1.503 + { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } 1.504 + }; 1.505 + 1.506 + vec[0].normalize(); 1.507 + vec[0].scale(SK_ScalarHalf); 1.508 + vec[1].normalize(); 1.509 + vec[1].scale(SK_ScalarHalf); 1.510 + 1.511 + // create the rotated rect 1.512 + fan0Pos->setRectFan(rect.fLeft, rect.fTop, 1.513 + rect.fRight, rect.fBottom, vsize); 1.514 + combinedMatrix.mapPointsWithStride(fan0Pos, vsize, 4); 1.515 + 1.516 + // Now create the inset points and then outset the original 1.517 + // rotated points 1.518 + 1.519 + // TL 1.520 + *((SkPoint*)((intptr_t)fan1Pos + 0 * vsize)) = 1.521 + *((SkPoint*)((intptr_t)fan0Pos + 0 * vsize)) + vec[0] + vec[1]; 1.522 + *((SkPoint*)((intptr_t)fan0Pos + 0 * vsize)) -= vec[0] + vec[1]; 1.523 + // BL 1.524 + *((SkPoint*)((intptr_t)fan1Pos + 1 * vsize)) = 1.525 + *((SkPoint*)((intptr_t)fan0Pos + 1 * vsize)) + vec[0] - vec[1]; 1.526 + *((SkPoint*)((intptr_t)fan0Pos + 1 * vsize)) -= vec[0] - vec[1]; 1.527 + // BR 1.528 + *((SkPoint*)((intptr_t)fan1Pos + 2 * vsize)) = 1.529 + *((SkPoint*)((intptr_t)fan0Pos + 2 * vsize)) - vec[0] - vec[1]; 1.530 + *((SkPoint*)((intptr_t)fan0Pos + 2 * vsize)) += vec[0] + vec[1]; 1.531 + // TR 1.532 + *((SkPoint*)((intptr_t)fan1Pos + 3 * vsize)) = 1.533 + *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) - vec[0] + vec[1]; 1.534 + *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1]; 1.535 + } 1.536 + 1.537 + verts += sizeof(GrPoint); 1.538 + for (int i = 0; i < 4; ++i) { 1.539 + *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; 1.540 + } 1.541 + 1.542 + int scale; 1.543 + if (inset < SK_ScalarHalf) { 1.544 + scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); 1.545 + SkASSERT(scale >= 0 && scale <= 255); 1.546 + } else { 1.547 + scale = 0xff; 1.548 + } 1.549 + 1.550 + GrColor innerColor; 1.551 + if (useVertexCoverage) { 1.552 + innerColor = GrColorPackRGBA(scale, scale, scale, scale); 1.553 + } else { 1.554 + if (0xff == scale) { 1.555 + innerColor = target->getDrawState().getColor(); 1.556 + } else { 1.557 + innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale); 1.558 + } 1.559 + } 1.560 + 1.561 + verts += 4 * vsize; 1.562 + for (int i = 0; i < 4; ++i) { 1.563 + *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; 1.564 + } 1.565 + 1.566 + target->setIndexSourceToBuffer(indexBuffer); 1.567 + target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 1.568 + kVertsPerAAFillRect, 1.569 + kIndicesPerAAFillRect); 1.570 + target->resetIndexSource(); 1.571 +} 1.572 + 1.573 +namespace { 1.574 + 1.575 +// Rotated 1.576 +struct RectVertex { 1.577 + GrPoint fPos; 1.578 + GrPoint fCenter; 1.579 + GrPoint fDir; 1.580 + GrPoint fWidthHeight; 1.581 +}; 1.582 + 1.583 +// Rotated 1.584 +extern const GrVertexAttrib gAARectVertexAttribs[] = { 1.585 + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 1.586 + { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, 1.587 + { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding } 1.588 +}; 1.589 + 1.590 +// Axis Aligned 1.591 +struct AARectVertex { 1.592 + GrPoint fPos; 1.593 + GrPoint fOffset; 1.594 + GrPoint fWidthHeight; 1.595 +}; 1.596 + 1.597 +// Axis Aligned 1.598 +extern const GrVertexAttrib gAAAARectVertexAttribs[] = { 1.599 + { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, 1.600 + { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding }, 1.601 +}; 1.602 + 1.603 +}; 1.604 + 1.605 +void GrAARectRenderer::shaderFillAARect(GrGpu* gpu, 1.606 + GrDrawTarget* target, 1.607 + const SkRect& rect, 1.608 + const SkMatrix& combinedMatrix) { 1.609 + GrDrawState* drawState = target->drawState(); 1.610 + 1.611 + SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY()); 1.612 + combinedMatrix.mapPoints(¢er, 1); 1.613 + 1.614 + // compute transformed (0, 1) vector 1.615 + SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] }; 1.616 + dir.normalize(); 1.617 + 1.618 + // compute transformed (width, 0) and (0, height) vectors 1.619 + SkVector vec[2] = { 1.620 + { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] }, 1.621 + { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] } 1.622 + }; 1.623 + 1.624 + SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf; 1.625 + SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf; 1.626 + drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs)); 1.627 + SkASSERT(sizeof(RectVertex) == drawState->getVertexSize()); 1.628 + 1.629 + GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 1.630 + if (!geo.succeeded()) { 1.631 + GrPrintf("Failed to get space for vertices!\n"); 1.632 + return; 1.633 + } 1.634 + 1.635 + RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices()); 1.636 + 1.637 + GrEffectRef* effect = GrRectEffect::Create(); 1.638 + static const int kRectAttrIndex = 1; 1.639 + static const int kWidthIndex = 2; 1.640 + drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref(); 1.641 + 1.642 + for (int i = 0; i < 4; ++i) { 1.643 + verts[i].fCenter = center; 1.644 + verts[i].fDir = dir; 1.645 + verts[i].fWidthHeight.fX = newWidth; 1.646 + verts[i].fWidthHeight.fY = newHeight; 1.647 + } 1.648 + 1.649 + SkRect devRect; 1.650 + combinedMatrix.mapRect(&devRect, rect); 1.651 + 1.652 + SkRect devBounds = { 1.653 + devRect.fLeft - SK_ScalarHalf, 1.654 + devRect.fTop - SK_ScalarHalf, 1.655 + devRect.fRight + SK_ScalarHalf, 1.656 + devRect.fBottom + SK_ScalarHalf 1.657 + }; 1.658 + 1.659 + verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); 1.660 + verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); 1.661 + verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); 1.662 + verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); 1.663 + 1.664 + target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); 1.665 + target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); 1.666 + target->resetIndexSource(); 1.667 +} 1.668 + 1.669 +void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu, 1.670 + GrDrawTarget* target, 1.671 + const SkRect& rect, 1.672 + const SkMatrix& combinedMatrix) { 1.673 + GrDrawState* drawState = target->drawState(); 1.674 + SkASSERT(combinedMatrix.rectStaysRect()); 1.675 + 1.676 + drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs)); 1.677 + SkASSERT(sizeof(AARectVertex) == drawState->getVertexSize()); 1.678 + 1.679 + GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 1.680 + if (!geo.succeeded()) { 1.681 + GrPrintf("Failed to get space for vertices!\n"); 1.682 + return; 1.683 + } 1.684 + 1.685 + AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices()); 1.686 + 1.687 + GrEffectRef* effect = GrAlignedRectEffect::Create(); 1.688 + static const int kOffsetIndex = 1; 1.689 + drawState->addCoverageEffect(effect, kOffsetIndex)->unref(); 1.690 + 1.691 + SkRect devRect; 1.692 + combinedMatrix.mapRect(&devRect, rect); 1.693 + 1.694 + SkRect devBounds = { 1.695 + devRect.fLeft - SK_ScalarHalf, 1.696 + devRect.fTop - SK_ScalarHalf, 1.697 + devRect.fRight + SK_ScalarHalf, 1.698 + devRect.fBottom + SK_ScalarHalf 1.699 + }; 1.700 + 1.701 + GrPoint widthHeight = { 1.702 + SkScalarHalf(devRect.width()) + SK_ScalarHalf, 1.703 + SkScalarHalf(devRect.height()) + SK_ScalarHalf 1.704 + }; 1.705 + 1.706 + verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop); 1.707 + verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY); 1.708 + verts[0].fWidthHeight = widthHeight; 1.709 + 1.710 + verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom); 1.711 + verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY); 1.712 + verts[1].fWidthHeight = widthHeight; 1.713 + 1.714 + verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom); 1.715 + verts[2].fOffset = widthHeight; 1.716 + verts[2].fWidthHeight = widthHeight; 1.717 + 1.718 + verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop); 1.719 + verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY); 1.720 + verts[3].fWidthHeight = widthHeight; 1.721 + 1.722 + target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer()); 1.723 + target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6); 1.724 + target->resetIndexSource(); 1.725 +} 1.726 + 1.727 +void GrAARectRenderer::strokeAARect(GrGpu* gpu, 1.728 + GrDrawTarget* target, 1.729 + const SkRect& rect, 1.730 + const SkMatrix& combinedMatrix, 1.731 + const SkRect& devRect, 1.732 + const SkStrokeRec* stroke, 1.733 + bool useVertexCoverage) { 1.734 + GrVec devStrokeSize; 1.735 + SkScalar width = stroke->getWidth(); 1.736 + if (width > 0) { 1.737 + devStrokeSize.set(width, width); 1.738 + combinedMatrix.mapVectors(&devStrokeSize, 1); 1.739 + devStrokeSize.setAbs(devStrokeSize); 1.740 + } else { 1.741 + devStrokeSize.set(SK_Scalar1, SK_Scalar1); 1.742 + } 1.743 + 1.744 + const SkScalar dx = devStrokeSize.fX; 1.745 + const SkScalar dy = devStrokeSize.fY; 1.746 + const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf); 1.747 + const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf); 1.748 + 1.749 + // Temporarily #if'ed out. We don't want to pass in the devRect but 1.750 + // right now it is computed in GrContext::apply_aa_to_rect and we don't 1.751 + // want to throw away the work 1.752 +#if 0 1.753 + SkRect devRect; 1.754 + combinedMatrix.mapRect(&devRect, rect); 1.755 +#endif 1.756 + 1.757 + SkScalar spare; 1.758 + { 1.759 + SkScalar w = devRect.width() - dx; 1.760 + SkScalar h = devRect.height() - dy; 1.761 + spare = GrMin(w, h); 1.762 + } 1.763 + 1.764 + SkRect devOutside(devRect); 1.765 + devOutside.outset(rx, ry); 1.766 + 1.767 + bool miterStroke = true; 1.768 + // small miter limit means right angles show bevel... 1.769 + if (stroke->getJoin() != SkPaint::kMiter_Join || stroke->getMiter() < SK_ScalarSqrt2) { 1.770 + miterStroke = false; 1.771 + } 1.772 + 1.773 + if (spare <= 0 && miterStroke) { 1.774 + this->fillAARect(gpu, target, devOutside, SkMatrix::I(), 1.775 + devOutside, useVertexCoverage); 1.776 + return; 1.777 + } 1.778 + 1.779 + SkRect devInside(devRect); 1.780 + devInside.inset(rx, ry); 1.781 + 1.782 + SkRect devOutsideAssist(devRect); 1.783 + 1.784 + // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist) 1.785 + // to draw the outer of the rect. Because there are 8 vertices on the outer 1.786 + // edge, while vertex number of inner edge is 4, the same as miter-stroke. 1.787 + if (!miterStroke) { 1.788 + devOutside.inset(0, ry); 1.789 + devOutsideAssist.outset(0, ry); 1.790 + } 1.791 + 1.792 + this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, 1.793 + devInside, useVertexCoverage, miterStroke); 1.794 +} 1.795 + 1.796 +void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu, 1.797 + GrDrawTarget* target, 1.798 + const SkRect& devOutside, 1.799 + const SkRect& devOutsideAssist, 1.800 + const SkRect& devInside, 1.801 + bool useVertexCoverage, 1.802 + bool miterStroke) { 1.803 + GrDrawState* drawState = target->drawState(); 1.804 + 1.805 + set_aa_rect_vertex_attributes(drawState, useVertexCoverage); 1.806 + 1.807 + int innerVertexNum = 4; 1.808 + int outerVertexNum = miterStroke ? 4 : 8; 1.809 + int totalVertexNum = (outerVertexNum + innerVertexNum) * 2; 1.810 + 1.811 + GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0); 1.812 + if (!geo.succeeded()) { 1.813 + GrPrintf("Failed to get space for vertices!\n"); 1.814 + return; 1.815 + } 1.816 + GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu, miterStroke); 1.817 + if (NULL == indexBuffer) { 1.818 + GrPrintf("Failed to create index buffer!\n"); 1.819 + return; 1.820 + } 1.821 + 1.822 + intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices()); 1.823 + size_t vsize = drawState->getVertexSize(); 1.824 + SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize); 1.825 + 1.826 + // We create vertices for four nested rectangles. There are two ramps from 0 to full 1.827 + // coverage, one on the exterior of the stroke and the other on the interior. 1.828 + // The following pointers refer to the four rects, from outermost to innermost. 1.829 + GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts); 1.830 + GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + outerVertexNum * vsize); 1.831 + GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 2 * outerVertexNum * vsize); 1.832 + GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vsize); 1.833 + 1.834 +#ifndef SK_IGNORE_THIN_STROKED_RECT_FIX 1.835 + // TODO: this only really works if the X & Y margins are the same all around 1.836 + // the rect 1.837 + SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight); 1.838 + inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft); 1.839 + inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop); 1.840 + if (miterStroke) { 1.841 + inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom); 1.842 + } else { 1.843 + inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom); 1.844 + } 1.845 + SkASSERT(inset >= 0); 1.846 +#else 1.847 + SkScalar inset = SK_ScalarHalf; 1.848 +#endif 1.849 + 1.850 + if (miterStroke) { 1.851 + // outermost 1.852 + set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); 1.853 + // inner two 1.854 + set_inset_fan(fan1Pos, vsize, devOutside, inset, inset); 1.855 + set_inset_fan(fan2Pos, vsize, devInside, -inset, -inset); 1.856 + // innermost 1.857 + set_inset_fan(fan3Pos, vsize, devInside, SK_ScalarHalf, SK_ScalarHalf); 1.858 + } else { 1.859 + GrPoint* fan0AssistPos = reinterpret_cast<GrPoint*>(verts + 4 * vsize); 1.860 + GrPoint* fan1AssistPos = reinterpret_cast<GrPoint*>(verts + (outerVertexNum + 4) * vsize); 1.861 + // outermost 1.862 + set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf); 1.863 + set_inset_fan(fan0AssistPos, vsize, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf); 1.864 + // outer one of the inner two 1.865 + set_inset_fan(fan1Pos, vsize, devOutside, inset, inset); 1.866 + set_inset_fan(fan1AssistPos, vsize, devOutsideAssist, inset, inset); 1.867 + // inner one of the inner two 1.868 + set_inset_fan(fan2Pos, vsize, devInside, -inset, -inset); 1.869 + // innermost 1.870 + set_inset_fan(fan3Pos, vsize, devInside, SK_ScalarHalf, SK_ScalarHalf); 1.871 + } 1.872 + 1.873 + // The outermost rect has 0 coverage 1.874 + verts += sizeof(GrPoint); 1.875 + for (int i = 0; i < outerVertexNum; ++i) { 1.876 + *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; 1.877 + } 1.878 + 1.879 + int scale; 1.880 + if (inset < SK_ScalarHalf) { 1.881 + scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); 1.882 + SkASSERT(scale >= 0 && scale <= 255); 1.883 + } else { 1.884 + scale = 0xff; 1.885 + } 1.886 + 1.887 + // The inner two rects have full coverage 1.888 + GrColor innerColor; 1.889 + if (useVertexCoverage) { 1.890 + innerColor = GrColorPackRGBA(scale, scale, scale, scale); 1.891 + } else { 1.892 + if (0xff == scale) { 1.893 + innerColor = target->getDrawState().getColor(); 1.894 + } else { 1.895 + innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale); 1.896 + } 1.897 + } 1.898 + 1.899 + verts += outerVertexNum * vsize; 1.900 + for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { 1.901 + *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor; 1.902 + } 1.903 + 1.904 + // The innermost rect has 0 coverage 1.905 + verts += (outerVertexNum + innerVertexNum) * vsize; 1.906 + for (int i = 0; i < innerVertexNum; ++i) { 1.907 + *reinterpret_cast<GrColor*>(verts + i * vsize) = 0; 1.908 + } 1.909 + 1.910 + target->setIndexSourceToBuffer(indexBuffer); 1.911 + target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 1.912 + totalVertexNum, aaStrokeRectIndexCount(miterStroke)); 1.913 +} 1.914 + 1.915 +void GrAARectRenderer::fillAANestedRects(GrGpu* gpu, 1.916 + GrDrawTarget* target, 1.917 + const SkRect rects[2], 1.918 + const SkMatrix& combinedMatrix, 1.919 + bool useVertexCoverage) { 1.920 + SkASSERT(combinedMatrix.rectStaysRect()); 1.921 + SkASSERT(!rects[1].isEmpty()); 1.922 + 1.923 + SkRect devOutside, devOutsideAssist, devInside; 1.924 + combinedMatrix.mapRect(&devOutside, rects[0]); 1.925 + // can't call mapRect for devInside since it calls sort 1.926 + combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2); 1.927 + 1.928 + if (devInside.isEmpty()) { 1.929 + this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside, useVertexCoverage); 1.930 + return; 1.931 + } 1.932 + 1.933 + this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, 1.934 + devInside, useVertexCoverage, true); 1.935 +}