beziereffects.cpp revision 4b31de8328bbf3ee789157ae1dc6fe7cc74c796a
1 2/* 3 * Copyright 2013 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 "GrBufferAllocPool.h" 17#include "GrContext.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 25#include "effects/GrBezierEffect.h" 26 27static inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) { 28 return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]); 29} 30 31namespace skiagm { 32 33class BezierCubicOrConicTestBatch : public GrTestBatch { 34public: 35 struct Geometry : public GrTestBatch::Geometry { 36 SkRect fBounds; 37 }; 38 39 const char* name() const SK_OVERRIDE { return "BezierCubicOrConicTestBatch"; } 40 41 static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo, 42 const SkScalar klmEqs[9], SkScalar sign) { 43 return SkNEW_ARGS(BezierCubicOrConicTestBatch, (gp, geo, klmEqs, sign)); 44 } 45 46private: 47 BezierCubicOrConicTestBatch(const GrGeometryProcessor* gp, const Geometry& geo, 48 const SkScalar klmEqs[9], SkScalar sign) 49 : INHERITED(gp) { 50 for (int i = 0; i < 9; i++) { 51 fKlmEqs[i] = klmEqs[i]; 52 } 53 54 fGeometry = geo; 55 fSign = sign; 56 } 57 58 struct Vertex { 59 SkPoint fPosition; 60 float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 61 }; 62 63 Geometry* geoData(int index) SK_OVERRIDE { 64 SkASSERT(0 == index); 65 return &fGeometry; 66 } 67 68 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { 69 size_t vertexStride = this->geometryProcessor()->getVertexStride(); 70 71 const GrVertexBuffer* vertexBuffer; 72 int firstVertex; 73 74 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, 75 kVertsPerCubic, 76 &vertexBuffer, 77 &firstVertex); 78 79 if (!vertices || !batchTarget->quadIndexBuffer()) { 80 SkDebugf("Could not allocate buffers\n"); 81 return; 82 } 83 84 SkASSERT(vertexStride == sizeof(Vertex)); 85 Vertex* verts = reinterpret_cast<Vertex*>(vertices); 86 87 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop, 88 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom, 89 sizeof(Vertex)); 90 for (int v = 0; v < 4; ++v) { 91 verts[v].fKLM[0] = eval_line(verts[v].fPosition, fKlmEqs + 0, fSign); 92 verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign); 93 verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f); 94 } 95 96 GrDrawTarget::DrawInfo drawInfo; 97 drawInfo.setPrimitiveType(kTriangleFan_GrPrimitiveType); 98 drawInfo.setVertexBuffer(vertexBuffer); 99 drawInfo.setStartVertex(firstVertex); 100 drawInfo.setVertexCount(kVertsPerCubic); 101 drawInfo.setStartIndex(0); 102 drawInfo.setIndexCount(kIndicesPerCubic); 103 drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer()); 104 batchTarget->draw(drawInfo); 105 } 106 107 Geometry fGeometry; 108 SkScalar fKlmEqs[9]; 109 SkScalar fSign; 110 111 static const int kVertsPerCubic = 4; 112 static const int kIndicesPerCubic = 6; 113 114 typedef GrTestBatch INHERITED; 115}; 116 117/** 118 * This GM directly exercises effects that draw Bezier curves in the GPU backend. 119 */ 120class BezierCubicEffects : public GM { 121public: 122 BezierCubicEffects() { 123 this->setBGColor(0xFFFFFFFF); 124 } 125 126protected: 127 SkString onShortName() SK_OVERRIDE { 128 return SkString("bezier_cubic_effects"); 129 } 130 131 SkISize onISize() SK_OVERRIDE { 132 return SkISize::Make(800, 800); 133 } 134 135 void onDraw(SkCanvas* canvas) SK_OVERRIDE { 136 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 137 if (NULL == rt) { 138 this->drawGpuOnlyMessage(canvas); 139 return; 140 } 141 GrContext* context = rt->getContext(); 142 if (NULL == context) { 143 return; 144 } 145 146 struct Vertex { 147 SkPoint fPosition; 148 float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 149 }; 150 151 static const int kNumCubics = 15; 152 SkRandom rand; 153 154 // Mult by 3 for each edge effect type 155 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3))); 156 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols); 157 SkScalar w = SkIntToScalar(rt->width()) / numCols; 158 SkScalar h = SkIntToScalar(rt->height()) / numRows; 159 int row = 0; 160 int col = 0; 161 162 for (int i = 0; i < kNumCubics; ++i) { 163 SkPoint baseControlPts[] = { 164 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 165 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 166 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 167 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 168 }; 169 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 170 SkAutoTUnref<GrGeometryProcessor> gp; 171 { // scope to contain GrTestTarget 172 GrTestTarget tt; 173 context->getTestTarget(&tt); 174 if (NULL == tt.target()) { 175 continue; 176 } 177 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 178 gp.reset(GrCubicEffect::Create(0xff000000, SkMatrix::I(), et, 179 *tt.target()->caps())); 180 if (!gp) { 181 continue; 182 } 183 } 184 185 SkScalar x = SkScalarMul(col, w); 186 SkScalar y = SkScalarMul(row, h); 187 SkPoint controlPts[] = { 188 {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 189 {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 190 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}, 191 {x + baseControlPts[3].fX, y + baseControlPts[3].fY} 192 }; 193 SkPoint chopped[10]; 194 SkScalar klmEqs[9]; 195 SkScalar klmSigns[3]; 196 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts, 197 chopped, 198 klmEqs, 199 klmSigns); 200 201 SkPaint ctrlPtPaint; 202 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 203 for (int i = 0; i < 4; ++i) { 204 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 205 } 206 207 SkPaint polyPaint; 208 polyPaint.setColor(0xffA0A0A0); 209 polyPaint.setStrokeWidth(0); 210 polyPaint.setStyle(SkPaint::kStroke_Style); 211 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint); 212 213 SkPaint choppedPtPaint; 214 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 215 216 for (int c = 0; c < cnt; ++c) { 217 SkPoint* pts = chopped + 3 * c; 218 219 for (int i = 0; i < 4; ++i) { 220 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 221 } 222 223 SkRect bounds; 224 bounds.set(pts, 4); 225 226 SkPaint boundsPaint; 227 boundsPaint.setColor(0xff808080); 228 boundsPaint.setStrokeWidth(0); 229 boundsPaint.setStyle(SkPaint::kStroke_Style); 230 canvas->drawRect(bounds, boundsPaint); 231 232 GrTestTarget tt; 233 context->getTestTarget(&tt); 234 SkASSERT(tt.target()); 235 236 GrPipelineBuilder pipelineBuilder; 237 pipelineBuilder.setRenderTarget(rt); 238 239 BezierCubicOrConicTestBatch::Geometry geometry; 240 geometry.fColor = gp->color(); 241 geometry.fBounds = bounds; 242 243 SkAutoTUnref<GrBatch> batch( 244 BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, klmSigns[c])); 245 246 tt.target()->drawBatch(&pipelineBuilder, batch, NULL); 247 } 248 ++col; 249 if (numCols == col) { 250 col = 0; 251 ++row; 252 } 253 } 254 } 255 } 256 257private: 258 typedef GM INHERITED; 259}; 260 261////////////////////////////////////////////////////////////////////////////// 262 263/** 264 * This GM directly exercises effects that draw Bezier curves in the GPU backend. 265 */ 266class BezierConicEffects : public GM { 267public: 268 BezierConicEffects() { 269 this->setBGColor(0xFFFFFFFF); 270 } 271 272protected: 273 SkString onShortName() SK_OVERRIDE { 274 return SkString("bezier_conic_effects"); 275 } 276 277 SkISize onISize() SK_OVERRIDE { 278 return SkISize::Make(800, 800); 279 } 280 281 282 void onDraw(SkCanvas* canvas) SK_OVERRIDE { 283 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 284 if (NULL == rt) { 285 this->drawGpuOnlyMessage(canvas); 286 return; 287 } 288 GrContext* context = rt->getContext(); 289 if (NULL == context) { 290 return; 291 } 292 293 struct Vertex { 294 SkPoint fPosition; 295 float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 296 }; 297 298 static const int kNumConics = 10; 299 SkRandom rand; 300 301 // Mult by 3 for each edge effect type 302 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3))); 303 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols); 304 SkScalar w = SkIntToScalar(rt->width()) / numCols; 305 SkScalar h = SkIntToScalar(rt->height()) / numRows; 306 int row = 0; 307 int col = 0; 308 309 for (int i = 0; i < kNumConics; ++i) { 310 SkPoint baseControlPts[] = { 311 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 312 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 313 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 314 }; 315 SkScalar weight = rand.nextRangeF(0.f, 2.f); 316 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 317 SkAutoTUnref<GrGeometryProcessor> gp; 318 { // scope to contain GrTestTarget 319 GrTestTarget tt; 320 context->getTestTarget(&tt); 321 if (NULL == tt.target()) { 322 continue; 323 } 324 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 325 gp.reset(GrConicEffect::Create(0xff000000, SkMatrix::I(), et, 326 *tt.target()->caps(), SkMatrix::I())); 327 if (!gp) { 328 continue; 329 } 330 } 331 332 SkScalar x = SkScalarMul(col, w); 333 SkScalar y = SkScalarMul(row, h); 334 SkPoint controlPts[] = { 335 {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 336 {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 337 {x + baseControlPts[2].fX, y + baseControlPts[2].fY} 338 }; 339 SkConic dst[4]; 340 SkScalar klmEqs[9]; 341 int cnt = chop_conic(controlPts, dst, weight); 342 GrPathUtils::getConicKLM(controlPts, weight, klmEqs); 343 344 SkPaint ctrlPtPaint; 345 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 346 for (int i = 0; i < 3; ++i) { 347 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 348 } 349 350 SkPaint polyPaint; 351 polyPaint.setColor(0xffA0A0A0); 352 polyPaint.setStrokeWidth(0); 353 polyPaint.setStyle(SkPaint::kStroke_Style); 354 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 355 356 SkPaint choppedPtPaint; 357 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 358 359 for (int c = 0; c < cnt; ++c) { 360 SkPoint* pts = dst[c].fPts; 361 for (int i = 0; i < 3; ++i) { 362 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 363 } 364 365 SkRect bounds; 366 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}}; 367 //bounds.set(bPts, 2); 368 bounds.set(pts, 3); 369 370 SkPaint boundsPaint; 371 boundsPaint.setColor(0xff808080); 372 boundsPaint.setStrokeWidth(0); 373 boundsPaint.setStyle(SkPaint::kStroke_Style); 374 canvas->drawRect(bounds, boundsPaint); 375 376 GrTestTarget tt; 377 context->getTestTarget(&tt); 378 SkASSERT(tt.target()); 379 380 GrPipelineBuilder pipelineBuilder; 381 pipelineBuilder.setRenderTarget(rt); 382 383 BezierCubicOrConicTestBatch::Geometry geometry; 384 geometry.fColor = gp->color(); 385 geometry.fBounds = bounds; 386 387 SkAutoTUnref<GrBatch> batch( 388 BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, 1.f)); 389 390 tt.target()->drawBatch(&pipelineBuilder, batch, NULL); 391 } 392 ++col; 393 if (numCols == col) { 394 col = 0; 395 ++row; 396 } 397 } 398 } 399 } 400 401private: 402 // Uses the max curvature function for quads to estimate 403 // where to chop the conic. If the max curvature is not 404 // found along the curve segment it will return 1 and 405 // dst[0] is the original conic. If it returns 2 the dst[0] 406 // and dst[1] are the two new conics. 407 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 408 SkScalar t = SkFindQuadMaxCurvature(src); 409 if (t == 0) { 410 if (dst) { 411 dst[0].set(src, weight); 412 } 413 return 1; 414 } else { 415 if (dst) { 416 SkConic conic; 417 conic.set(src, weight); 418 conic.chopAt(t, dst); 419 } 420 return 2; 421 } 422 } 423 424 // Calls split_conic on the entire conic and then once more on each subsection. 425 // Most cases will result in either 1 conic (chop point is not within t range) 426 // or 3 points (split once and then one subsection is split again). 427 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) { 428 SkConic dstTemp[2]; 429 int conicCnt = split_conic(src, dstTemp, weight); 430 if (2 == conicCnt) { 431 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW); 432 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW); 433 } else { 434 dst[0] = dstTemp[0]; 435 } 436 return conicCnt; 437 } 438 439 typedef GM INHERITED; 440}; 441 442////////////////////////////////////////////////////////////////////////////// 443 444class BezierQuadTestBatch : public GrTestBatch { 445public: 446 struct Geometry : public GrTestBatch::Geometry { 447 SkRect fBounds; 448 }; 449 450 const char* name() const SK_OVERRIDE { return "BezierQuadTestBatch"; } 451 452 static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo, 453 const GrPathUtils::QuadUVMatrix& devToUV) { 454 return SkNEW_ARGS(BezierQuadTestBatch, (gp, geo, devToUV)); 455 } 456 457private: 458 BezierQuadTestBatch(const GrGeometryProcessor* gp, const Geometry& geo, 459 const GrPathUtils::QuadUVMatrix& devToUV) 460 : INHERITED(gp) 461 , fGeometry(geo) 462 , fDevToUV(devToUV) { 463 } 464 465 struct Vertex { 466 SkPoint fPosition; 467 float fKLM[4]; // The last value is ignored. The effect expects a vec4f. 468 }; 469 470 Geometry* geoData(int index) SK_OVERRIDE { 471 SkASSERT(0 == index); 472 return &fGeometry; 473 } 474 475 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE { 476 size_t vertexStride = this->geometryProcessor()->getVertexStride(); 477 478 const GrVertexBuffer* vertexBuffer; 479 int firstVertex; 480 481 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, 482 kVertsPerCubic, 483 &vertexBuffer, 484 &firstVertex); 485 486 if (!vertices || !batchTarget->quadIndexBuffer()) { 487 SkDebugf("Could not allocate buffers\n"); 488 return; 489 } 490 491 SkASSERT(vertexStride == sizeof(Vertex)); 492 Vertex* verts = reinterpret_cast<Vertex*>(vertices); 493 494 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop, 495 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom, 496 sizeof(Vertex)); 497 498 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts); 499 500 501 GrDrawTarget::DrawInfo drawInfo; 502 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType); 503 drawInfo.setVertexBuffer(vertexBuffer); 504 drawInfo.setStartVertex(firstVertex); 505 drawInfo.setVertexCount(kVertsPerCubic); 506 drawInfo.setStartIndex(0); 507 drawInfo.setIndexCount(kIndicesPerCubic); 508 drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer()); 509 batchTarget->draw(drawInfo); 510 } 511 512 Geometry fGeometry; 513 GrPathUtils::QuadUVMatrix fDevToUV; 514 515 static const int kVertsPerCubic = 4; 516 static const int kIndicesPerCubic = 6; 517 518 typedef GrTestBatch INHERITED; 519}; 520 521/** 522 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend. 523 */ 524class BezierQuadEffects : public GM { 525public: 526 BezierQuadEffects() { 527 this->setBGColor(0xFFFFFFFF); 528 } 529 530protected: 531 SkString onShortName() SK_OVERRIDE { 532 return SkString("bezier_quad_effects"); 533 } 534 535 SkISize onISize() SK_OVERRIDE { 536 return SkISize::Make(800, 800); 537 } 538 539 540 void onDraw(SkCanvas* canvas) SK_OVERRIDE { 541 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 542 if (NULL == rt) { 543 this->drawGpuOnlyMessage(canvas); 544 return; 545 } 546 GrContext* context = rt->getContext(); 547 if (NULL == context) { 548 return; 549 } 550 551 struct Vertex { 552 SkPoint fPosition; 553 float fUV[4]; // The last two values are ignored. The effect expects a vec4f. 554 }; 555 556 static const int kNumQuads = 5; 557 SkRandom rand; 558 559 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3))); 560 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols); 561 SkScalar w = SkIntToScalar(rt->width()) / numCols; 562 SkScalar h = SkIntToScalar(rt->height()) / numRows; 563 int row = 0; 564 int col = 0; 565 566 for (int i = 0; i < kNumQuads; ++i) { 567 SkPoint baseControlPts[] = { 568 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 569 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}, 570 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)} 571 }; 572 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) { 573 SkAutoTUnref<GrGeometryProcessor> gp; 574 { // scope to contain GrTestTarget 575 GrTestTarget tt; 576 context->getTestTarget(&tt); 577 if (NULL == tt.target()) { 578 continue; 579 } 580 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType; 581 gp.reset(GrQuadEffect::Create(0xff000000, SkMatrix::I(), et, 582 *tt.target()->caps(), SkMatrix::I())); 583 if (!gp) { 584 continue; 585 } 586 } 587 588 SkScalar x = SkScalarMul(col, w); 589 SkScalar y = SkScalarMul(row, h); 590 SkPoint controlPts[] = { 591 {x + baseControlPts[0].fX, y + baseControlPts[0].fY}, 592 {x + baseControlPts[1].fX, y + baseControlPts[1].fY}, 593 {x + baseControlPts[2].fX, y + baseControlPts[2].fY} 594 }; 595 SkPoint chopped[5]; 596 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped); 597 598 SkPaint ctrlPtPaint; 599 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); 600 for (int i = 0; i < 3; ++i) { 601 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); 602 } 603 604 SkPaint polyPaint; 605 polyPaint.setColor(0xffA0A0A0); 606 polyPaint.setStrokeWidth(0); 607 polyPaint.setStyle(SkPaint::kStroke_Style); 608 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint); 609 610 SkPaint choppedPtPaint; 611 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000); 612 613 for (int c = 0; c < cnt; ++c) { 614 SkPoint* pts = chopped + 2 * c; 615 616 for (int i = 0; i < 3; ++i) { 617 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint); 618 } 619 620 SkRect bounds; 621 bounds.set(pts, 3); 622 623 SkPaint boundsPaint; 624 boundsPaint.setColor(0xff808080); 625 boundsPaint.setStrokeWidth(0); 626 boundsPaint.setStyle(SkPaint::kStroke_Style); 627 canvas->drawRect(bounds, boundsPaint); 628 629 GrTestTarget tt; 630 context->getTestTarget(&tt); 631 SkASSERT(tt.target()); 632 633 GrPipelineBuilder pipelineBuilder; 634 pipelineBuilder.setRenderTarget(rt); 635 636 GrPathUtils::QuadUVMatrix DevToUV(pts); 637 638 BezierQuadTestBatch::Geometry geometry; 639 geometry.fColor = gp->color(); 640 geometry.fBounds = bounds; 641 642 SkAutoTUnref<GrBatch> batch(BezierQuadTestBatch::Create(gp, geometry, DevToUV)); 643 644 tt.target()->drawBatch(&pipelineBuilder, batch, NULL); 645 } 646 ++col; 647 if (numCols == col) { 648 col = 0; 649 ++row; 650 } 651 } 652 } 653 } 654 655private: 656 typedef GM INHERITED; 657}; 658 659DEF_GM( return SkNEW(BezierCubicEffects); ) 660DEF_GM( return SkNEW(BezierConicEffects); ) 661DEF_GM( return SkNEW(BezierQuadEffects); ) 662 663} 664 665#endif 666