Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |