blob: 28c6922d99fadf4af0a4a6f54b43b28837932a3a [file] [log] [blame]
jvanverth14b88032015-08-07 12:18:54 -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 "GrDrawAtlasBatch.h"
9#include "GrBatchTest.h"
jvanverth5a4d2352015-08-12 08:15:31 -070010#include "SkGr.h"
jvanverth14b88032015-08-07 12:18:54 -070011#include "SkRandom.h"
jvanverth5a4d2352015-08-12 08:15:31 -070012#include "SkRSXform.h"
jvanverth14b88032015-08-07 12:18:54 -070013
bsalomon91d844d2015-08-10 10:47:29 -070014void GrDrawAtlasBatch::initBatchTracker(const GrPipelineOptimizations& opt) {
jvanverth14b88032015-08-07 12:18:54 -070015 // Handle any color overrides
bsalomon91d844d2015-08-10 10:47:29 -070016 if (!opt.readsColor()) {
jvanverth14b88032015-08-07 12:18:54 -070017 fGeoData[0].fColor = GrColor_ILLEGAL;
18 }
bsalomon91d844d2015-08-10 10:47:29 -070019 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
jvanverth14b88032015-08-07 12:18:54 -070020
21 // setup batch properties
bsalomon91d844d2015-08-10 10:47:29 -070022 fColorIgnored = !opt.readsColor();
jvanverth14b88032015-08-07 12:18:54 -070023 fColor = fGeoData[0].fColor;
joshualittd22f37c2015-08-10 08:02:58 -070024 // We'd like to assert this, but we can't because of GLPrograms test
25 //SkASSERT(init.readsLocalCoords());
bsalomon91d844d2015-08-10 10:47:29 -070026 fCoverageIgnored = !opt.readsCoverage();
jvanverth14b88032015-08-07 12:18:54 -070027}
28
jvanverth5a4d2352015-08-12 08:15:31 -070029static const GrGeometryProcessor* set_vertex_attributes(bool hasColors,
jvanverth14b88032015-08-07 12:18:54 -070030 GrColor color,
31 const SkMatrix& viewMatrix,
32 bool coverageIgnored) {
33 using namespace GrDefaultGeoProcFactory;
jvanverth14b88032015-08-07 12:18:54 -070034 Color gpColor(color);
35 if (hasColors) {
36 gpColor.fType = Color::kAttribute_Type;
37 }
38
39 Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_Type);
jvanverth5a4d2352015-08-12 08:15:31 -070040 LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
jvanverth14b88032015-08-07 12:18:54 -070041 return GrDefaultGeoProcFactory::Create(gpColor, coverage, localCoords, viewMatrix);
42}
43
44void GrDrawAtlasBatch::generateGeometry(GrBatchTarget* batchTarget) {
jvanverth14b88032015-08-07 12:18:54 -070045 // Setup geometry processor
jvanverth5a4d2352015-08-12 08:15:31 -070046 SkAutoTUnref<const GrGeometryProcessor> gp(set_vertex_attributes(this->hasColors(),
47 this->color(),
48 this->viewMatrix(),
49 this->coverageIgnored()));
jvanverth14b88032015-08-07 12:18:54 -070050
51 batchTarget->initDraw(gp, this->pipeline());
52
53 int instanceCount = fGeoData.count();
54 size_t vertexStride = gp->getVertexStride();
55 SkASSERT(vertexStride == sizeof(SkPoint) + sizeof(SkPoint)
56 + (this->hasColors() ? sizeof(GrColor) : 0));
57
58 QuadHelper helper;
jvanverth5a4d2352015-08-12 08:15:31 -070059 int numQuads = this->quadCount();
jvanverth14b88032015-08-07 12:18:54 -070060 void* verts = helper.init(batchTarget, vertexStride, numQuads);
61 if (!verts) {
62 SkDebugf("Could not allocate vertices\n");
63 return;
64 }
65
jvanverth5a4d2352015-08-12 08:15:31 -070066 uint8_t* vertPtr = reinterpret_cast<uint8_t*>(verts);
jvanverth14b88032015-08-07 12:18:54 -070067 for (int i = 0; i < instanceCount; i++) {
68 const Geometry& args = fGeoData[i];
69
jvanverth5a4d2352015-08-12 08:15:31 -070070 size_t allocSize = args.fVerts.count();
71 memcpy(vertPtr, args.fVerts.begin(), allocSize);
72 vertPtr += allocSize;
jvanverth14b88032015-08-07 12:18:54 -070073 }
74 helper.issueDraw(batchTarget);
75}
76
77GrDrawAtlasBatch::GrDrawAtlasBatch(const Geometry& geometry, const SkMatrix& viewMatrix,
jvanverth5a4d2352015-08-12 08:15:31 -070078 int spriteCount, const SkRSXform* xforms, const SkRect* rects,
79 const SkColor* colors) {
jvanverth14b88032015-08-07 12:18:54 -070080 this->initClassID<GrDrawAtlasBatch>();
jvanverth5a4d2352015-08-12 08:15:31 -070081 SkASSERT(xforms);
82 SkASSERT(rects);
jvanverth14b88032015-08-07 12:18:54 -070083
84 fViewMatrix = viewMatrix;
85 Geometry& installedGeo = fGeoData.push_back(geometry);
86
jvanverth5a4d2352015-08-12 08:15:31 -070087 // Figure out stride and offsets
88 // Order within the vertex is: position [color] texCoord
89 size_t texOffset = sizeof(SkPoint);
90 size_t vertexStride = 2*sizeof(SkPoint);
91 fHasColors = SkToBool(colors);
jvanverth14b88032015-08-07 12:18:54 -070092 if (colors) {
jvanverth5a4d2352015-08-12 08:15:31 -070093 texOffset += sizeof(GrColor);
94 vertexStride += sizeof(GrColor);
jvanverth14b88032015-08-07 12:18:54 -070095 }
96
jvanverth5a4d2352015-08-12 08:15:31 -070097 // Compute buffer size and alloc buffer
98 fQuadCount = spriteCount;
99 int allocSize = static_cast<int>(4*vertexStride*spriteCount);
100 installedGeo.fVerts.reset(allocSize);
101 uint8_t* currVertex = installedGeo.fVerts.begin();
jvanverth14b88032015-08-07 12:18:54 -0700102
jvanverth5a4d2352015-08-12 08:15:31 -0700103 SkRect bounds;
104 bounds.setLargestInverted();
105 int paintAlpha = GrColorUnpackA(installedGeo.fColor);
106 for (int spriteIndex = 0; spriteIndex < spriteCount; ++spriteIndex) {
107 // Transform rect
108 SkPoint quad[4];
109 const SkRect& currRect = rects[spriteIndex];
110 xforms[spriteIndex].toQuad(currRect.width(), currRect.height(), quad);
111
112 // Copy colors if necessary
113 if (colors) {
114 // convert to GrColor
115 SkColor color = colors[spriteIndex];
116 if (paintAlpha != 255) {
117 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paintAlpha));
118 }
119 GrColor grColor = SkColor2GrColor(color);
120
121 *(reinterpret_cast<GrColor*>(currVertex+sizeof(SkPoint))) = grColor;
122 *(reinterpret_cast<GrColor*>(currVertex+vertexStride+sizeof(SkPoint))) = grColor;
123 *(reinterpret_cast<GrColor*>(currVertex+2*vertexStride+sizeof(SkPoint))) = grColor;
124 *(reinterpret_cast<GrColor*>(currVertex+3*vertexStride+sizeof(SkPoint))) = grColor;
125 }
126
127 // Copy position and uv to verts
128 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[0];
129 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = SkPoint::Make(currRect.fLeft,
130 currRect.fTop);
131 bounds.growToInclude(quad[0].fX, quad[0].fY);
132 currVertex += vertexStride;
133
134 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[1];
135 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = SkPoint::Make(currRect.fRight,
136 currRect.fTop);
137 bounds.growToInclude(quad[1].fX, quad[1].fY);
138 currVertex += vertexStride;
139
140 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[2];
141 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = SkPoint::Make(currRect.fRight,
142 currRect.fBottom);
143 bounds.growToInclude(quad[2].fX, quad[2].fY);
144 currVertex += vertexStride;
145
146 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[3];
147 *(reinterpret_cast<SkPoint*>(currVertex+texOffset)) = SkPoint::Make(currRect.fLeft,
148 currRect.fBottom);
149 bounds.growToInclude(quad[3].fX, quad[3].fY);
150 currVertex += vertexStride;
151 }
152
153 viewMatrix.mapRect(&bounds);
154 // Outset for a half pixel in each direction to account for snapping in non-AA case
155 bounds.outset(0.5f, 0.5f);
jvanverth14b88032015-08-07 12:18:54 -0700156 this->setBounds(bounds);
157}
158
bsalomoncb02b382015-08-12 11:14:50 -0700159bool GrDrawAtlasBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) {
bsalomonabd30f52015-08-13 13:34:48 -0700160 GrDrawAtlasBatch* that = t->cast<GrDrawAtlasBatch>();
161
162 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
163 that->bounds(), caps)) {
jvanverth14b88032015-08-07 12:18:54 -0700164 return false;
165 }
bsalomonabd30f52015-08-13 13:34:48 -0700166
jvanverth14b88032015-08-07 12:18:54 -0700167 // We currently use a uniform viewmatrix for this batch
168 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
169 return false;
170 }
171
172 if (this->hasColors() != that->hasColors()) {
173 return false;
174 }
175
176 if (!this->hasColors() && this->color() != that->color()) {
177 return false;
178 }
179
180 if (this->color() != that->color()) {
181 fColor = GrColor_ILLEGAL;
182 }
183 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
jvanverth5a4d2352015-08-12 08:15:31 -0700184 fQuadCount += that->quadCount();
jvanverth14b88032015-08-07 12:18:54 -0700185
186 this->joinBounds(that->bounds());
187 return true;
188}
189
190#ifdef GR_TEST_UTILS
191
jvanverth5a4d2352015-08-12 08:15:31 -0700192static SkRSXform random_xform(SkRandom* random) {
193 static const SkScalar kMinExtent = -100.f;
194 static const SkScalar kMaxExtent = 100.f;
195 static const SkScalar kMinScale = 0.1f;
196 static const SkScalar kMaxScale = 100.f;
197 static const SkScalar kMinRotate = -SK_ScalarPI;
198 static const SkScalar kMaxRotate = SK_ScalarPI;
199
200 SkRSXform xform = SkRSXform::MakeFromRadians(random->nextRangeScalar(kMinScale, kMaxScale),
201 random->nextRangeScalar(kMinRotate, kMaxRotate),
202 random->nextRangeScalar(kMinExtent, kMaxExtent),
203 random->nextRangeScalar(kMinExtent, kMaxExtent),
204 random->nextRangeScalar(kMinExtent, kMaxExtent),
205 random->nextRangeScalar(kMinExtent, kMaxExtent));
206 return xform;
jvanverth14b88032015-08-07 12:18:54 -0700207}
208
jvanverth5a4d2352015-08-12 08:15:31 -0700209static SkRect random_texRect(SkRandom* random) {
210 static const SkScalar kMinCoord = 0.0f;
211 static const SkScalar kMaxCoord = 1024.f;
212
213 SkRect texRect = SkRect::MakeLTRB(random->nextRangeScalar(kMinCoord, kMaxCoord),
214 random->nextRangeScalar(kMinCoord, kMaxCoord),
215 random->nextRangeScalar(kMinCoord, kMaxCoord),
216 random->nextRangeScalar(kMinCoord, kMaxCoord));
217 texRect.sort();
218 return texRect;
219}
220
221static void randomize_params(uint32_t count, SkRandom* random,
222 SkTArray<SkRSXform>* xforms,
223 SkTArray<SkRect>* texRects,
jvanverth14b88032015-08-07 12:18:54 -0700224 SkTArray<GrColor>* colors, bool hasColors) {
225 for (uint32_t v = 0; v < count; v++) {
jvanverth5a4d2352015-08-12 08:15:31 -0700226 xforms->push_back(random_xform(random));
227 texRects->push_back(random_texRect(random));
jvanverth14b88032015-08-07 12:18:54 -0700228 if (hasColors) {
229 colors->push_back(GrRandomColor(random));
230 }
231 }
232}
233
bsalomonabd30f52015-08-13 13:34:48 -0700234DRAW_BATCH_TEST_DEFINE(GrDrawAtlasBatch) {
jvanverth14b88032015-08-07 12:18:54 -0700235 uint32_t spriteCount = random->nextRangeU(1, 100);
236
jvanverth5a4d2352015-08-12 08:15:31 -0700237 SkTArray<SkRSXform> xforms(spriteCount);
238 SkTArray<SkRect> texRects(spriteCount);
jvanverth1acf2502015-08-13 11:53:39 -0700239 SkTArray<GrColor> colors;
jvanverth14b88032015-08-07 12:18:54 -0700240
241 bool hasColors = random->nextBool();
242
jvanverth5a4d2352015-08-12 08:15:31 -0700243 randomize_params(spriteCount,
jvanverth14b88032015-08-07 12:18:54 -0700244 random,
jvanverth5a4d2352015-08-12 08:15:31 -0700245 &xforms,
246 &texRects,
jvanverth14b88032015-08-07 12:18:54 -0700247 &colors, hasColors);
248
249 SkMatrix viewMatrix = GrTest::TestMatrix(random);
jvanverth14b88032015-08-07 12:18:54 -0700250
251 GrDrawAtlasBatch::Geometry geometry;
252 geometry.fColor = GrRandomColor(random);
jvanverth5a4d2352015-08-12 08:15:31 -0700253 return GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount, xforms.begin(),
254 texRects.begin(), colors.begin());
jvanverth14b88032015-08-07 12:18:54 -0700255}
256
257#endif