LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/ops - GrNonAAStrokeRectOp.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 101 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 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 "GrNonAAStrokeRectOp.h"
       9             : 
      10             : #include "GrColor.h"
      11             : #include "GrDefaultGeoProcFactory.h"
      12             : #include "GrDrawOpTest.h"
      13             : #include "GrMeshDrawOp.h"
      14             : #include "GrOpFlushState.h"
      15             : #include "SkStrokeRec.h"
      16             : #include "SkRandom.h"
      17             : 
      18             : /*  create a triangle strip that strokes the specified rect. There are 8
      19             :     unique vertices, but we repeat the last 2 to close up. Alternatively we
      20             :     could use an indices array, and then only send 8 verts, but not sure that
      21             :     would be faster.
      22             :     */
      23           0 : static void init_stroke_rect_strip(SkPoint verts[10], const SkRect& rect, SkScalar width) {
      24           0 :     const SkScalar rad = SkScalarHalf(width);
      25             :     // TODO we should be able to enable this assert, but we'd have to filter these draws
      26             :     // this is a bug
      27             :     // SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2);
      28             : 
      29           0 :     verts[0].set(rect.fLeft + rad, rect.fTop + rad);
      30           0 :     verts[1].set(rect.fLeft - rad, rect.fTop - rad);
      31           0 :     verts[2].set(rect.fRight - rad, rect.fTop + rad);
      32           0 :     verts[3].set(rect.fRight + rad, rect.fTop - rad);
      33           0 :     verts[4].set(rect.fRight - rad, rect.fBottom - rad);
      34           0 :     verts[5].set(rect.fRight + rad, rect.fBottom + rad);
      35           0 :     verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
      36           0 :     verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
      37           0 :     verts[8] = verts[0];
      38           0 :     verts[9] = verts[1];
      39           0 : }
      40             : 
      41             : // Allow all hairlines and all miters, so long as the miter limit doesn't produce beveled corners.
      42           0 : inline static bool allowed_stroke(const SkStrokeRec& stroke) {
      43           0 :     SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style ||
      44             :              stroke.getStyle() == SkStrokeRec::kHairline_Style);
      45           0 :     return !stroke.getWidth() ||
      46           0 :            (stroke.getJoin() == SkPaint::kMiter_Join && stroke.getMiter() > SK_ScalarSqrt2);
      47             : }
      48             : 
      49           0 : class NonAAStrokeRectOp final : public GrLegacyMeshDrawOp {
      50             : public:
      51           0 :     DEFINE_OP_CLASS_ID
      52             : 
      53           0 :     const char* name() const override { return "NonAAStrokeRectOp"; }
      54             : 
      55           0 :     SkString dumpInfo() const override {
      56           0 :         SkString string;
      57           0 :         string.appendf(
      58             :                 "Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f], "
      59             :                 "StrokeWidth: %.2f\n",
      60           0 :                 fColor, fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, fStrokeWidth);
      61           0 :         string.append(DumpPipelineInfo(*this->pipeline()));
      62           0 :         string.append(INHERITED::dumpInfo());
      63           0 :         return string;
      64             :     }
      65             : 
      66           0 :     static std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color, const SkMatrix& viewMatrix,
      67             :                                                     const SkRect& rect, const SkStrokeRec& stroke,
      68             :                                                     bool snapToPixelCenters) {
      69           0 :         if (!allowed_stroke(stroke)) {
      70           0 :             return nullptr;
      71             :         }
      72           0 :         NonAAStrokeRectOp* op = new NonAAStrokeRectOp();
      73           0 :         op->fColor = color;
      74           0 :         op->fViewMatrix = viewMatrix;
      75           0 :         op->fRect = rect;
      76             :         // Sort the rect for hairlines
      77           0 :         op->fRect.sort();
      78           0 :         op->fStrokeWidth = stroke.getWidth();
      79             : 
      80           0 :         SkScalar rad = SkScalarHalf(op->fStrokeWidth);
      81           0 :         SkRect bounds = rect;
      82           0 :         bounds.outset(rad, rad);
      83             : 
      84             :         // If our caller snaps to pixel centers then we have to round out the bounds
      85           0 :         if (snapToPixelCenters) {
      86           0 :             viewMatrix.mapRect(&bounds);
      87             :             // We want to be consistent with how we snap non-aa lines. To match what we do in
      88             :             // GrGLSLVertexShaderBuilder, we first floor all the vertex values and then add half a
      89             :             // pixel to force us to pixel centers.
      90           0 :             bounds.set(SkScalarFloorToScalar(bounds.fLeft),
      91             :                        SkScalarFloorToScalar(bounds.fTop),
      92             :                        SkScalarFloorToScalar(bounds.fRight),
      93           0 :                        SkScalarFloorToScalar(bounds.fBottom));
      94           0 :             bounds.offset(0.5f, 0.5f);
      95           0 :             op->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
      96             :         } else {
      97           0 :             op->setTransformedBounds(bounds, op->fViewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
      98             :         }
      99           0 :         return std::unique_ptr<GrLegacyMeshDrawOp>(op);
     100             :     }
     101             : 
     102             : private:
     103           0 :     NonAAStrokeRectOp() : INHERITED(ClassID()) {}
     104             : 
     105           0 :     void getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
     106             :                                     GrProcessorAnalysisCoverage* coverage) const override {
     107           0 :         color->setToConstant(fColor);
     108           0 :         *coverage = GrProcessorAnalysisCoverage::kNone;
     109           0 :     }
     110             : 
     111           0 :     void onPrepareDraws(Target* target) const override {
     112           0 :         sk_sp<GrGeometryProcessor> gp;
     113             :         {
     114             :             using namespace GrDefaultGeoProcFactory;
     115           0 :             Color color(fColor);
     116           0 :             LocalCoords::Type localCoordsType = fNeedsLocalCoords
     117           0 :                                                         ? LocalCoords::kUsePosition_Type
     118           0 :                                                         : LocalCoords::kUnused_Type;
     119           0 :             gp = GrDefaultGeoProcFactory::Make(color, Coverage::kSolid_Type, localCoordsType,
     120           0 :                                                fViewMatrix);
     121             :         }
     122             : 
     123           0 :         size_t vertexStride = gp->getVertexStride();
     124             : 
     125           0 :         SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr));
     126             : 
     127           0 :         int vertexCount = kVertsPerHairlineRect;
     128           0 :         if (fStrokeWidth > 0) {
     129           0 :             vertexCount = kVertsPerStrokeRect;
     130             :         }
     131             : 
     132             :         const GrBuffer* vertexBuffer;
     133             :         int firstVertex;
     134             : 
     135             :         void* verts =
     136           0 :                 target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
     137             : 
     138           0 :         if (!verts) {
     139           0 :             SkDebugf("Could not allocate vertices\n");
     140           0 :             return;
     141             :         }
     142             : 
     143           0 :         SkPoint* vertex = reinterpret_cast<SkPoint*>(verts);
     144             : 
     145             :         GrPrimitiveType primType;
     146           0 :         if (fStrokeWidth > 0) {
     147           0 :             primType = kTriangleStrip_GrPrimitiveType;
     148           0 :             init_stroke_rect_strip(vertex, fRect, fStrokeWidth);
     149             :         } else {
     150             :             // hairline
     151           0 :             primType = kLineStrip_GrPrimitiveType;
     152           0 :             vertex[0].set(fRect.fLeft, fRect.fTop);
     153           0 :             vertex[1].set(fRect.fRight, fRect.fTop);
     154           0 :             vertex[2].set(fRect.fRight, fRect.fBottom);
     155           0 :             vertex[3].set(fRect.fLeft, fRect.fBottom);
     156           0 :             vertex[4].set(fRect.fLeft, fRect.fTop);
     157             :         }
     158             : 
     159           0 :         GrMesh mesh;
     160           0 :         mesh.init(primType, vertexBuffer, firstVertex, vertexCount);
     161           0 :         target->draw(gp.get(), this->pipeline(), mesh);
     162             :     }
     163             : 
     164           0 :     void applyPipelineOptimizations(const PipelineOptimizations& optimizations) override {
     165           0 :         optimizations.getOverrideColorIfSet(&fColor);
     166           0 :         fNeedsLocalCoords = optimizations.readsLocalCoords();
     167           0 :     }
     168             : 
     169           0 :     bool onCombineIfPossible(GrOp* t, const GrCaps&) override {
     170             :         // NonAA stroke rects cannot combine right now
     171             :         // TODO make these combinable.
     172           0 :         return false;
     173             :     }
     174             : 
     175             :     GrColor fColor;
     176             :     SkMatrix fViewMatrix;
     177             :     SkRect fRect;
     178             :     SkScalar fStrokeWidth;
     179             :     bool fNeedsLocalCoords;
     180             : 
     181             :     const static int kVertsPerHairlineRect = 5;
     182             :     const static int kVertsPerStrokeRect = 10;
     183             : 
     184             :     typedef GrLegacyMeshDrawOp INHERITED;
     185             : };
     186             : 
     187             : namespace GrNonAAStrokeRectOp {
     188             : 
     189           0 : std::unique_ptr<GrLegacyMeshDrawOp> Make(GrColor color,
     190             :                                          const SkMatrix& viewMatrix,
     191             :                                          const SkRect& rect,
     192             :                                          const SkStrokeRec& stroke,
     193             :                                          bool snapToPixelCenters) {
     194           0 :     return NonAAStrokeRectOp::Make(color, viewMatrix, rect, stroke, snapToPixelCenters);
     195             : }
     196             : }
     197             : 
     198             : #if GR_TEST_UTILS
     199             : 
     200           0 : DRAW_OP_TEST_DEFINE(NonAAStrokeRectOp) {
     201           0 :     SkMatrix viewMatrix = GrTest::TestMatrix(random);
     202           0 :     GrColor color = GrRandomColor(random);
     203           0 :     SkRect rect = GrTest::TestRect(random);
     204           0 :     SkScalar strokeWidth = random->nextBool() ? 0.0f : 2.0f;
     205           0 :     SkPaint paint;
     206           0 :     paint.setStrokeWidth(strokeWidth);
     207           0 :     paint.setStyle(SkPaint::kStroke_Style);
     208           0 :     paint.setStrokeJoin(SkPaint::kMiter_Join);
     209           0 :     SkStrokeRec strokeRec(paint);
     210           0 :     return GrNonAAStrokeRectOp::Make(color, viewMatrix, rect, strokeRec, random->nextBool());
     211             : }
     212             : 
     213             : #endif

Generated by: LCOV version 1.13