Chromium Code Reviews| 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 |