Home | History | Annotate | Download | only in gpu
      1 /*
      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"
      9 #include "GrGpu.h"
     10 #include "gl/builders/GrGLFullProgramBuilder.h"
     11 #include "gl/GrGLProcessor.h"
     12 #include "gl/GrGLGeometryProcessor.h"
     13 #include "GrTBackendProcessorFactory.h"
     14 #include "SkColorPriv.h"
     15 #include "GrGeometryProcessor.h"
     16 
     17 ///////////////////////////////////////////////////////////////////////////////
     18 class GrGLAlignedRectEffect;
     19 
     20 // Axis Aligned special case
     21 class GrAlignedRectEffect : public GrGeometryProcessor {
     22 public:
     23     static GrGeometryProcessor* Create() {
     24         GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gAlignedRectEffect, GrAlignedRectEffect, ());
     25         gAlignedRectEffect->ref();
     26         return gAlignedRectEffect;
     27     }
     28 
     29     virtual ~GrAlignedRectEffect() {}
     30 
     31     static const char* Name() { return "AlignedRectEdge"; }
     32 
     33     virtual void getConstantColorComponents(GrColor* color,
     34                                             uint32_t* validFlags) const SK_OVERRIDE {
     35         *validFlags = 0;
     36     }
     37 
     38     const GrShaderVar& inRect() const { return fInRect; }
     39 
     40     virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE {
     41         return GrTBackendGeometryProcessorFactory<GrAlignedRectEffect>::getInstance();
     42     }
     43 
     44     class GLProcessor : public GrGLGeometryProcessor {
     45     public:
     46         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
     47         : INHERITED (factory) {}
     48 
     49         virtual void emitCode(GrGLFullProgramBuilder* builder,
     50                               const GrGeometryProcessor& geometryProcessor,
     51                               const GrProcessorKey& key,
     52                               const char* outputColor,
     53                               const char* inputColor,
     54                               const TransformedCoordsArray&,
     55                               const TextureSamplerArray& samplers) SK_OVERRIDE {
     56             // setup the varying for the Axis aligned rect effect
     57             //      xy -> interpolated offset
     58             //      zw -> w/2+0.5, h/2+0.5
     59             const char *vsRectName, *fsRectName;
     60             builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
     61 
     62             const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
     63             GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
     64             vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
     65 
     66             GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
     67             // TODO: compute all these offsets, spans, and scales in the VS
     68             fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
     69             fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
     70             fsBuilder->codeAppend("\tfloat outset = 0.5;\n");
     71             // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
     72             // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
     73             fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n");
     74             fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n");
     75             // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
     76             // value of coverage that is used. In other words it is the coverage that is
     77             // used in the interior of the rect after the ramp.
     78             fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n");
     79             fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n");
     80 
     81             // Compute the coverage for the rect's width
     82             fsBuilder->codeAppendf(
     83                 "\tfloat coverage = scaleW*clamp((%s.z-abs(%s.x))/spanW, 0.0, 1.0);\n", fsRectName,
     84                 fsRectName);
     85             // Compute the coverage for the rect's height and merge with the width
     86             fsBuilder->codeAppendf(
     87                 "\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n",
     88                 fsRectName, fsRectName);
     89 
     90 
     91             fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
     92                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
     93         }
     94 
     95         static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
     96 
     97         virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {}
     98 
     99     private:
    100         typedef GrGLGeometryProcessor INHERITED;
    101     };
    102 
    103 
    104 private:
    105     GrAlignedRectEffect()
    106         : fInRect(this->addVertexAttrib(GrShaderVar("inRect",
    107                                                     kVec4f_GrSLType,
    108                                                     GrShaderVar::kAttribute_TypeModifier))) {
    109     }
    110 
    111     const GrShaderVar& fInRect;
    112 
    113     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
    114 
    115     GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
    116 
    117     typedef GrGeometryProcessor INHERITED;
    118 };
    119 
    120 
    121 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrAlignedRectEffect);
    122 
    123 GrGeometryProcessor* GrAlignedRectEffect::TestCreate(SkRandom* random,
    124                                                      GrContext* context,
    125                                                      const GrDrawTargetCaps&,
    126                                                      GrTexture* textures[]) {
    127     return GrAlignedRectEffect::Create();
    128 }
    129 
    130 ///////////////////////////////////////////////////////////////////////////////
    131 class GrGLRectEffect;
    132 
    133 /**
    134  * The output of this effect is a modulation of the input color and coverage
    135  * for an arbitrarily oriented rect. The rect is specified as:
    136  *      Center of the rect
    137  *      Unit vector point down the height of the rect
    138  *      Half width + 0.5
    139  *      Half height + 0.5
    140  * The center and vector are stored in a vec4 varying ("RectEdge") with the
    141  * center in the xy components and the vector in the zw components.
    142  * The munged width and height are stored in a vec2 varying ("WidthHeight")
    143  * with the width in x and the height in y.
    144  */
    145 
    146 class GrRectEffect : public GrGeometryProcessor {
    147 public:
    148     static GrGeometryProcessor* Create() {
    149         GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gRectEffect, GrRectEffect, ());
    150         gRectEffect->ref();
    151         return gRectEffect;
    152     }
    153 
    154     virtual ~GrRectEffect() {}
    155 
    156     static const char* Name() { return "RectEdge"; }
    157 
    158     virtual void getConstantColorComponents(GrColor* color,
    159                                             uint32_t* validFlags) const SK_OVERRIDE {
    160         *validFlags = 0;
    161     }
    162 
    163     const GrShaderVar& inRectEdge() const { return fInRectEdge; }
    164     const GrShaderVar& inWidthHeight() const { return fInWidthHeight; }
    165 
    166     virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE {
    167         return GrTBackendGeometryProcessorFactory<GrRectEffect>::getInstance();
    168     }
    169 
    170     class GLProcessor : public GrGLGeometryProcessor {
    171     public:
    172         GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
    173         : INHERITED (factory) {}
    174 
    175         virtual void emitCode(GrGLFullProgramBuilder* builder,
    176                               const GrGeometryProcessor& geometryProcessor,
    177                               const GrProcessorKey& key,
    178                               const char* outputColor,
    179                               const char* inputColor,
    180                               const TransformedCoordsArray&,
    181                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    182             // setup the varying for the center point and the unit vector
    183             // that points down the height of the rect
    184             const char *vsRectEdgeName, *fsRectEdgeName;
    185             builder->addVarying(kVec4f_GrSLType, "RectEdge",
    186                                 &vsRectEdgeName, &fsRectEdgeName);
    187 
    188             const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
    189             GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
    190             vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
    191 
    192             // setup the varying for width/2+.5 and height/2+.5
    193             const char *vsWidthHeightName, *fsWidthHeightName;
    194             builder->addVarying(kVec2f_GrSLType, "WidthHeight",
    195                                 &vsWidthHeightName, &fsWidthHeightName);
    196             vsBuilder->codeAppendf("%s = %s;",
    197                                    vsWidthHeightName,
    198                                    rectEffect.inWidthHeight().c_str());
    199 
    200             GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    201             // TODO: compute all these offsets, spans, and scales in the VS
    202             fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
    203             fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
    204             fsBuilder->codeAppend("\tfloat outset = 0.5;\n");
    205             // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
    206             // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
    207             fsBuilder->codeAppend("\tfloat spanW = insetW + outset;\n");
    208             fsBuilder->codeAppend("\tfloat spanH = insetH + outset;\n");
    209             // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
    210             // value of coverage that is used. In other words it is the coverage that is
    211             // used in the interior of the rect after the ramp.
    212             fsBuilder->codeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n");
    213             fsBuilder->codeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n");
    214 
    215             // Compute the coverage for the rect's width
    216             fsBuilder->codeAppendf("\tvec2 offset = %s.xy - %s.xy;\n",
    217                                    fsBuilder->fragmentPosition(), fsRectEdgeName);
    218             fsBuilder->codeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n",
    219                                    fsRectEdgeName, fsRectEdgeName);
    220             fsBuilder->codeAppendf(
    221                 "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n",
    222                 fsWidthHeightName);
    223 
    224             // Compute the coverage for the rect's height and merge with the width
    225             fsBuilder->codeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n",
    226                                    fsRectEdgeName);
    227             fsBuilder->codeAppendf(
    228                     "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n",
    229                     fsWidthHeightName);
    230 
    231 
    232             fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
    233                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
    234         }
    235 
    236         static void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*) {}
    237 
    238         virtual void setData(const GrGLProgramDataManager& pdman, const GrProcessor&) SK_OVERRIDE {}
    239 
    240     private:
    241         typedef GrGLGeometryProcessor INHERITED;
    242     };
    243 
    244 
    245 
    246 private:
    247     GrRectEffect()
    248         : fInRectEdge(this->addVertexAttrib(GrShaderVar("inRectEdge",
    249                                                         kVec4f_GrSLType,
    250                                                         GrShaderVar::kAttribute_TypeModifier)))
    251         , fInWidthHeight(this->addVertexAttrib(
    252                 GrShaderVar("inWidthHeight",
    253                             kVec2f_GrSLType,
    254                             GrShaderVar::kAttribute_TypeModifier))) {
    255         this->setWillReadFragmentPosition();
    256     }
    257 
    258     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE { return true; }
    259 
    260     const GrShaderVar& fInRectEdge;
    261     const GrShaderVar& fInWidthHeight;
    262 
    263     GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
    264 
    265     typedef GrGeometryProcessor INHERITED;
    266 };
    267 
    268 
    269 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRectEffect);
    270 
    271 GrGeometryProcessor* GrRectEffect::TestCreate(SkRandom* random,
    272                                               GrContext* context,
    273                                               const GrDrawTargetCaps&,
    274                                               GrTexture* textures[]) {
    275     return GrRectEffect::Create();
    276 }
    277 
    278 ///////////////////////////////////////////////////////////////////////////////
    279 
    280 namespace {
    281 extern const GrVertexAttrib gAARectAttribs[] = {
    282     {kVec2f_GrVertexAttribType,  0,                                 kPosition_GrVertexAttribBinding},
    283     {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                   kColor_GrVertexAttribBinding},
    284     {kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
    285 };
    286 
    287 // Should the coverage be multiplied into the color attrib or use a separate attrib.
    288 enum CoverageAttribType {
    289     kUseColor_CoverageAttribType,
    290     kUseCoverage_CoverageAttribType,
    291 };
    292 }
    293 
    294 static CoverageAttribType set_rect_attribs(GrDrawState* drawState) {
    295     if (drawState->canTweakAlphaForCoverage()) {
    296         drawState->setVertexAttribs<gAARectAttribs>(2, sizeof(SkPoint) + sizeof(SkColor));
    297         return kUseColor_CoverageAttribType;
    298     } else {
    299         drawState->setVertexAttribs<gAARectAttribs>(3, sizeof(SkPoint) + 2 * sizeof(SkColor));
    300         return kUseCoverage_CoverageAttribType;
    301     }
    302 }
    303 
    304 static void set_inset_fan(SkPoint* pts, size_t stride,
    305                           const SkRect& r, SkScalar dx, SkScalar dy) {
    306     pts->setRectFan(r.fLeft + dx, r.fTop + dy,
    307                     r.fRight - dx, r.fBottom - dy, stride);
    308 }
    309 
    310 void GrAARectRenderer::reset() {
    311     SkSafeSetNull(fAAFillRectIndexBuffer);
    312     SkSafeSetNull(fAAMiterStrokeRectIndexBuffer);
    313     SkSafeSetNull(fAABevelStrokeRectIndexBuffer);
    314 }
    315 
    316 static const uint16_t gFillAARectIdx[] = {
    317     0, 1, 5, 5, 4, 0,
    318     1, 2, 6, 6, 5, 1,
    319     2, 3, 7, 7, 6, 2,
    320     3, 0, 4, 4, 7, 3,
    321     4, 5, 6, 6, 7, 4,
    322 };
    323 
    324 static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx);
    325 static const int kVertsPerAAFillRect = 8;
    326 static const int kNumAAFillRectsInIndexBuffer = 256;
    327 
    328 GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
    329     static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect *
    330                                                      sizeof(uint16_t) *
    331                                                      kNumAAFillRectsInIndexBuffer;
    332 
    333     if (NULL == fAAFillRectIndexBuffer) {
    334         fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
    335         if (fAAFillRectIndexBuffer) {
    336             uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->map();
    337             bool useTempData = (NULL == data);
    338             if (useTempData) {
    339                 data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect);
    340             }
    341             for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) {
    342                 // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around
    343                 // the inner rect (for AA) and 2 for the inner rect.
    344                 int baseIdx = i * kIndicesPerAAFillRect;
    345                 uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect);
    346                 for (int j = 0; j < kIndicesPerAAFillRect; ++j) {
    347                     data[baseIdx+j] = baseVert + gFillAARectIdx[j];
    348                 }
    349             }
    350             if (useTempData) {
    351                 if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
    352                     SkFAIL("Can't get AA Fill Rect indices into buffer!");
    353                 }
    354                 SkDELETE_ARRAY(data);
    355             } else {
    356                 fAAFillRectIndexBuffer->unmap();
    357             }
    358         }
    359     }
    360 
    361     return fAAFillRectIndexBuffer;
    362 }
    363 
    364 static const uint16_t gMiterStrokeAARectIdx[] = {
    365     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
    366     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
    367     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
    368     3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
    369 
    370     0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
    371     1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
    372     2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
    373     3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
    374 
    375     0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
    376     1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
    377     2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
    378     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
    379 };
    380 
    381 /**
    382  * As in miter-stroke, index = a + b, and a is the current index, b is the shift
    383  * from the first index. The index layout:
    384  * outer AA line: 0~3, 4~7
    385  * outer edge:    8~11, 12~15
    386  * inner edge:    16~19
    387  * inner AA line: 20~23
    388  * Following comes a bevel-stroke rect and its indices:
    389  *
    390  *           4                                 7
    391  *            *********************************
    392  *          *   ______________________________  *
    393  *         *  / 12                          15 \  *
    394  *        *  /                                  \  *
    395  *     0 *  |8     16_____________________19  11 |  * 3
    396  *       *  |       |                    |       |  *
    397  *       *  |       |  ****************  |       |  *
    398  *       *  |       |  * 20        23 *  |       |  *
    399  *       *  |       |  *              *  |       |  *
    400  *       *  |       |  * 21        22 *  |       |  *
    401  *       *  |       |  ****************  |       |  *
    402  *       *  |       |____________________|       |  *
    403  *     1 *  |9    17                      18   10|  * 2
    404  *        *  \                                  /  *
    405  *         *  \13 __________________________14/  *
    406  *          *                                   *
    407  *           **********************************
    408  *          5                                  6
    409  */
    410 static const uint16_t gBevelStrokeAARectIdx[] = {
    411     // Draw outer AA, from outer AA line to outer edge, shift is 0.
    412     0 + 0, 1 + 0, 9 + 0, 9 + 0, 8 + 0, 0 + 0,
    413     1 + 0, 5 + 0, 13 + 0, 13 + 0, 9 + 0, 1 + 0,
    414     5 + 0, 6 + 0, 14 + 0, 14 + 0, 13 + 0, 5 + 0,
    415     6 + 0, 2 + 0, 10 + 0, 10 + 0, 14 + 0, 6 + 0,
    416     2 + 0, 3 + 0, 11 + 0, 11 + 0, 10 + 0, 2 + 0,
    417     3 + 0, 7 + 0, 15 + 0, 15 + 0, 11 + 0, 3 + 0,
    418     7 + 0, 4 + 0, 12 + 0, 12 + 0, 15 + 0, 7 + 0,
    419     4 + 0, 0 + 0, 8 + 0, 8 + 0, 12 + 0, 4 + 0,
    420 
    421     // Draw the stroke, from outer edge to inner edge, shift is 8.
    422     0 + 8, 1 + 8, 9 + 8, 9 + 8, 8 + 8, 0 + 8,
    423     1 + 8, 5 + 8, 9 + 8,
    424     5 + 8, 6 + 8, 10 + 8, 10 + 8, 9 + 8, 5 + 8,
    425     6 + 8, 2 + 8, 10 + 8,
    426     2 + 8, 3 + 8, 11 + 8, 11 + 8, 10 + 8, 2 + 8,
    427     3 + 8, 7 + 8, 11 + 8,
    428     7 + 8, 4 + 8, 8 + 8, 8 + 8, 11 + 8, 7 + 8,
    429     4 + 8, 0 + 8, 8 + 8,
    430 
    431     // Draw the inner AA, from inner edge to inner AA line, shift is 16.
    432     0 + 16, 1 + 16, 5 + 16, 5 + 16, 4 + 16, 0 + 16,
    433     1 + 16, 2 + 16, 6 + 16, 6 + 16, 5 + 16, 1 + 16,
    434     2 + 16, 3 + 16, 7 + 16, 7 + 16, 6 + 16, 2 + 16,
    435     3 + 16, 0 + 16, 4 + 16, 4 + 16, 7 + 16, 3 + 16,
    436 };
    437 
    438 int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) {
    439     return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) :
    440                          SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
    441 }
    442 
    443 GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) {
    444     if (miterStroke) {
    445         if (NULL == fAAMiterStrokeRectIndexBuffer) {
    446             fAAMiterStrokeRectIndexBuffer =
    447                 gpu->createIndexBuffer(sizeof(gMiterStrokeAARectIdx), false);
    448             if (fAAMiterStrokeRectIndexBuffer) {
    449 #ifdef SK_DEBUG
    450                 bool updated =
    451 #endif
    452                 fAAMiterStrokeRectIndexBuffer->updateData(gMiterStrokeAARectIdx,
    453                                                           sizeof(gMiterStrokeAARectIdx));
    454                 GR_DEBUGASSERT(updated);
    455             }
    456         }
    457         return fAAMiterStrokeRectIndexBuffer;
    458     } else {
    459         if (NULL == fAABevelStrokeRectIndexBuffer) {
    460             fAABevelStrokeRectIndexBuffer =
    461                 gpu->createIndexBuffer(sizeof(gBevelStrokeAARectIdx), false);
    462             if (fAABevelStrokeRectIndexBuffer) {
    463 #ifdef SK_DEBUG
    464                 bool updated =
    465 #endif
    466                 fAABevelStrokeRectIndexBuffer->updateData(gBevelStrokeAARectIdx,
    467                                                           sizeof(gBevelStrokeAARectIdx));
    468                 GR_DEBUGASSERT(updated);
    469             }
    470         }
    471         return fAABevelStrokeRectIndexBuffer;
    472     }
    473 }
    474 
    475 void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
    476                                           GrDrawTarget* target,
    477                                           const SkRect& rect,
    478                                           const SkMatrix& combinedMatrix,
    479                                           const SkRect& devRect) {
    480     GrDrawState* drawState = target->drawState();
    481 
    482     GrColor color = drawState->getColor();
    483 
    484     CoverageAttribType covAttribType = set_rect_attribs(drawState);
    485     if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) {
    486         drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
    487     }
    488 
    489     GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
    490     if (!geo.succeeded()) {
    491         GrPrintf("Failed to get space for vertices!\n");
    492         return;
    493     }
    494 
    495     GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
    496     if (NULL == indexBuffer) {
    497         GrPrintf("Failed to create index buffer!\n");
    498         return;
    499     }
    500 
    501     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    502     size_t vstride = drawState->getVertexStride();
    503 
    504     SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
    505     SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vstride);
    506 
    507     SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
    508     inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
    509 
    510     if (combinedMatrix.rectStaysRect()) {
    511         // Temporarily #if'ed out. We don't want to pass in the devRect but
    512         // right now it is computed in GrContext::apply_aa_to_rect and we don't
    513         // want to throw away the work
    514 #if 0
    515         SkRect devRect;
    516         combinedMatrix.mapRect(&devRect, rect);
    517 #endif
    518 
    519         set_inset_fan(fan0Pos, vstride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
    520         set_inset_fan(fan1Pos, vstride, devRect, inset,  inset);
    521     } else {
    522         // compute transformed (1, 0) and (0, 1) vectors
    523         SkVector vec[2] = {
    524           { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
    525           { combinedMatrix[SkMatrix::kMSkewX],  combinedMatrix[SkMatrix::kMScaleY] }
    526         };
    527 
    528         vec[0].normalize();
    529         vec[0].scale(SK_ScalarHalf);
    530         vec[1].normalize();
    531         vec[1].scale(SK_ScalarHalf);
    532 
    533         // create the rotated rect
    534         fan0Pos->setRectFan(rect.fLeft, rect.fTop,
    535                             rect.fRight, rect.fBottom, vstride);
    536         combinedMatrix.mapPointsWithStride(fan0Pos, vstride, 4);
    537 
    538         // Now create the inset points and then outset the original
    539         // rotated points
    540 
    541         // TL
    542         *((SkPoint*)((intptr_t)fan1Pos + 0 * vstride)) =
    543             *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) + vec[0] + vec[1];
    544         *((SkPoint*)((intptr_t)fan0Pos + 0 * vstride)) -= vec[0] + vec[1];
    545         // BL
    546         *((SkPoint*)((intptr_t)fan1Pos + 1 * vstride)) =
    547             *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) + vec[0] - vec[1];
    548         *((SkPoint*)((intptr_t)fan0Pos + 1 * vstride)) -= vec[0] - vec[1];
    549         // BR
    550         *((SkPoint*)((intptr_t)fan1Pos + 2 * vstride)) =
    551             *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) - vec[0] - vec[1];
    552         *((SkPoint*)((intptr_t)fan0Pos + 2 * vstride)) += vec[0] + vec[1];
    553         // TR
    554         *((SkPoint*)((intptr_t)fan1Pos + 3 * vstride)) =
    555             *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) - vec[0] + vec[1];
    556         *((SkPoint*)((intptr_t)fan0Pos + 3 * vstride)) += vec[0] - vec[1];
    557     }
    558 
    559     // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
    560     verts += sizeof(SkPoint);
    561     for (int i = 0; i < 4; ++i) {
    562         if (kUseCoverage_CoverageAttribType == covAttribType) {
    563             *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
    564             *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
    565         } else {
    566             *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
    567         }
    568     }
    569 
    570     int scale;
    571     if (inset < SK_ScalarHalf) {
    572         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
    573         SkASSERT(scale >= 0 && scale <= 255);
    574     } else {
    575         scale = 0xff;
    576     }
    577 
    578     GrColor innerCoverage;
    579     if (kUseCoverage_CoverageAttribType == covAttribType) {
    580         innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
    581     } else {
    582         innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
    583     }
    584     verts += 4 * vstride;
    585     for (int i = 0; i < 4; ++i) {
    586         if (kUseCoverage_CoverageAttribType == covAttribType) {
    587             *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
    588             *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage;
    589         } else {
    590             *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage;
    591         }
    592     }
    593 
    594     target->setIndexSourceToBuffer(indexBuffer);
    595     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
    596                                  kVertsPerAAFillRect,
    597                                  kIndicesPerAAFillRect);
    598     target->resetIndexSource();
    599 }
    600 
    601 namespace {
    602 
    603 // Rotated
    604 struct RectVertex {
    605     SkPoint fPos;
    606     SkPoint fCenter;
    607     SkPoint fDir;
    608     SkPoint fWidthHeight;
    609 };
    610 
    611 // Rotated
    612 extern const GrVertexAttrib gAARectVertexAttribs[] = {
    613     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
    614     { kVec4f_GrVertexAttribType, sizeof(SkPoint),   kGeometryProcessor_GrVertexAttribBinding },
    615     { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding }
    616 };
    617 
    618 // Axis Aligned
    619 struct AARectVertex {
    620     SkPoint fPos;
    621     SkPoint fOffset;
    622     SkPoint fWidthHeight;
    623 };
    624 
    625 // Axis Aligned
    626 extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
    627     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
    628     { kVec4f_GrVertexAttribType, sizeof(SkPoint),   kGeometryProcessor_GrVertexAttribBinding },
    629 };
    630 
    631 };
    632 
    633 void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
    634                                         GrDrawTarget* target,
    635                                         const SkRect& rect,
    636                                         const SkMatrix& combinedMatrix) {
    637     GrDrawState* drawState = target->drawState();
    638 
    639     SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
    640     combinedMatrix.mapPoints(&center, 1);
    641 
    642     // compute transformed (0, 1) vector
    643     SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] };
    644     dir.normalize();
    645 
    646     // compute transformed (width, 0) and (0, height) vectors
    647     SkVector vec[2] = {
    648       { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
    649       { combinedMatrix[SkMatrix::kMSkewX],  combinedMatrix[SkMatrix::kMScaleY] }
    650     };
    651 
    652     SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf;
    653     SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf;
    654     drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs),
    655                                                       sizeof(RectVertex));
    656 
    657     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    658     if (!geo.succeeded()) {
    659         GrPrintf("Failed to get space for vertices!\n");
    660         return;
    661     }
    662 
    663     RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices());
    664 
    665     GrGeometryProcessor* gp = GrRectEffect::Create();
    666     drawState->setGeometryProcessor(gp)->unref();
    667 
    668     for (int i = 0; i < 4; ++i) {
    669         verts[i].fCenter = center;
    670         verts[i].fDir = dir;
    671         verts[i].fWidthHeight.fX = newWidth;
    672         verts[i].fWidthHeight.fY = newHeight;
    673     }
    674 
    675     SkRect devRect;
    676     combinedMatrix.mapRect(&devRect, rect);
    677 
    678     SkRect devBounds = {
    679         devRect.fLeft   - SK_ScalarHalf,
    680         devRect.fTop    - SK_ScalarHalf,
    681         devRect.fRight  + SK_ScalarHalf,
    682         devRect.fBottom + SK_ScalarHalf
    683     };
    684 
    685     verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
    686     verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
    687     verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
    688     verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
    689 
    690     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
    691     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
    692     target->resetIndexSource();
    693 }
    694 
    695 void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
    696                                                GrDrawTarget* target,
    697                                                const SkRect& rect,
    698                                                const SkMatrix& combinedMatrix) {
    699     GrDrawState* drawState = target->drawState();
    700     SkASSERT(combinedMatrix.rectStaysRect());
    701 
    702     drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs),
    703                                                         sizeof(AARectVertex));
    704 
    705     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    706     if (!geo.succeeded()) {
    707         GrPrintf("Failed to get space for vertices!\n");
    708         return;
    709     }
    710 
    711     AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices());
    712 
    713     GrGeometryProcessor* gp = GrAlignedRectEffect::Create();
    714     drawState->setGeometryProcessor(gp)->unref();
    715 
    716     SkRect devRect;
    717     combinedMatrix.mapRect(&devRect, rect);
    718 
    719     SkRect devBounds = {
    720         devRect.fLeft   - SK_ScalarHalf,
    721         devRect.fTop    - SK_ScalarHalf,
    722         devRect.fRight  + SK_ScalarHalf,
    723         devRect.fBottom + SK_ScalarHalf
    724     };
    725 
    726     SkPoint widthHeight = {
    727         SkScalarHalf(devRect.width()) + SK_ScalarHalf,
    728         SkScalarHalf(devRect.height()) + SK_ScalarHalf
    729     };
    730 
    731     verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
    732     verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY);
    733     verts[0].fWidthHeight = widthHeight;
    734 
    735     verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
    736     verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY);
    737     verts[1].fWidthHeight = widthHeight;
    738 
    739     verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
    740     verts[2].fOffset = widthHeight;
    741     verts[2].fWidthHeight = widthHeight;
    742 
    743     verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
    744     verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY);
    745     verts[3].fWidthHeight = widthHeight;
    746 
    747     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
    748     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
    749     target->resetIndexSource();
    750 }
    751 
    752 void GrAARectRenderer::strokeAARect(GrGpu* gpu,
    753                                     GrDrawTarget* target,
    754                                     const SkRect& rect,
    755                                     const SkMatrix& combinedMatrix,
    756                                     const SkRect& devRect,
    757                                     const SkStrokeRec& stroke) {
    758     SkVector devStrokeSize;
    759     SkScalar width = stroke.getWidth();
    760     if (width > 0) {
    761         devStrokeSize.set(width, width);
    762         combinedMatrix.mapVectors(&devStrokeSize, 1);
    763         devStrokeSize.setAbs(devStrokeSize);
    764     } else {
    765         devStrokeSize.set(SK_Scalar1, SK_Scalar1);
    766     }
    767 
    768     const SkScalar dx = devStrokeSize.fX;
    769     const SkScalar dy = devStrokeSize.fY;
    770     const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
    771     const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
    772 
    773     // Temporarily #if'ed out. We don't want to pass in the devRect but
    774     // right now it is computed in GrContext::apply_aa_to_rect and we don't
    775     // want to throw away the work
    776 #if 0
    777     SkRect devRect;
    778     combinedMatrix.mapRect(&devRect, rect);
    779 #endif
    780 
    781     SkScalar spare;
    782     {
    783         SkScalar w = devRect.width() - dx;
    784         SkScalar h = devRect.height() - dy;
    785         spare = SkTMin(w, h);
    786     }
    787 
    788     SkRect devOutside(devRect);
    789     devOutside.outset(rx, ry);
    790 
    791     bool miterStroke = true;
    792     // For hairlines, make bevel and round joins appear the same as mitered ones.
    793     // small miter limit means right angles show bevel...
    794     if ((width > 0) && (stroke.getJoin() != SkPaint::kMiter_Join ||
    795                         stroke.getMiter() < SK_ScalarSqrt2)) {
    796         miterStroke = false;
    797     }
    798 
    799     if (spare <= 0 && miterStroke) {
    800         this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
    801         return;
    802     }
    803 
    804     SkRect devInside(devRect);
    805     devInside.inset(rx, ry);
    806 
    807     SkRect devOutsideAssist(devRect);
    808 
    809     // For bevel-stroke, use 2 SkRect instances(devOutside and devOutsideAssist)
    810     // to draw the outer of the rect. Because there are 8 vertices on the outer
    811     // edge, while vertex number of inner edge is 4, the same as miter-stroke.
    812     if (!miterStroke) {
    813         devOutside.inset(0, ry);
    814         devOutsideAssist.outset(0, ry);
    815     }
    816 
    817     this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, miterStroke);
    818 }
    819 
    820 void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
    821                                             GrDrawTarget* target,
    822                                             const SkRect& devOutside,
    823                                             const SkRect& devOutsideAssist,
    824                                             const SkRect& devInside,
    825                                             bool miterStroke) {
    826     GrDrawState* drawState = target->drawState();
    827 
    828     CoverageAttribType covAttribType = set_rect_attribs(drawState);
    829 
    830     GrColor color = drawState->getColor();
    831     if (kUseCoverage_CoverageAttribType == covAttribType && GrColorIsOpaque(color)) {
    832         drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
    833     }
    834 
    835     int innerVertexNum = 4;
    836     int outerVertexNum = miterStroke ? 4 : 8;
    837     int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
    838 
    839     GrDrawTarget::AutoReleaseGeometry geo(target, totalVertexNum, 0);
    840     if (!geo.succeeded()) {
    841         GrPrintf("Failed to get space for vertices!\n");
    842         return;
    843     }
    844     GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu, miterStroke);
    845     if (NULL == indexBuffer) {
    846         GrPrintf("Failed to create index buffer!\n");
    847         return;
    848     }
    849 
    850     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    851     size_t vstride = drawState->getVertexStride();
    852 
    853     // We create vertices for four nested rectangles. There are two ramps from 0 to full
    854     // coverage, one on the exterior of the stroke and the other on the interior.
    855     // The following pointers refer to the four rects, from outermost to innermost.
    856     SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
    857     SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vstride);
    858     SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vstride);
    859     SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vstride);
    860 
    861 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
    862     // TODO: this only really works if the X & Y margins are the same all around
    863     // the rect
    864     SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight);
    865     inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
    866     inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
    867     if (miterStroke) {
    868         inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom);
    869     } else {
    870         inset = SK_ScalarHalf * SkMinScalar(inset, devOutsideAssist.fBottom - devInside.fBottom);
    871     }
    872     SkASSERT(inset >= 0);
    873 #else
    874     SkScalar inset = SK_ScalarHalf;
    875 #endif
    876 
    877     if (miterStroke) {
    878         // outermost
    879         set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
    880         // inner two
    881         set_inset_fan(fan1Pos, vstride, devOutside,  inset,  inset);
    882         set_inset_fan(fan2Pos, vstride, devInside,  -inset, -inset);
    883         // innermost
    884         set_inset_fan(fan3Pos, vstride, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
    885     } else {
    886         SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vstride);
    887         SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vstride);
    888         // outermost
    889         set_inset_fan(fan0Pos, vstride, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
    890         set_inset_fan(fan0AssistPos, vstride, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf);
    891         // outer one of the inner two
    892         set_inset_fan(fan1Pos, vstride, devOutside,  inset,  inset);
    893         set_inset_fan(fan1AssistPos, vstride, devOutsideAssist,  inset,  inset);
    894         // inner one of the inner two
    895         set_inset_fan(fan2Pos, vstride, devInside,  -inset, -inset);
    896         // innermost
    897         set_inset_fan(fan3Pos, vstride, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
    898     }
    899 
    900     // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
    901     // The outermost rect has 0 coverage
    902     verts += sizeof(SkPoint);
    903     for (int i = 0; i < outerVertexNum; ++i) {
    904         if (kUseCoverage_CoverageAttribType == covAttribType) {
    905             *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
    906             *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
    907         } else {
    908             *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
    909         }
    910     }
    911 
    912     // scale is the coverage for the the inner two rects.
    913     int scale;
    914     if (inset < SK_ScalarHalf) {
    915         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
    916         SkASSERT(scale >= 0 && scale <= 255);
    917     } else {
    918         scale = 0xff;
    919     }
    920 
    921     verts += outerVertexNum * vstride;
    922     GrColor innerCoverage;
    923     if (kUseCoverage_CoverageAttribType == covAttribType) {
    924         innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
    925     } else {
    926         innerCoverage = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
    927     }
    928 
    929     for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
    930         if (kUseCoverage_CoverageAttribType == covAttribType) {
    931             *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
    932             *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = innerCoverage;
    933         } else {
    934             *reinterpret_cast<GrColor*>(verts + i * vstride) = innerCoverage;
    935         }
    936     }
    937 
    938     // The innermost rect has 0 coverage
    939     verts += (outerVertexNum + innerVertexNum) * vstride;
    940     for (int i = 0; i < innerVertexNum; ++i) {
    941         if (kUseCoverage_CoverageAttribType == covAttribType) {
    942             *reinterpret_cast<GrColor*>(verts + i * vstride) = color;
    943             *reinterpret_cast<GrColor*>(verts + i * vstride + sizeof(GrColor)) = 0;
    944         } else {
    945             *reinterpret_cast<GrColor*>(verts + i * vstride) = 0;
    946         }
    947     }
    948 
    949     target->setIndexSourceToBuffer(indexBuffer);
    950     target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0,
    951                         totalVertexNum, aaStrokeRectIndexCount(miterStroke));
    952 }
    953 
    954 void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
    955                                          GrDrawTarget* target,
    956                                          const SkRect rects[2],
    957                                          const SkMatrix& combinedMatrix) {
    958     SkASSERT(combinedMatrix.rectStaysRect());
    959     SkASSERT(!rects[1].isEmpty());
    960 
    961     SkRect devOutside, devOutsideAssist, devInside;
    962     combinedMatrix.mapRect(&devOutside, rects[0]);
    963     // can't call mapRect for devInside since it calls sort
    964     combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
    965 
    966     if (devInside.isEmpty()) {
    967         this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
    968         return;
    969     }
    970 
    971     this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, true);
    972 }
    973