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 | |
robertphillips
2015/02/27 17:37:37
Shouldn't this be rect.width()/2 and rect.height()
| |
621 //SkASSERT(rad < rect.width() && rad < rect.height()); | |
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 { | |
robertphillips
2015/02/27 17:37:37
missing space here ?
| |
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 | |
robertphillips
2015/02/27 17:37:37
interleaved ?
| |
918 // TODO we can actually cache this interleave 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 |