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