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

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

Issue 1277933003: First pass at drawAtlas batching. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update to ToT; fix interface change Created 5 years, 4 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 | « include/gpu/GrDrawContext.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | 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 2015 Google Inc. 3 * Copyright 2015 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 "GrAARectRenderer.h" 9 #include "GrAARectRenderer.h"
10 #include "GrAtlasTextContext.h" 10 #include "GrAtlasTextContext.h"
11 #include "GrBatch.h" 11 #include "GrBatch.h"
12 #include "GrBatchTest.h" 12 #include "GrBatchTest.h"
13 #include "GrColor.h"
13 #include "GrDefaultGeoProcFactory.h" 14 #include "GrDefaultGeoProcFactory.h"
14 #include "GrDrawContext.h" 15 #include "GrDrawContext.h"
15 #include "GrOvalRenderer.h" 16 #include "GrOvalRenderer.h"
16 #include "GrPathRenderer.h" 17 #include "GrPathRenderer.h"
17 #include "GrRenderTarget.h" 18 #include "GrRenderTarget.h"
18 #include "GrRenderTargetPriv.h" 19 #include "GrRenderTargetPriv.h"
19 #include "GrStrokeRectBatch.h" 20 #include "GrStrokeRectBatch.h"
20 #include "GrStencilAndCoverTextContext.h" 21 #include "GrStencilAndCoverTextContext.h"
21 22
23 #include "SkGr.h"
24 #include "SkRSXform.h"
25
22 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext) 26 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
23 #define RETURN_IF_ABANDONED if (!fDrawTarget) { return; } 27 #define RETURN_IF_ABANDONED if (!fDrawTarget) { return; }
24 #define RETURN_FALSE_IF_ABANDONED if (!fDrawTarget) { return false; } 28 #define RETURN_FALSE_IF_ABANDONED if (!fDrawTarget) { return false; }
25 #define RETURN_NULL_IF_ABANDONED if (!fDrawTarget) { return NULL; } 29 #define RETURN_NULL_IF_ABANDONED if (!fDrawTarget) { return NULL; }
26 30
27 class AutoCheckFlush { 31 class AutoCheckFlush {
28 public: 32 public:
29 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); } 33 AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
30 ~AutoCheckFlush() { fContext->flushIfNecessary(); } 34 ~AutoCheckFlush() { fContext->flushIfNecessary(); }
31 35
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, viewMatrix, 687 SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveTyp e, viewMatrix,
684 positions, vertexCount , indices, 688 positions, vertexCount , indices,
685 indexCount, colors, te xCoords, 689 indexCount, colors, te xCoords,
686 bounds)); 690 bounds));
687 691
688 fDrawTarget->drawBatch(pipelineBuilder, batch); 692 fDrawTarget->drawBatch(pipelineBuilder, batch);
689 } 693 }
690 694
691 /////////////////////////////////////////////////////////////////////////////// 695 ///////////////////////////////////////////////////////////////////////////////
692 696
697 class DrawAtlasBatch : public GrBatch {
698 public:
699 struct Geometry {
700 GrColor fColor;
701 SkTDArray<SkPoint> fPositions;
robertphillips 2015/08/07 13:36:37 Can we remove 'fIndices' ?
jvanverth1 2015/08/07 15:55:17 Done.
702 SkTDArray<uint16_t> fIndices;
703 SkTDArray<GrColor> fColors;
704 SkTDArray<SkPoint> fLocalCoords;
705 };
706
707 static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveTy pe,
708 const SkMatrix& viewMatrix,
709 const SkPoint* positions, int vertexCount,
710 const GrColor* colors, const SkPoint* localCoords,
711 const SkRect& bounds) {
712 return SkNEW_ARGS(DrawAtlasBatch, (geometry, primitiveType, viewMatrix, positions,
713 vertexCount, colors, localCoords, bou nds));
714 }
715
716 const char* name() const override { return "DrawAtlasBatch"; }
717
718 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
719 // When this is called on a batch, there is only one geometry bundle
720 if (this->hasColors()) {
721 out->setUnknownFourComponents();
722 } else {
723 out->setKnownFourComponents(fGeoData[0].fColor);
724 }
725 }
726
727 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
728 out->setKnownSingleComponent(0xff);
729 }
730
731 void initBatchTracker(const GrPipelineInfo& init) override {
732 // Handle any color overrides
733 if (!init.readsColor()) {
734 fGeoData[0].fColor = GrColor_ILLEGAL;
735 }
736 init.getOverrideColorIfSet(&fGeoData[0].fColor);
737
738 // setup batch properties
739 fBatch.fColorIgnored = !init.readsColor();
740 fBatch.fColor = fGeoData[0].fColor;
741 fBatch.fUsesLocalCoords = init.readsLocalCoords();
742 fBatch.fCoverageIgnored = !init.readsCoverage();
743 }
744
745 void generateGeometry(GrBatchTarget* batchTarget) override {
746 int colorOffset = -1, texOffset = -1;
747 // Setup geometry processor
748 SkAutoTUnref<const GrGeometryProcessor> gp(
749 set_vertex_attributes(true, this->hasColors(), & colorOffset,
750 &texOffset, this->color(), this->viewMatrix(),
751 this->coverageIgnored()));
752
753 batchTarget->initDraw(gp, this->pipeline());
754
755 int instanceCount = fGeoData.count();
756 size_t vertexStride = gp->getVertexStride();
757 SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(SkPoint)
758 + (this->hasColors() ? sizeof(GrColor) : 0));
759
760 QuadHelper helper;
761 int numQuads = this->vertexCount()/4;
762 void* verts = helper.init(batchTarget, vertexStride, numQuads);
763 if (!verts) {
764 SkDebugf("Could not allocate vertices\n");
765 return;
766 }
767
768 int vertexOffset = 0;
769 for (int i = 0; i < instanceCount; i++) {
770 const Geometry& args = fGeoData[i];
771
772 for (int j = 0; j < args.fPositions.count(); ++j) {
773 *((SkPoint*)verts) = args.fPositions[j];
774 if (this->hasColors()) {
775 *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j] ;
776 }
777 *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j];
778 verts = (void*)((intptr_t)verts + vertexStride);
779 vertexOffset++;
780 }
781 }
782 helper.issueDraw(batchTarget);
783 }
784
785 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
786
787 private:
788 DrawAtlasBatch(const Geometry& geometry, GrPrimitiveType primitiveType,
789 const SkMatrix& viewMatrix,
790 const SkPoint* positions, int vertexCount,
791 const GrColor* colors, const SkPoint* localCoords, const SkRe ct& bounds) {
792 this->initClassID<DrawVerticesBatch>();
793 SkASSERT(positions);
794 SkASSERT(localCoords);
795
796 fBatch.fViewMatrix = viewMatrix;
797 Geometry& installedGeo = fGeoData.push_back(geometry);
798
799 installedGeo.fPositions.append(vertexCount, positions);
800
801 if (colors) {
802 installedGeo.fColors.append(vertexCount, colors);
803 fBatch.fHasColors = true;
804 } else {
805 fBatch.fHasColors = false;
806 }
807
808 installedGeo.fLocalCoords.append(vertexCount, localCoords);
809 fBatch.fVertexCount = vertexCount;
810 fBatch.fPrimitiveType = primitiveType;
811
812 this->setBounds(bounds);
813 }
814
815 GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; }
816 bool batchablePrimitiveType() const {
robertphillips 2015/08/07 13:36:38 Don't we always know fPrimitiveType will be kTrian
jvanverth1 2015/08/07 15:55:17 Done.
817 return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType ||
robertphillips 2015/08/07 13:36:37 tab these over ?
jvanverth1 2015/08/07 15:55:17 Removed.
818 kLines_GrPrimitiveType == fBatch.fPrimitiveType ||
819 kPoints_GrPrimitiveType == fBatch.fPrimitiveType;
820 }
821 GrColor color() const { return fBatch.fColor; }
robertphillips 2015/08/07 13:36:38 Can we just return true from 'usesLocalCoords' ?
jvanverth1 2015/08/07 15:55:17 Removed.
822 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
823 bool colorIgnored() const { return fBatch.fColorIgnored; }
824 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
825 bool hasColors() const { return fBatch.fHasColors; }
826 int vertexCount() const { return fBatch.fVertexCount; }
827 bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
828
829 bool onCombineIfPossible(GrBatch* t) override {
830 if (!this->pipeline()->isEqual(*t->pipeline())) {
831 return false;
832 }
833
834 DrawAtlasBatch* that = t->cast<DrawAtlasBatch>();
835
robertphillips 2015/08/07 13:36:37 Can we skip this check ?
jvanverth1 2015/08/07 15:55:17 Done.
836 if (!this->batchablePrimitiveType() || this->primitiveType() != that->pr imitiveType()) {
837 return false;
838 }
839
840 SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
841
842 // We currently use a uniform viewmatrix for this batch
843 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
844 return false;
845 }
846
robertphillips 2015/08/07 13:36:37 We could, in theory, generate white vertex colors
jvanverth1 2015/08/07 15:55:17 It's possible, though, so for now I think I'll lea
847 if (this->hasColors() != that->hasColors()) {
848 return false;
849 }
850
851 if (!this->hasColors() && this->color() != that->color()) {
852 return false;
853 }
854
855 if (this->color() != that->color()) {
856 fBatch.fColor = GrColor_ILLEGAL;
857 }
858 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
859 fBatch.fVertexCount += that->vertexCount();
860
861 this->joinBounds(that->bounds());
862 return true;
863 }
864
865 struct BatchTracker {
866 GrPrimitiveType fPrimitiveType;
867 SkMatrix fViewMatrix;
868 GrColor fColor;
869 bool fUsesLocalCoords;
870 bool fColorIgnored;
871 bool fCoverageIgnored;
872 bool fHasColors;
873 int fVertexCount;
874 };
875
876 BatchTracker fBatch;
877 SkSTArray<1, Geometry, true> fGeoData;
878 };
879
880 void GrDrawContext::drawAtlas(GrRenderTarget* rt,
881 const GrClip& clip,
882 const GrPaint& paint,
883 const SkMatrix& viewMatrix,
884 int spriteCount,
885 const SkRSXform xform[],
886 const SkRect texRect[],
887 const SkColor colors[]) {
888 RETURN_IF_ABANDONED
889 AutoCheckFlush acf(fContext);
890 if (!this->prepareToDraw(rt)) {
891 return;
892 }
893
894 GrPipelineBuilder pipelineBuilder(paint, rt, clip);
895
896 // TODO clients should give us bounds
897 SkRect bounds;
robertphillips 2015/08/07 13:36:38 Hmmm ... I think you have to transform each texRec
jvanverth1 2015/08/07 15:55:17 Done. Moved to after we build the vertex locations
898 if (!bounds.setBoundsCheck(reinterpret_cast<const SkPoint*>(texRect), 2*spri teCount)) {
899 SkDebugf("drawAtlas call empty bounds\n");
900 return;
901 }
902
903 viewMatrix.mapRect(&bounds);
904
905 // If we don't have AA then we outset for a half pixel in each direction to account for
906 // snapping
907 if (!paint.isAntiAlias()) {
908 bounds.outset(0.5f, 0.5f);
909 }
910
robertphillips 2015/08/07 13:36:38 Is the plan to interleave here ?
jvanverth1 2015/08/07 15:55:17 The plan is that the interleaving will happen when
911 // now build the renderable geometry
912 const int vertCount = spriteCount * 4;
913 SkAutoTMalloc<SkPoint> vertStorage(vertCount * 2);
914 SkPoint* verts = vertStorage.get();
915 SkPoint* texs = verts + vertCount;
916
917 for (int i = 0; i < spriteCount; ++i) {
918 xform[i].toQuad(texRect[i].width(), texRect[i].height(), verts);
919 texRect[i].toQuad(texs);
920 verts += 4;
921 texs += 4;
922 }
923
924 SkAutoTMalloc<GrColor> colorStorage;
925 GrColor* vertCols = NULL;
926 if (colors) {
927 colorStorage.reset(vertCount);
928 vertCols = colorStorage.get();
929
930 int paintAlpha = GrColorUnpackA(paint.getColor());
931
932 // need to convert byte order and from non-PM to PM
933 for (int i = 0; i < spriteCount; ++i) {
934 SkColor color = colors[i];
935 if (paintAlpha != 255) {
936 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paintAlpha));
937 }
938 GrColor grColor = SkColor2GrColor(color);
939
robertphillips 2015/08/07 13:36:37 :(
jvanverth1 2015/08/07 15:55:17 Acknowledged.
940 vertCols[0] = vertCols[1] = vertCols[2] = vertCols[3] = grColor;
941 vertCols += 4;
942 }
943 }
944
945 verts = vertStorage.get();
946 texs = verts + vertCount;
947 vertCols = colorStorage.get();
948
949 DrawAtlasBatch::Geometry geometry;
950 geometry.fColor = paint.getColor();
951 SkAutoTUnref<GrBatch> batch(DrawAtlasBatch::Create(geometry, kTriangles_GrPr imitiveType,
952 viewMatrix, verts, vertCo unt, vertCols, texs,
953 bounds));
954
955 fDrawTarget->drawBatch(pipelineBuilder, batch);
956 }
957
958 ///////////////////////////////////////////////////////////////////////////////
959
693 void GrDrawContext::drawRRect(GrRenderTarget*rt, 960 void GrDrawContext::drawRRect(GrRenderTarget*rt,
694 const GrClip& clip, 961 const GrClip& clip,
695 const GrPaint& paint, 962 const GrPaint& paint,
696 const SkMatrix& viewMatrix, 963 const SkMatrix& viewMatrix,
697 const SkRRect& rrect, 964 const SkRRect& rrect,
698 const GrStrokeInfo& strokeInfo) { 965 const GrStrokeInfo& strokeInfo) {
699 RETURN_IF_ABANDONED 966 RETURN_IF_ABANDONED
700 if (rrect.isEmpty()) { 967 if (rrect.isEmpty()) {
701 return; 968 return;
702 } 969 }
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 return DrawVerticesBatch::Create(geometry, type, viewMatrix, 1401 return DrawVerticesBatch::Create(geometry, type, viewMatrix,
1135 positions.begin(), vertexCount, 1402 positions.begin(), vertexCount,
1136 indices.begin(), hasIndices ? vertexCount : 0, 1403 indices.begin(), hasIndices ? vertexCount : 0,
1137 colors.begin(), 1404 colors.begin(),
1138 texCoords.begin(), 1405 texCoords.begin(),
1139 bounds); 1406 bounds);
1140 } 1407 }
1141 1408
1142 #endif 1409 #endif
1143 1410
OLDNEW
« no previous file with comments | « include/gpu/GrDrawContext.h ('k') | src/gpu/SkGpuDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698