Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(447)

Side by Side Diff: src/gpu/GrContext.cpp

Issue 913253003: Context batches (Closed) Base URL: https://skia.googlesource.com/skia.git@rect
Patch Set: cleanup Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698