gfx/skia/trunk/src/gpu/GrAARectRenderer.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
     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"
    16 ///////////////////////////////////////////////////////////////////////////////
    17 class GrGLAlignedRectEffect;
    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     }
    28     virtual ~GrAlignedRectEffect() {}
    30     static const char* Name() { return "AlignedRectEdge"; }
    32     virtual void getConstantColorComponents(GrColor* color,
    33                                             uint32_t* validFlags) const SK_OVERRIDE {
    34         *validFlags = 0;
    35     }
    37     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
    38         return GrTBackendEffectFactory<GrAlignedRectEffect>::getInstance();
    39     }
    41     class GLEffect : public GrGLVertexEffect {
    42     public:
    43         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    44         : INHERITED (factory) {}
    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());
    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");
    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);
    86             builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    87                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
    88         }
    90         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    91             return 0;
    92         }
    94         virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {}
    96     private:
    97         typedef GrGLVertexEffect INHERITED;
    98     };
   101 private:
   102     GrAlignedRectEffect() : GrVertexEffect() {
   103         this->addVertexAttrib(kVec4f_GrSLType);
   104     }
   106     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; }
   108     GR_DECLARE_EFFECT_TEST;
   110     typedef GrVertexEffect INHERITED;
   111 };
   114 GR_DEFINE_EFFECT_TEST(GrAlignedRectEffect);
   116 GrEffectRef* GrAlignedRectEffect::TestCreate(SkRandom* random,
   117                                              GrContext* context,
   118                                              const GrDrawTargetCaps&,
   119                                              GrTexture* textures[]) {
   120     return GrAlignedRectEffect::Create();
   121 }
   123 ///////////////////////////////////////////////////////////////////////////////
   124 class GrGLRectEffect;
   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     }
   146     virtual ~GrRectEffect() {}
   148     static const char* Name() { return "RectEdge"; }
   150     virtual void getConstantColorComponents(GrColor* color,
   151                                             uint32_t* validFlags) const SK_OVERRIDE {
   152         *validFlags = 0;
   153     }
   155     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
   156         return GrTBackendEffectFactory<GrRectEffect>::getInstance();
   157     }
   159     class GLEffect : public GrGLVertexEffect {
   160     public:
   161         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
   162         : INHERITED (factory) {}
   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());
   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());
   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");
   202             // Compute the coverage for the rect's width
   203             builder->fsCodeAppendf("\tvec2 offset = %s.xy - %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);
   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);
   219             builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
   220                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("coverage")).c_str());
   221         }
   223         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
   224             return 0;
   225         }
   227         virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect&) SK_OVERRIDE {}
   229     private:
   230         typedef GrGLVertexEffect INHERITED;
   231     };
   234 private:
   235     GrRectEffect() : GrVertexEffect() {
   236         this->addVertexAttrib(kVec4f_GrSLType);
   237         this->addVertexAttrib(kVec2f_GrSLType);
   238         this->setWillReadFragmentPosition();
   239     }
   241     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; }
   243     GR_DECLARE_EFFECT_TEST;
   245     typedef GrVertexEffect INHERITED;
   246 };
   249 GR_DEFINE_EFFECT_TEST(GrRectEffect);
   251 GrEffectRef* GrRectEffect::TestCreate(SkRandom* random,
   252                                       GrContext* context,
   253                                       const GrDrawTargetCaps&,
   254                                       GrTexture* textures[]) {
   255     return GrRectEffect::Create();
   256 }
   258 ///////////////////////////////////////////////////////////////////////////////
   260 namespace {
   262 extern const GrVertexAttrib gAARectCoverageAttribs[] = {
   263     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
   264     {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
   265 };
   267 extern const GrVertexAttrib gAARectColorAttribs[] = {
   268     {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
   269     {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
   270 };
   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 }
   280 static void set_inset_fan(GrPoint* 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 }
   286 };
   288 void GrAARectRenderer::reset() {
   289     SkSafeSetNull(fAAFillRectIndexBuffer);
   290     SkSafeSetNull(fAAMiterStrokeRectIndexBuffer);
   291     SkSafeSetNull(fAABevelStrokeRectIndexBuffer);
   292 }
   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 };
   302 static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx);
   303 static const int kVertsPerAAFillRect = 8;
   304 static const int kNumAAFillRectsInIndexBuffer = 256;
   306 GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
   307     static const size_t kAAFillRectIndexBufferSize = kIndicesPerAAFillRect *
   308                                                      sizeof(uint16_t) *
   309                                                      kNumAAFillRectsInIndexBuffer;
   311     if (NULL == fAAFillRectIndexBuffer) {
   312         fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
   313         if (NULL != fAAFillRectIndexBuffer) {
   314             uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock();
   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                     GrCrash("Can't get AA Fill Rect indices into buffer!");
   331                 }
   332                 SkDELETE_ARRAY(data);
   333             } else {
   334                 fAAFillRectIndexBuffer->unlock();
   335             }
   336         }
   337     }
   339     return fAAFillRectIndexBuffer;
   340 }
   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,
   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,
   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 };
   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,
   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,
   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 };
   416 int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) {
   417     return miterStroke ? GR_ARRAY_COUNT(gMiterStrokeAARectIdx) :
   418                          GR_ARRAY_COUNT(gBevelStrokeAARectIdx);
   419 }
   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 }
   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();
   461     set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
   463     GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
   464     if (!geo.succeeded()) {
   465         GrPrintf("Failed to get space for vertices!\n");
   466         return;
   467     }
   469     GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer(gpu);
   470     if (NULL == indexBuffer) {
   471         GrPrintf("Failed to create index buffer!\n");
   472         return;
   473     }
   475     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
   476     size_t vsize = drawState->getVertexSize();
   477     SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
   479     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
   480     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
   482     SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
   483     inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
   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
   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         };
   503         vec[0].normalize();
   504         vec[0].scale(SK_ScalarHalf);
   505         vec[1].normalize();
   506         vec[1].scale(SK_ScalarHalf);
   508         // create the rotated rect
   509         fan0Pos->setRectFan(rect.fLeft, rect.fTop,
   510                             rect.fRight, rect.fBottom, vsize);
   511         combinedMatrix.mapPointsWithStride(fan0Pos, vsize, 4);
   513         // Now create the inset points and then outset the original
   514         // rotated points
   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     }
   534     verts += sizeof(GrPoint);
   535     for (int i = 0; i < 4; ++i) {
   536         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
   537     }
   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     }
   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     }
   558     verts += 4 * vsize;
   559     for (int i = 0; i < 4; ++i) {
   560         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
   561     }
   563     target->setIndexSourceToBuffer(indexBuffer);
   564     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1,
   565                                  kVertsPerAAFillRect,
   566                                  kIndicesPerAAFillRect);
   567     target->resetIndexSource();
   568 }
   570 namespace {
   572 // Rotated
   573 struct RectVertex {
   574     GrPoint fPos;
   575     GrPoint fCenter;
   576     GrPoint fDir;
   577     GrPoint fWidthHeight;
   578 };
   580 // Rotated
   581 extern const GrVertexAttrib gAARectVertexAttribs[] = {
   582     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
   583     { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
   584     { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
   585 };
   587 // Axis Aligned
   588 struct AARectVertex {
   589     GrPoint fPos;
   590     GrPoint fOffset;
   591     GrPoint fWidthHeight;
   592 };
   594 // Axis Aligned
   595 extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
   596     { kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding },
   597     { kVec4f_GrVertexAttribType, sizeof(GrPoint),   kEffect_GrVertexAttribBinding },
   598 };
   600 };
   602 void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
   603                                         GrDrawTarget* target,
   604                                         const SkRect& rect,
   605                                         const SkMatrix& combinedMatrix) {
   606     GrDrawState* drawState = target->drawState();
   608     SkPoint center = SkPoint::Make(rect.centerX(), rect.centerY());
   609     combinedMatrix.mapPoints(&center, 1);
   611     // compute transformed (0, 1) vector
   612     SkVector dir = { combinedMatrix[SkMatrix::kMSkewX], combinedMatrix[SkMatrix::kMScaleY] };
   613     dir.normalize();
   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     };
   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());
   626     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
   627     if (!geo.succeeded()) {
   628         GrPrintf("Failed to get space for vertices!\n");
   629         return;
   630     }
   632     RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices());
   634     GrEffectRef* effect = GrRectEffect::Create();
   635     static const int kRectAttrIndex = 1;
   636     static const int kWidthIndex = 2;
   637     drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref();
   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     }
   646     SkRect devRect;
   647     combinedMatrix.mapRect(&devRect, rect);
   649     SkRect devBounds = {
   650         devRect.fLeft   - SK_ScalarHalf,
   651         devRect.fTop    - SK_ScalarHalf,
   652         devRect.fRight  + SK_ScalarHalf,
   653         devRect.fBottom + SK_ScalarHalf
   654     };
   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);
   661     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
   662     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
   663     target->resetIndexSource();
   664 }
   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());
   673     drawState->setVertexAttribs<gAAAARectVertexAttribs>(SK_ARRAY_COUNT(gAAAARectVertexAttribs));
   674     SkASSERT(sizeof(AARectVertex) == drawState->getVertexSize());
   676     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
   677     if (!geo.succeeded()) {
   678         GrPrintf("Failed to get space for vertices!\n");
   679         return;
   680     }
   682     AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices());
   684     GrEffectRef* effect = GrAlignedRectEffect::Create();
   685     static const int kOffsetIndex = 1;
   686     drawState->addCoverageEffect(effect, kOffsetIndex)->unref();
   688     SkRect devRect;
   689     combinedMatrix.mapRect(&devRect, rect);
   691     SkRect devBounds = {
   692         devRect.fLeft   - SK_ScalarHalf,
   693         devRect.fTop    - SK_ScalarHalf,
   694         devRect.fRight  + SK_ScalarHalf,
   695         devRect.fBottom + SK_ScalarHalf
   696     };
   698     GrPoint widthHeight = {
   699         SkScalarHalf(devRect.width()) + SK_ScalarHalf,
   700         SkScalarHalf(devRect.height()) + SK_ScalarHalf
   701     };
   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;
   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;
   711     verts[2].fPos = SkPoint::Make(devBounds.fRight, devBounds.fBottom);
   712     verts[2].fOffset = widthHeight;
   713     verts[2].fWidthHeight = widthHeight;
   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;
   719     target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
   720     target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6);
   721     target->resetIndexSource();
   722 }
   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     GrVec 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     }
   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);
   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
   754     SkScalar spare;
   755     {
   756         SkScalar w = devRect.width() - dx;
   757         SkScalar h = devRect.height() - dy;
   758         spare = GrMin(w, h);
   759     }
   761     SkRect devOutside(devRect);
   762     devOutside.outset(rx, ry);
   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     }
   770     if (spare <= 0 && miterStroke) {
   771         this->fillAARect(gpu, target, devOutside, SkMatrix::I(),
   772                          devOutside, useVertexCoverage);
   773         return;
   774     }
   776     SkRect devInside(devRect);
   777     devInside.inset(rx, ry);
   779     SkRect devOutsideAssist(devRect);
   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     }
   789     this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
   790                                devInside, useVertexCoverage, miterStroke);
   791 }
   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();
   802     set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
   804     int innerVertexNum = 4;
   805     int outerVertexNum = miterStroke ? 4 : 8;
   806     int totalVertexNum = (outerVertexNum + innerVertexNum) * 2;
   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     }
   819     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
   820     size_t vsize = drawState->getVertexSize();
   821     SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
   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     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
   827     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + outerVertexNum * vsize);
   828     GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 2 * outerVertexNum * vsize);
   829     GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vsize);
   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
   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         GrPoint* fan0AssistPos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
   857         GrPoint* fan1AssistPos = reinterpret_cast<GrPoint*>(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     }
   870     // The outermost rect has 0 coverage
   871     verts += sizeof(GrPoint);
   872     for (int i = 0; i < outerVertexNum; ++i) {
   873         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
   874     }
   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     }
   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     }
   896     verts += outerVertexNum * vsize;
   897     for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
   898         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
   899     }
   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     }
   907     target->setIndexSourceToBuffer(indexBuffer);
   908     target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0,
   909                         totalVertexNum, aaStrokeRectIndexCount(miterStroke));
   910 }
   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());
   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);
   925     if (devInside.isEmpty()) {
   926         this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside, useVertexCoverage);
   927         return;
   928     }
   930     this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
   931                                devInside, useVertexCoverage, true);
   932 }

mercurial