convexpolyeffect.cpp revision f0b0cda76fce5756aa12df4b807349e6dd85fd20
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 25namespace { 26extern const GrVertexAttrib kAttribs[] = { 27 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 28}; 29} 30 31namespace skiagm { 32/** 33 * This GM directly exercises a GrEffect that draws convex polygons. 34 */ 35class ConvexPolyEffect : public GM { 36public: 37 ConvexPolyEffect() { 38 this->setBGColor(0xFFFFFFFF); 39 } 40 41protected: 42 virtual SkString onShortName() SK_OVERRIDE { 43 return SkString("convex_poly_effect"); 44 } 45 46 virtual SkISize onISize() SK_OVERRIDE { 47 return make_isize(475, 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 106 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 107 SkBaseDevice* device = canvas->getTopDevice(); 108 GrRenderTarget* rt = device->accessRenderTarget(); 109 if (NULL == rt) { 110 return; 111 } 112 GrContext* context = rt->getContext(); 113 if (NULL == context) { 114 return; 115 } 116 117 SkScalar y = 0; 118 for (SkTLList<SkPath>::Iter iter(fPaths, SkTLList<SkPath>::Iter::kHead_IterStart); 119 NULL != iter.get(); 120 iter.next()) { 121 const SkPath* path = iter.get(); 122 SkScalar x = 0; 123 124 for (int et = 0; et < GrConvexPolyEffect::kEdgeTypeCnt; ++et) { 125 GrTestTarget tt; 126 context->getTestTarget(&tt); 127 if (NULL == tt.target()) { 128 SkDEBUGFAIL("Couldn't get Gr test target."); 129 return; 130 } 131 GrDrawState* drawState = tt.target()->drawState(); 132 drawState->setVertexAttribs<kAttribs>(SK_ARRAY_COUNT(kAttribs)); 133 134 SkMatrix m; 135 SkPath p; 136 m.setTranslate(x, y); 137 path->transform(m, &p); 138 139 GrConvexPolyEffect::EdgeType edgeType = (GrConvexPolyEffect::EdgeType) et; 140 SkAutoTUnref<GrEffectRef> effect(GrConvexPolyEffect::Create(edgeType, p)); 141 if (!effect) { 142 SkDEBUGFAIL("Couldn't create convex poly effect."); 143 return; 144 } 145 drawState->addCoverageEffect(effect, 1); 146 drawState->setIdentityViewMatrix(); 147 drawState->setRenderTarget(rt); 148 drawState->setColor(0xff000000); 149 150 SkPoint verts[4]; 151 SkRect bounds = p.getBounds(); 152 // Make sure any artifacts around the exterior of path are visible by using overly 153 // conservative bounding geometry. 154 bounds.outset(5.f, 5.f); 155 bounds.toQuad(verts); 156 157 tt.target()->setVertexSourceToArray(verts, 4); 158 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); 159 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6); 160 161 x += SkScalarCeilToScalar(path->getBounds().width() + 10.f); 162 } 163 164 // Draw AA and non AA paths using normal API for reference. 165 canvas->save(); 166 canvas->translate(x, y); 167 SkPaint paint; 168 canvas->drawPath(*path, paint); 169 canvas->translate(path->getBounds().width() + 10.f, 0); 170 paint.setAntiAlias(true); 171 canvas->drawPath(*path, paint); 172 canvas->restore(); 173 174 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f); 175 } 176 177 // Draw rects. We only have specialized effect code for the AA case, so don't do non-AA. 178 for (SkTLList<SkRect>::Iter iter(fRects, SkTLList<SkRect>::Iter::kHead_IterStart); 179 NULL != iter.get(); 180 iter.next()) { 181 182 SkScalar x = 0; 183 184 GrTestTarget tt; 185 context->getTestTarget(&tt); 186 if (NULL == tt.target()) { 187 SkDEBUGFAIL("Couldn't get Gr test target."); 188 return; 189 } 190 191 SkRect rect = *iter.get(); 192 rect.offset(x, y); 193 SkAutoTUnref<GrEffectRef> effect(GrConvexPolyEffect::CreateForAAFillRect(rect)); 194 if (!effect) { 195 SkDEBUGFAIL("Couldn't create convex poly effect."); 196 return; 197 } 198 199 GrDrawState* drawState = tt.target()->drawState(); 200 drawState->setVertexAttribs<kAttribs>(SK_ARRAY_COUNT(kAttribs)); 201 drawState->addCoverageEffect(effect, 1); 202 drawState->setIdentityViewMatrix(); 203 drawState->setRenderTarget(rt); 204 drawState->setColor(0xff000000); 205 206 SkPoint verts[4]; 207 SkRect bounds = rect; 208 bounds.outset(5.f, 5.f); 209 bounds.toQuad(verts); 210 211 tt.target()->setVertexSourceToArray(verts, 4); 212 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); 213 tt.target()->drawIndexed(kTriangleFan_GrPrimitiveType, 0, 0, 4, 6); 214 215 x += SkScalarCeilToScalar(rect.width() + 10.f); 216 217 // Draw AA rect using normal API for reference 218 canvas->save(); 219 canvas->translate(x, y); 220 SkPaint paint; 221 paint.setAntiAlias(true); 222 canvas->drawRect(*iter.get(), paint); 223 canvas->restore(); 224 225 y += SkScalarCeilToScalar(rect.height() + 20.f); 226 } 227 } 228 229private: 230 SkTLList<SkPath> fPaths; 231 SkTLList<SkRect> fRects; 232 233 typedef GM INHERITED; 234}; 235 236DEF_GM( return SkNEW(ConvexPolyEffect); ) 237} 238 239#endif 240