beziereffects.cpp revision 8059eb9f6e24ed609393fbda4ad71edea03ac258
1bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 2bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt/* 3bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * Copyright 2013 Google Inc. 4bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * 5bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * Use of this source code is governed by a BSD-style license that can be 6bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * found in the LICENSE file. 7bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt */ 8bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 9bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt// This test only works with the GPU backend. 10bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 11bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "gm.h" 12bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 13bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#if SK_SUPPORT_GPU 14bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 15bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "GrContext.h" 16bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "GrPathUtils.h" 17bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "GrTest.h" 18bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "SkColorPriv.h" 19bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "SkDevice.h" 20bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "SkGeometry.h" 21bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 22bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt#include "effects/GrBezierEffect.h" 23bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 24bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtstatic inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) { 25bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]); 26bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt} 27bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 28bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtnamespace skiagm { 29bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt/** 30bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * This GM directly exercises effects that draw Bezier curves in the GPU backend. 31bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt */ 32bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtclass BezierCubicEffects : public GM { 33bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtpublic: 34bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt BezierCubicEffects() { 35bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt this->setBGColor(0xFFFFFFFF); 36bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 37bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 38bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtprotected: 39bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkString onShortName() SK_OVERRIDE { 40bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkString("bezier_cubic_effects"); 41bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 42bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 43bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkISize onISize() SK_OVERRIDE { 44bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkISize::Make(800, 800); 45bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 46bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 47bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual uint32_t onGetFlags() const SK_OVERRIDE { 48bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // This is a GPU-specific GM. 49bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return kGPUOnly_Flag; 50bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 51bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 52bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 53bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 54bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 55bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == rt) { 56bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 57bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 58bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrContext* context = rt->getContext(); 59bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == context) { 60bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 61bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 62bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 63bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt struct Vertex { 64bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint fPosition; 65bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 66bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 67bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 68bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt static const int kNumCubics = 15; 69bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkRandom rand; 70bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 71bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // Mult by 3 for each edge effect type 72bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3))); 73bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols); 74bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar w = SkIntToScalar(rt->width()) / numCols; 75bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar h = SkIntToScalar(rt->height()) / numRows; 76bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int row = 0; 77bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int col = 0; 78bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 79bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < kNumCubics; ++i) { 80bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint baseControlPts[] = { 81bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 82bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 83bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 84bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 85bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 86bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 87bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkAutoTUnref<GrGeometryProcessor> gp; 88bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt { // scope to contain GrTestTarget 89bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrTestTarget tt; 90bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt context->getTestTarget(&tt); 91bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == tt.target()) { 92bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt continue; 93bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 94bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 95bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt gp.reset(GrCubicEffect::Create(0xff000000, SkMatrix::I(), et, 96bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt *tt.target()->caps())); 97bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (!gp) { 98bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt continue; 99bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 100bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 101bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 102bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar x = SkScalarMul(col, w); 103bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar y = SkScalarMul(row, h); 104bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint controlPts[] = { 105bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 106bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 107bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[2].fX, y + baseControlPts[2].fY}, 108bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[3].fX, y + baseControlPts[3].fY} 109bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 110bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint chopped[10]; 111bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar klmEqs[9]; 112bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar klmSigns[3]; 113bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts, 114bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt chopped, 115bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt klmEqs, 116bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt klmSigns); 117bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 118bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint ctrlPtPaint; 119bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 120bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < 4; ++i) { 121bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 122bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 123bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 124bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint polyPaint; 125bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setColor(0xffA0A0A0); 126bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setStrokeWidth(0); 127bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setStyle(SkPaint::kStroke_Style); 128bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint); 129bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 130bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint choppedPtPaint; 131bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 132bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 133bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int c = 0; c < cnt; ++c) { 134bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint* pts = chopped + 3 * c; 135bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 136bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < 4; ++i) { 137bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 138bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 139bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 140bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkRect bounds; 141bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt bounds.set(pts, 4); 142bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 143bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint boundsPaint; 144bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setColor(0xff808080); 145bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setStrokeWidth(0); 146bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setStyle(SkPaint::kStroke_Style); 147bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawRect(bounds, boundsPaint); 148bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 149bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrTestTarget tt; 150bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt context->getTestTarget(&tt); 151bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkASSERT(tt.target()); 152bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 153bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrDrawState ds; 154bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 155bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); 156bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkASSERT(gp->getVertexStride() == sizeof(Vertex)); 157bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); 158bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 159bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, 160bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt bounds.fRight, bounds.fBottom, 161bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt sizeof(Vertex)); 162bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int v = 0; v < 4; ++v) { 163bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[0] = eval_line(verts[v].fPosition, klmEqs + 0, klmSigns[c]); 164bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[1] = eval_line(verts[v].fPosition, klmEqs + 3, klmSigns[c]); 165bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[2] = eval_line(verts[v].fPosition, klmEqs + 6, 1.f); 166bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 167bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 168bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ds.setRenderTarget(rt); 169bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 170bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); 171bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt tt.target()->drawIndexed(&ds, gp, kTriangleFan_GrPrimitiveType, 0, 0,4,6); 172bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 173bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ++col; 174bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (numCols == col) { 175bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt col = 0; 176bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ++row; 177bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 178bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 179bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 180bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 181bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 182bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtprivate: 183bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt typedef GM INHERITED; 184bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt}; 185bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 186bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt////////////////////////////////////////////////////////////////////////////// 187bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 188bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt/** 189bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * This GM directly exercises effects that draw Bezier curves in the GPU backend. 190bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt */ 191bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtclass BezierConicEffects : public GM { 192bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtpublic: 193bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt BezierConicEffects() { 194bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt this->setBGColor(0xFFFFFFFF); 195bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 196bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 197bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtprotected: 198bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkString onShortName() SK_OVERRIDE { 199bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkString("bezier_conic_effects"); 200bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 201bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 202bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkISize onISize() SK_OVERRIDE { 203bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkISize::Make(800, 800); 204bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 205bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 206bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual uint32_t onGetFlags() const SK_OVERRIDE { 207bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // This is a GPU-specific GM. 208bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return kGPUOnly_Flag; 209bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 210bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 211bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 212bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 213bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 214bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == rt) { 215bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 216bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 217bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrContext* context = rt->getContext(); 218bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == context) { 219bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 220bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 221bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 222bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt struct Vertex { 223bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint fPosition; 224bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 225bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 226bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 227bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt static const int kNumConics = 10; 228bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkRandom rand; 229bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 230bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // Mult by 3 for each edge effect type 231bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3))); 232bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols); 233bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar w = SkIntToScalar(rt->width()) / numCols; 234bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar h = SkIntToScalar(rt->height()) / numRows; 235bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int row = 0; 236bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int col = 0; 237bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 238bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < kNumConics; ++i) { 239bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint baseControlPts[] = { 240bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 241bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 242bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 243bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 244bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar weight = rand.nextRangeF(0.f, 2.f); 245bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 246bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkAutoTUnref<GrGeometryProcessor> gp; 247bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt { // scope to contain GrTestTarget 248bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrTestTarget tt; 249bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt context->getTestTarget(&tt); 250bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == tt.target()) { 251bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt continue; 252bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 253bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 254bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt gp.reset(GrConicEffect::Create(0xff000000, SkMatrix::I(), et, 255bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt *tt.target()->caps(), SkMatrix::I())); 256bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (!gp) { 257bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt continue; 258bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 259bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 260bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 261bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar x = SkScalarMul(col, w); 262bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar y = SkScalarMul(row, h); 263bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint controlPts[] = { 264bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 265bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 266bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {x + baseControlPts[2].fX, y + baseControlPts[2].fY} 267bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 268bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkConic dst[4]; 269bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar klmEqs[9]; 270bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int cnt = chop_conic(controlPts, dst, weight); 271bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrPathUtils::getConicKLM(controlPts, weight, klmEqs); 272bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 273bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint ctrlPtPaint; 274bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 275bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < 3; ++i) { 276bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 277bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 278bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 279bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint polyPaint; 280bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setColor(0xffA0A0A0); 281bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setStrokeWidth(0); 282bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt polyPaint.setStyle(SkPaint::kStroke_Style); 283bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 284bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 285bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint choppedPtPaint; 286bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 287bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 288bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int c = 0; c < cnt; ++c) { 289bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint* pts = dst[c].fPts; 290bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < 3; ++i) { 291bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 292bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 293bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 294bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkRect bounds; 295bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}}; 296bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt //bounds.set(bPts, 2); 297bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt bounds.set(pts, 3); 298bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 299bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPaint boundsPaint; 300bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setColor(0xff808080); 301bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setStrokeWidth(0); 302bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt boundsPaint.setStyle(SkPaint::kStroke_Style); 303bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt canvas->drawRect(bounds, boundsPaint); 304bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 305bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrTestTarget tt; 306bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt context->getTestTarget(&tt); 307bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkASSERT(tt.target()); 308bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 309bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrDrawState ds; 310bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 311bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); 312bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkASSERT(gp->getVertexStride() == sizeof(Vertex)); 313bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); 314bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 315bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, 316bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt bounds.fRight, bounds.fBottom, 317bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt sizeof(Vertex)); 318bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int v = 0; v < 4; ++v) { 319bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[0] = eval_line(verts[v].fPosition, klmEqs + 0, 1.f); 320bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[1] = eval_line(verts[v].fPosition, klmEqs + 3, 1.f); 321bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt verts[v].fKLM[2] = eval_line(verts[v].fPosition, klmEqs + 6, 1.f); 322bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 323bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 324bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ds.setRenderTarget(rt); 325bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 326bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); 327bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt tt.target()->drawIndexed(&ds, gp, kTriangleFan_GrPrimitiveType, 0, 0,4,6); 328bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 329bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ++col; 330bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (numCols == col) { 331bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt col = 0; 332bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt ++row; 333bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 334bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 335bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 336bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 337bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 338bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtprivate: 339bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // Uses the max curvature function for quads to estimate 340bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // where to chop the conic. If the max curvature is not 341bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // found along the curve segment it will return 1 and 342bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // dst[0] is the original conic. If it returns 2 the dst[0] 343bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // and dst[1] are the two new conics. 344bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 345bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar t = SkFindQuadMaxCurvature(src); 346bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (t == 0) { 347bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (dst) { 348bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt dst[0].set(src, weight); 349bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 350bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return 1; 351bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } else { 352bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (dst) { 353bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkConic conic; 354bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt conic.set(src, weight); 355bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt conic.chopAt(t, dst); 356bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 357bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return 2; 358bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 359bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 360bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 361bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // Calls split_conic on the entire conic and then once more on each subsection. 362bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // Most cases will result in either 1 conic (chop point is not within t range) 363bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // or 3 points (split once and then one subsection is split again). 364bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 365bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkConic dstTemp[2]; 366bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int conicCnt = split_conic(src, dstTemp, weight); 367bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (2 == conicCnt) { 368bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW); 369bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW); 370bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } else { 371bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt dst[0] = dstTemp[0]; 372bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 373bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return conicCnt; 374bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 375bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 376bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt typedef GM INHERITED; 377bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt}; 378bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 379bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt////////////////////////////////////////////////////////////////////////////// 380bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt/** 381bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt * This GM directly exercises effects that draw Bezier quad curves in the GPU backend. 382bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt */ 383bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtclass BezierQuadEffects : public GM { 384bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtpublic: 385bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt BezierQuadEffects() { 386bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt this->setBGColor(0xFFFFFFFF); 387bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 388bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 389bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholtprotected: 390bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkString onShortName() SK_OVERRIDE { 391bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkString("bezier_quad_effects"); 392bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 393bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 394bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual SkISize onISize() SK_OVERRIDE { 395bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return SkISize::Make(800, 800); 396bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 397bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 398bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual uint32_t onGetFlags() const SK_OVERRIDE { 399bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt // This is a GPU-specific GM. 400bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return kGPUOnly_Flag; 401bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 402bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 403bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 404bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { 405bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 406bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == rt) { 407bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 408bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 409bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt GrContext* context = rt->getContext(); 410bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt if (NULL == context) { 411bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt return; 412bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt } 413bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 414bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt struct Vertex { 415bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint fPosition; 416bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt float fUV[4]; // The last two values are ignored. The effect expects a vec4f. 417bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt }; 418bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 419bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt static const int kNumQuads = 5; 420bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkRandom rand; 421bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 422bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3))); 423bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols); 424bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar w = SkIntToScalar(rt->width()) / numCols; 425bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkScalar h = SkIntToScalar(rt->height()) / numRows; 426bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int row = 0; 427bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt int col = 0; 428bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt 429bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt for (int i = 0; i < kNumQuads; ++i) { 430bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt SkPoint baseControlPts[] = { 431bf3c50fba221f216e38d3f60f89161ced4c684c0Eric Anholt {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 432 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 433 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 434 }; 435 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 436 SkAutoTUnref<GrGeometryProcessor> gp; 437 { // scope to contain GrTestTarget 438 GrTestTarget tt; 439 context->getTestTarget(&tt); 440 if (NULL == tt.target()) { 441 continue; 442 } 443 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 444 gp.reset(GrQuadEffect::Create(0xff000000, SkMatrix::I(), et, 445 *tt.target()->caps(), SkMatrix::I())); 446 if (!gp) { 447 continue; 448 } 449 } 450 451 SkScalar x = SkScalarMul(col, w); 452 SkScalar y = SkScalarMul(row, h); 453 SkPoint controlPts[] = { 454 {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 455 {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 456 {x + baseControlPts[2].fX, y + baseControlPts[2].fY} 457 }; 458 SkPoint chopped[5]; 459 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped); 460 461 SkPaint ctrlPtPaint; 462 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 463 for (int i = 0; i < 3; ++i) { 464 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 465 } 466 467 SkPaint polyPaint; 468 polyPaint.setColor(0xffA0A0A0); 469 polyPaint.setStrokeWidth(0); 470 polyPaint.setStyle(SkPaint::kStroke_Style); 471 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 472 473 SkPaint choppedPtPaint; 474 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 475 476 for (int c = 0; c < cnt; ++c) { 477 SkPoint* pts = chopped + 2 * c; 478 479 for (int i = 0; i < 3; ++i) { 480 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 481 } 482 483 SkRect bounds; 484 bounds.set(pts, 3); 485 486 SkPaint boundsPaint; 487 boundsPaint.setColor(0xff808080); 488 boundsPaint.setStrokeWidth(0); 489 boundsPaint.setStyle(SkPaint::kStroke_Style); 490 canvas->drawRect(bounds, boundsPaint); 491 492 GrTestTarget tt; 493 context->getTestTarget(&tt); 494 SkASSERT(tt.target()); 495 496 GrDrawState ds; 497 498 GrDrawTarget::AutoReleaseGeometry geo(tt.target(), 4, gp->getVertexStride(), 0); 499 SkASSERT(gp->getVertexStride() == sizeof(Vertex)); 500 Vertex* verts = reinterpret_cast<Vertex*>(geo.vertices()); 501 502 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, 503 bounds.fRight, bounds.fBottom, 504 sizeof(Vertex)); 505 506 GrPathUtils::QuadUVMatrix DevToUV(pts); 507 DevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts); 508 509 ds.setRenderTarget(rt); 510 511 tt.target()->setIndexSourceToBuffer(context->getQuadIndexBuffer()); 512 tt.target()->drawIndexed(&ds, gp, kTriangles_GrPrimitiveType, 0, 0, 4, 6); 513 } 514 ++col; 515 if (numCols == col) { 516 col = 0; 517 ++row; 518 } 519 } 520 } 521 } 522 523private: 524 typedef GM INHERITED; 525}; 526 527DEF_GM( return SkNEW(BezierCubicEffects); ) 528DEF_GM( return SkNEW(BezierConicEffects); ) 529DEF_GM( return SkNEW(BezierQuadEffects); ) 530 531} 532 533#endif 534