Make DefaultPathOp surface its programInfo at record time
Here is another Op w/ multiple GrMeshes drawn w/ a single programInfo (cf., AAConvexPathOp). Bug: skia:9455 Change-Id: I3d1eec03d1d9d4fc8e117aa2960472027ea96105 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/276220 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
fdf94044ff
commit
9028bacebc
@ -19,6 +19,7 @@
|
||||
#include "src/gpu/GrFixedClip.h"
|
||||
#include "src/gpu/GrMesh.h"
|
||||
#include "src/gpu/GrOpFlushState.h"
|
||||
#include "src/gpu/GrProgramInfo.h"
|
||||
#include "src/gpu/GrRenderTargetContextPriv.h"
|
||||
#include "src/gpu/GrStyle.h"
|
||||
#include "src/gpu/GrSurfaceContextPriv.h"
|
||||
@ -66,20 +67,21 @@ namespace {
|
||||
|
||||
class PathGeoBuilder {
|
||||
public:
|
||||
PathGeoBuilder(GrPrimitiveType primitiveType, GrMeshDrawOp::Target* target,
|
||||
const GrGeometryProcessor* geometryProcessor)
|
||||
PathGeoBuilder(GrPrimitiveType primitiveType,
|
||||
GrMeshDrawOp::Target* target,
|
||||
SkTDArray<GrMesh*>* meshes)
|
||||
: fPrimitiveType(primitiveType)
|
||||
, fTarget(target)
|
||||
, fVertexStride(sizeof(SkPoint))
|
||||
, fGeometryProcessor(geometryProcessor)
|
||||
, fFirstIndex(0)
|
||||
, fIndicesInChunk(0)
|
||||
, fIndices(nullptr) {
|
||||
, fIndices(nullptr)
|
||||
, fMeshes(meshes) {
|
||||
this->allocNewBuffers();
|
||||
}
|
||||
|
||||
~PathGeoBuilder() {
|
||||
this->emitMeshAndPutBackReserve();
|
||||
this->createMeshAndPutBackReserve();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,14 +264,15 @@ private:
|
||||
}
|
||||
|
||||
// Emits a single draw with all accumulated vertex/index data
|
||||
void emitMeshAndPutBackReserve() {
|
||||
void createMeshAndPutBackReserve() {
|
||||
int vertexCount = fCurVert - fVertices;
|
||||
int indexCount = fCurIdx - fIndices;
|
||||
SkASSERT(vertexCount <= fVerticesInChunk);
|
||||
SkASSERT(indexCount <= fIndicesInChunk);
|
||||
|
||||
GrMesh* mesh = nullptr;
|
||||
if (this->isIndexed() ? SkToBool(indexCount) : SkToBool(vertexCount)) {
|
||||
GrMesh* mesh = fTarget->allocMesh();
|
||||
mesh = fTarget->allocMesh();
|
||||
if (!this->isIndexed()) {
|
||||
mesh->setNonIndexedNonInstanced(vertexCount);
|
||||
} else {
|
||||
@ -277,11 +280,14 @@ private:
|
||||
vertexCount - 1, GrPrimitiveRestart::kNo);
|
||||
}
|
||||
mesh->setVertexData(std::move(fVertexBuffer), fFirstVertex);
|
||||
fTarget->recordDraw(fGeometryProcessor, mesh, 1, fPrimitiveType);
|
||||
}
|
||||
|
||||
fTarget->putBackIndices((size_t)(fIndicesInChunk - indexCount));
|
||||
fTarget->putBackVertices((size_t)(fVerticesInChunk - vertexCount), fVertexStride);
|
||||
|
||||
if (mesh) {
|
||||
fMeshes->push_back(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
void needSpace(int vertsNeeded, int indicesNeeded = 0) {
|
||||
@ -297,7 +303,7 @@ private:
|
||||
SkPoint subpathStartPt = fVertices[fSubpathIndexStart];
|
||||
|
||||
// Draw the mesh we've accumulated, and put back any unused space
|
||||
this->emitMeshAndPutBackReserve();
|
||||
this->createMeshAndPutBackReserve();
|
||||
|
||||
// Get new buffers
|
||||
this->allocNewBuffers();
|
||||
@ -313,7 +319,6 @@ private:
|
||||
GrPrimitiveType fPrimitiveType;
|
||||
GrMeshDrawOp::Target* fTarget;
|
||||
size_t fVertexStride;
|
||||
const GrGeometryProcessor* fGeometryProcessor;
|
||||
|
||||
sk_sp<const GrBuffer> fVertexBuffer;
|
||||
int fFirstVertex;
|
||||
@ -327,6 +332,8 @@ private:
|
||||
uint16_t* fIndices;
|
||||
uint16_t* fCurIdx;
|
||||
uint16_t fSubpathIndexStart;
|
||||
|
||||
SkTDArray<GrMesh*>* fMeshes;
|
||||
};
|
||||
|
||||
class DefaultPathOp final : public GrMeshDrawOp {
|
||||
@ -354,7 +361,11 @@ public:
|
||||
const char* name() const override { return "DefaultPathOp"; }
|
||||
|
||||
void visitProxies(const VisitProxyFunc& func) const override {
|
||||
fHelper.visitProxies(func);
|
||||
if (fProgramInfo) {
|
||||
fProgramInfo->visitProxies(func);
|
||||
} else {
|
||||
fHelper.visitProxies(func);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
@ -401,7 +412,25 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void onPrepareDraws(Target* target) override {
|
||||
GrPrimitiveType primType() const {
|
||||
if (this->isHairline()) {
|
||||
int instanceCount = fPaths.count();
|
||||
|
||||
// We avoid indices when we have a single hairline contour.
|
||||
bool isIndexed = instanceCount > 1 ||
|
||||
PathGeoBuilder::PathHasMultipleSubpaths(fPaths[0].fPath);
|
||||
|
||||
return isIndexed ? GrPrimitiveType::kLines : GrPrimitiveType::kLineStrip;
|
||||
}
|
||||
|
||||
return GrPrimitiveType::kTriangles;
|
||||
}
|
||||
|
||||
GrProgramInfo* createProgramInfo(const GrCaps* caps,
|
||||
SkArenaAlloc* arena,
|
||||
const GrSurfaceProxyView* outputView,
|
||||
GrAppliedClip&& appliedClip,
|
||||
const GrXferProcessor::DstProxyView& dstProxyView) {
|
||||
GrGeometryProcessor* gp;
|
||||
{
|
||||
using namespace GrDefaultGeoProcFactory;
|
||||
@ -409,8 +438,8 @@ private:
|
||||
Coverage coverage(this->coverage());
|
||||
LocalCoords localCoords(fHelper.usesLocalCoords() ? LocalCoords::kUsePosition_Type
|
||||
: LocalCoords::kUnused_Type);
|
||||
gp = GrDefaultGeoProcFactory::Make(target->allocator(),
|
||||
target->caps().shaderCaps(),
|
||||
gp = GrDefaultGeoProcFactory::Make(arena,
|
||||
caps->shaderCaps(),
|
||||
color,
|
||||
coverage,
|
||||
localCoords,
|
||||
@ -419,32 +448,57 @@ private:
|
||||
|
||||
SkASSERT(gp->vertexStride() == sizeof(SkPoint));
|
||||
|
||||
int instanceCount = fPaths.count();
|
||||
return fHelper.createProgramInfoWithStencil(caps, arena, outputView, std::move(appliedClip),
|
||||
dstProxyView, gp, this->primType());
|
||||
|
||||
// We avoid indices when we have a single hairline contour.
|
||||
bool isIndexed = !this->isHairline() || instanceCount > 1 ||
|
||||
PathGeoBuilder::PathHasMultipleSubpaths(fPaths[0].fPath);
|
||||
}
|
||||
|
||||
// determine primitiveType
|
||||
GrPrimitiveType primitiveType;
|
||||
if (this->isHairline()) {
|
||||
primitiveType = isIndexed ? GrPrimitiveType::kLines : GrPrimitiveType::kLineStrip;
|
||||
} else {
|
||||
primitiveType = GrPrimitiveType::kTriangles;
|
||||
}
|
||||
PathGeoBuilder pathGeoBuilder(primitiveType, target, gp);
|
||||
GrProgramInfo* createProgramInfo(Target* target) {
|
||||
return this->createProgramInfo(&target->caps(),
|
||||
target->allocator(),
|
||||
target->outputView(),
|
||||
target->detachAppliedClip(),
|
||||
target->dstProxyView());
|
||||
}
|
||||
|
||||
void onPrePrepareDraws(GrRecordingContext* context,
|
||||
const GrSurfaceProxyView* outputView,
|
||||
GrAppliedClip* clip,
|
||||
const GrXferProcessor::DstProxyView& dstProxyView) override {
|
||||
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
|
||||
|
||||
// This is equivalent to a GrOpFlushState::detachAppliedClip
|
||||
GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip();
|
||||
|
||||
fProgramInfo = this->createProgramInfo(context->priv().caps(), arena, outputView,
|
||||
std::move(appliedClip), dstProxyView);
|
||||
|
||||
context->priv().recordProgramInfo(fProgramInfo);
|
||||
}
|
||||
|
||||
void onPrepareDraws(Target* target) override {
|
||||
PathGeoBuilder pathGeoBuilder(this->primType(), target, &fMeshes);
|
||||
|
||||
// fill buffers
|
||||
for (int i = 0; i < instanceCount; i++) {
|
||||
for (int i = 0; i < fPaths.count(); i++) {
|
||||
const PathData& args = fPaths[i];
|
||||
pathGeoBuilder.addPath(args.fPath, args.fTolerance);
|
||||
}
|
||||
}
|
||||
|
||||
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
|
||||
auto pipeline = fHelper.createPipelineWithStencil(flushState);
|
||||
if (!fProgramInfo) {
|
||||
fProgramInfo = this->createProgramInfo(flushState);
|
||||
}
|
||||
|
||||
flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, pipeline);
|
||||
if (!fProgramInfo || !fMeshes.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
flushState->opsRenderPass()->bindPipeline(*fProgramInfo, chainBounds);
|
||||
for (int i = 0; i < fMeshes.count(); ++i) {
|
||||
flushState->opsRenderPass()->drawMeshes(*fProgramInfo, fMeshes[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
CombineResult onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
|
||||
@ -491,6 +545,9 @@ private:
|
||||
SkMatrix fViewMatrix;
|
||||
bool fIsHairline;
|
||||
|
||||
SkTDArray<GrMesh*> fMeshes;
|
||||
GrProgramInfo* fProgramInfo = nullptr;
|
||||
|
||||
typedef GrMeshDrawOp INHERITED;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user