Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrContext.h" | 9 #include "GrContext.h" |
| 10 | 10 |
| 11 #include "GrAARectRenderer.h" | 11 #include "GrAARectRenderer.h" |
| 12 #include "GrBatch.h" | |
| 13 #include "GrBatchTarget.h" | |
| 12 #include "GrBufferAllocPool.h" | 14 #include "GrBufferAllocPool.h" |
| 13 #include "GrDefaultGeoProcFactory.h" | 15 #include "GrDefaultGeoProcFactory.h" |
| 14 #include "GrFontCache.h" | 16 #include "GrFontCache.h" |
| 15 #include "GrGpuResource.h" | 17 #include "GrGpuResource.h" |
| 16 #include "GrGpuResourcePriv.h" | 18 #include "GrGpuResourcePriv.h" |
| 17 #include "GrDistanceFieldTextContext.h" | 19 #include "GrDistanceFieldTextContext.h" |
| 18 #include "GrDrawTargetCaps.h" | 20 #include "GrDrawTargetCaps.h" |
| 19 #include "GrGpu.h" | 21 #include "GrGpu.h" |
| 20 #include "GrIndexBuffer.h" | 22 #include "GrIndexBuffer.h" |
| 21 #include "GrInOrderDrawBuffer.h" | 23 #include "GrInOrderDrawBuffer.h" |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 } | 426 } |
| 425 | 427 |
| 426 #ifdef SK_DEVELOPER | 428 #ifdef SK_DEVELOPER |
| 427 void GrContext::dumpFontCache() const { | 429 void GrContext::dumpFontCache() const { |
| 428 fFontCache->dump(); | 430 fFontCache->dump(); |
| 429 } | 431 } |
| 430 #endif | 432 #endif |
| 431 | 433 |
| 432 //////////////////////////////////////////////////////////////////////////////// | 434 //////////////////////////////////////////////////////////////////////////////// |
| 433 | 435 |
| 434 /* create a triangle strip that strokes the specified triangle. There are 8 | |
| 435 unique vertices, but we repreat the last 2 to close up. Alternatively we | |
| 436 could use an indices array, and then only send 8 verts, but not sure that | |
| 437 would be faster. | |
| 438 */ | |
| 439 static void setStrokeRectStrip(SkPoint verts[10], SkRect rect, | |
| 440 SkScalar width) { | |
| 441 const SkScalar rad = SkScalarHalf(width); | |
| 442 rect.sort(); | |
| 443 | |
| 444 verts[0].set(rect.fLeft + rad, rect.fTop + rad); | |
| 445 verts[1].set(rect.fLeft - rad, rect.fTop - rad); | |
| 446 verts[2].set(rect.fRight - rad, rect.fTop + rad); | |
| 447 verts[3].set(rect.fRight + rad, rect.fTop - rad); | |
| 448 verts[4].set(rect.fRight - rad, rect.fBottom - rad); | |
| 449 verts[5].set(rect.fRight + rad, rect.fBottom + rad); | |
| 450 verts[6].set(rect.fLeft + rad, rect.fBottom - rad); | |
| 451 verts[7].set(rect.fLeft - rad, rect.fBottom + rad); | |
| 452 verts[8] = verts[0]; | |
| 453 verts[9] = verts[1]; | |
| 454 } | |
| 455 | |
| 456 static inline bool is_irect(const SkRect& r) { | 436 static inline bool is_irect(const SkRect& r) { |
| 457 return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) && | 437 return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) && |
| 458 SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom); | 438 SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom); |
| 459 } | 439 } |
| 460 | 440 |
| 461 static bool apply_aa_to_rect(GrDrawTarget* target, | 441 static bool apply_aa_to_rect(GrDrawTarget* target, |
| 462 GrPipelineBuilder* pipelineBuilder, | 442 GrPipelineBuilder* pipelineBuilder, |
| 463 SkRect* devBoundRect, | 443 SkRect* devBoundRect, |
| 464 const SkRect& rect, | 444 const SkRect& rect, |
| 465 SkScalar strokeWidth, | 445 SkScalar strokeWidth, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 494 } | 474 } |
| 495 | 475 |
| 496 return true; | 476 return true; |
| 497 } | 477 } |
| 498 | 478 |
| 499 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& po int) { | 479 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& po int) { |
| 500 return point.fX >= rect.fLeft && point.fX <= rect.fRight && | 480 return point.fX >= rect.fLeft && point.fX <= rect.fRight && |
| 501 point.fY >= rect.fTop && point.fY <= rect.fBottom; | 481 point.fY >= rect.fTop && point.fY <= rect.fBottom; |
| 502 } | 482 } |
| 503 | 483 |
| 484 class StrokeRectBatch : public GrBatch { | |
| 485 public: | |
| 486 struct Geometry { | |
| 487 GrColor fColor; | |
|
robertphillips
2015/02/25 15:50:26
Not the view matrix again :(
| |
| 488 SkMatrix fViewMatrix; | |
| 489 SkRect fRect; | |
| 490 SkScalar fStrokeWidth; | |
| 491 }; | |
| 492 | |
| 493 static GrBatch* Create(const Geometry& geometry) { | |
| 494 return SkNEW_ARGS(StrokeRectBatch, (geometry)); | |
| 495 } | |
| 496 | |
| 497 const char* name() const SK_OVERRIDE { return "StrokeRectBatch"; } | |
| 498 | |
| 499 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { | |
| 500 // When this is called on a batch, there is only one geometry bundle | |
| 501 out->setKnownFourComponents(fGeoData[0].fColor); | |
| 502 } | |
| 503 | |
| 504 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E { | |
| 505 out->setKnownSingleComponent(0xff); | |
| 506 } | |
| 507 | |
| 508 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { | |
| 509 // Handle any color overrides | |
| 510 if (init.fColorIgnored) { | |
| 511 fGeoData[0].fColor = GrColor_ILLEGAL; | |
| 512 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | |
| 513 fGeoData[0].fColor = init.fOverrideColor; | |
| 514 } | |
| 515 | |
| 516 // setup batch properties | |
| 517 fBatch.fColorIgnored = init.fColorIgnored; | |
| 518 fBatch.fColor = fGeoData[0].fColor; | |
| 519 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
| 520 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
| 521 } | |
| 522 | |
| 523 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { | |
| 524 SkAutoTUnref<const GrGeometryProcessor> gp( | |
| 525 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPositi on_GPType, | |
| 526 this->color(), | |
| 527 this->viewMatrix(), | |
| 528 SkMatrix::I())); | |
| 529 | |
| 530 batchTarget->initDraw(gp, pipeline); | |
| 531 | |
| 532 // TODO this is hacky, but the only way we have to initialize the GP is to use the | |
| 533 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch | |
| 534 // everywhere we can remove this nastiness | |
| 535 GrPipelineInfo init; | |
| 536 init.fColorIgnored = fBatch.fColorIgnored; | |
| 537 init.fOverrideColor = GrColor_ILLEGAL; | |
| 538 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
| 539 init.fUsesLocalCoords = this->usesLocalCoords(); | |
| 540 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
| 541 | |
| 542 size_t vertexStride = gp->getVertexStride(); | |
| 543 | |
| 544 SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr)); | |
| 545 | |
| 546 const Geometry& args = fGeoData[0]; | |
| 547 | |
| 548 int vertexCount = kVertsPerHairlineRect; | |
| 549 if (args.fStrokeWidth > 0) { | |
| 550 vertexCount = kVertsPerStrokeRect; | |
| 551 } | |
| 552 | |
| 553 const GrVertexBuffer* vertexBuffer; | |
| 554 int firstVertex; | |
| 555 | |
| 556 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
| 557 vertexCount, | |
| 558 &vertexBuffer, | |
| 559 &firstVertex); | |
| 560 | |
| 561 SkPoint* vertex = reinterpret_cast<SkPoint*>(vertices); | |
| 562 | |
| 563 GrPrimitiveType primType; | |
| 564 | |
| 565 | |
| 566 if (args.fStrokeWidth > 0) {; | |
| 567 primType = kTriangleStrip_GrPrimitiveType; | |
| 568 this->setStrokeRectStrip(vertex, args.fRect, args.fStrokeWidth); | |
| 569 } else { | |
| 570 // hairline | |
| 571 primType = kLineStrip_GrPrimitiveType; | |
| 572 vertex[0].set(args.fRect.fLeft, args.fRect.fTop); | |
| 573 vertex[1].set(args.fRect.fRight, args.fRect.fTop); | |
| 574 vertex[2].set(args.fRect.fRight, args.fRect.fBottom); | |
| 575 vertex[3].set(args.fRect.fLeft, args.fRect.fBottom); | |
| 576 vertex[4].set(args.fRect.fLeft, args.fRect.fTop); | |
| 577 } | |
| 578 | |
| 579 GrDrawTarget::DrawInfo drawInfo; | |
| 580 drawInfo.setPrimitiveType(primType); | |
| 581 drawInfo.setVertexBuffer(vertexBuffer); | |
| 582 drawInfo.setStartVertex(firstVertex); | |
| 583 drawInfo.setVertexCount(vertexCount); | |
| 584 drawInfo.setStartIndex(0); | |
| 585 drawInfo.setIndexCount(0); | |
| 586 drawInfo.setInstanceCount(0); | |
| 587 drawInfo.setVerticesPerInstance(0); | |
| 588 drawInfo.setIndicesPerInstance(0); | |
| 589 batchTarget->draw(drawInfo); | |
| 590 } | |
| 591 | |
| 592 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 593 | |
| 594 private: | |
| 595 StrokeRectBatch(const Geometry& geometry) { | |
| 596 this->initClassID<StrokeRectBatch>(); | |
| 597 | |
| 598 fBatch.fHairline = geometry.fStrokeWidth == 0; | |
| 599 | |
| 600 fGeoData.push_back(geometry); | |
| 601 } | |
| 602 | |
|
robertphillips
2015/02/25 15:50:26
specified triangle -> specified rect ?
| |
| 603 /* create a triangle strip that strokes the specified triangle. There are 8 | |
|
robertphillips
2015/02/25 15:50:26
repreat ?
| |
| 604 unique vertices, but we repreat the last 2 to close up. Alternatively we | |
| 605 could use an indices array, and then only send 8 verts, but not sure that | |
| 606 would be faster. | |
| 607 */ | |
|
robertphillips
2015/02/25 15:50:26
Do we need an assert that the stroke width/2 is le
| |
| 608 void setStrokeRectStrip(SkPoint verts[10], SkRect rect, SkScalar width) { | |
|
robertphillips
2015/02/25 15:50:26
Can we call 'sort' on the SkRect when we put it in
| |
| 609 const SkScalar rad = SkScalarHalf(width); | |
| 610 rect.sort(); | |
| 611 | |
| 612 verts[0].set(rect.fLeft + rad, rect.fTop + rad); | |
| 613 verts[1].set(rect.fLeft - rad, rect.fTop - rad); | |
| 614 verts[2].set(rect.fRight - rad, rect.fTop + rad); | |
| 615 verts[3].set(rect.fRight + rad, rect.fTop - rad); | |
| 616 verts[4].set(rect.fRight - rad, rect.fBottom - rad); | |
| 617 verts[5].set(rect.fRight + rad, rect.fBottom + rad); | |
| 618 verts[6].set(rect.fLeft + rad, rect.fBottom - rad); | |
| 619 verts[7].set(rect.fLeft - rad, rect.fBottom + rad); | |
| 620 verts[8] = verts[0]; | |
| 621 verts[9] = verts[1]; | |
| 622 } | |
| 623 | |
| 624 | |
| 625 GrColor color() const { return fBatch.fColor; } | |
| 626 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 627 bool colorIgnored() const { return fBatch.fColorIgnored; } | |
| 628 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 629 bool hairline() const { return fBatch.fHairline; } | |
| 630 | |
| 631 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { | |
| 632 // StrokeRectBatch* that = t->cast<StrokeRectBatch>(); | |
| 633 | |
| 634 // NonAA stroke rects cannot batch right now | |
| 635 // TODO make these batchable | |
| 636 return false; | |
| 637 } | |
| 638 | |
| 639 struct BatchTracker { | |
| 640 GrColor fColor; | |
| 641 bool fUsesLocalCoords; | |
| 642 bool fColorIgnored; | |
| 643 bool fCoverageIgnored; | |
| 644 bool fHairline; | |
| 645 }; | |
| 646 | |
| 647 const static int kVertsPerHairlineRect = 5; | |
| 648 const static int kVertsPerStrokeRect = 10; | |
| 649 | |
| 650 BatchTracker fBatch; | |
| 651 SkSTArray<1, Geometry, true> fGeoData; | |
| 652 }; | |
| 653 | |
| 504 void GrContext::drawRect(GrRenderTarget* rt, | 654 void GrContext::drawRect(GrRenderTarget* rt, |
| 505 const GrPaint& paint, | 655 const GrPaint& paint, |
| 506 const SkMatrix& viewMatrix, | 656 const SkMatrix& viewMatrix, |
| 507 const SkRect& rect, | 657 const SkRect& rect, |
| 508 const GrStrokeInfo* strokeInfo) { | 658 const GrStrokeInfo* strokeInfo) { |
| 509 if (strokeInfo && strokeInfo->isDashed()) { | 659 if (strokeInfo && strokeInfo->isDashed()) { |
| 510 SkPath path; | 660 SkPath path; |
| 511 path.addRect(rect); | 661 path.addRect(rect); |
| 512 this->drawPath(rt, paint, viewMatrix, path, *strokeInfo); | 662 this->drawPath(rt, paint, viewMatrix, path, *strokeInfo); |
| 513 return; | 663 return; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 &pipelineBuilder, | 729 &pipelineBuilder, |
| 580 color, | 730 color, |
| 581 viewMatrix, | 731 viewMatrix, |
| 582 rect, | 732 rect, |
| 583 devBoundRect); | 733 devBoundRect); |
| 584 } | 734 } |
| 585 return; | 735 return; |
| 586 } | 736 } |
| 587 | 737 |
| 588 if (width >= 0) { | 738 if (width >= 0) { |
| 589 // TODO: consider making static vertex buffers for these cases. | 739 StrokeRectBatch::Geometry geometry; |
| 590 // Hairline could be done by just adding closing vertex to | 740 geometry.fViewMatrix = viewMatrix; |
| 591 // unitSquareVertexBuffer() | 741 geometry.fColor = color; |
| 742 geometry.fRect = rect; | |
| 743 geometry.fStrokeWidth = width; | |
| 592 | 744 |
| 593 static const int worstCaseVertCount = 10; | 745 SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry)); |
| 594 SkAutoTUnref<const GrGeometryProcessor> gp( | |
| 595 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPositi on_GPType, | |
| 596 color, | |
| 597 viewMatrix, | |
| 598 SkMatrix::I())); | |
| 599 GrDrawTarget::AutoReleaseGeometry geo(target, | |
| 600 worstCaseVertCount, | |
| 601 gp->getVertexStride(), | |
| 602 0); | |
| 603 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); | |
| 604 | 746 |
| 605 if (!geo.succeeded()) { | 747 SkRect bounds = rect; |
| 606 SkDebugf("Failed to get space for vertices!\n"); | 748 SkScalar rad = SkScalarHalf(width); |
| 607 return; | 749 bounds.outset(rad, rad); |
| 608 } | 750 viewMatrix.mapRect(&bounds); |
| 609 | 751 target->drawBatch(&pipelineBuilder, batch, &bounds); |
| 610 GrPrimitiveType primType; | |
| 611 int vertCount; | |
| 612 SkPoint* vertex = geo.positions(); | |
| 613 | |
| 614 if (width > 0) { | |
| 615 vertCount = 10; | |
| 616 primType = kTriangleStrip_GrPrimitiveType; | |
| 617 setStrokeRectStrip(vertex, rect, width); | |
| 618 } else { | |
| 619 // hairline | |
| 620 vertCount = 5; | |
| 621 primType = kLineStrip_GrPrimitiveType; | |
| 622 vertex[0].set(rect.fLeft, rect.fTop); | |
| 623 vertex[1].set(rect.fRight, rect.fTop); | |
| 624 vertex[2].set(rect.fRight, rect.fBottom); | |
| 625 vertex[3].set(rect.fLeft, rect.fBottom); | |
| 626 vertex[4].set(rect.fLeft, rect.fTop); | |
| 627 } | |
| 628 | |
| 629 target->drawNonIndexed(&pipelineBuilder, gp, primType, 0, vertCount); | |
| 630 } else { | 752 } else { |
| 631 // filled BW rect | 753 // filled BW rect |
| 632 target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); | 754 target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect); |
| 633 } | 755 } |
| 634 } | 756 } |
| 635 | 757 |
| 636 void GrContext::drawNonAARectToRect(GrRenderTarget* rt, | 758 void GrContext::drawNonAARectToRect(GrRenderTarget* rt, |
| 637 const GrPaint& paint, | 759 const GrPaint& paint, |
| 638 const SkMatrix& viewMatrix, | 760 const SkMatrix& viewMatrix, |
| 639 const SkRect& rectToDraw, | 761 const SkRect& rectToDraw, |
| 640 const SkRect& localRect, | 762 const SkRect& localRect, |
| 641 const SkMatrix* localMatrix) { | 763 const SkMatrix* localMatrix) { |
| 642 AutoCheckFlush acf(this); | 764 AutoCheckFlush acf(this); |
| 643 GrPipelineBuilder pipelineBuilder; | 765 GrPipelineBuilder pipelineBuilder; |
| 644 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, &paint, &ac f); | 766 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, &paint, &ac f); |
| 645 if (NULL == target) { | 767 if (NULL == target) { |
| 646 return; | 768 return; |
| 647 } | 769 } |
| 648 | 770 |
| 649 GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target); | 771 GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target); |
| 650 | 772 |
| 651 target->drawRect(&pipelineBuilder, | 773 target->drawRect(&pipelineBuilder, |
| 652 paint.getColor(), | 774 paint.getColor(), |
| 653 viewMatrix, | 775 viewMatrix, |
| 654 rectToDraw, | 776 rectToDraw, |
| 655 &localRect, | 777 &localRect, |
| 656 localMatrix); | 778 localMatrix); |
| 657 } | 779 } |
| 658 | 780 |
| 659 static const GrGeometryProcessor* set_vertex_attributes(const SkPoint* texCoords , | 781 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, |
| 660 const GrColor* colors, | 782 bool hasColors, |
| 661 int* colorOffset, | 783 int* colorOffset, |
| 662 int* texOffset, | 784 int* texOffset, |
| 663 GrColor color, | 785 GrColor color, |
| 664 const SkMatrix& viewMatr ix) { | 786 const SkMatrix& viewMatr ix) { |
| 665 *texOffset = -1; | 787 *texOffset = -1; |
| 666 *colorOffset = -1; | 788 *colorOffset = -1; |
| 667 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; | 789 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType; |
| 668 if (texCoords && colors) { | 790 if (hasLocalCoords && hasColors) { |
| 669 *colorOffset = sizeof(SkPoint); | 791 *colorOffset = sizeof(SkPoint); |
| 670 *texOffset = sizeof(SkPoint) + sizeof(GrColor); | 792 *texOffset = sizeof(SkPoint) + sizeof(GrColor); |
| 671 flags |= GrDefaultGeoProcFactory::kColor_GPType | | 793 flags |= GrDefaultGeoProcFactory::kColor_GPType | |
| 672 GrDefaultGeoProcFactory::kLocalCoord_GPType; | 794 GrDefaultGeoProcFactory::kLocalCoord_GPType; |
| 673 } else if (texCoords) { | 795 } else if (hasLocalCoords) { |
| 674 *texOffset = sizeof(SkPoint); | 796 *texOffset = sizeof(SkPoint); |
| 675 flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType; | 797 flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType; |
| 676 } else if (colors) { | 798 } else if (hasColors) { |
| 677 *colorOffset = sizeof(SkPoint); | 799 *colorOffset = sizeof(SkPoint); |
| 678 flags |= GrDefaultGeoProcFactory::kColor_GPType; | 800 flags |= GrDefaultGeoProcFactory::kColor_GPType; |
| 679 } | 801 } |
| 680 return GrDefaultGeoProcFactory::Create(flags, color, viewMatrix, SkMatrix::I ()); | 802 return GrDefaultGeoProcFactory::Create(flags, color, viewMatrix, SkMatrix::I ()); |
| 681 } | 803 } |
| 682 | 804 |
| 805 class DrawVerticesBatch : public GrBatch { | |
| 806 public: | |
| 807 struct Geometry { | |
| 808 GrColor fColor; | |
|
robertphillips
2015/02/25 15:50:26
:(
| |
| 809 SkMatrix fViewMatrix; | |
|
robertphillips
2015/02/25 15:50:26
SkTDArrays?
raw memory?
SkAutoFree/SkAutoMalloc?
| |
| 810 SkTArray<SkPoint>* fPositions; | |
| 811 SkTArray<uint16_t>* fIndices; | |
| 812 SkTArray<GrColor>* fColors; | |
| 813 SkTArray<SkPoint>* fLocalCoords; | |
|
robertphillips
2015/02/25 15:50:26
Aren't these last two duplicated in the SkTArrays?
| |
| 814 int fVertexCount; | |
| 815 int fIndexCount; | |
| 816 }; | |
| 817 | |
| 818 static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveTy pe, | |
| 819 const SkPoint* positions, | |
| 820 const uint16_t* indices, const GrColor* colors, | |
| 821 const SkPoint* localCoords) { | |
| 822 return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, positions , indices, colors, | |
| 823 localCoords)); | |
| 824 } | |
| 825 | |
| 826 const char* name() const SK_OVERRIDE { return "DrawVerticesBatch"; } | |
| 827 | |
| 828 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { | |
| 829 // When this is called on a batch, there is only one geometry bundle | |
| 830 if (this->hasColors()) { | |
| 831 out->setUnknownFourComponents(); | |
| 832 } else { | |
| 833 out->setKnownFourComponents(fGeoData[0].fColor); | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E { | |
| 838 out->setUnknownSingleComponent(); | |
| 839 } | |
| 840 | |
| 841 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { | |
| 842 // Handle any color overrides | |
| 843 if (init.fColorIgnored) { | |
| 844 fGeoData[0].fColor = GrColor_ILLEGAL; | |
| 845 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | |
| 846 fGeoData[0].fColor = init.fOverrideColor; | |
| 847 } | |
| 848 | |
| 849 // setup batch properties | |
| 850 fBatch.fColorIgnored = init.fColorIgnored; | |
| 851 fBatch.fColor = fGeoData[0].fColor; | |
| 852 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
| 853 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
| 854 } | |
| 855 | |
|
robertphillips
2015/02/25 15:50:26
Not that I'm suggesting it right now but, could we
| |
| 856 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { | |
| 857 int colorOffset = -1, texOffset = -1; | |
| 858 SkAutoTUnref<const GrGeometryProcessor> gp( | |
| 859 set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset, | |
| 860 &texOffset, this->color(), this->viewMatri x())); | |
| 861 | |
| 862 batchTarget->initDraw(gp, pipeline); | |
| 863 | |
| 864 // TODO this is hacky, but the only way we have to initialize the GP is to use the | |
| 865 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch | |
| 866 // everywhere we can remove this nastiness | |
| 867 GrPipelineInfo init; | |
| 868 init.fColorIgnored = fBatch.fColorIgnored; | |
| 869 init.fOverrideColor = GrColor_ILLEGAL; | |
| 870 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
| 871 init.fUsesLocalCoords = this->usesLocalCoords(); | |
| 872 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
| 873 | |
| 874 size_t vertexStride = gp->getVertexStride(); | |
| 875 | |
| 876 SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? siz eof(SkPoint) : 0) | |
| 877 + (this->hasColors() ? sizeof(G rColor) : 0)); | |
| 878 | |
| 879 int instanceCount = fGeoData.count(); | |
| 880 | |
| 881 const GrVertexBuffer* vertexBuffer; | |
| 882 int firstVertex; | |
| 883 | |
| 884 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
| 885 this->vertexCount( ), | |
| 886 &vertexBuffer, | |
| 887 &firstVertex); | |
| 888 | |
| 889 const GrIndexBuffer* indexBuffer; | |
| 890 int firstIndex; | |
| 891 | |
| 892 void* indices = NULL; | |
| 893 if (this->hasIndices()) { | |
| 894 indices = batchTarget->indexPool()->makeSpace(this->indexCount(), | |
| 895 &indexBuffer, | |
| 896 &firstIndex); | |
| 897 } | |
| 898 | |
| 899 int indexOffset = 0; | |
| 900 int vertexOffset = 0; | |
| 901 for (int i = 0; i < instanceCount; i++) { | |
| 902 const Geometry& args = fGeoData[i]; | |
| 903 | |
| 904 if (this->hasIndices()) { | |
| 905 for (int j = 0; j < args.fIndexCount; ++j, ++indexOffset) { | |
| 906 *((uint16_t*)indices + indexOffset) = (*args.fIndices)[j] + vertexOffset; | |
| 907 } | |
|
robertphillips
2015/02/25 15:50:26
Can we ever delete a DrawVerticesBatch without fir
| |
| 908 SkDELETE(args.fIndices); | |
| 909 } | |
| 910 | |
| 911 for (int j = 0; j < args.fVertexCount; ++j) { | |
| 912 *((SkPoint*)vertices) = (*args.fPositions)[j]; | |
| 913 if (this->hasColors()) { | |
| 914 *(GrColor*)((intptr_t)vertices + colorOffset) = (*args.fColo rs)[j]; | |
| 915 } | |
| 916 if (this->hasLocalCoords()) { | |
| 917 *(SkPoint*)((intptr_t)vertices + texOffset) = (*args.fLocalC oords)[j]; | |
| 918 } | |
| 919 vertices = (void*)((intptr_t)vertices + vertexStride); | |
| 920 vertexOffset++; | |
| 921 } | |
| 922 | |
| 923 if (this->hasColors()) { | |
| 924 SkDELETE(args.fColors); | |
| 925 } | |
| 926 | |
| 927 if (this->hasLocalCoords()) { | |
| 928 SkDELETE(args.fLocalCoords); | |
| 929 } | |
| 930 } | |
| 931 | |
| 932 GrDrawTarget::DrawInfo drawInfo; | |
| 933 drawInfo.setPrimitiveType(this->primitiveType()); | |
| 934 drawInfo.setVertexBuffer(vertexBuffer); | |
| 935 drawInfo.setStartVertex(firstVertex); | |
| 936 drawInfo.setVertexCount(this->vertexCount()); | |
| 937 if (this->hasIndices()) { | |
| 938 drawInfo.setIndexBuffer(indexBuffer); | |
| 939 drawInfo.setStartIndex(firstIndex); | |
| 940 drawInfo.setIndexCount(this->indexCount()); | |
| 941 } else { | |
| 942 drawInfo.setStartIndex(0); | |
| 943 drawInfo.setIndexCount(0); | |
| 944 } | |
| 945 batchTarget->draw(drawInfo); | |
| 946 } | |
| 947 | |
| 948 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
| 949 | |
| 950 private: | |
| 951 DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType, | |
| 952 const SkPoint* positions, const uint16_t* indices, | |
| 953 const GrColor* colors, const SkPoint* localCoords) { | |
| 954 this->initClassID<DrawVerticesBatch>(); | |
| 955 SkASSERT(positions); | |
| 956 | |
| 957 Geometry& installedGeo = fGeoData.push_back(geometry); | |
| 958 | |
| 959 int vertexCount = installedGeo.fVertexCount; | |
| 960 installedGeo.fPositions = SkNEW_ARGS(SkTArray<SkPoint>, (positions, vert exCount)); | |
|
robertphillips
2015/02/25 15:50:26
Don't think you need these SkToBools here
| |
| 961 if (SkToBool(indices)) { | |
| 962 installedGeo.fIndices = SkNEW_ARGS(SkTArray<uint16_t>, (indices, geo metry.fIndexCount)); | |
|
robertphillips
2015/02/25 15:50:26
Can we use the NULLness of fIndices in place of fH
| |
| 963 fBatch.fHasIndices = true; | |
| 964 } else { | |
| 965 installedGeo.fIndices = NULL; | |
| 966 fBatch.fHasIndices = false; | |
| 967 } | |
| 968 | |
| 969 if (SkToBool(colors)) { | |
| 970 installedGeo.fColors = SkNEW_ARGS(SkTArray<GrColor>, (colors, vertex Count)); | |
| 971 fBatch.fHasColors = true; | |
| 972 } else { | |
| 973 installedGeo.fColors = NULL; | |
| 974 fBatch.fHasColors = false; | |
| 975 } | |
| 976 | |
| 977 if (SkToBool(localCoords)) { | |
| 978 installedGeo.fLocalCoords = SkNEW_ARGS(SkTArray<SkPoint>, (localCoor ds, vertexCount)); | |
| 979 fBatch.fHasLocalCoords = true; | |
| 980 } else { | |
| 981 installedGeo.fLocalCoords = NULL; | |
| 982 fBatch.fHasLocalCoords = false; | |
| 983 } | |
| 984 fBatch.fVertexCount = vertexCount; | |
| 985 fBatch.fIndexCount = geometry.fIndexCount; | |
| 986 fBatch.fPrimitiveType = primitiveType; | |
| 987 } | |
| 988 | |
| 989 GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; } | |
| 990 bool batchablePrimitiveType() const { | |
| 991 return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType || | |
| 992 kLines_GrPrimitiveType == fBatch.fPrimitiveType || | |
| 993 kPoints_GrPrimitiveType == fBatch.fPrimitiveType; | |
| 994 } | |
| 995 GrColor color() const { return fBatch.fColor; } | |
| 996 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | |
| 997 bool colorIgnored() const { return fBatch.fColorIgnored; } | |
| 998 const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; } | |
| 999 bool hasColors() const { return fBatch.fHasColors; } | |
| 1000 bool hasIndices() const { return fBatch.fHasIndices; } | |
| 1001 bool hasLocalCoords() const { return fBatch.fHasLocalCoords; } | |
| 1002 int vertexCount() const { return fBatch.fVertexCount; } | |
| 1003 int indexCount() const { return fBatch.fIndexCount; } | |
| 1004 | |
| 1005 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { | |
| 1006 DrawVerticesBatch* that = t->cast<DrawVerticesBatch>(); | |
| 1007 | |
| 1008 if (!this->batchablePrimitiveType() || this->primitiveType() != that->pr imitiveType()) { | |
| 1009 return false; | |
| 1010 } | |
| 1011 | |
| 1012 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords()); | |
| 1013 | |
| 1014 // We currently use a uniform viewmatrix for this batch | |
| 1015 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | |
| 1016 return false; | |
| 1017 } | |
| 1018 | |
| 1019 if (this->hasColors() != that->hasColors()) { | |
| 1020 return false; | |
| 1021 } | |
| 1022 | |
| 1023 if (this->hasIndices() != that->hasIndices()) { | |
| 1024 return false; | |
| 1025 } | |
| 1026 | |
| 1027 if (this->hasLocalCoords() != that->hasLocalCoords()) { | |
| 1028 return false; | |
| 1029 } | |
| 1030 | |
| 1031 if (!this->hasColors() && this->color() != that->color()) { | |
| 1032 return false; | |
| 1033 } | |
| 1034 | |
| 1035 if (this->color() != that->color()) { | |
| 1036 fBatch.fColor = GrColor_ILLEGAL; | |
| 1037 } | |
| 1038 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | |
| 1039 fBatch.fVertexCount += that->vertexCount(); | |
| 1040 fBatch.fIndexCount += that->indexCount(); | |
| 1041 return true; | |
| 1042 } | |
| 1043 | |
| 1044 struct BatchTracker { | |
| 1045 GrPrimitiveType fPrimitiveType; | |
| 1046 GrColor fColor; | |
| 1047 bool fUsesLocalCoords; | |
| 1048 bool fColorIgnored; | |
| 1049 bool fCoverageIgnored; | |
| 1050 bool fHasColors; | |
| 1051 bool fHasIndices; | |
| 1052 bool fHasLocalCoords; | |
| 1053 int fVertexCount; | |
| 1054 int fIndexCount; | |
| 1055 }; | |
| 1056 | |
| 1057 BatchTracker fBatch; | |
| 1058 SkSTArray<1, Geometry, true> fGeoData; | |
| 1059 }; | |
| 1060 | |
| 683 void GrContext::drawVertices(GrRenderTarget* rt, | 1061 void GrContext::drawVertices(GrRenderTarget* rt, |
| 684 const GrPaint& paint, | 1062 const GrPaint& paint, |
| 685 const SkMatrix& viewMatrix, | 1063 const SkMatrix& viewMatrix, |
| 686 GrPrimitiveType primitiveType, | 1064 GrPrimitiveType primitiveType, |
| 687 int vertexCount, | 1065 int vertexCount, |
| 688 const SkPoint positions[], | 1066 const SkPoint positions[], |
| 689 const SkPoint texCoords[], | 1067 const SkPoint texCoords[], |
| 690 const GrColor colors[], | 1068 const GrColor colors[], |
| 691 const uint16_t indices[], | 1069 const uint16_t indices[], |
| 692 int indexCount) { | 1070 int indexCount) { |
| 693 AutoCheckFlush acf(this); | 1071 AutoCheckFlush acf(this); |
| 694 GrPipelineBuilder pipelineBuilder; | 1072 GrPipelineBuilder pipelineBuilder; |
| 695 GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scop e | 1073 GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scop e |
| 696 | 1074 |
| 697 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, &paint, &ac f); | 1075 GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, &paint, &ac f); |
| 698 if (NULL == target) { | 1076 if (NULL == target) { |
| 699 return; | 1077 return; |
| 700 } | 1078 } |
| 701 | 1079 |
| 702 GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target); | 1080 GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target); |
| 703 | 1081 |
| 704 int colorOffset = -1, texOffset = -1; | 1082 DrawVerticesBatch::Geometry geometry; |
| 705 SkAutoTUnref<const GrGeometryProcessor> gp( | 1083 geometry.fColor = paint.getColor(); |
| 706 set_vertex_attributes(texCoords, colors, &colorOffset, &texOffset, | 1084 geometry.fViewMatrix = viewMatrix; |
| 707 paint.getColor(), viewMatrix)); | 1085 geometry.fVertexCount = vertexCount; |
| 1086 geometry.fIndexCount = indexCount; | |
| 708 | 1087 |
| 709 size_t vertexStride = gp->getVertexStride(); | 1088 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, positions, |
| 710 SkASSERT(vertexStride == sizeof(SkPoint) + (SkToBool(texCoords) ? sizeof(SkP oint) : 0) | 1089 indices, colors, texCo ords)); |
| 711 + (SkToBool(colors) ? sizeof(GrColo r) : 0)); | |
| 712 if (!geo.set(target, vertexCount, vertexStride, indexCount)) { | |
| 713 SkDebugf("Failed to get space for vertices!\n"); | |
| 714 return; | |
| 715 } | |
| 716 void* curVertex = geo.vertices(); | |
| 717 | 1090 |
| 718 for (int i = 0; i < vertexCount; ++i) { | 1091 // TODO figure out bounds |
| 719 *((SkPoint*)curVertex) = positions[i]; | 1092 target->drawBatch(&pipelineBuilder, batch, NULL); |
| 720 | |
| 721 if (texOffset >= 0) { | |
| 722 *(SkPoint*)((intptr_t)curVertex + texOffset) = texCoords[i]; | |
| 723 } | |
| 724 if (colorOffset >= 0) { | |
| 725 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i]; | |
| 726 } | |
| 727 curVertex = (void*)((intptr_t)curVertex + vertexStride); | |
| 728 } | |
| 729 | |
| 730 // we don't currently apply offscreen AA to this path. Need improved | |
| 731 // management of GrDrawTarget's geometry to avoid copying points per-tile. | |
| 732 if (indices) { | |
| 733 uint16_t* curIndex = (uint16_t*)geo.indices(); | |
| 734 for (int i = 0; i < indexCount; ++i) { | |
| 735 curIndex[i] = indices[i]; | |
| 736 } | |
| 737 target->drawIndexed(&pipelineBuilder, gp, primitiveType, 0, 0, vertexCou nt, indexCount); | |
| 738 } else { | |
| 739 target->drawNonIndexed(&pipelineBuilder, gp, primitiveType, 0, vertexCou nt); | |
| 740 } | |
| 741 } | 1093 } |
| 742 | 1094 |
| 743 /////////////////////////////////////////////////////////////////////////////// | 1095 /////////////////////////////////////////////////////////////////////////////// |
| 744 | 1096 |
| 745 void GrContext::drawRRect(GrRenderTarget*rt, | 1097 void GrContext::drawRRect(GrRenderTarget*rt, |
| 746 const GrPaint& paint, | 1098 const GrPaint& paint, |
| 747 const SkMatrix& viewMatrix, | 1099 const SkMatrix& viewMatrix, |
| 748 const SkRRect& rrect, | 1100 const SkRRect& rrect, |
| 749 const GrStrokeInfo& strokeInfo) { | 1101 const GrStrokeInfo& strokeInfo) { |
| 750 if (rrect.isEmpty()) { | 1102 if (rrect.isEmpty()) { |
| (...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1602 } | 1954 } |
| 1603 } | 1955 } |
| 1604 | 1956 |
| 1605 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { | 1957 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) { |
| 1606 fGpu->removeGpuTraceMarker(marker); | 1958 fGpu->removeGpuTraceMarker(marker); |
| 1607 if (fDrawBuffer) { | 1959 if (fDrawBuffer) { |
| 1608 fDrawBuffer->removeGpuTraceMarker(marker); | 1960 fDrawBuffer->removeGpuTraceMarker(marker); |
| 1609 } | 1961 } |
| 1610 } | 1962 } |
| 1611 | 1963 |
| OLD | NEW |