GrDrawAtlasOp.cpp revision 5ec9def2dd7bba572398ff2aa9361fbbb3b478ed
1/* 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 "GrDrawAtlasOp.h" 9#include "GrDrawOpTest.h" 10#include "GrOpFlushState.h" 11#include "SkGr.h" 12#include "SkRSXform.h" 13#include "SkRandom.h" 14 15void GrDrawAtlasOp::initBatchTracker(const GrXPOverridesForBatch& overrides) { 16 SkASSERT(fGeoData.count() == 1); 17 // Handle any color overrides 18 if (!overrides.readsColor()) { 19 fGeoData[0].fColor = GrColor_ILLEGAL; 20 } 21 if (overrides.getOverrideColorIfSet(&fGeoData[0].fColor) && fHasColors) { 22 size_t vertexStride = 23 sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0); 24 uint8_t* currVertex = fGeoData[0].fVerts.begin(); 25 for (int i = 0; i < 4 * fQuadCount; ++i) { 26 *(reinterpret_cast<GrColor*>(currVertex + sizeof(SkPoint))) = fGeoData[0].fColor; 27 currVertex += vertexStride; 28 } 29 } 30 31 // setup batch properties 32 fColorIgnored = !overrides.readsColor(); 33 fColor = fGeoData[0].fColor; 34 // We'd like to assert this, but we can't because of GLPrograms test 35 // SkASSERT(init.readsLocalCoords()); 36 fCoverageIgnored = !overrides.readsCoverage(); 37} 38 39static sk_sp<GrGeometryProcessor> set_vertex_attributes(bool hasColors, 40 GrColor color, 41 const SkMatrix& viewMatrix, 42 bool coverageIgnored) { 43 using namespace GrDefaultGeoProcFactory; 44 Color gpColor(color); 45 if (hasColors) { 46 gpColor.fType = Color::kAttribute_Type; 47 } 48 49 Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_Type); 50 LocalCoords localCoords(LocalCoords::kHasExplicit_Type); 51 return GrDefaultGeoProcFactory::Make(gpColor, coverage, localCoords, viewMatrix); 52} 53 54void GrDrawAtlasOp::onPrepareDraws(Target* target) const { 55 // Setup geometry processor 56 sk_sp<GrGeometryProcessor> gp(set_vertex_attributes( 57 this->hasColors(), this->color(), this->viewMatrix(), this->coverageIgnored())); 58 59 int instanceCount = fGeoData.count(); 60 size_t vertexStride = gp->getVertexStride(); 61 SkASSERT(vertexStride == 62 sizeof(SkPoint) + sizeof(SkPoint) + (this->hasColors() ? sizeof(GrColor) : 0)); 63 64 QuadHelper helper; 65 int numQuads = this->quadCount(); 66 void* verts = helper.init(target, vertexStride, numQuads); 67 if (!verts) { 68 SkDebugf("Could not allocate vertices\n"); 69 return; 70 } 71 72 uint8_t* vertPtr = reinterpret_cast<uint8_t*>(verts); 73 for (int i = 0; i < instanceCount; i++) { 74 const Geometry& args = fGeoData[i]; 75 76 size_t allocSize = args.fVerts.count(); 77 memcpy(vertPtr, args.fVerts.begin(), allocSize); 78 vertPtr += allocSize; 79 } 80 helper.recordDraw(target, gp.get()); 81} 82 83GrDrawAtlasOp::GrDrawAtlasOp(GrColor color, const SkMatrix& viewMatrix, int spriteCount, 84 const SkRSXform* xforms, const SkRect* rects, const SkColor* colors) 85 : INHERITED(ClassID()) { 86 SkASSERT(xforms); 87 SkASSERT(rects); 88 89 fViewMatrix = viewMatrix; 90 Geometry& installedGeo = fGeoData.push_back(); 91 installedGeo.fColor = color; 92 93 // Figure out stride and offsets 94 // Order within the vertex is: position [color] texCoord 95 size_t texOffset = sizeof(SkPoint); 96 size_t vertexStride = 2 * sizeof(SkPoint); 97 fHasColors = SkToBool(colors); 98 if (colors) { 99 texOffset += sizeof(GrColor); 100 vertexStride += sizeof(GrColor); 101 } 102 103 // Compute buffer size and alloc buffer 104 fQuadCount = spriteCount; 105 int allocSize = static_cast<int>(4 * vertexStride * spriteCount); 106 installedGeo.fVerts.reset(allocSize); 107 uint8_t* currVertex = installedGeo.fVerts.begin(); 108 109 SkRect bounds; 110 bounds.setLargestInverted(); 111 int paintAlpha = GrColorUnpackA(installedGeo.fColor); 112 for (int spriteIndex = 0; spriteIndex < spriteCount; ++spriteIndex) { 113 // Transform rect 114 SkPoint quad[4]; 115 const SkRect& currRect = rects[spriteIndex]; 116 xforms[spriteIndex].toQuad(currRect.width(), currRect.height(), quad); 117 118 // Copy colors if necessary 119 if (colors) { 120 // convert to GrColor 121 SkColor color = colors[spriteIndex]; 122 if (paintAlpha != 255) { 123 color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paintAlpha)); 124 } 125 GrColor grColor = SkColorToPremulGrColor(color); 126 127 *(reinterpret_cast<GrColor*>(currVertex + sizeof(SkPoint))) = grColor; 128 *(reinterpret_cast<GrColor*>(currVertex + vertexStride + sizeof(SkPoint))) = grColor; 129 *(reinterpret_cast<GrColor*>(currVertex + 2 * vertexStride + sizeof(SkPoint))) = 130 grColor; 131 *(reinterpret_cast<GrColor*>(currVertex + 3 * vertexStride + sizeof(SkPoint))) = 132 grColor; 133 } 134 135 // Copy position and uv to verts 136 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[0]; 137 *(reinterpret_cast<SkPoint*>(currVertex + texOffset)) = 138 SkPoint::Make(currRect.fLeft, currRect.fTop); 139 bounds.growToInclude(quad[0].fX, quad[0].fY); 140 currVertex += vertexStride; 141 142 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[1]; 143 *(reinterpret_cast<SkPoint*>(currVertex + texOffset)) = 144 SkPoint::Make(currRect.fRight, currRect.fTop); 145 bounds.growToInclude(quad[1].fX, quad[1].fY); 146 currVertex += vertexStride; 147 148 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[2]; 149 *(reinterpret_cast<SkPoint*>(currVertex + texOffset)) = 150 SkPoint::Make(currRect.fRight, currRect.fBottom); 151 bounds.growToInclude(quad[2].fX, quad[2].fY); 152 currVertex += vertexStride; 153 154 *(reinterpret_cast<SkPoint*>(currVertex)) = quad[3]; 155 *(reinterpret_cast<SkPoint*>(currVertex + texOffset)) = 156 SkPoint::Make(currRect.fLeft, currRect.fBottom); 157 bounds.growToInclude(quad[3].fX, quad[3].fY); 158 currVertex += vertexStride; 159 } 160 161 this->setTransformedBounds(bounds, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo); 162} 163 164bool GrDrawAtlasOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { 165 GrDrawAtlasOp* that = t->cast<GrDrawAtlasOp>(); 166 167 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), 168 that->bounds(), caps)) { 169 return false; 170 } 171 172 // We currently use a uniform viewmatrix for this op. 173 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 174 return false; 175 } 176 177 if (this->hasColors() != that->hasColors()) { 178 return false; 179 } 180 181 if (!this->hasColors() && this->color() != that->color()) { 182 return false; 183 } 184 185 if (this->color() != that->color()) { 186 fColor = GrColor_ILLEGAL; 187 } 188 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); 189 fQuadCount += that->quadCount(); 190 191 this->joinBounds(*that); 192 return true; 193} 194 195#ifdef GR_TEST_UTILS 196 197static SkRSXform random_xform(SkRandom* random) { 198 static const SkScalar kMinExtent = -100.f; 199 static const SkScalar kMaxExtent = 100.f; 200 static const SkScalar kMinScale = 0.1f; 201 static const SkScalar kMaxScale = 100.f; 202 static const SkScalar kMinRotate = -SK_ScalarPI; 203 static const SkScalar kMaxRotate = SK_ScalarPI; 204 205 SkRSXform xform = SkRSXform::MakeFromRadians(random->nextRangeScalar(kMinScale, kMaxScale), 206 random->nextRangeScalar(kMinRotate, kMaxRotate), 207 random->nextRangeScalar(kMinExtent, kMaxExtent), 208 random->nextRangeScalar(kMinExtent, kMaxExtent), 209 random->nextRangeScalar(kMinExtent, kMaxExtent), 210 random->nextRangeScalar(kMinExtent, kMaxExtent)); 211 return xform; 212} 213 214static SkRect random_texRect(SkRandom* random) { 215 static const SkScalar kMinCoord = 0.0f; 216 static const SkScalar kMaxCoord = 1024.f; 217 218 SkRect texRect = SkRect::MakeLTRB(random->nextRangeScalar(kMinCoord, kMaxCoord), 219 random->nextRangeScalar(kMinCoord, kMaxCoord), 220 random->nextRangeScalar(kMinCoord, kMaxCoord), 221 random->nextRangeScalar(kMinCoord, kMaxCoord)); 222 texRect.sort(); 223 return texRect; 224} 225 226static void randomize_params(uint32_t count, SkRandom* random, SkTArray<SkRSXform>* xforms, 227 SkTArray<SkRect>* texRects, SkTArray<GrColor>* colors, 228 bool hasColors) { 229 for (uint32_t v = 0; v < count; v++) { 230 xforms->push_back(random_xform(random)); 231 texRects->push_back(random_texRect(random)); 232 if (hasColors) { 233 colors->push_back(GrRandomColor(random)); 234 } 235 } 236} 237 238DRAW_OP_TEST_DEFINE(GrDrawAtlasOp) { 239 uint32_t spriteCount = random->nextRangeU(1, 100); 240 241 SkTArray<SkRSXform> xforms(spriteCount); 242 SkTArray<SkRect> texRects(spriteCount); 243 SkTArray<GrColor> colors; 244 245 bool hasColors = random->nextBool(); 246 247 randomize_params(spriteCount, random, &xforms, &texRects, &colors, hasColors); 248 249 SkMatrix viewMatrix = GrTest::TestMatrix(random); 250 251 GrColor color = GrRandomColor(random); 252 return GrDrawAtlasOp::Make(color, viewMatrix, spriteCount, xforms.begin(), texRects.begin(), 253 hasColors ? colors.begin() : nullptr); 254} 255 256#endif 257