38 const char*
name()
const override {
return "DrawAtlasOp"; }
66#if defined(GR_TEST_UTILS)
67 SkString onDumpInfo()
const override;
72 bool hasColors()
const {
return fHasColors; }
73 int quadCount()
const {
return fQuadCount; }
100 gpColor.fType = Color::kPremulGrColorAttribute_Type;
104 LocalCoords::kHasExplicit_Type, viewMatrix);
116 Geometry& installedGeo = fGeoData.push_back();
117 installedGeo.fColor =
color;
121 size_t texOffset =
sizeof(
SkPoint);
122 size_t vertexStride = 2 *
sizeof(
SkPoint);
126 vertexStride +=
sizeof(
GrColor);
130 fQuadCount = spriteCount;
131 int allocSize =
static_cast<int>(4 * vertexStride * spriteCount);
132 installedGeo.fVerts.reset(allocSize);
133 uint8_t* currVertex = installedGeo.fVerts.begin();
137 int paintAlpha =
GrColorUnpackA(installedGeo.fColor.toBytes_RGBA());
138 for (
int spriteIndex = 0; spriteIndex < spriteCount; ++spriteIndex) {
141 const SkRect& currRect = rects[spriteIndex];
148 if (paintAlpha != 255) {
154 *(
reinterpret_cast<GrColor*
>(currVertex +
sizeof(
SkPoint))) = grColor;
155 *(
reinterpret_cast<GrColor*
>(currVertex + vertexStride +
sizeof(
SkPoint))) = grColor;
156 *(
reinterpret_cast<GrColor*
>(currVertex + 2 * vertexStride +
sizeof(
SkPoint))) =
158 *(
reinterpret_cast<GrColor*
>(currVertex + 3 * vertexStride +
sizeof(
SkPoint))) =
163 *(
reinterpret_cast<SkPoint*
>(currVertex)) = strip[0];
164 *(
reinterpret_cast<SkPoint*
>(currVertex + texOffset)) =
167 currVertex += vertexStride;
169 *(
reinterpret_cast<SkPoint*
>(currVertex)) = strip[1];
170 *(
reinterpret_cast<SkPoint*
>(currVertex + texOffset)) =
173 currVertex += vertexStride;
175 *(
reinterpret_cast<SkPoint*
>(currVertex)) = strip[2];
176 *(
reinterpret_cast<SkPoint*
>(currVertex + texOffset)) =
179 currVertex += vertexStride;
181 *(
reinterpret_cast<SkPoint*
>(currVertex)) = strip[3];
182 *(
reinterpret_cast<SkPoint*
>(currVertex + texOffset)) =
185 currVertex += vertexStride;
188 this->setTransformedBounds(
bounds, viewMatrix, HasAABloat::kNo, IsHairline::kNo);
191#if defined(GR_TEST_UTILS)
192SkString DrawAtlasOpImpl::onDumpInfo()
const {
194 for (
const auto& geo : fGeoData) {
195 string.
appendf(
"Color: 0x%08x, Quads: %d\n", geo.fColor.toBytes_RGBA(),
196 geo.fVerts.size() / 4);
198 string += fHelper.dumpInfo();
203void DrawAtlasOpImpl::onCreateProgramInfo(
const GrCaps* caps,
206 bool usesMSAASurface,
217 fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, usesMSAASurface,
218 std::move(appliedClip), dstProxyView, gp,
225 this->createProgramInfo(
target);
228 int instanceCount = fGeoData.size();
231 int numQuads = this->quadCount();
232 QuadHelper helper(
target, vertexStride, numQuads);
233 void* verts = helper.vertices();
235 SkDebugf(
"Could not allocate vertices\n");
239 uint8_t* vertPtr =
reinterpret_cast<uint8_t*
>(verts);
240 for (
int i = 0;
i < instanceCount;
i++) {
241 const Geometry&
args = fGeoData[
i];
243 size_t allocSize =
args.fVerts.size();
244 memcpy(vertPtr,
args.fVerts.begin(), allocSize);
245 vertPtr += allocSize;
248 fMesh = helper.mesh();
252 if (!fProgramInfo || !fMesh) {
264 auto that = t->
cast<DrawAtlasOpImpl>();
266 if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
267 return CombineResult::kCannotCombine;
272 return CombineResult::kCannotCombine;
275 if (this->hasColors() != that->hasColors()) {
276 return CombineResult::kCannotCombine;
279 if (!this->hasColors() && this->
color() != that->color()) {
280 return CombineResult::kCannotCombine;
283 fGeoData.push_back_n(that->fGeoData.size(), that->fGeoData.begin());
284 fQuadCount += that->quadCount();
286 return CombineResult::kMerged;
290 return fHelper.fixedFunctionFlags();
297 if (this->hasColors()) {
302 auto result = fHelper.finalizeProcessors(caps,
clip, clampType,
322 return GrSimpleMeshDrawOpHelper::FactoryHelper<DrawAtlasOpImpl>(context, std::move(
paint),
330#if defined(GR_TEST_UTILS)
334 static const SkScalar kMinExtent = -100.f;
335 static const SkScalar kMaxExtent = 100.f;
336 static const SkScalar kMinScale = 0.1f;
337 static const SkScalar kMaxScale = 100.f;
351 static const SkScalar kMinCoord = 0.0f;
352 static const SkScalar kMaxCoord = 1024.f;
365 for (uint32_t v = 0; v <
count; v++) {
366 xforms->push_back(random_xform(random));
367 texRects->
push_back(random_texRect(random));
369 colors->push_back(GrTest::RandomColor(random));
374GR_DRAW_OP_TEST_DEFINE(DrawAtlasOp) {
375 uint32_t spriteCount = random->
nextRangeU(1, 100);
381 bool hasColors = random->
nextBool();
383 randomize_params(spriteCount, random, &
xforms, &texRects, &
colors, hasColors);
385 SkMatrix viewMatrix = GrTest::TestMatrix(random);
387 if (numSamples > 1 && random->
nextBool()) {
398 hasColors ?
colors.begin() :
nullptr);
#define GrColorUnpackA(color)
#define DEFINE_OP_CLASS_ID
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
static constexpr SkColor SkColorSetA(SkColor c, U8CPU a)
#define SkColorGetA(color)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static GrColor SkColorToPremulGrColor(SkColor c)
static U8CPU SkMulDiv255Round(U16CPU a, U16CPU b)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
static constexpr bool SkToBool(const T &x)
virtual FixedFunctionFlags fixedFunctionFlags() const
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
friend class GrSimpleMeshDrawOpHelper
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
std::unique_ptr< GrOp > Owner
virtual const char * name() const =0
virtual void visitProxies(const GrVisitProxyFunc &) const
virtual CombineResult onCombineIfPossible(GrOp *, SkArenaAlloc *, const GrCaps &)
bool isConstant(SkPMColor4f *color=nullptr) const
void setToConstant(const SkPMColor4f &color)
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
void visitProxies(const GrVisitProxyFunc &func) const
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
SkScalar nextRangeScalar(SkScalar min, SkScalar max)
uint32_t nextRangeU(uint32_t min, uint32_t max)
static constexpr SkRect MakeLargestInverted()
static void GrowToInclude(SkRect *r, const SkPoint &pt)
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GrGeometryProcessor * Make(SkArenaAlloc *, const Color &, const Coverage &, const LocalCoords &, const SkMatrix &viewMatrix)
Optional< SkRect > bounds
PODArray< SkRSXform > xforms
PODArray< SkColor > colors
GrOp::Owner Make(GrRecordingContext *context, GrPaint &&paint, const SkMatrix &viewMatrix, GrAAType aaType, int spriteCount, const SkRSXform *xforms, const SkRect *rects, const SkColor *colors)
static constexpr SkPoint Make(float x, float y)
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
constexpr float height() const
constexpr float width() const
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds