LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/ops - GrAAFillRectOp.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 184 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 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 "GrAAFillRectOp.h"
       9             : 
      10             : #include "GrColor.h"
      11             : #include "GrDefaultGeoProcFactory.h"
      12             : #include "GrMeshDrawOp.h"
      13             : #include "GrOpFlushState.h"
      14             : #include "GrResourceKey.h"
      15             : #include "GrResourceProvider.h"
      16             : #include "GrTypes.h"
      17             : #include "SkMatrix.h"
      18             : #include "SkRect.h"
      19             : 
      20             : GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
      21             : 
      22           0 : static void set_inset_fan(SkPoint* pts, size_t stride, const SkRect& r, SkScalar dx, SkScalar dy) {
      23           0 :     pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
      24           0 : }
      25             : 
      26             : static const int kNumAAFillRectsInIndexBuffer = 256;
      27             : static const int kVertsPerAAFillRect = 8;
      28             : static const int kIndicesPerAAFillRect = 30;
      29             : 
      30           0 : const GrBuffer* get_index_buffer(GrResourceProvider* resourceProvider) {
      31           0 :     GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
      32             : 
      33             :     // clang-format off
      34             :     static const uint16_t gFillAARectIdx[] = {
      35             :         0, 1, 5, 5, 4, 0,
      36             :         1, 2, 6, 6, 5, 1,
      37             :         2, 3, 7, 7, 6, 2,
      38             :         3, 0, 4, 4, 7, 3,
      39             :         4, 5, 6, 6, 7, 4,
      40             :     };
      41             :     // clang-format on
      42             : 
      43             :     GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect);
      44           0 :     return resourceProvider->findOrCreateInstancedIndexBuffer(
      45             :             gFillAARectIdx, kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer,
      46           0 :             kVertsPerAAFillRect, gAAFillRectIndexBufferKey);
      47             : }
      48             : 
      49           0 : static void generate_aa_fill_rect_geometry(intptr_t verts,
      50             :                                            size_t vertexStride,
      51             :                                            GrColor color,
      52             :                                            const SkMatrix& viewMatrix,
      53             :                                            const SkRect& rect,
      54             :                                            const SkRect& devRect,
      55             :                                            bool tweakAlphaForCoverage,
      56             :                                            const SkMatrix* localMatrix) {
      57           0 :     SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
      58           0 :     SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vertexStride);
      59             : 
      60             :     SkScalar inset;
      61             : 
      62           0 :     if (viewMatrix.rectStaysRect()) {
      63           0 :         inset = SkMinScalar(devRect.width(), SK_Scalar1);
      64           0 :         inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
      65             : 
      66           0 :         set_inset_fan(fan0Pos, vertexStride, devRect, -SK_ScalarHalf, -SK_ScalarHalf);
      67           0 :         set_inset_fan(fan1Pos, vertexStride, devRect, inset, inset);
      68             :     } else {
      69             :         // compute transformed (1, 0) and (0, 1) vectors
      70           0 :         SkVector vec[2] = {{viewMatrix[SkMatrix::kMScaleX], viewMatrix[SkMatrix::kMSkewY]},
      71           0 :                            {viewMatrix[SkMatrix::kMSkewX], viewMatrix[SkMatrix::kMScaleY]}};
      72             : 
      73           0 :         SkScalar len1 = SkPoint::Normalize(&vec[0]);
      74           0 :         vec[0].scale(SK_ScalarHalf);
      75           0 :         SkScalar len2 = SkPoint::Normalize(&vec[1]);
      76           0 :         vec[1].scale(SK_ScalarHalf);
      77             : 
      78           0 :         inset = SkMinScalar(len1 * rect.width(), SK_Scalar1);
      79           0 :         inset = SK_ScalarHalf * SkMinScalar(inset, len2 * rect.height());
      80             : 
      81             :         // create the rotated rect
      82           0 :         fan0Pos->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vertexStride);
      83           0 :         viewMatrix.mapPointsWithStride(fan0Pos, vertexStride, 4);
      84             : 
      85             :         // Now create the inset points and then outset the original
      86             :         // rotated points
      87             : 
      88             :         // TL
      89             :         *((SkPoint*)((intptr_t)fan1Pos + 0 * vertexStride)) =
      90           0 :                 *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) + vec[0] + vec[1];
      91           0 :         *((SkPoint*)((intptr_t)fan0Pos + 0 * vertexStride)) -= vec[0] + vec[1];
      92             :         // BL
      93             :         *((SkPoint*)((intptr_t)fan1Pos + 1 * vertexStride)) =
      94           0 :                 *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) + vec[0] - vec[1];
      95           0 :         *((SkPoint*)((intptr_t)fan0Pos + 1 * vertexStride)) -= vec[0] - vec[1];
      96             :         // BR
      97             :         *((SkPoint*)((intptr_t)fan1Pos + 2 * vertexStride)) =
      98           0 :                 *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) - vec[0] - vec[1];
      99           0 :         *((SkPoint*)((intptr_t)fan0Pos + 2 * vertexStride)) += vec[0] + vec[1];
     100             :         // TR
     101             :         *((SkPoint*)((intptr_t)fan1Pos + 3 * vertexStride)) =
     102           0 :                 *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) - vec[0] + vec[1];
     103           0 :         *((SkPoint*)((intptr_t)fan0Pos + 3 * vertexStride)) += vec[0] - vec[1];
     104             :     }
     105             : 
     106           0 :     if (localMatrix) {
     107             :         SkMatrix invViewMatrix;
     108           0 :         if (!viewMatrix.invert(&invViewMatrix)) {
     109           0 :             SkDebugf("View matrix is non-invertible, local coords will be wrong.");
     110           0 :             invViewMatrix = SkMatrix::I();
     111             :         }
     112             :         SkMatrix localCoordMatrix;
     113           0 :         localCoordMatrix.setConcat(*localMatrix, invViewMatrix);
     114           0 :         SkPoint* fan0Loc = reinterpret_cast<SkPoint*>(verts + sizeof(SkPoint) + sizeof(GrColor));
     115           0 :         localCoordMatrix.mapPointsWithStride(fan0Loc, fan0Pos, vertexStride, 8);
     116             :     }
     117             : 
     118             :     // Make verts point to vertex color and then set all the color and coverage vertex attrs
     119             :     // values.
     120           0 :     verts += sizeof(SkPoint);
     121             : 
     122             :     // The coverage offset is always the last vertex attribute
     123           0 :     intptr_t coverageOffset = vertexStride - sizeof(GrColor) - sizeof(SkPoint);
     124           0 :     for (int i = 0; i < 4; ++i) {
     125           0 :         if (tweakAlphaForCoverage) {
     126           0 :             *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0;
     127             :         } else {
     128           0 :             *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
     129           0 :             *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = 0;
     130             :         }
     131             :     }
     132             : 
     133             :     int scale;
     134           0 :     if (inset < SK_ScalarHalf) {
     135           0 :         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
     136           0 :         SkASSERT(scale >= 0 && scale <= 255);
     137             :     } else {
     138           0 :         scale = 0xff;
     139             :     }
     140             : 
     141           0 :     verts += 4 * vertexStride;
     142             : 
     143           0 :     float innerCoverage = GrNormalizeByteToFloat(scale);
     144           0 :     GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
     145             : 
     146           0 :     for (int i = 0; i < 4; ++i) {
     147           0 :         if (tweakAlphaForCoverage) {
     148           0 :             *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor;
     149             :         } else {
     150           0 :             *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color;
     151           0 :             *reinterpret_cast<float*>(verts + i * vertexStride + coverageOffset) = innerCoverage;
     152             :         }
     153             :     }
     154           0 : }
     155             : 
     156           0 : class AAFillRectOp final : public GrLegacyMeshDrawOp {
     157             : public:
     158           0 :     DEFINE_OP_CLASS_ID
     159             : 
     160           0 :     AAFillRectOp(GrColor color,
     161             :                  const SkMatrix& viewMatrix,
     162             :                  const SkRect& rect,
     163             :                  const SkRect& devRect,
     164             :                  const SkMatrix* localMatrix)
     165           0 :             : INHERITED(ClassID()) {
     166           0 :         if (localMatrix) {
     167           0 :             void* mem = fRectData.push_back_n(sizeof(RectWithLocalMatrixInfo));
     168           0 :             new (mem) RectWithLocalMatrixInfo(color, viewMatrix, rect, devRect, *localMatrix);
     169             :         } else {
     170           0 :             void* mem = fRectData.push_back_n(sizeof(RectInfo));
     171           0 :             new (mem) RectInfo(color, viewMatrix, rect, devRect);
     172             :         }
     173             :         IsZeroArea zeroArea =
     174           0 :                 (!rect.width() || !rect.height()) ? IsZeroArea::kYes : IsZeroArea::kNo;
     175           0 :         this->setBounds(devRect, HasAABloat::kYes, zeroArea);
     176           0 :         fRectCnt = 1;
     177           0 :     }
     178             : 
     179           0 :     const char* name() const override { return "AAFillRectOp"; }
     180             : 
     181           0 :     SkString dumpInfo() const override {
     182           0 :         SkString str;
     183           0 :         str.appendf("# combined: %d\n", fRectCnt);
     184           0 :         const RectInfo* info = this->first();
     185           0 :         for (int i = 0; i < fRectCnt; ++i) {
     186           0 :             const SkRect& rect = info->rect();
     187           0 :             str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
     188           0 :                         info->color(), rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
     189           0 :             info = this->next(info);
     190             :         }
     191           0 :         str.append(DumpPipelineInfo(*this->pipeline()));
     192           0 :         str.append(INHERITED::dumpInfo());
     193           0 :         return str;
     194             :     }
     195             : 
     196           0 :     void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
     197             :         GrColor color;
     198           0 :         if (optimizations.getOverrideColorIfSet(&color)) {
     199           0 :             this->first()->setColor(color);
     200             :         }
     201           0 :         fCanTweakAlphaForCoverage = optimizations.canTweakAlphaForCoverage();
     202           0 :         fNeedsLocalCoords = optimizations.readsLocalCoords();
     203           0 :     }
     204             : 
     205             : private:
     206           0 :     void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
     207             :                                     GrProcessorAnalysisCoverage* coverage) const override {
     208           0 :         color->setToConstant(this->first()->color());
     209           0 :         *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
     210           0 :     }
     211             : 
     212           0 :     void onPrepareDraws(Target* target) const override {
     213             :         using namespace GrDefaultGeoProcFactory;
     214             : 
     215           0 :         Color color(Color::kPremulGrColorAttribute_Type);
     216             :         Coverage::Type coverageType;
     217           0 :         if (fCanTweakAlphaForCoverage) {
     218           0 :             coverageType = Coverage::kSolid_Type;
     219             :         } else {
     220           0 :             coverageType = Coverage::kAttribute_Type;
     221             :         }
     222             :         LocalCoords lc =
     223           0 :                 fNeedsLocalCoords ? LocalCoords::kHasExplicit_Type : LocalCoords::kUnused_Type;
     224             :         sk_sp<GrGeometryProcessor> gp =
     225           0 :                 GrDefaultGeoProcFactory::Make(color, coverageType, lc, SkMatrix::I());
     226           0 :         if (!gp) {
     227           0 :             SkDebugf("Couldn't create GrGeometryProcessor\n");
     228           0 :             return;
     229             :         }
     230             : 
     231           0 :         size_t vertexStride = gp->getVertexStride();
     232             : 
     233           0 :         sk_sp<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
     234           0 :         InstancedHelper helper;
     235             :         void* vertices =
     236           0 :                 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer.get(),
     237           0 :                             kVertsPerAAFillRect, kIndicesPerAAFillRect, fRectCnt);
     238           0 :         if (!vertices || !indexBuffer) {
     239           0 :             SkDebugf("Could not allocate vertices\n");
     240           0 :             return;
     241             :         }
     242             : 
     243           0 :         const RectInfo* info = this->first();
     244           0 :         const SkMatrix* localMatrix = nullptr;
     245           0 :         for (int i = 0; i < fRectCnt; i++) {
     246             :             intptr_t verts =
     247           0 :                     reinterpret_cast<intptr_t>(vertices) + i * kVertsPerAAFillRect * vertexStride;
     248           0 :             if (fNeedsLocalCoords) {
     249           0 :                 if (info->hasLocalMatrix()) {
     250           0 :                     localMatrix = &static_cast<const RectWithLocalMatrixInfo*>(info)->localMatrix();
     251             :                 } else {
     252           0 :                     localMatrix = &SkMatrix::I();
     253             :                 }
     254             :             }
     255           0 :             generate_aa_fill_rect_geometry(verts, vertexStride, info->color(), info->viewMatrix(),
     256           0 :                                            info->rect(), info->devRect(), fCanTweakAlphaForCoverage,
     257           0 :                                            localMatrix);
     258           0 :             info = this->next(info);
     259             :         }
     260           0 :         helper.recordDraw(target, gp.get(), this->pipeline());
     261             :     }
     262             : 
     263           0 :     bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
     264           0 :         AAFillRectOp* that = t->cast<AAFillRectOp>();
     265           0 :         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
     266             :                                     that->bounds(), caps)) {
     267           0 :             return false;
     268             :         }
     269             : 
     270           0 :         SkASSERT(fNeedsLocalCoords == that->fNeedsLocalCoords);
     271             : 
     272             :         // In the event of two ops, one who can tweak, one who cannot, we just fall back to not
     273             :         // tweaking.
     274           0 :         if (fCanTweakAlphaForCoverage && !that->fCanTweakAlphaForCoverage) {
     275           0 :             fCanTweakAlphaForCoverage = false;
     276             :         }
     277             : 
     278           0 :         fRectData.push_back_n(that->fRectData.count(), that->fRectData.begin());
     279           0 :         fRectCnt += that->fRectCnt;
     280           0 :         this->joinBounds(*that);
     281           0 :         return true;
     282             :     }
     283             : 
     284             :     struct RectInfo {
     285             :     public:
     286           0 :         RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
     287             :                  const SkRect& devRect)
     288           0 :                 : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kNo) {}
     289           0 :         bool hasLocalMatrix() const { return HasLocalMatrix::kYes == fHasLocalMatrix; }
     290           0 :         GrColor color() const { return fColor; }
     291           0 :         const SkMatrix& viewMatrix() const { return fViewMatrix; }
     292           0 :         const SkRect& rect() const { return fRect; }
     293           0 :         const SkRect& devRect() const { return fDevRect; }
     294             : 
     295           0 :         void setColor(GrColor color) { fColor = color; }
     296             : 
     297             :     protected:
     298             :         enum class HasLocalMatrix : uint32_t { kNo, kYes };
     299             : 
     300           0 :         RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
     301             :                  const SkRect& devRect, HasLocalMatrix hasLM)
     302           0 :                 : fHasLocalMatrix(hasLM)
     303             :                 , fColor(color)
     304             :                 , fViewMatrix(viewMatrix)
     305             :                 , fRect(rect)
     306           0 :                 , fDevRect(devRect) {}
     307             : 
     308             :         HasLocalMatrix fHasLocalMatrix;
     309             :         GrColor fColor;
     310             :         SkMatrix fViewMatrix;
     311             :         SkRect fRect;
     312             :         SkRect fDevRect;
     313             :     };
     314             : 
     315             :     struct RectWithLocalMatrixInfo : public RectInfo {
     316             :     public:
     317           0 :         RectWithLocalMatrixInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
     318             :                                 const SkRect& devRect, const SkMatrix& localMatrix)
     319           0 :                 : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kYes)
     320           0 :                 , fLocalMatrix(localMatrix) {}
     321           0 :         const SkMatrix& localMatrix() const { return fLocalMatrix; }
     322             : 
     323             :     private:
     324             :         SkMatrix fLocalMatrix;
     325             :     };
     326             : 
     327           0 :     RectInfo* first() { return reinterpret_cast<RectInfo*>(fRectData.begin()); }
     328           0 :     const RectInfo* first() const { return reinterpret_cast<const RectInfo*>(fRectData.begin()); }
     329           0 :     const RectInfo* next(const RectInfo* prev) const {
     330             :         intptr_t next =
     331           0 :                 reinterpret_cast<intptr_t>(prev) +
     332           0 :                 (prev->hasLocalMatrix() ? sizeof(RectWithLocalMatrixInfo) : sizeof(RectInfo));
     333           0 :         return reinterpret_cast<const RectInfo*>(next);
     334             :     }
     335             : 
     336             :     bool fNeedsLocalCoords;
     337             :     bool fCanTweakAlphaForCoverage;
     338             :     SkSTArray<4 * sizeof(RectWithLocalMatrixInfo), uint8_t, true> fRectData;
     339             :     int fRectCnt;
     340             : 
     341             :     typedef GrLegacyMeshDrawOp INHERITED;
     342             : };
     343             : 
     344             : namespace GrAAFillRectOp {
     345             : 
     346           0 : std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color,
     347             :                                          const SkMatrix& viewMatrix,
     348             :                                          const SkRect& rect,
     349             :                                          const SkRect& devRect) {
     350             :     return std::unique_ptr<GrLegacyMeshDrawOp>(
     351           0 :             new AAFillRectOp(color, viewMatrix, rect, devRect, nullptr));
     352             : }
     353             : 
     354           0 : std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color,
     355             :                                          const SkMatrix& viewMatrix,
     356             :                                          const SkMatrix& localMatrix,
     357             :                                          const SkRect& rect,
     358             :                                          const SkRect& devRect) {
     359             :     return std::unique_ptr<GrLegacyMeshDrawOp>(
     360           0 :             new AAFillRectOp(color, viewMatrix, rect, devRect, &localMatrix));
     361             : }
     362             : 
     363           0 : std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color,
     364             :                                          const SkMatrix& viewMatrix,
     365             :                                          const SkMatrix& localMatrix,
     366             :                                          const SkRect& rect) {
     367             :     SkRect devRect;
     368           0 :     viewMatrix.mapRect(&devRect, rect);
     369           0 :     return Make(color, viewMatrix, localMatrix, rect, devRect);
     370             : }
     371             : 
     372           0 : std::unique_ptr<GrLegacyMeshDrawOp> MakeWithLocalRect(GrColor color,
     373             :                                                       const SkMatrix& viewMatrix,
     374             :                                                       const SkRect& rect,
     375             :                                                       const SkRect& localRect) {
     376             :     SkRect devRect;
     377           0 :     viewMatrix.mapRect(&devRect, rect);
     378             :     SkMatrix localMatrix;
     379           0 :     if (!localMatrix.setRectToRect(rect, localRect, SkMatrix::kFill_ScaleToFit)) {
     380           0 :         return nullptr;
     381             :     }
     382           0 :     return Make(color, viewMatrix, localMatrix, rect, devRect);
     383             : }
     384             : };
     385             : 
     386             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     387             : 
     388             : #if GR_TEST_UTILS
     389             : 
     390             : #include "GrDrawOpTest.h"
     391             : 
     392           0 : DRAW_OP_TEST_DEFINE(AAFillRectOp) {
     393           0 :     GrColor color = GrRandomColor(random);
     394           0 :     SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
     395           0 :     SkRect rect = GrTest::TestRect(random);
     396           0 :     SkRect devRect = GrTest::TestRect(random);
     397           0 :     return GrAAFillRectOp::Make(color, viewMatrix, rect, devRect);
     398             : }
     399             : 
     400           0 : DRAW_OP_TEST_DEFINE(AAFillRectOpLocalMatrix) {
     401           0 :     GrColor color = GrRandomColor(random);
     402           0 :     SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
     403           0 :     SkMatrix localMatrix = GrTest::TestMatrix(random);
     404           0 :     SkRect rect = GrTest::TestRect(random);
     405           0 :     SkRect devRect = GrTest::TestRect(random);
     406           0 :     return GrAAFillRectOp::Make(color, viewMatrix, localMatrix, rect, devRect);
     407             : }
     408             : 
     409             : #endif

Generated by: LCOV version 1.13