blob: dd1ed627c60c05e7be6d0b62e4a4bd6639feff62 [file] [log] [blame]
joshualitt2771b562015-08-07 12:46:26 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrDrawVerticesBatch.h"
9
bsalomon75398562015-08-17 12:55:38 -070010#include "GrBatchFlushState.h"
joshualitt2771b562015-08-07 12:46:26 -070011#include "GrInvariantOutput.h"
12#include "GrDefaultGeoProcFactory.h"
13
bungeman06ca8ec2016-06-09 08:01:03 -070014static sk_sp<GrGeometryProcessor> set_vertex_attributes(bool hasLocalCoords,
joshualitt2771b562015-08-07 12:46:26 -070015 int* colorOffset,
16 int* texOffset,
joshualitt2771b562015-08-07 12:46:26 -070017 const SkMatrix& viewMatrix,
18 bool coverageIgnored) {
19 using namespace GrDefaultGeoProcFactory;
20 *texOffset = -1;
21 *colorOffset = -1;
joshualitt2771b562015-08-07 12:46:26 -070022
23 Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_Type);
24 LocalCoords localCoords(hasLocalCoords ? LocalCoords::kHasExplicit_Type :
25 LocalCoords::kUsePosition_Type);
bsalomon14eaaa62015-09-24 07:01:26 -070026 *colorOffset = sizeof(SkPoint);
27 if (hasLocalCoords) {
joshualitt2771b562015-08-07 12:46:26 -070028 *texOffset = sizeof(SkPoint) + sizeof(GrColor);
joshualitt2771b562015-08-07 12:46:26 -070029 }
bungeman06ca8ec2016-06-09 08:01:03 -070030 return GrDefaultGeoProcFactory::Make(Color(Color::kAttribute_Type),
31 coverage, localCoords, viewMatrix);
joshualitt2771b562015-08-07 12:46:26 -070032}
33
34GrDrawVerticesBatch::GrDrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType,
35 const SkMatrix& viewMatrix,
36 const SkPoint* positions, int vertexCount,
37 const uint16_t* indices, int indexCount,
38 const GrColor* colors, const SkPoint* localCoords,
reed1b55a962015-09-17 20:16:13 -070039 const SkRect& bounds)
40 : INHERITED(ClassID()) {
joshualitt2771b562015-08-07 12:46:26 -070041 SkASSERT(positions);
42
bsalomon14eaaa62015-09-24 07:01:26 -070043 fViewMatrix = viewMatrix;
joshualitt2771b562015-08-07 12:46:26 -070044 Geometry& installedGeo = fGeoData.push_back(geometry);
45
46 installedGeo.fPositions.append(vertexCount, positions);
47 if (indices) {
48 installedGeo.fIndices.append(indexCount, indices);
joshualitt2771b562015-08-07 12:46:26 -070049 }
50
51 if (colors) {
bsalomon14eaaa62015-09-24 07:01:26 -070052 fVariableColor = true;
joshualitt2771b562015-08-07 12:46:26 -070053 installedGeo.fColors.append(vertexCount, colors);
joshualitt2771b562015-08-07 12:46:26 -070054 } else {
bsalomon14eaaa62015-09-24 07:01:26 -070055 fVariableColor = false;
joshualitt2771b562015-08-07 12:46:26 -070056 }
57
58 if (localCoords) {
59 installedGeo.fLocalCoords.append(vertexCount, localCoords);
joshualitt2771b562015-08-07 12:46:26 -070060 }
bsalomon14eaaa62015-09-24 07:01:26 -070061 fVertexCount = vertexCount;
62 fIndexCount = indexCount;
63 fPrimitiveType = primitiveType;
joshualitt2771b562015-08-07 12:46:26 -070064
65 this->setBounds(bounds);
66}
67
halcanary9d524f22016-03-29 09:03:52 -070068void GrDrawVerticesBatch::computePipelineOptimizations(GrInitInvariantOutput* color,
ethannicholasff210322015-11-24 12:10:10 -080069 GrInitInvariantOutput* coverage,
70 GrBatchToXPOverrides* overrides) const {
joshualitt2771b562015-08-07 12:46:26 -070071 // When this is called on a batch, there is only one geometry bundle
bsalomon14eaaa62015-09-24 07:01:26 -070072 if (fVariableColor) {
ethannicholasff210322015-11-24 12:10:10 -080073 color->setUnknownFourComponents();
joshualitt2771b562015-08-07 12:46:26 -070074 } else {
ethannicholasff210322015-11-24 12:10:10 -080075 color->setKnownFourComponents(fGeoData[0].fColor);
joshualitt2771b562015-08-07 12:46:26 -070076 }
ethannicholasff210322015-11-24 12:10:10 -080077 coverage->setKnownSingleComponent(0xff);
joshualitt2771b562015-08-07 12:46:26 -070078}
79
ethannicholasff210322015-11-24 12:10:10 -080080void GrDrawVerticesBatch::initBatchTracker(const GrXPOverridesForBatch& overrides) {
bsalomon14eaaa62015-09-24 07:01:26 -070081 SkASSERT(fGeoData.count() == 1);
82 GrColor overrideColor;
ethannicholasff210322015-11-24 12:10:10 -080083 if (overrides.getOverrideColorIfSet(&overrideColor)) {
bsalomon14eaaa62015-09-24 07:01:26 -070084 fGeoData[0].fColor = overrideColor;
85 fGeoData[0].fColors.reset();
86 fVariableColor = false;
joshualitt2771b562015-08-07 12:46:26 -070087 }
ethannicholasff210322015-11-24 12:10:10 -080088 fCoverageIgnored = !overrides.readsCoverage();
89 if (!overrides.readsLocalCoords()) {
bsalomon14eaaa62015-09-24 07:01:26 -070090 fGeoData[0].fLocalCoords.reset();
91 }
joshualitt2771b562015-08-07 12:46:26 -070092}
93
joshualitt144c3c82015-11-30 12:30:13 -080094void GrDrawVerticesBatch::onPrepareDraws(Target* target) const {
bsalomon14eaaa62015-09-24 07:01:26 -070095 bool hasLocalCoords = !fGeoData[0].fLocalCoords.isEmpty();
joshualitt2771b562015-08-07 12:46:26 -070096 int colorOffset = -1, texOffset = -1;
bungeman06ca8ec2016-06-09 08:01:03 -070097 sk_sp<GrGeometryProcessor> gp(set_vertex_attributes(hasLocalCoords, &colorOffset, &texOffset,
98 fViewMatrix, fCoverageIgnored));
joshualitt2771b562015-08-07 12:46:26 -070099 size_t vertexStride = gp->getVertexStride();
100
bsalomon14eaaa62015-09-24 07:01:26 -0700101 SkASSERT(vertexStride == sizeof(SkPoint) + (hasLocalCoords ? sizeof(SkPoint) : 0)
102 + sizeof(GrColor));
joshualitt2771b562015-08-07 12:46:26 -0700103
104 int instanceCount = fGeoData.count();
105
cdalton397536c2016-03-25 12:15:03 -0700106 const GrBuffer* vertexBuffer;
joshualitt2771b562015-08-07 12:46:26 -0700107 int firstVertex;
108
bsalomon14eaaa62015-09-24 07:01:26 -0700109 void* verts = target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex);
joshualitt2771b562015-08-07 12:46:26 -0700110
111 if (!verts) {
112 SkDebugf("Could not allocate vertices\n");
113 return;
114 }
115
cdalton397536c2016-03-25 12:15:03 -0700116 const GrBuffer* indexBuffer = nullptr;
joshualitt2771b562015-08-07 12:46:26 -0700117 int firstIndex = 0;
118
halcanary96fcdcc2015-08-27 07:41:13 -0700119 uint16_t* indices = nullptr;
bsalomon14eaaa62015-09-24 07:01:26 -0700120 if (!fGeoData[0].fIndices.isEmpty()) {
121 indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
joshualitt2771b562015-08-07 12:46:26 -0700122
123 if (!indices) {
124 SkDebugf("Could not allocate indices\n");
125 return;
126 }
127 }
128
129 int indexOffset = 0;
130 int vertexOffset = 0;
131 for (int i = 0; i < instanceCount; i++) {
132 const Geometry& args = fGeoData[i];
133
134 // TODO we can actually cache this interleaved and then just memcopy
bsalomon14eaaa62015-09-24 07:01:26 -0700135 if (indices) {
joshualitt2771b562015-08-07 12:46:26 -0700136 for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) {
137 *(indices + indexOffset) = args.fIndices[j] + vertexOffset;
138 }
139 }
140
141 for (int j = 0; j < args.fPositions.count(); ++j) {
142 *((SkPoint*)verts) = args.fPositions[j];
bsalomon14eaaa62015-09-24 07:01:26 -0700143 if (args.fColors.isEmpty()) {
144 *(GrColor*)((intptr_t)verts + colorOffset) = args.fColor;
145 } else {
joshualitt2771b562015-08-07 12:46:26 -0700146 *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j];
147 }
bsalomon14eaaa62015-09-24 07:01:26 -0700148 if (hasLocalCoords) {
joshualitt2771b562015-08-07 12:46:26 -0700149 *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j];
150 }
151 verts = (void*)((intptr_t)verts + vertexStride);
152 vertexOffset++;
153 }
154 }
155
egdaniel0e1853c2016-03-17 11:35:45 -0700156 GrMesh mesh;
bsalomon14eaaa62015-09-24 07:01:26 -0700157 if (indices) {
egdaniel0e1853c2016-03-17 11:35:45 -0700158 mesh.initIndexed(this->primitiveType(), vertexBuffer, indexBuffer, firstVertex,
159 firstIndex, fVertexCount, fIndexCount);
joshualitt2771b562015-08-07 12:46:26 -0700160
161 } else {
egdaniel0e1853c2016-03-17 11:35:45 -0700162 mesh.init(this->primitiveType(), vertexBuffer, firstVertex, fVertexCount);
joshualitt2771b562015-08-07 12:46:26 -0700163 }
bungeman06ca8ec2016-06-09 08:01:03 -0700164 target->draw(gp.get(), mesh);
joshualitt2771b562015-08-07 12:46:26 -0700165}
166
bsalomoncb02b382015-08-12 11:14:50 -0700167bool GrDrawVerticesBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
bsalomonabd30f52015-08-13 13:34:48 -0700168 GrDrawVerticesBatch* that = t->cast<GrDrawVerticesBatch>();
169
170 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
171 that->bounds(), caps)) {
joshualitt2771b562015-08-07 12:46:26 -0700172 return false;
173 }
174
joshualitt2771b562015-08-07 12:46:26 -0700175 if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) {
176 return false;
177 }
178
joshualitt2771b562015-08-07 12:46:26 -0700179 // We currently use a uniform viewmatrix for this batch
bsalomon14eaaa62015-09-24 07:01:26 -0700180 if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
joshualitt2771b562015-08-07 12:46:26 -0700181 return false;
182 }
183
bsalomon14eaaa62015-09-24 07:01:26 -0700184 if (fGeoData[0].fIndices.isEmpty() != that->fGeoData[0].fIndices.isEmpty()) {
joshualitt2771b562015-08-07 12:46:26 -0700185 return false;
186 }
187
bsalomon14eaaa62015-09-24 07:01:26 -0700188 if (fGeoData[0].fLocalCoords.isEmpty() != that->fGeoData[0].fLocalCoords.isEmpty()) {
joshualitt2771b562015-08-07 12:46:26 -0700189 return false;
190 }
191
bsalomon14eaaa62015-09-24 07:01:26 -0700192 if (!fVariableColor) {
193 if (that->fVariableColor || that->fGeoData[0].fColor != fGeoData[0].fColor) {
194 fVariableColor = true;
195 }
joshualitt2771b562015-08-07 12:46:26 -0700196 }
197
joshualitt2771b562015-08-07 12:46:26 -0700198 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
bsalomon14eaaa62015-09-24 07:01:26 -0700199 fVertexCount += that->fVertexCount;
200 fIndexCount += that->fIndexCount;
joshualitt2771b562015-08-07 12:46:26 -0700201
202 this->joinBounds(that->bounds());
203 return true;
204}
205
206///////////////////////////////////////////////////////////////////////////////////////////////////
207
208#ifdef GR_TEST_UTILS
209
210#include "GrBatchTest.h"
211
212static uint32_t seed_vertices(GrPrimitiveType type) {
213 switch (type) {
214 case kTriangles_GrPrimitiveType:
215 case kTriangleStrip_GrPrimitiveType:
216 case kTriangleFan_GrPrimitiveType:
217 return 3;
218 case kPoints_GrPrimitiveType:
219 return 1;
220 case kLines_GrPrimitiveType:
221 case kLineStrip_GrPrimitiveType:
222 return 2;
223 }
224 SkFAIL("Incomplete switch\n");
225 return 0;
226}
227
228static uint32_t primitive_vertices(GrPrimitiveType type) {
229 switch (type) {
230 case kTriangles_GrPrimitiveType:
231 return 3;
232 case kLines_GrPrimitiveType:
233 return 2;
234 case kTriangleStrip_GrPrimitiveType:
235 case kTriangleFan_GrPrimitiveType:
236 case kPoints_GrPrimitiveType:
237 case kLineStrip_GrPrimitiveType:
238 return 1;
239 }
240 SkFAIL("Incomplete switch\n");
241 return 0;
242}
243
244static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
245 SkPoint p;
246 p.fX = random->nextRangeScalar(min, max);
247 p.fY = random->nextRangeScalar(min, max);
248 return p;
249}
250
251static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
252 SkRandom* random,
253 SkTArray<SkPoint>* positions,
254 SkTArray<SkPoint>* texCoords, bool hasTexCoords,
255 SkTArray<GrColor>* colors, bool hasColors,
256 SkTArray<uint16_t>* indices, bool hasIndices) {
257 for (uint32_t v = 0; v < count; v++) {
258 positions->push_back(random_point(random, min, max));
259 if (hasTexCoords) {
260 texCoords->push_back(random_point(random, min, max));
261 }
262 if (hasColors) {
263 colors->push_back(GrRandomColor(random));
264 }
265 if (hasIndices) {
266 SkASSERT(maxVertex <= SK_MaxU16);
267 indices->push_back(random->nextULessThan((uint16_t)maxVertex));
268 }
269 }
270}
271
bsalomonabd30f52015-08-13 13:34:48 -0700272DRAW_BATCH_TEST_DEFINE(VerticesBatch) {
joshualitt2771b562015-08-07 12:46:26 -0700273 GrPrimitiveType type = GrPrimitiveType(random->nextULessThan(kLast_GrPrimitiveType + 1));
274 uint32_t primitiveCount = random->nextRangeU(1, 100);
275
276 // TODO make 'sensible' indexbuffers
277 SkTArray<SkPoint> positions;
278 SkTArray<SkPoint> texCoords;
279 SkTArray<GrColor> colors;
280 SkTArray<uint16_t> indices;
281
282 bool hasTexCoords = random->nextBool();
283 bool hasIndices = random->nextBool();
284 bool hasColors = random->nextBool();
285
286 uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type);
287
288 static const SkScalar kMinVertExtent = -100.f;
289 static const SkScalar kMaxVertExtent = 100.f;
290 randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
291 random,
292 &positions,
293 &texCoords, hasTexCoords,
294 &colors, hasColors,
295 &indices, hasIndices);
296
297 for (uint32_t i = 1; i < primitiveCount; i++) {
298 randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
299 random,
300 &positions,
301 &texCoords, hasTexCoords,
302 &colors, hasColors,
303 &indices, hasIndices);
304 }
305
306 SkMatrix viewMatrix = GrTest::TestMatrix(random);
307 SkRect bounds;
308 SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexCount);
309 SkASSERT(result);
310
311 viewMatrix.mapRect(&bounds);
312
313 GrDrawVerticesBatch::Geometry geometry;
314 geometry.fColor = GrRandomColor(random);
315 return GrDrawVerticesBatch::Create(geometry, type, viewMatrix,
316 positions.begin(), vertexCount,
317 indices.begin(), hasIndices ? vertexCount : 0,
318 colors.begin(),
319 texCoords.begin(),
320 bounds);
321}
322
323#endif