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