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