OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrDrawAtlasBatch.h" | 8 #include "GrDrawAtlasBatch.h" |
9 #include "GrBatchTest.h" | 9 #include "GrBatchTest.h" |
10 #include "SkRandom.h" | 10 #include "SkRandom.h" |
11 #include "SkRSXform.h" | |
11 | 12 |
12 void GrDrawAtlasBatch::initBatchTracker(const GrPipelineOptimizations& opt) { | 13 void GrDrawAtlasBatch::initBatchTracker(const GrPipelineOptimizations& opt) { |
13 // Handle any color overrides | 14 // Handle any color overrides |
14 if (!opt.readsColor()) { | 15 if (!opt.readsColor()) { |
15 fGeoData[0].fColor = GrColor_ILLEGAL; | 16 fGeoData[0].fColor = GrColor_ILLEGAL; |
16 } | 17 } |
17 opt.getOverrideColorIfSet(&fGeoData[0].fColor); | 18 opt.getOverrideColorIfSet(&fGeoData[0].fColor); |
18 | 19 |
19 // setup batch properties | 20 // setup batch properties |
20 fColorIgnored = !opt.readsColor(); | 21 fColorIgnored = !opt.readsColor(); |
21 fColor = fGeoData[0].fColor; | 22 fColor = fGeoData[0].fColor; |
22 // We'd like to assert this, but we can't because of GLPrograms test | 23 // We'd like to assert this, but we can't because of GLPrograms test |
23 //SkASSERT(init.readsLocalCoords()); | 24 //SkASSERT(init.readsLocalCoords()); |
24 fCoverageIgnored = !opt.readsCoverage(); | 25 fCoverageIgnored = !opt.readsCoverage(); |
25 } | 26 } |
26 | 27 |
27 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords, | 28 static const GrGeometryProcessor* set_vertex_attributes(bool hasColors, |
28 bool hasColors, | |
29 int* colorOffset, | |
30 int* texOffset, | |
31 GrColor color, | 29 GrColor color, |
32 const SkMatrix& viewMatr ix, | 30 const SkMatrix& viewMatr ix, |
33 bool coverageIgnored) { | 31 bool coverageIgnored) { |
34 using namespace GrDefaultGeoProcFactory; | 32 using namespace GrDefaultGeoProcFactory; |
35 *texOffset = -1; | |
36 *colorOffset = -1; | |
37 Color gpColor(color); | 33 Color gpColor(color); |
38 if (hasColors) { | 34 if (hasColors) { |
39 gpColor.fType = Color::kAttribute_Type; | 35 gpColor.fType = Color::kAttribute_Type; |
40 } | 36 } |
41 | 37 |
42 Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_ Type); | 38 Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_ Type); |
43 LocalCoords localCoords(hasLocalCoords ? LocalCoords::kHasExplicit_Type : | 39 LocalCoords localCoords(LocalCoords::kHasExplicit_Type); |
44 LocalCoords::kUsePosition_Type); | |
45 if (hasLocalCoords && hasColors) { | |
46 *colorOffset = sizeof(SkPoint); | |
47 *texOffset = sizeof(SkPoint) + sizeof(GrColor); | |
48 } else if (hasLocalCoords) { | |
49 *texOffset = sizeof(SkPoint); | |
50 } else if (hasColors) { | |
51 *colorOffset = sizeof(SkPoint); | |
52 } | |
53 return GrDefaultGeoProcFactory::Create(gpColor, coverage, localCoords, viewM atrix); | 40 return GrDefaultGeoProcFactory::Create(gpColor, coverage, localCoords, viewM atrix); |
54 } | 41 } |
55 | 42 |
56 void GrDrawAtlasBatch::generateGeometry(GrBatchTarget* batchTarget) { | 43 void GrDrawAtlasBatch::generateGeometry(GrBatchTarget* batchTarget) { |
57 int colorOffset = -1, texOffset = -1; | |
58 // Setup geometry processor | 44 // Setup geometry processor |
59 SkAutoTUnref<const GrGeometryProcessor> gp( | 45 SkAutoTUnref<const GrGeometryProcessor> gp(set_vertex_attributes(this->hasCo lors(), |
60 set_vertex_attributes(true, this->hasColors(), & colorOffset, | 46 this->color (), |
61 &texOffset, this->color(), this->viewMatrix(), | 47 this->viewM atrix(), |
62 this->coverageIgnored())); | 48 this->cover ageIgnored())); |
63 | 49 |
64 batchTarget->initDraw(gp, this->pipeline()); | 50 batchTarget->initDraw(gp, this->pipeline()); |
65 | 51 |
66 int instanceCount = fGeoData.count(); | 52 int instanceCount = fGeoData.count(); |
67 size_t vertexStride = gp->getVertexStride(); | 53 size_t vertexStride = gp->getVertexStride(); |
68 SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(SkPoint) | 54 SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(SkPoint) |
69 + (this->hasColors() ? sizeof(GrColor) : 0)); | 55 + (this->hasColors() ? sizeof(GrColor) : 0)); |
70 | 56 |
71 QuadHelper helper; | 57 QuadHelper helper; |
72 int numQuads = this->vertexCount()/4; | 58 int numQuads = this->quadCount(); |
73 void* verts = helper.init(batchTarget, vertexStride, numQuads); | 59 void* verts = helper.init(batchTarget, vertexStride, numQuads); |
74 if (!verts) { | 60 if (!verts) { |
75 SkDebugf("Could not allocate vertices\n"); | 61 SkDebugf("Could not allocate vertices\n"); |
76 return; | 62 return; |
77 } | 63 } |
78 | 64 |
79 int vertexOffset = 0; | 65 uint8_t* vertPtr = reinterpret_cast<uint8_t*>(verts); |
80 for (int i = 0; i < instanceCount; i++) { | 66 for (int i = 0; i < instanceCount; i++) { |
81 const Geometry& args = fGeoData[i]; | 67 const Geometry& args = fGeoData[i]; |
82 | 68 |
83 for (int j = 0; j < args.fPositions.count(); ++j) { | 69 size_t allocSize = args.fVerts.count(); |
84 *((SkPoint*)verts) = args.fPositions[j]; | 70 memcpy(vertPtr, args.fVerts.begin(), allocSize); |
85 if (this->hasColors()) { | 71 vertPtr += allocSize; |
86 *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j]; | |
87 } | |
88 *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j]; | |
89 verts = (void*)((intptr_t)verts + vertexStride); | |
90 vertexOffset++; | |
91 } | |
92 } | 72 } |
93 helper.issueDraw(batchTarget); | 73 helper.issueDraw(batchTarget); |
94 } | 74 } |
95 | 75 |
96 GrDrawAtlasBatch::GrDrawAtlasBatch(const Geometry& geometry, const SkMatrix& vie wMatrix, | 76 GrDrawAtlasBatch::GrDrawAtlasBatch(const Geometry& geometry, const SkMatrix& vie wMatrix, |
97 const SkPoint* positions, int vertexCount, | 77 int spriteCount, const SkRSXform* xforms, con st SkRect* rects, |
98 const GrColor* colors, const SkPoint* localCo ords, | 78 const SkColor* colors) { |
99 const SkRect& bounds) { | |
100 this->initClassID<GrDrawAtlasBatch>(); | 79 this->initClassID<GrDrawAtlasBatch>(); |
101 SkASSERT(positions); | 80 SkASSERT(xforms); |
102 SkASSERT(localCoords); | 81 SkASSERT(rects); |
103 | 82 |
104 fViewMatrix = viewMatrix; | 83 fViewMatrix = viewMatrix; |
105 Geometry& installedGeo = fGeoData.push_back(geometry); | 84 Geometry& installedGeo = fGeoData.push_back(geometry); |
106 | 85 |
107 installedGeo.fPositions.append(vertexCount, positions); | 86 // figure out stride and offsets |
robertphillips
2015/08/11 15:32:05
// Order within the vertex is: position [color] te
jvanverth1
2015/08/11 20:22:55
Done.
| |
108 | 87 SkColor dummyColor; |
88 const SkColor* colorPtr = &dummyColor; | |
89 size_t colorStep = 0; | |
90 size_t colorOffset = sizeof(SkPoint); | |
91 size_t texOffset = sizeof(SkPoint); | |
robertphillips
2015/08/11 15:32:05
stride -> vertexStride ?
jvanverth1
2015/08/11 20:22:55
Done.
| |
92 size_t stride = 2*sizeof(SkPoint); | |
93 fHasColors = false; | |
109 if (colors) { | 94 if (colors) { |
110 installedGeo.fColors.append(vertexCount, colors); | 95 colorOffset = sizeof(SkPoint); |
96 texOffset += sizeof(GrColor); | |
97 stride += sizeof(GrColor); | |
98 colorPtr = colors; | |
99 colorStep = sizeof(GrColor); | |
111 fHasColors = true; | 100 fHasColors = true; |
112 } else { | |
113 fHasColors = false; | |
114 } | 101 } |
115 | 102 |
116 installedGeo.fLocalCoords.append(vertexCount, localCoords); | 103 // compute buffer size and alloc buffer |
117 fVertexCount = vertexCount; | 104 fQuadCount = spriteCount; |
105 size_t allocSize = 4*stride*spriteCount; | |
106 installedGeo.fVerts.reset(allocSize); | |
107 uint8_t* currVertex = installedGeo.fVerts.begin(); | |
118 | 108 |
109 SkRect bounds; | |
robertphillips
2015/08/11 15:32:05
Hmmm ... isn't this going to force the bounds to a
jvanverth1
2015/08/11 20:22:55
Done.
| |
110 sk_bzero(&bounds, sizeof(SkRect)); | |
111 for (int spriteIndex = 0; spriteIndex < spriteCount; ++spriteIndex) { | |
112 // transform rect | |
113 SkPoint quad[4]; | |
114 xforms[spriteIndex].toQuad(rects[spriteIndex].width(), rects[spriteIndex ].height(), quad); | |
115 | |
116 // copy to verts | |
117 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[0]; | |
robertphillips
2015/08/11 15:32:05
Hmmm ... could we have a second separate loop if w
jvanverth1
2015/08/11 20:22:55
Talked to mtlklein and revised to make it cleaner.
| |
118 *(reinterpret_cast<SkColor*>(currVertex+colorOffset)) = *colorPtr; | |
119 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = | |
120 SkPoint::Make(rects[spriteIndex].fLeft, rects[sprite Index].fTop); | |
121 bounds.growToInclude(quad[0].fX, quad[0].fY); | |
122 currVertex += stride; | |
123 | |
124 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[1]; | |
125 *(reinterpret_cast<SkColor*>(currVertex+colorOffset)) = *colorPtr; | |
126 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = | |
127 SkPoint::Make(rects[spriteIndex].fRight, rects[sprit eIndex].fTop); | |
128 bounds.growToInclude(quad[1].fX, quad[1].fY); | |
129 currVertex += stride; | |
130 | |
131 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[2]; | |
132 *(reinterpret_cast<SkColor*>(currVertex+colorOffset)) = *colorPtr; | |
133 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = | |
134 SkPoint::Make(rects[spriteIndex].fRight, rects[sprit eIndex].fBottom); | |
135 bounds.growToInclude(quad[2].fX, quad[2].fY); | |
136 currVertex += stride; | |
137 | |
138 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[3]; | |
139 *(reinterpret_cast<SkColor*>(currVertex+colorOffset)) = *colorPtr; | |
140 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = | |
141 SkPoint::Make(rects[spriteIndex].fLeft, rects[sprite Index].fBottom); | |
142 bounds.growToInclude(quad[3].fX, quad[3].fY); | |
143 currVertex += stride; | |
144 | |
145 // step to next sprite | |
146 colorPtr += colorStep; | |
147 } | |
148 | |
149 viewMatrix.mapRect(&bounds); | |
150 // outset for a half pixel in each direction to account for snapping in non- AA case | |
151 bounds.outset(0.5f, 0.5f); | |
119 this->setBounds(bounds); | 152 this->setBounds(bounds); |
120 } | 153 } |
121 | 154 |
122 bool GrDrawAtlasBatch::onCombineIfPossible(GrBatch* t) { | 155 bool GrDrawAtlasBatch::onCombineIfPossible(GrBatch* t) { |
156 return false; | |
jvanverth1
2015/08/11 14:49:50
Not sure if this should be here or not.
robertphillips
2015/08/11 15:01:06
I think we should just let it batch or add a big c
jvanverth1
2015/08/11 15:27:43
Re-enabled it.
| |
157 | |
123 if (!this->pipeline()->isEqual(*t->pipeline())) { | 158 if (!this->pipeline()->isEqual(*t->pipeline())) { |
124 return false; | 159 return false; |
125 } | 160 } |
126 | 161 |
127 GrDrawAtlasBatch* that = t->cast<GrDrawAtlasBatch>(); | 162 GrDrawAtlasBatch* that = t->cast<GrDrawAtlasBatch>(); |
128 | 163 |
129 // We currently use a uniform viewmatrix for this batch | 164 // We currently use a uniform viewmatrix for this batch |
130 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | 165 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
131 return false; | 166 return false; |
132 } | 167 } |
133 | 168 |
134 if (this->hasColors() != that->hasColors()) { | 169 if (this->hasColors() != that->hasColors()) { |
135 return false; | 170 return false; |
136 } | 171 } |
137 | 172 |
138 if (!this->hasColors() && this->color() != that->color()) { | 173 if (!this->hasColors() && this->color() != that->color()) { |
139 return false; | 174 return false; |
140 } | 175 } |
141 | 176 |
142 if (this->color() != that->color()) { | 177 if (this->color() != that->color()) { |
143 fColor = GrColor_ILLEGAL; | 178 fColor = GrColor_ILLEGAL; |
144 } | 179 } |
145 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); | 180 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
146 fVertexCount += that->vertexCount(); | 181 fQuadCount += that->quadCount(); |
147 | 182 |
148 this->joinBounds(that->bounds()); | 183 this->joinBounds(that->bounds()); |
149 return true; | 184 return true; |
150 } | 185 } |
151 | 186 |
152 #ifdef GR_TEST_UTILS | 187 #ifdef GR_TEST_UTILS |
153 | 188 |
robertphillips
2015/08/11 15:32:05
Do we need to pass in the width & height of the te
jvanverth1
2015/08/11 20:22:55
Added random anchor points. It doesn't affect the
| |
154 static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) { | 189 static SkRSXform random_xform(SkRandom* random) { |
155 SkPoint p; | 190 static const SkScalar kMinExtent = -100.f; |
156 p.fX = random->nextRangeScalar(min, max); | 191 static const SkScalar kMaxExtent = 100.f; |
157 p.fY = random->nextRangeScalar(min, max); | 192 static const SkScalar kMinScale = 0.1f; |
158 return p; | 193 static const SkScalar kMaxScale = 100.f; |
194 static const SkScalar kMinRotate = -SK_ScalarPI; | |
195 static const SkScalar kMaxRotate = SK_ScalarPI; | |
196 | |
197 SkRSXform xform = SkRSXform::MakeFromRadians(random->nextRangeScalar(kMinSca le, kMaxScale), | |
198 random->nextRangeScalar(kMinRot ate, kMaxRotate), | |
199 random->nextRangeScalar(kMinExt ent, kMaxExtent), | |
200 random->nextRangeScalar(kMinExt ent, kMaxExtent), | |
201 0.0, 0.0f); | |
202 return xform; | |
159 } | 203 } |
160 | 204 |
161 static void randomize_params(size_t count, SkScalar min, SkScalar max, | 205 static SkRect random_texRect(SkRandom* random) { |
162 SkRandom* random, | 206 static const SkScalar kMinCoord = 0.0f; |
163 SkTArray<SkPoint>* positions, | 207 static const SkScalar kMaxCoord = 1024.f; |
164 SkTArray<SkPoint>* texCoords, | 208 SkRect texRect = SkRect::MakeLTRB(random->nextRangeScalar(kMinCoord, kMaxCoo rd), |
209 random->nextRangeScalar(kMinCoord, kMaxCoo rd), | |
210 random->nextRangeScalar(kMinCoord, kMaxCoo rd), | |
211 random->nextRangeScalar(kMinCoord, kMaxCoo rd)); | |
robertphillips
2015/08/11 15:32:05
Do we need a sort call here ?
jvanverth1
2015/08/11 20:22:54
Done.
| |
212 return texRect; | |
213 } | |
214 | |
robertphillips
2015/08/11 15:32:05
Seems like 'count' should be an int.
jvanverth1
2015/08/11 20:22:55
Done.
| |
215 static void randomize_params(size_t count, SkRandom* random, | |
216 SkTArray<SkRSXform>* xforms, | |
217 SkTArray<SkRect>* texRects, | |
165 SkTArray<GrColor>* colors, bool hasColors) { | 218 SkTArray<GrColor>* colors, bool hasColors) { |
166 for (uint32_t v = 0; v < count; v++) { | 219 for (uint32_t v = 0; v < count; v++) { |
167 positions->push_back(random_point(random, min, max)); | 220 xforms->push_back(random_xform(random)); |
168 texCoords->push_back(random_point(random, min, max)); | 221 texRects->push_back(random_texRect(random)); |
169 if (hasColors) { | 222 if (hasColors) { |
170 colors->push_back(GrRandomColor(random)); | 223 colors->push_back(GrRandomColor(random)); |
171 } | 224 } |
172 } | 225 } |
173 } | 226 } |
174 | 227 |
175 | |
176 BATCH_TEST_DEFINE(GrDrawAtlasBatch) { | 228 BATCH_TEST_DEFINE(GrDrawAtlasBatch) { |
177 uint32_t spriteCount = random->nextRangeU(1, 100); | 229 uint32_t spriteCount = random->nextRangeU(1, 100); |
178 | 230 |
robertphillips
2015/08/11 15:32:05
(spriteCount) on xforms, texRects & colors ?
jvanverth1
2015/08/11 20:22:55
Done.
| |
179 // TODO make 'sensible' indexbuffers | 231 SkTArray<SkRSXform> xforms; |
180 SkTArray<SkPoint> positions; | 232 SkTArray<SkRect> texRects; |
181 SkTArray<SkPoint> texCoords; | |
182 SkTArray<GrColor> colors; | 233 SkTArray<GrColor> colors; |
183 | 234 |
184 bool hasColors = random->nextBool(); | 235 bool hasColors = random->nextBool(); |
185 | 236 |
186 uint32_t vertexCount = 4*spriteCount; | 237 randomize_params(spriteCount, |
187 | |
188 static const SkScalar kMinVertExtent = -100.f; | |
189 static const SkScalar kMaxVertExtent = 100.f; | |
190 randomize_params(vertexCount, kMinVertExtent, kMaxVertExtent, | |
191 random, | 238 random, |
192 &positions, | 239 &xforms, |
193 &texCoords, | 240 &texRects, |
194 &colors, hasColors); | 241 &colors, hasColors); |
195 | 242 |
196 SkMatrix viewMatrix = GrTest::TestMatrix(random); | 243 SkMatrix viewMatrix = GrTest::TestMatrix(random); |
197 SkRect bounds; | |
198 SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexC ount); | |
199 SkASSERT(result); | |
200 | |
201 viewMatrix.mapRect(&bounds); | |
202 | 244 |
203 GrDrawAtlasBatch::Geometry geometry; | 245 GrDrawAtlasBatch::Geometry geometry; |
204 geometry.fColor = GrRandomColor(random); | 246 geometry.fColor = GrRandomColor(random); |
205 return GrDrawAtlasBatch::Create(geometry, viewMatrix, | 247 return GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount, xforms.be gin(), |
206 positions.begin(), vertexCount, | 248 texRects.begin(), colors.begin()); |
207 colors.begin(), | |
208 texCoords.begin(), | |
209 bounds); | |
210 } | 249 } |
211 | 250 |
212 #endif | 251 #endif |
OLD | NEW |