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 "GrContext.h"
     16 #include "GrPathUtils.h"
     17 #include "GrTest.h"
     18 #include "SkColorPriv.h"
     19 #include "SkDevice.h"
     20 #include "SkGeometry.h"
     21 #include "SkTLList.h"
     22 
     23 #include "effects/GrConvexPolyEffect.h"
     24 
     25 namespace skiagm {
     26 /**
     27  * This GM directly exercises a GrProcessor that draws convex polygons.
     28  */
     29 class ConvexPolyEffect : public GM {
     30 public:
     31     ConvexPolyEffect() {
     32         this->setBGColor(0xFFFFFFFF);
     33     }
     34 
     35 protected:
     36     virtual SkString onShortName() SK_OVERRIDE {
     37         return SkString("convex_poly_effect");
     38     }
     39 
     40     virtual SkISize onISize() SK_OVERRIDE {
     41         return SkISize::Make(720, 800);
     42     }
     43 
     44     virtual uint32_t onGetFlags() const SK_OVERRIDE {
     45         // This is a GPU-specific GM.
     46         return kGPUOnly_Flag;
     47     }
     48 
     49     virtual void onOnceBeforeDraw() SK_OVERRIDE {
     50         SkPath tri;
     51         tri.moveTo(5.f, 5.f);
     52         tri.lineTo(100.f, 20.f);
     53         tri.lineTo(15.f, 100.f);
     54 
     55         fPaths.addToTail(tri);
     56         fPaths.addToTail(SkPath())->reverseAddPath(tri);
     57 
     58         tri.close();
     59         fPaths.addToTail(tri);
     60 
     61         SkPath ngon;
     62         static const SkScalar kRadius = 50.f;
     63         const SkPoint center = { kRadius, kRadius };
     64         for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
     65             SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
     66             SkPoint point;
     67             point.fY = SkScalarSinCos(angle, &point.fX);
     68             point.scale(kRadius);
     69             point = center + point;
     70             if (0 == i) {
     71                 ngon.moveTo(point);
     72             } else {
     73                 ngon.lineTo(point);
     74             }
     75         }
     76 
     77         fPaths.addToTail(ngon);
     78         SkMatrix scaleM;
     79         scaleM.setScale(1.1f, 0.4f);
     80         ngon.transform(scaleM);
     81         fPaths.addToTail(ngon);
     82 
     83         // integer edges
     84         fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
     85         // half-integer edges
     86         fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
     87         // vertically/horizontally thin rects that cover pixel centers
     88         fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
     89         fRects.addToTail(SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f));
     90         // vertically/horizontally thin rects that don't cover pixel centers
     91         fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
     92         fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
     93         // small in x and y
     94         fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
     95         // inverted in x and y
     96         fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
     97     }
     98 
     99     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
    100         GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
    101         if (NULL == rt) {
    102             return;
    103         }
    104         GrContext* context = rt->getContext();
    105         if (NULL == context) {
    106             return;
    107         }
    108 
    109         SkScalar y = 0;
    110         for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart);
    111              iter.get();
    112              iter.next()) {
    113             const SkPath* path = iter.get();
    114             SkScalar x = 0;
    115 
    116             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
    117                 GrTestTarget tt;
    118                 context->getTestTarget(&tt);
    119                 if (NULL == tt.target()) {
    120                     SkDEBUGFAIL("Couldn't get Gr test target.");
    121                     return;
    122                 }
    123                 GrDrawState* drawState = tt.target()->drawState();
    124 
    125                 SkMatrix m;
    126                 SkPath p;
    127                 m.setTranslate(x, y);
    128                 path->transform(m, &p);
    129 
    130                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
    131                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
    132                 if (!fp) {
    133                     continue;
    134                 }
    135                 drawState->addCoverageProcessor(fp);
    136                 drawState->setIdentityViewMatrix();
    137                 drawState->setRenderTarget(rt);
    138                 drawState->setColor(0xff000000);
    139 
    140                 SkPoint verts[4];
    141                 SkRect bounds = p.getBounds();
    142                 // Make sure any artifacts around the exterior of path are visible by using overly
    143                 // conservative bounding geometry.
    144                 bounds.outset(5.f, 5.f);
    145                 bounds.toQuad(verts);
    146 
    147                 tt.target()->setVertexSourceToArray(verts, 4);
    148                 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
    149                 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
    150 
    151                 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f);
    152             }
    153 
    154             // Draw AA and non AA paths using normal API for reference.
    155             canvas->save();
    156             canvas->translate(x, y);
    157             SkPaint paint;
    158             canvas->drawPath(*path, paint);
    159             canvas->translate(path->getBounds().width() + 10.f, 0);
    160             paint.setAntiAlias(true);
    161             canvas->drawPath(*path, paint);
    162             canvas->restore();
    163 
    164             y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
    165         }
    166 
    167         for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart);
    168              iter.get();
    169              iter.next()) {
    170 
    171             SkScalar x = 0;
    172 
    173             for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
    174                 GrTestTarget tt;
    175                 context->getTestTarget(&tt);
    176                 if (NULL == tt.target()) {
    177                     SkDEBUGFAIL("Couldn't get Gr test target.");
    178                     return;
    179                 }
    180                 SkRect rect = *iter.get();
    181                 rect.offset(x, y);
    182                 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
    183                 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
    184                 if (!fp) {
    185                     continue;
    186                 }
    187 
    188                 GrDrawState* drawState = tt.target()->drawState();
    189                 drawState->addCoverageProcessor(fp);
    190                 drawState->setIdentityViewMatrix();
    191                 drawState->setRenderTarget(rt);
    192                 drawState->setColor(0xff000000);
    193 
    194                 SkPoint verts[4];
    195                 SkRect bounds = rect;
    196                 bounds.outset(5.f, 5.f);
    197                 bounds.toQuad(verts);
    198 
    199                 tt.target()->setVertexSourceToArray(verts, 4);
    200                 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer());
    201                 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6);
    202 
    203                 x += SkScalarCeilToScalar(rect.width() + 10.f);
    204             }
    205 
    206             // Draw rect without and with AA using normal API for reference
    207             canvas->save();
    208             canvas->translate(x, y);
    209             SkPaint paint;
    210             canvas->drawRect(*iter.get(), paint);
    211             x += SkScalarCeilToScalar(iter.get()->width() + 10.f);
    212             paint.setAntiAlias(true);
    213             canvas->drawRect(*iter.get(), paint);
    214             canvas->restore();
    215 
    216             y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
    217         }
    218     }
    219 
    220 private:
    221     SkTLList<SkPath> fPaths;
    222     SkTLList<SkRect> fRects;
    223 
    224     typedef GM INHERITED;
    225 };
    226 
    227 DEF_GM( return SkNEW(ConvexPolyEffect); )
    228 }
    229 
    230 #endif
    231