Add helper to determine the index buffer that will be used
This CL doesn't use the new VertexSpec member variable but should clarify the path forward (i.e., we will determine the index buffer option at characterize time and enforce that decision at onPrepare time for all the meshes). This also refactors the GrTextureOp::characterize call. Change-Id: I7010385abf5a462c12fd47e314aad893bca85fb9 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251002 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
659b21d480
commit
c554dcf4b5
@ -409,7 +409,7 @@ private:
|
||||
static const GrQuadPerEdgeAA::VertexSpec kSpec =
|
||||
{GrQuad::Type::kGeneral, GrQuadPerEdgeAA::ColorType::kNone,
|
||||
GrQuad::Type::kAxisAligned, false, GrQuadPerEdgeAA::Domain::kNo,
|
||||
GrAAType::kCoverage, false};
|
||||
GrAAType::kCoverage, false, GrQuadPerEdgeAA::IndexBufferOption::kPictureFramed};
|
||||
static const GrQuad kIgnored(SkRect::MakeEmpty());
|
||||
|
||||
GrQuadAAFlags flags = GrQuadAAFlags::kNone;
|
||||
|
@ -192,9 +192,12 @@ private:
|
||||
using Domain = GrQuadPerEdgeAA::Domain;
|
||||
static constexpr SkRect kEmptyDomain = SkRect::MakeEmpty();
|
||||
|
||||
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(fHelper.aaType(),
|
||||
fQuads.count());
|
||||
|
||||
VertexSpec vertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
|
||||
fHelper.usesLocalCoords(), Domain::kNo, fHelper.aaType(),
|
||||
fHelper.compatibleWithCoverageAsAlpha());
|
||||
fHelper.compatibleWithCoverageAsAlpha(), indexBufferOption);
|
||||
// Make sure that if the op thought it was a solid color, the vertex spec does not use
|
||||
// local coords.
|
||||
SkASSERT(!fHelper.isTrivial() || !fHelper.usesLocalCoords());
|
||||
|
@ -526,7 +526,7 @@ static sk_sp<const GrGpuBuffer> get_index_buffer(GrResourceProvider* resourcePro
|
||||
GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
|
||||
|
||||
// clang-format off
|
||||
static const uint16_t gFillAARectIdx[] = {
|
||||
static const uint16_t gFillAARectIdx[kIndicesPerAAFillRect] = {
|
||||
0, 1, 2, 1, 3, 2,
|
||||
0, 4, 1, 4, 5, 1,
|
||||
0, 6, 4, 0, 2, 6,
|
||||
@ -545,6 +545,16 @@ static sk_sp<const GrGpuBuffer> get_index_buffer(GrResourceProvider* resourcePro
|
||||
|
||||
namespace GrQuadPerEdgeAA {
|
||||
|
||||
IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads) {
|
||||
if (aa == GrAAType::kCoverage) {
|
||||
return IndexBufferOption::kPictureFramed;
|
||||
} else if (numQuads > 1) {
|
||||
return IndexBufferOption::kIndexedRects;
|
||||
} else {
|
||||
return IndexBufferOption::kTriStrips;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a more elaborate version of SkPMColor4fNeedsWideColor that allows "no color" for white
|
||||
ColorType MinColorType(SkPMColor4f color, GrClampType clampType, const GrCaps& caps) {
|
||||
if (color == SK_PMColor4fWHITE) {
|
||||
@ -625,6 +635,8 @@ void* Tessellate(void* vertices, const VertexSpec& spec, const GrQuad& deviceQua
|
||||
bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const VertexSpec& spec,
|
||||
int quadCount) {
|
||||
if (spec.usesCoverageAA()) {
|
||||
SkASSERT(spec.indexBufferOption() == IndexBufferOption::kPictureFramed);
|
||||
|
||||
// AA quads use 8 vertices, basically nested rectangles
|
||||
sk_sp<const GrGpuBuffer> ibuffer = get_index_buffer(target->resourceProvider());
|
||||
if (!ibuffer) {
|
||||
@ -637,6 +649,8 @@ bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const Vert
|
||||
} else {
|
||||
// Non-AA quads use 4 vertices, and regular triangle strip layout
|
||||
if (quadCount > 1) {
|
||||
SkASSERT(spec.indexBufferOption() == IndexBufferOption::kIndexedRects);
|
||||
|
||||
sk_sp<const GrGpuBuffer> ibuffer = target->resourceProvider()->refQuadIndexBuffer();
|
||||
if (!ibuffer) {
|
||||
return false;
|
||||
@ -646,6 +660,8 @@ bool ConfigureMeshIndices(GrMeshDrawOp::Target* target, GrMesh* mesh, const Vert
|
||||
mesh->setIndexedPatterned(std::move(ibuffer), 6, 4, quadCount,
|
||||
GrResourceProvider::QuadCountOfQuadBuffer());
|
||||
} else {
|
||||
SkASSERT(spec.indexBufferOption() != IndexBufferOption::kPictureFramed);
|
||||
|
||||
mesh->setPrimitiveType(GrPrimitiveType::kTriangleStrip);
|
||||
mesh->setNonIndexedNonInstanced(4);
|
||||
}
|
||||
|
@ -30,6 +30,16 @@ namespace GrQuadPerEdgeAA {
|
||||
enum class ColorType { kNone, kByte, kHalf, kLast = kHalf };
|
||||
static const int kColorTypeCount = static_cast<int>(ColorType::kLast) + 1;
|
||||
|
||||
enum class IndexBufferOption {
|
||||
kPictureFramed, // geometrically AA'd -> 8 verts/quad + an index buffer
|
||||
kIndexedRects, // non-AA'd but indexed -> 4 verts/quad + an index buffer
|
||||
kTriStrips, // non-AA'd -> 4 verts/quad but no index buffer
|
||||
kLast = kTriStrips
|
||||
};
|
||||
static const int kIndexBufferOptionCount = static_cast<int>(IndexBufferOption::kLast) + 1;
|
||||
|
||||
IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads);
|
||||
|
||||
// Gets the minimum ColorType that can represent a color.
|
||||
ColorType MinColorType(SkPMColor4f, GrClampType, const GrCaps&);
|
||||
|
||||
@ -42,17 +52,20 @@ namespace GrQuadPerEdgeAA {
|
||||
VertexSpec()
|
||||
: fDeviceQuadType(0) // kAxisAligned
|
||||
, fLocalQuadType(0) // kAxisAligned
|
||||
, fIndexBufferOption(0) // kPictureFramed
|
||||
, fHasLocalCoords(false)
|
||||
, fColorType(0) // kNone
|
||||
, fHasDomain(false)
|
||||
, fUsesCoverageAA(false)
|
||||
, fCompatibleWithCoverageAsAlpha(false)
|
||||
, fRequiresGeometryDomain(false) { }
|
||||
, fRequiresGeometryDomain(false) {}
|
||||
|
||||
VertexSpec(GrQuad::Type deviceQuadType, ColorType colorType, GrQuad::Type localQuadType,
|
||||
bool hasLocalCoords, Domain domain, GrAAType aa, bool coverageAsAlpha)
|
||||
bool hasLocalCoords, Domain domain, GrAAType aa, bool coverageAsAlpha,
|
||||
IndexBufferOption indexBufferOption)
|
||||
: fDeviceQuadType(static_cast<unsigned>(deviceQuadType))
|
||||
, fLocalQuadType(static_cast<unsigned>(localQuadType))
|
||||
, fIndexBufferOption(static_cast<unsigned>(indexBufferOption))
|
||||
, fHasLocalCoords(hasLocalCoords)
|
||||
, fColorType(static_cast<unsigned>(colorType))
|
||||
, fHasDomain(static_cast<unsigned>(domain))
|
||||
@ -63,6 +76,9 @@ namespace GrQuadPerEdgeAA {
|
||||
|
||||
GrQuad::Type deviceQuadType() const { return static_cast<GrQuad::Type>(fDeviceQuadType); }
|
||||
GrQuad::Type localQuadType() const { return static_cast<GrQuad::Type>(fLocalQuadType); }
|
||||
IndexBufferOption indexBufferOption() const {
|
||||
return static_cast<IndexBufferOption>(fIndexBufferOption);
|
||||
}
|
||||
bool hasLocalCoords() const { return fHasLocalCoords; }
|
||||
ColorType colorType() const { return static_cast<ColorType>(fColorType); }
|
||||
bool hasVertexColors() const { return ColorType::kNone != this->colorType(); }
|
||||
@ -83,9 +99,11 @@ namespace GrQuadPerEdgeAA {
|
||||
private:
|
||||
static_assert(GrQuad::kTypeCount <= 4, "GrQuad::Type doesn't fit in 2 bits");
|
||||
static_assert(kColorTypeCount <= 4, "Color doesn't fit in 2 bits");
|
||||
static_assert(kIndexBufferOptionCount <= 4, "IndexBufferOption doesn't fit in 2 bits");
|
||||
|
||||
unsigned fDeviceQuadType: 2;
|
||||
unsigned fLocalQuadType: 2;
|
||||
unsigned fIndexBufferOption: 2;
|
||||
unsigned fHasLocalCoords: 1;
|
||||
unsigned fColorType : 2;
|
||||
unsigned fHasDomain: 1;
|
||||
|
@ -531,8 +531,8 @@ private:
|
||||
|
||||
fPrePreparedDesc = arena->make<PrePreparedDesc>();
|
||||
|
||||
fPrePreparedDesc->fVertexSpec = this->characterize(&fPrePreparedDesc->fNumProxies,
|
||||
&fPrePreparedDesc->fNumTotalQuads);
|
||||
this->characterize(fPrePreparedDesc);
|
||||
|
||||
fPrePreparedDesc->allocateCommon(arena, clip);
|
||||
|
||||
fPrePreparedDesc->allocatePrePrepareOnly(arena);
|
||||
@ -605,15 +605,16 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
VertexSpec characterize(int* numProxies, int* numTotalQuads) const {
|
||||
void characterize(PrePreparedDesc* desc) const {
|
||||
GrQuad::Type quadType = GrQuad::Type::kAxisAligned;
|
||||
ColorType colorType = ColorType::kNone;
|
||||
GrQuad::Type srcQuadType = GrQuad::Type::kAxisAligned;
|
||||
Domain domain = Domain::kNo;
|
||||
GrAAType overallAAType = this->aaType();
|
||||
|
||||
*numProxies = 0;
|
||||
*numTotalQuads = 0;
|
||||
desc->fNumProxies = 0;
|
||||
desc->fNumTotalQuads = 0;
|
||||
int maxQuadsPerMesh = 0;
|
||||
|
||||
for (const auto& op : ChainRange<TextureOp>(this)) {
|
||||
if (op.fQuads.deviceQuadType() > quadType) {
|
||||
@ -626,17 +627,22 @@ private:
|
||||
domain = Domain::kYes;
|
||||
}
|
||||
colorType = SkTMax(colorType, static_cast<ColorType>(op.fColorType));
|
||||
*numProxies += op.fProxyCnt;
|
||||
desc->fNumProxies += op.fProxyCnt;
|
||||
for (unsigned p = 0; p < op.fProxyCnt; ++p) {
|
||||
*numTotalQuads += op.fProxyCountPairs[p].fQuadCnt;
|
||||
desc->fNumTotalQuads += op.fProxyCountPairs[p].fQuadCnt;
|
||||
maxQuadsPerMesh = SkTMax(op.fProxyCountPairs[p].fQuadCnt, maxQuadsPerMesh);
|
||||
}
|
||||
if (op.aaType() == GrAAType::kCoverage) {
|
||||
overallAAType = GrAAType::kCoverage;
|
||||
}
|
||||
}
|
||||
|
||||
return VertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true, domain,
|
||||
overallAAType, /* alpha as coverage */ true);
|
||||
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(overallAAType,
|
||||
maxQuadsPerMesh);
|
||||
|
||||
desc->fVertexSpec = VertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true,
|
||||
domain, overallAAType, /* alpha as coverage */ true,
|
||||
indexBufferOption);
|
||||
}
|
||||
|
||||
// onPrePrepareDraws may or may not have been called at this point
|
||||
@ -652,7 +658,7 @@ private:
|
||||
} else {
|
||||
SkArenaAlloc* arena = target->allocator();
|
||||
|
||||
desc.fVertexSpec = this->characterize(&desc.fNumProxies, &desc.fNumTotalQuads);
|
||||
this->characterize(&desc);
|
||||
desc.allocateCommon(arena, target->appliedClip());
|
||||
|
||||
SkASSERT(!desc.fVertexOffsets && !desc.fVertices);
|
||||
|
Loading…
Reference in New Issue
Block a user