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 "GrRefCnt.h"
     10 #include "GrGpu.h"
     11 #include "gl/GrGLEffect.h"
     12 #include "GrTBackendEffectFactory.h"
     13 #include "SkColorPriv.h"
     14 
     15 SK_DEFINE_INST_COUNT(GrAARectRenderer)
     16 
     17 ///////////////////////////////////////////////////////////////////////////////
     18 class GrGLAlignedRectEffect;
     19 
     20 // Axis Aligned special case
     21 class GrAlignedRectEffect : public GrEffect {
     22 public:
     23     static GrEffectRef* Create() {
     24         GR_CREATE_STATIC_EFFECT(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     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
     39         return GrTBackendEffectFactory<GrAlignedRectEffect>::getInstance();
     40     }
     41 
     42     class GLEffect : public GrGLEffect {
     43     public:
     44         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
     45         : INHERITED (factory) {}
     46 
     47         virtual void emitCode(GrGLShaderBuilder* builder,
     48                               const GrDrawEffect& drawEffect,
     49                               EffectKey key,
     50                               const char* outputColor,
     51                               const char* inputColor,
     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             SkString modulate;
     86             GrGLSLModulatef<4>(&modulate, inputColor, "coverage");
     87             builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.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 GrGLEffect INHERITED;
     98     };
     99 
    100 
    101 private:
    102     GrAlignedRectEffect() : GrEffect() {
    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 GrEffect INHERITED;
    111 };
    112 
    113 
    114 GR_DEFINE_EFFECT_TEST(GrAlignedRectEffect);
    115 
    116 GrEffectRef* GrAlignedRectEffect::TestCreate(SkMWCRandom* 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 GrEffect {
    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 GrGLEffect {
    160     public:
    161         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    162         : INHERITED (factory) {}
    163 
    164         virtual void emitCode(GrGLShaderBuilder* builder,
    165                               const GrDrawEffect& drawEffect,
    166                               EffectKey key,
    167                               const char* outputColor,
    168                               const char* inputColor,
    169                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    170             // setup the varying for the center point and the unit vector
    171             // that points down the height of the rect
    172             const char *vsRectEdgeName, *fsRectEdgeName;
    173             builder->addVarying(kVec4f_GrSLType, "RectEdge",
    174                                 &vsRectEdgeName, &fsRectEdgeName);
    175             const SkString* attr0Name =
    176                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    177             builder->vsCodeAppendf("\t%s = %s;\n", vsRectEdgeName, attr0Name->c_str());
    178 
    179             // setup the varying for width/2+.5 and height/2+.5
    180             const char *vsWidthHeightName, *fsWidthHeightName;
    181             builder->addVarying(kVec2f_GrSLType, "WidthHeight",
    182                                 &vsWidthHeightName, &fsWidthHeightName);
    183             const SkString* attr1Name =
    184                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
    185             builder->vsCodeAppendf("\t%s = %s;\n", vsWidthHeightName, attr1Name->c_str());
    186 
    187             // TODO: compute all these offsets, spans, and scales in the VS
    188             builder->fsCodeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
    189             builder->fsCodeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
    190             builder->fsCodeAppend("\tfloat outset = 0.5;\n");
    191             // For rects > 1 pixel wide and tall the span's are noops (i.e., 1.0). For rects
    192             // < 1 pixel wide or tall they serve to normalize the < 1 ramp to a 0 .. 1 range.
    193             builder->fsCodeAppend("\tfloat spanW = insetW + outset;\n");
    194             builder->fsCodeAppend("\tfloat spanH = insetH + outset;\n");
    195             // For rects < 1 pixel wide or tall, these scale factors are used to cap the maximum
    196             // value of coverage that is used. In other words it is the coverage that is
    197             // used in the interior of the rect after the ramp.
    198             builder->fsCodeAppend("\tfloat scaleW = min(1.0, 2.0*insetW/spanW);\n");
    199             builder->fsCodeAppend("\tfloat scaleH = min(1.0, 2.0*insetH/spanH);\n");
    200 
    201             // Compute the coverage for the rect's width
    202             builder->fsCodeAppendf("\tvec2 offset = %s.xy - %s.xy;\n",
    203                                    builder->fragmentPosition(), fsRectEdgeName);
    204             builder->fsCodeAppendf("\tfloat perpDot = abs(offset.x * %s.w - offset.y * %s.z);\n",
    205                                    fsRectEdgeName, fsRectEdgeName);
    206             builder->fsCodeAppendf(
    207                 "\tfloat coverage = scaleW*clamp((%s.x-perpDot)/spanW, 0.0, 1.0);\n",
    208                 fsWidthHeightName);
    209 
    210             // Compute the coverage for the rect's height and merge with the width
    211             builder->fsCodeAppendf("\tperpDot = abs(dot(offset, %s.zw));\n",
    212                                    fsRectEdgeName);
    213             builder->fsCodeAppendf(
    214                     "\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n",
    215                     fsWidthHeightName);
    216 
    217             SkString modulate;
    218             GrGLSLModulatef<4>(&modulate, inputColor, "coverage");
    219             builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
    220         }
    221 
    222         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    223             return 0;
    224         }
    225 
    226         virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {}
    227 
    228     private:
    229         typedef GrGLEffect INHERITED;
    230     };
    231 
    232 
    233 private:
    234     GrRectEffect() : GrEffect() {
    235         this->addVertexAttrib(kVec4f_GrSLType);
    236         this->addVertexAttrib(kVec2f_GrSLType);
    237         this->setWillReadFragmentPosition();
    238     }
    239 
    240     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; }
    241 
    242     GR_DECLARE_EFFECT_TEST;
    243 
    244     typedef GrEffect INHERITED;
    245 };
    246 
    247 
    248 GR_DEFINE_EFFECT_TEST(GrRectEffect);
    249 
    250 GrEffectRef* GrRectEffect::TestCreate(SkMWCRandom* random,
    251                                       GrContext* context,
    252                                       const GrDrawTargetCaps&,
    253                                       GrTexture* textures[]) {
    254     return GrRectEffect::Create();
    255 }
    256 
    257 ///////////////////////////////////////////////////////////////////////////////
    258 
    259 namespace {
    260 
    261 extern const GrVertexAttrib gAARectCoverageAttribs[] = {
    262     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
    263     {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
    264 };
    265 
    266 extern const GrVertexAttrib gAARectColorAttribs[] = {
    267     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
    268     {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
    269 };
    270 
    271 static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) {
    272     if (useCoverage) {
    273         drawState->setVertexAttribs<gAARectCoverageAttribs>(SK_ARRAY_COUNT(gAARectCoverageAttribs));
    274     } else {
    275         drawState->setVertexAttribs<gAARectColorAttribs>(SK_ARRAY_COUNT(gAARectColorAttribs));
    276     }
    277 }
    278 
    279 static void set_inset_fan(GrPoint* pts, size_t stride,
    280                           const SkRect& r, SkScalar dx, SkScalar dy) {
    281     pts->setRectFan(r.fLeft + dx, r.fTop + dy,
    282                     r.fRight - dx, r.fBottom - dy, stride);
    283 }
    284 
    285 };
    286 
    287 void GrAARectRenderer::reset() {
    288     GrSafeSetNull(fAAFillRectIndexBuffer);
    289     GrSafeSetNull(fAAStrokeRectIndexBuffer);
    290 }
    291 
    292 static const uint16_t gFillAARectIdx[] = {
    293     0, 1, 5, 5, 4, 0,
    294     1, 2, 6, 6, 5, 1,
    295     2, 3, 7, 7, 6, 2,
    296     3, 0, 4, 4, 7, 3,
    297     4, 5, 6, 6, 7, 4,
    298 };
    299 
    300 static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx);
    301 static const int kVertsPerAAFillRect = 8;
    302 static const int kNumAAFillRectsInIndexBuffer = 256;
    303 
    304 GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
    305     static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect *
    306                                                      sizeof(uint16_t) *
    307                                                      kNumAAFillRectsInIndexBuffer;
    308 
    309     if (NULL == fAAFillRectIndexBuffer) {
    310         fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
    311         if (NULL != fAAFillRectIndexBuffer) {
    312             uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock();
    313             bool useTempData = (NULL == data);
    314             if (useTempData) {
    315                 data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect);
    316             }
    317             for (int i = 0; i < kNumAAFillRectsInIndexBuffer; ++i) {
    318                 // Each AA filled rect is drawn with 8 vertices and 10 triangles (8 around
    319                 // the inner rect (for AA) and 2 for the inner rect.
    320                 int baseIdx = i * kIndicesPerAAFillRect;
    321                 uint16_t baseVert = (uint16_t)(i * kVertsPerAAFillRect);
    322                 for (int j = 0; j < kIndicesPerAAFillRect; ++j) {
    323                     data[baseIdx+j] = baseVert + gFillAARectIdx[j];
    324                 }
    325             }
    326             if (useTempData) {
    327                 if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
    328                     GrCrash("Can't get AA Fill Rect indices into buffer!");
    329                 }
    330                 SkDELETE_ARRAY(data);
    331             } else {
    332                 fAAFillRectIndexBuffer->unlock();
    333             }
    334         }
    335     }
    336 
    337     return fAAFillRectIndexBuffer;
    338 }
    339 
    340 static const uint16_t gStrokeAARectIdx[] = {
    341     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
    342     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
    343     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
    344     3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
    345 
    346     0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
    347     1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
    348     2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
    349     3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
    350 
    351     0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
    352     1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
    353     2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
    354     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
    355 };
    356 
    357 int GrAARectRenderer::aaStrokeRectIndexCount() {
    358     return GR_ARRAY_COUNT(gStrokeAARectIdx);
    359 }
    360 
    361 GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu) {
    362     if (NULL == fAAStrokeRectIndexBuffer) {
    363         fAAStrokeRectIndexBuffer =
    364                   gpu->createIndexBuffer(sizeof(gStrokeAARectIdx), false);
    365         if (NULL != fAAStrokeRectIndexBuffer) {
    366 #if GR_DEBUG
    367             bool updated =
    368 #endif
    369             fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
    370                                                  sizeof(gStrokeAARectIdx));
    371             GR_DEBUGASSERT(updated);
    372         }
    373     }
    374     return fAAStrokeRectIndexBuffer;
    375 }
    376 
    377 void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
    378                                           GrDrawTarget* target,
    379                                           const SkRect& rect,
    380                                           const SkMatrix& combinedMatrix,
    381                                           const SkRect& devRect,
    382                                           bool useVertexCoverage) {
    383     GrDrawState* drawState = target->drawState();
    384 
    385     set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
    386 
    387     GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
    388     if (!geo.succeeded()) {
    389         GrPrintf("Failed to get space for vertices!\n");
    390         return;
    391     }
    392 
    393     GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
    394     if (NULL == indexBuffer) {
    395         GrPrintf("Failed to create index buffer!\n");
    396         return;
    397     }
    398 
    399     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    400     size_t vsize = drawState->getVertexSize();
    401     GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize);
    402 
    403     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    404     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    405 
    406     SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
    407     inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
    408 
    409     if (combinedMatrix.rectStaysRect()) {
    410         // Temporarily #if'ed out. We don't want to pass in the devRect but
    411         // right now it is computed in GrContext::apply_aa_to_rect and we don't
    412         // want to throw away the work
    413 #if 0
    414         SkRect devRect;
    415         combinedMatrix.mapRect(&devRect, rect);
    416 #endif
    417 
    418         set_inset_fan(fan0Pos, vsize, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
    419         set_inset_fan(fan1Pos, vsize, devRect, inset,  inset);
    420     } else {
    421         // compute transformed (1, 0) and (0, 1) vectors
    422         SkVector vec[2] = {
    423           { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
    424           { combinedMatrix[SkMatrix::kMSkewX],  combinedMatrix[SkMatrix::kMScaleY] }
    425         };
    426 
    427         vec[0].normalize();
    428         vec[0].scale(SK_ScalarHalf);
    429         vec[1].normalize();
    430         vec[1].scale(SK_ScalarHalf);
    431 
    432         // create the rotated rect
    433         fan0Pos->setRectFan(rect.fLeft, rect.fTop,
    434                             rect.fRight, rect.fBottom, vsize);
    435         combinedMatrix.mapPointsWithStride(fan0Pos, vsize, 4);
    436 
    437         // Now create the inset points and then outset the original
    438         // rotated points
    439 
    440         // TL
    441         *((SkPoint*)((intptr_t)fan1Pos + 0 * vsize)) =
    442             *((SkPoint*)((intptr_t)fan0Pos + 0 * vsize)) + vec[0] + vec[1];
    443         *((SkPoint*)((intptr_t)fan0Pos + 0 * vsize)) -= vec[0] + vec[1];
    444         // BL
    445         *((SkPoint*)((intptr_t)fan1Pos + 1 * vsize)) =
    446             *((SkPoint*)((intptr_t)fan0Pos + 1 * vsize)) + vec[0] - vec[1];
    447         *((SkPoint*)((intptr_t)fan0Pos + 1 * vsize)) -= vec[0] - vec[1];
    448         // BR
    449         *((SkPoint*)((intptr_t)fan1Pos + 2 * vsize)) =
    450             *((SkPoint*)((intptr_t)fan0Pos + 2 * vsize)) - vec[0] - vec[1];
    451         *((SkPoint*)((intptr_t)fan0Pos + 2 * vsize)) += vec[0] + vec[1];
    452         // TR
    453         *((SkPoint*)((intptr_t)fan1Pos + 3 * vsize)) =
    454             *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) - vec[0] + vec[1];
    455         *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1];
    456     }
    457 
    458     verts += sizeof(GrPoint);
    459     for (int i = 0; i < 4; ++i) {
    460         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    461     }
    462 
    463     int scale;
    464     if (inset < SK_ScalarHalf) {
    465         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
    466         SkASSERT(scale >= 0 && scale <= 255);
    467     } else {
    468         scale = 0xff;
    469     }
    470 
    471     GrColor innerColor;
    472     if (useVertexCoverage) {
    473         innerColor = GrColorPackRGBA(scale, scale, scale, scale);
    474     } else {
    475         if (0xff == scale) {
    476             innerColor = target->getDrawState().getColor();
    477         } else {
    478             innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
    479         }
    480     }
    481 
    482     verts += 4 * vsize;
    483     for (int i = 0; i < 4; ++i) {
    484         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    485     }
    486 
    487     target->setIndexSourceToBuffer(indexBuffer);
    488     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
    489                                  kVertsPerAAFillRect,
    490                                  kIndicesPerAAFillRect);
    491     target->resetIndexSource();
    492 }
    493 
    494 namespace {
    495 
    496 // Rotated
    497 struct RectVertex {
    498     GrPoint fPos;
    499     GrPoint fCenter;
    500     GrPoint fDir;
    501     GrPoint fWidthHeight;
    502 };
    503 
    504 // Rotated
    505 extern const GrVertexAttrib gAARectVertexAttribs[] = {
    506     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
    507     { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
    508     { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
    509 };
    510 
    511 // Axis Aligned
    512 struct AARectVertex {
    513     GrPoint fPos;
    514     GrPoint fOffset;
    515     GrPoint fWidthHeight;
    516 };
    517 
    518 // Axis Aligned
    519 extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
    520     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
    521     { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
    522 };
    523 
    524 };
    525 
    526 void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
    527                                         GrDrawTarget* target,
    528                                         const SkRect& rect,
    529                                         const SkMatrix& combinedMatrix) {
    530     GrDrawState* drawState = target->drawState();
    531 
    532     SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
    533     combinedMatrix.mapPoints(&center, 1);
    534 
    535     // compute transformed (0, 1) vector
    536     SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] };
    537     dir.normalize();
    538 
    539     // compute transformed (width, 0) and (0, height) vectors
    540     SkVector vec[2] = {
    541       { combinedMatrix[SkMatrix::kMScaleX], combinedMatrix[SkMatrix::kMSkewY] },
    542       { combinedMatrix[SkMatrix::kMSkewX],  combinedMatrix[SkMatrix::kMScaleY] }
    543     };
    544 
    545     SkScalar newWidth = SkScalarHalf(rect.width() * vec[0].length()) + SK_ScalarHalf;
    546     SkScalar newHeight = SkScalarHalf(rect.height() * vec[1].length()) + SK_ScalarHalf;
    547     drawState->setVertexAttribs<gAARectVertexAttribs>(SK_ARRAY_COUNT(gAARectVertexAttribs));
    548     GrAssert(sizeof(RectVertex) == drawState->getVertexSize());
    549 
    550     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    551     if (!geo.succeeded()) {
    552         GrPrintf("Failed to get space for vertices!\n");
    553         return;
    554     }
    555 
    556     RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices());
    557 
    558     GrEffectRef* effect = GrRectEffect::Create();
    559     static const int kRectAttrIndex = 1;
    560     static const int kWidthIndex = 2;
    561     drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref();
    562 
    563     for (int i = 0; i < 4; ++i) {
    564         verts[i].fCenter = center;
    565         verts[i].fDir = dir;
    566         verts[i].fWidthHeight.fX = newWidth;
    567         verts[i].fWidthHeight.fY = newHeight;
    568     }
    569 
    570     SkRect devRect;
    571     combinedMatrix.mapRect(&devRect, rect);
    572 
    573     SkRect devBounds = {
    574         devRect.fLeft   - SK_ScalarHalf,
    575         devRect.fTop    - SK_ScalarHalf,
    576         devRect.fRight  + SK_ScalarHalf,
    577         devRect.fBottom + SK_ScalarHalf
    578     };
    579 
    580     verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
    581     verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
    582     verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
    583     verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
    584 
    585     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
    586     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
    587     target->resetIndexSource();
    588 }
    589 
    590 void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
    591                                                GrDrawTarget* target,
    592                                                const SkRect& rect,
    593                                                const SkMatrix& combinedMatrix) {
    594     GrDrawState* drawState = target->drawState();
    595     SkASSERT(combinedMatrix.rectStaysRect());
    596 
    597     drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs));
    598     GrAssert(sizeof(AARectVertex) == drawState->getVertexSize());
    599 
    600     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    601     if (!geo.succeeded()) {
    602         GrPrintf("Failed to get space for vertices!\n");
    603         return;
    604     }
    605 
    606     AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices());
    607 
    608     GrEffectRef* effect = GrAlignedRectEffect::Create();
    609     static const int kOffsetIndex = 1;
    610     drawState->addCoverageEffect(effect, kOffsetIndex)->unref();
    611 
    612     SkRect devRect;
    613     combinedMatrix.mapRect(&devRect, rect);
    614 
    615     SkRect devBounds = {
    616         devRect.fLeft   - SK_ScalarHalf,
    617         devRect.fTop    - SK_ScalarHalf,
    618         devRect.fRight  + SK_ScalarHalf,
    619         devRect.fBottom + SK_ScalarHalf
    620     };
    621 
    622     GrPoint widthHeight = {
    623         SkScalarHalf(devRect.width()) + SK_ScalarHalf,
    624         SkScalarHalf(devRect.height()) + SK_ScalarHalf
    625     };
    626 
    627     verts[0].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fTop);
    628     verts[0].fOffset = SkPoint::Make(-widthHeight.fX, -widthHeight.fY);
    629     verts[0].fWidthHeight = widthHeight;
    630 
    631     verts[1].fPos = SkPoint::Make(devBounds.fLeft, devBounds.fBottom);
    632     verts[1].fOffset = SkPoint::Make(-widthHeight.fX, widthHeight.fY);
    633     verts[1].fWidthHeight = widthHeight;
    634 
    635     verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
    636     verts[2].fOffset = widthHeight;
    637     verts[2].fWidthHeight = widthHeight;
    638 
    639     verts[3].fPos = SkPoint::Make(devBounds.fRight, devBounds.fTop);
    640     verts[3].fOffset = SkPoint::Make(widthHeight.fX, -widthHeight.fY);
    641     verts[3].fWidthHeight = widthHeight;
    642 
    643     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
    644     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
    645     target->resetIndexSource();
    646 }
    647 
    648 void GrAARectRenderer::strokeAARect(GrGpu* gpu,
    649                                     GrDrawTarget* target,
    650                                     const SkRect& rect,
    651                                     const SkMatrix& combinedMatrix,
    652                                     const SkRect& devRect,
    653                                     SkScalar width,
    654                                     bool useVertexCoverage) {
    655     GrVec devStrokeSize;
    656     if (width > 0) {
    657         devStrokeSize.set(width, width);
    658         combinedMatrix.mapVectors(&devStrokeSize, 1);
    659         devStrokeSize.setAbs(devStrokeSize);
    660     } else {
    661         devStrokeSize.set(SK_Scalar1, SK_Scalar1);
    662     }
    663 
    664     const SkScalar dx = devStrokeSize.fX;
    665     const SkScalar dy = devStrokeSize.fY;
    666     const SkScalar rx = SkScalarMul(dx, SK_ScalarHalf);
    667     const SkScalar ry = SkScalarMul(dy, SK_ScalarHalf);
    668 
    669     // Temporarily #if'ed out. We don't want to pass in the devRect but
    670     // right now it is computed in GrContext::apply_aa_to_rect and we don't
    671     // want to throw away the work
    672 #if 0
    673     SkRect devRect;
    674     combinedMatrix.mapRect(&devRect, rect);
    675 #endif
    676 
    677     SkScalar spare;
    678     {
    679         SkScalar w = devRect.width() - dx;
    680         SkScalar h = devRect.height() - dy;
    681         spare = GrMin(w, h);
    682     }
    683 
    684     SkRect devOutside(devRect);
    685     devOutside.outset(rx, ry);
    686 
    687     if (spare <= 0) {
    688         this->fillAARect(gpu, target, devOutside, SkMatrix::I(),
    689                          devOutside, useVertexCoverage);
    690         return;
    691     }
    692 
    693     SkRect devInside(devRect);
    694     devInside.inset(rx, ry);
    695 
    696     this->geometryStrokeAARect(gpu, target, devOutside, devInside, useVertexCoverage);
    697 }
    698 
    699 void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
    700                                             GrDrawTarget* target,
    701                                             const SkRect& devOutside,
    702                                             const SkRect& devInside,
    703                                             bool useVertexCoverage) {
    704     GrDrawState* drawState = target->drawState();
    705 
    706     set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
    707 
    708     GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
    709     if (!geo.succeeded()) {
    710         GrPrintf("Failed to get space for vertices!\n");
    711         return;
    712     }
    713     GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer(gpu);
    714     if (NULL == indexBuffer) {
    715         GrPrintf("Failed to create index buffer!\n");
    716         return;
    717     }
    718 
    719     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    720     size_t vsize = drawState->getVertexSize();
    721     GrAssert(sizeof(GrPoint) + sizeof(GrColor) == vsize);
    722 
    723     // We create vertices for four nested rectangles. There are two ramps from 0 to full
    724     // coverage, one on the exterior of the stroke and the other on the interior.
    725     // The following pointers refer to the four rects, from outermost to innermost.
    726     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    727     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    728     GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
    729     GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
    730 
    731 #ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
    732     // TODO: this only really works if the X & Y margins are the same all around
    733     // the rect
    734     SkScalar inset = SkMinScalar(SK_Scalar1, devOutside.fRight - devInside.fRight);
    735     inset = SkMinScalar(inset, devInside.fLeft - devOutside.fLeft);
    736     inset = SkMinScalar(inset, devInside.fTop - devOutside.fTop);
    737     inset = SK_ScalarHalf * SkMinScalar(inset, devOutside.fBottom - devInside.fBottom);
    738     SkASSERT(inset >= 0);
    739 #else
    740     SkScalar inset = SK_ScalarHalf;
    741 #endif
    742 
    743     // outermost
    744     set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
    745     // inner two
    746     set_inset_fan(fan1Pos, vsize, devOutside,  inset,  inset);
    747     set_inset_fan(fan2Pos, vsize, devInside,  -inset, -inset);
    748     // innermost
    749     set_inset_fan(fan3Pos, vsize, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
    750 
    751     // The outermost rect has 0 coverage
    752     verts += sizeof(GrPoint);
    753     for (int i = 0; i < 4; ++i) {
    754         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    755     }
    756 
    757     int scale;
    758     if (inset < SK_ScalarHalf) {
    759         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
    760         SkASSERT(scale >= 0 && scale <= 255);
    761     } else {
    762         scale = 0xff;
    763     }
    764 
    765     // The inner two rects have full coverage
    766     GrColor innerColor;
    767     if (useVertexCoverage) {
    768         innerColor = GrColorPackRGBA(scale, scale, scale, scale);
    769     } else {
    770         if (0xff == scale) {
    771             innerColor = target->getDrawState().getColor();
    772         } else {
    773             innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
    774         }
    775     }
    776 
    777     verts += 4 * vsize;
    778     for (int i = 0; i < 8; ++i) {
    779         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    780     }
    781 
    782     // The innermost rect has 0 coverage
    783     verts += 8 * vsize;
    784     for (int i = 0; i < 4; ++i) {
    785         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    786     }
    787 
    788     target->setIndexSourceToBuffer(indexBuffer);
    789     target->drawIndexed(kTriangles_GrPrimitiveType,
    790                         0, 0, 16, aaStrokeRectIndexCount());
    791 }
    792 
    793 void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
    794                                          GrDrawTarget* target,
    795                                          const SkRect rects[2],
    796                                          const SkMatrix& combinedMatrix,
    797                                          bool useVertexCoverage) {
    798     SkASSERT(combinedMatrix.rectStaysRect());
    799     SkASSERT(!rects[1].isEmpty());
    800 
    801     SkRect devOutside, devInside;
    802     combinedMatrix.mapRect(&devOutside, rects[0]);
    803     // can't call mapRect for devInside since it calls sort
    804     combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
    805 
    806     if (devInside.isEmpty()) {
    807         this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside, useVertexCoverage);
    808         return;
    809     }
    810 
    811     this->geometryStrokeAARect(gpu, target, devOutside, devInside, useVertexCoverage);
    812 }
    813