Home | History | Annotate | Download | only in gm
      1 
      2 /*
      3  * Copyright 2014 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 // This test only works with the GPU backend.
     10 
     11 #include "gm.h"
     12 
     13 #if SK_SUPPORT_GPU
     14 
     15 #include "GrBatchTarget.h"
     16 #include "GrContext.h"
     17 #include "GrDefaultGeoProcFactory.h"
     18 #include "GrPathUtils.h"
     19 #include "GrTest.h"
     20 #include "GrTestBatch.h"
     21 #include "SkColorPriv.h"
     22 #include "SkDevice.h"
     23 #include "SkGeometry.h"
     24 #include "SkTLList.h"
     25 
     26 #include "effects/GrConvexPolyEffect.h"
     27 
     28 namespace skiagm {
     29 
     30 class ConvexPolyTestBatch : public GrTestBatch {
     31 public:
     32     struct Geometry : public GrTestBatch::Geometry {
     33         SkRect fBounds;
     34     };
     35 
     36     const char* name() const override { return "ConvexPolyTestBatch"; }
     37 
     38     static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo) {
     39         return SkNEW_ARGS(ConvexPolyTestBatch, (gp, geo));
     40     }
     41 
     42 private:
     43     ConvexPolyTestBatch(const GrGeometryProcessor* gp, const Geometry& geo)
     44         : INHERITED(gp, geo.fBounds)
     45         , fGeometry(geo) {
     46     }
     47 
     48     Geometry* geoData(int index) override {
     49         SkASSERT(0 == index);
     50         return &fGeometry;
     51     }
     52 
     53     const Geometry* geoData(int index) const override {
     54         SkASSERT(0 == index);
     55         return &fGeometry;
     56     }
     57 
     58     void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
     59         size_t vertexStride = this->geometryProcessor()->getVertexStride();
     60         SkASSERT(vertexStride == sizeof(SkPoint));
     61         QuadHelper helper;
     62         SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(batchTarget, vertexStride, 1));
     63         if (!verts) {
     64             return;
     65         }
     66 
     67         // Make sure any artifacts around the exterior of path are visible by using overly
     68         // conservative bounding geometry.
     69         fGeometry.fBounds.outset(5.f, 5.f);
     70         fGeometry.fBounds.toQuad(verts);
     71 
     72         helper.issueDraw(batchTarget);
     73     }
     74 
     75     Geometry fGeometry;
     76 
     77     typedef GrTestBatch INHERITED;
     78 };
     79 
     80 /**
     81  * This GM directly exercises a GrProcessor that draws convex polygons.
     82  */
     83 class ConvexPolyEffect : public GM {
     84 public:
     85     ConvexPolyEffect() {
     86         this->setBGColor(0xFFFFFFFF);
     87     }
     88 
     89 protected:
     90     SkString onShortName() override {
     91         return SkString("convex_poly_effect");
     92     }
     93 
     94     SkISize onISize() override {
     95         return SkISize::Make(720, 800);
     96     }
     97 
     98     void onOnceBeforeDraw() override {
     99         SkPath tri;
    100         tri.moveTo(5.f, 5.f);
    101         tri.lineTo(100.f, 20.f);
    102         tri.lineTo(15.f, 100.f);
    103 
    104         fPaths.addToTail(tri);
    105         fPaths.addToTail(SkPath())->reverseAddPath(tri);
    106 
    107         tri.close();
    108         fPaths.addToTail(tri);
    109 
    110         SkPath ngon;
    111         static const SkScalar kRadius = 50.f;
    112         const SkPoint center = { kRadius, kRadius };
    113         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
    114             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
    115             SkPoint point;
    116             point.fY = SkScalarSinCos(angle, &point.fX);
    117             point.scale(kRadius);
    118             point = center + point;
    119             if (0 == i) {
    120                 ngon.moveTo(point);
    121             } else {
    122                 ngon.lineTo(point);
    123             }
    124         }
    125 
    126         fPaths.addToTail(ngon);
    127         SkMatrix scaleM;
    128         scaleM.setScale(1.1f, 0.4f);
    129         ngon.transform(scaleM);
    130         fPaths.addToTail(ngon);
    131 
    132         // integer edges
    133         fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
    134         // half-integer edges
    135         fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
    136         // vertically/horizontally thin rects that cover pixel centers
    137         fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
    138         fRects.addToTail(SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f));
    139         // vertically/horizontally thin rects that don't cover pixel centers
    140         fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
    141         fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
    142         // small in x and y
    143         fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
    144         // inverted in x and y
    145         fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
    146     }
    147 
    148     void onDraw(SkCanvas* canvas) override {
    149         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
    150         if (NULL == rt) {
    151             this->drawGpuOnlyMessage(canvas);
    152             return;
    153         }
    154         GrContext* context = rt->getContext();
    155         if (NULL == context) {
    156             return;
    157         }
    158 
    159         static const GrColor color = 0xff000000;
    160         SkAutoTUnref<const GrGeometryProcessor> gp(
    161                 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType, color));
    162 
    163         SkScalar y = 0;
    164         for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
    165              iter.get();
    166              iter.next()) {
    167             const SkPath* path = iter.get();
    168             SkScalar x = 0;
    169 
    170             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
    171                 GrTestTarget tt;
    172                 context->getTestTarget(&tt);
    173                 if (NULL == tt.target()) {
    174                     SkDEBUGFAIL("Couldn't get Gr test target.");
    175                     return;
    176                 }
    177                 const SkMatrix m = SkMatrix::MakeTrans(x, y);
    178                 SkPath p;
    179                 path->transform(m, &p);
    180 
    181                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
    182                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
    183                 if (!fp) {
    184                     continue;
    185                 }
    186 
    187                 GrPipelineBuilder pipelineBuilder;
    188                 pipelineBuilder.addCoverageProcessor(fp);
    189                 pipelineBuilder.setRenderTarget(rt);
    190 
    191                 ConvexPolyTestBatch::Geometry geometry;
    192                 geometry.fColor = color;
    193                 geometry.fBounds = p.getBounds();
    194 
    195                 SkAutoTUnref<GrBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
    196 
    197                 tt.target()->drawBatch(&pipelineBuilder, batch);
    198 
    199                 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
    200             }
    201 
    202             // Draw AA and non AA paths using normal API for reference.
    203             canvas->save();
    204             canvas->translate(x, y);
    205             SkPaint paint;
    206             canvas->drawPath(*path, paint);
    207             canvas->translate(path->getBounds().width() + 10.f, 0);
    208             paint.setAntiAlias(true);
    209             canvas->drawPath(*path, paint);
    210             canvas->restore();
    211 
    212             y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
    213         }
    214 
    215         for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart);
    216              iter.get();
    217              iter.next()) {
    218 
    219             SkScalar x = 0;
    220 
    221             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
    222                 GrTestTarget tt;
    223                 context->getTestTarget(&tt);
    224                 if (NULL == tt.target()) {
    225                     SkDEBUGFAIL("Couldn't get Gr test target.");
    226                     return;
    227                 }
    228                 SkRect rect = *iter.get();
    229                 rect.offset(x, y);
    230                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
    231                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
    232                 if (!fp) {
    233                     continue;
    234                 }
    235 
    236                 GrPipelineBuilder pipelineBuilder;
    237                 pipelineBuilder.addCoverageProcessor(fp);
    238                 pipelineBuilder.setRenderTarget(rt);
    239 
    240                 ConvexPolyTestBatch::Geometry geometry;
    241                 geometry.fColor = color;
    242                 geometry.fBounds = rect;
    243 
    244                 SkAutoTUnref<GrBatch> batch(ConvexPolyTestBatch::Create(gp, geometry));
    245 
    246                 tt.target()->drawBatch(&pipelineBuilder, batch);
    247 
    248                 x += SkScalarCeilToScalar(rect.width() + 10.f);
    249             }
    250 
    251             // Draw rect without and with AA using normal API for reference
    252             canvas->save();
    253             canvas->translate(x, y);
    254             SkPaint paint;
    255             canvas->drawRect(*iter.get(), paint);
    256             x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
    257             paint.setAntiAlias(true);
    258             canvas->drawRect(*iter.get(), paint);
    259             canvas->restore();
    260 
    261             y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
    262         }
    263     }
    264 
    265 private:
    266     SkTLList<SkPath> fPaths;
    267     SkTLList<SkRect> fRects;
    268 
    269     typedef GM INHERITED;
    270 };
    271 
    272 DEF_GM( return SkNEW(ConvexPolyEffect); )
    273 }
    274 
    275 #endif
    276