Make deferred upload handling and draw recording be virtual interfaces implemented by GrOpFlushState.
The motivation for this is to allow other clients of GrDrawOpAtlas. Making GrMeshDrawOp::Target also be an abstract interface is somewhat incidental to this goal.
Bug: skia:
Change-Id: I0987adfa8a269aa2ca94147e933a2827d734c1cc
Reviewed-on: https://skia-review.googlesource.com/65121
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrDeferredUpload.h b/src/gpu/GrDeferredUpload.h
index 4110e55..821e523 100644
--- a/src/gpu/GrDeferredUpload.h
+++ b/src/gpu/GrDeferredUpload.h
@@ -14,6 +14,24 @@
class GrTextureProxy;
/**
+ * A word about deferred uploads and tokens: Ops should usually schedule their uploads to occur at
+ * the beginning of a frame whenever possible. These are called ASAP uploads. Of course, this
+ * requires that there are no draws that have yet to be flushed that rely on the old texture
+ * contents. In that case the ASAP upload would happen prior to the draw and therefore the draw
+ * would read the new (wrong) texture data. When this read-before-write data hazard exists they
+ * should schedule an inline upload.
+ *
+ * Ops, in conjunction with helpers such as GrDrawOpAtlas, use upload tokens to know what the most
+ * recent draw was that referenced a resource (or portion of a resource). Each draw is assigned a
+ * token. A resource (or portion thereof) can be tagged with the most recent reading draw's token.
+ * The deferred uploads target provides a facility for testing whether the draw corresponding to the
+ * token has been flushed. If it has not been flushed then the op must perform an inline upload
+ * instead so that the upload occurs after the draw depending on the old contents and before the
+ * draw depending on the updated contents. When scheduling an inline upload the op provides the
+ * token of the draw that the upload must occur before.
+ */
+
+/**
* GrDeferredUploadToken is used to sequence the uploads relative to each other and to draws.
*/
class GrDeferredUploadToken {
@@ -22,19 +40,44 @@
GrDeferredUploadToken(const GrDeferredUploadToken&) = default;
GrDeferredUploadToken& operator=(const GrDeferredUploadToken&) = default;
+
bool operator==(const GrDeferredUploadToken& that) const {
return fSequenceNumber == that.fSequenceNumber;
}
bool operator!=(const GrDeferredUploadToken& that) const { return !(*this == that); }
- bool inInterval(const GrDeferredUploadToken& start, const GrDeferredUploadToken& finish) {
- return fSequenceNumber >= start.fSequenceNumber &&
- fSequenceNumber <= finish.fSequenceNumber;
+ bool operator<(const GrDeferredUploadToken that) const {
+ return fSequenceNumber < that.fSequenceNumber;
+ }
+ bool operator<=(const GrDeferredUploadToken that) const {
+ return fSequenceNumber <= that.fSequenceNumber;
+ }
+ bool operator>(const GrDeferredUploadToken that) const {
+ return fSequenceNumber > that.fSequenceNumber;
+ }
+ bool operator>=(const GrDeferredUploadToken that) const {
+ return fSequenceNumber >= that.fSequenceNumber;
+ }
+
+ GrDeferredUploadToken& operator++() {
+ ++fSequenceNumber;
+ return *this;
+ }
+ GrDeferredUploadToken operator++(int) {
+ auto old = fSequenceNumber;
+ ++fSequenceNumber;
+ return GrDeferredUploadToken(old);
+ }
+
+ GrDeferredUploadToken next() const { return GrDeferredUploadToken(fSequenceNumber + 1); }
+
+ /** Is this token in the [start, end] inclusive interval? */
+ bool inInterval(const GrDeferredUploadToken& start, const GrDeferredUploadToken& end) {
+ return *this >= start && *this <= end;
}
private:
- GrDeferredUploadToken();
+ GrDeferredUploadToken() = delete;
explicit GrDeferredUploadToken(uint64_t sequenceNumber) : fSequenceNumber(sequenceNumber) {}
- friend class GrOpFlushState;
uint64_t fSequenceNumber;
};
@@ -53,4 +96,29 @@
*/
using GrDeferredTextureUploadFn = std::function<void(GrDeferredTextureUploadWritePixelsFn&)>;
+/**
+ * An interface for scheduling deferred uploads. It provides sequence tokens and accepts asap and
+ * deferred inline uploads.
+ */
+class GrDeferredUploadTarget {
+public:
+ virtual ~GrDeferredUploadTarget() {}
+
+ /** Returns the token of the draw that this upload will occur before. */
+ virtual GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) = 0;
+
+ /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
+ are done first during a flush, this will be the first token since the most recent
+ flush. */
+ virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) = 0;
+
+ /** Gets the token one beyond the last token that has been flushed. */
+ virtual GrDeferredUploadToken nextTokenToFlush() const = 0;
+
+ /** Gets the next draw token that will be issued by this target. This can be used by an op
+ to record that the next draw it issues will use a resource (e.g. texture) while preparing
+ that draw. */
+ virtual GrDeferredUploadToken nextDrawToken() const = 0;
+};
+
#endif
diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp
index 1a1452c..8d81285 100644
--- a/src/gpu/GrDrawOpAtlas.cpp
+++ b/src/gpu/GrDrawOpAtlas.cpp
@@ -173,14 +173,14 @@
++fAtlasGeneration;
}
-inline bool GrDrawOpAtlas::updatePlot(GrDrawOp::Target* target, AtlasID* id, Plot* plot) {
+inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* id, Plot* plot) {
int pageIdx = GetPageIndexFromID(plot->id());
this->makeMRU(plot, pageIdx);
// If our most recent upload has already occurred then we have to insert a new
// upload. Otherwise, we already have a scheduled upload that hasn't yet ocurred.
// This new update will piggy back on that previously scheduled update.
- if (target->hasDrawBeenFlushed(plot->lastUploadToken())) {
+ if (plot->lastUploadToken() < target->nextTokenToFlush()) {
// With c+14 we could move sk_sp into lamba to only ref once.
sk_sp<Plot> plotsp(SkRef(plot));
@@ -192,7 +192,7 @@
GrTextureProxy* proxy = fProxies[pageIdx].get();
- GrDeferredUploadToken lastUploadToken = target->addAsapUpload(
+ GrDeferredUploadToken lastUploadToken = target->addASAPUpload(
[plotsp, proxy](GrDeferredTextureUploadWritePixelsFn& writePixels) {
plotsp->uploadToTexture(writePixels, proxy);
});
@@ -210,7 +210,7 @@
// are rare; i.e., we are not continually refreshing the frame.
static constexpr auto kRecentlyUsedCount = 256;
-bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDrawOp::Target* target, int width, int height,
+bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int width, int height,
const void* image, SkIPoint16* loc) {
if (width > fPlotWidth || height > fPlotHeight) {
return false;
@@ -242,7 +242,7 @@
for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) {
Plot* plot = fPages[pageIdx].fPlotList.tail();
SkASSERT(plot);
- if ((fNumPages == kMaxPages && target->hasDrawBeenFlushed(plot->lastUseToken())) ||
+ if ((fNumPages == kMaxPages && plot->lastUseToken() < target->nextTokenToFlush()) ||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
this->processEvictionAndResetRects(plot);
SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp());
@@ -302,7 +302,7 @@
SkASSERT(verify);
// Note that this plot will be uploaded inline with the draws whereas the
- // one it displaced most likely was uploaded asap.
+ // one it displaced most likely was uploaded ASAP.
// With c+14 we could move sk_sp into lambda to only ref once.
sk_sp<Plot> plotsp(SkRef(newPlot.get()));
// MDB TODO: this is currently fine since the atlas' proxy is always pre-instantiated.
diff --git a/src/gpu/GrDrawOpAtlas.h b/src/gpu/GrDrawOpAtlas.h
index 694af30..91a88ec 100644
--- a/src/gpu/GrDrawOpAtlas.h
+++ b/src/gpu/GrDrawOpAtlas.h
@@ -29,7 +29,7 @@
* This class manages one or more atlas textures on behalf of GrDrawOps. The draw ops that use the
* atlas perform texture uploads when preparing their draws during flush. The class provides
* facilities for using GrDrawOpUploadToken to detect data hazards. Op's uploads are performed in
- * "asap" mode until it is impossible to add data without overwriting texels read by draws that
+ * "ASAP" mode until it is impossible to add data without overwriting texels read by draws that
* have not yet executed on the gpu. At that point, the atlas will attempt to allocate a new
* atlas texture (or "page") of the same size, up to a maximum number of textures, and upload
* to that texture. If that's not possible, the uploads are performed "inline" between draws. If a
@@ -100,7 +100,7 @@
* 'setUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to
* addToAtlas might cause the previous data to be overwritten before it has been read.
*/
- bool addToAtlas(AtlasID*, GrDrawOp::Target*, int width, int height, const void* image,
+ bool addToAtlas(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image,
SkIPoint16* loc);
GrContext* context() const { return fContext; }
@@ -327,7 +327,7 @@
return (id >> 16) & 0xffffffffffff;
}
- inline bool updatePlot(GrDrawOp::Target*, AtlasID*, Plot*);
+ inline bool updatePlot(GrDeferredUploadTarget*, AtlasID*, Plot*);
inline void makeMRU(Plot* plot, int pageIdx) {
if (fPages[pageIdx].fPlotList.head() == plot) {
diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp
index 1608519..f2a45a7 100644
--- a/src/gpu/GrOpFlushState.cpp
+++ b/src/gpu/GrOpFlushState.cpp
@@ -30,30 +30,6 @@
return fCommandBuffer->asRTCommandBuffer();
}
-void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount,
- const GrBuffer** buffer, int* startVertex) {
- return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
-}
-
-uint16_t* GrOpFlushState::makeIndexSpace(int indexCount,
- const GrBuffer** buffer, int* startIndex) {
- return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
-}
-
-void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
- int fallbackVertexCount, const GrBuffer** buffer,
- int* startVertex, int* actualVertexCount) {
- return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
- startVertex, actualVertexCount);
-}
-
-uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
- const GrBuffer** buffer, int* startIndex,
- int* actualIndexCount) {
- return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
- minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
-}
-
void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) {
GrDeferredTextureUploadWritePixelsFn wp = [this](GrTextureProxy* proxy, int left, int top,
int width, int height, GrPixelConfig config,
@@ -86,3 +62,85 @@
};
upload(wp);
}
+
+GrDeferredUploadToken GrOpFlushState::addInlineUpload(GrDeferredTextureUploadFn&& upload) {
+ SkASSERT(fOpArgs);
+ SkASSERT(fOpArgs->fOp);
+ // Here we're dangerously relying on only GrDrawOps calling this method. This gets fixed by
+ // storing inline uploads on GrOpFlushState and removing GrDrawOp::FlushStateAccess.
+ auto op = static_cast<GrDrawOp*>(fOpArgs->fOp);
+ auto token = this->nextDrawToken();
+ GrDrawOp::FlushStateAccess(op).addInlineUpload(std::move(upload), token);
+ return token;
+}
+
+GrDeferredUploadToken GrOpFlushState::addASAPUpload(GrDeferredTextureUploadFn&& upload) {
+ fASAPUploads.emplace_back(std::move(upload));
+ return this->nextTokenToFlush();
+}
+
+void GrOpFlushState::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
+ const GrMesh& mesh) {
+ SkASSERT(fOpArgs);
+ SkASSERT(fOpArgs->fOp);
+ // Here we're dangerously relying on only GrMeshDrawOps calling this method. This gets fixed by
+ // storing draw data on GrOpFlushState and removing GrMeshDrawOp::FlushStateAccess.
+ auto op = static_cast<GrMeshDrawOp*>(fOpArgs->fOp);
+ GrMeshDrawOp::FlushStateAccess fsa(op);
+
+ fsa.addMesh(mesh);
+ GrMeshDrawOp::FlushStateAccess::QueuedDraw* lastDraw = fsa.lastDraw();
+ if (lastDraw) {
+ // If the last draw shares a geometry processor and pipeline and there are no intervening
+ // uploads, add this mesh to it.
+ if (lastDraw->fGeometryProcessor == gp && lastDraw->fPipeline == pipeline &&
+ (fsa.lastUploadToken() != this->nextDrawToken())) {
+ ++lastDraw->fMeshCnt;
+ return;
+ }
+ }
+ GrMeshDrawOp::FlushStateAccess::QueuedDraw* draw = fsa.addDraw();
+ GrDeferredUploadToken token = this->issueDrawToken();
+
+ draw->fGeometryProcessor.reset(gp);
+ draw->fPipeline = pipeline;
+ draw->fMeshCnt = 1;
+ if (!lastDraw) {
+ fsa.setBaseDrawToken(token);
+ }
+}
+
+void* GrOpFlushState::makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer** buffer,
+ int* startVertex) {
+ return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex);
+}
+
+uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
+ return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex));
+}
+
+void* GrOpFlushState::makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
+ int fallbackVertexCount, const GrBuffer** buffer,
+ int* startVertex, int* actualVertexCount) {
+ return fVertexPool.makeSpaceAtLeast(vertexSize, minVertexCount, fallbackVertexCount, buffer,
+ startVertex, actualVertexCount);
+}
+
+uint16_t* GrOpFlushState::makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
+ const GrBuffer** buffer, int* startIndex,
+ int* actualIndexCount) {
+ return reinterpret_cast<uint16_t*>(fIndexPool.makeSpaceAtLeast(
+ minIndexCount, fallbackIndexCount, buffer, startIndex, actualIndexCount));
+}
+
+void GrOpFlushState::putBackIndices(int indexCount) {
+ fIndexPool.putBack(indexCount * sizeof(uint16_t));
+}
+
+void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) {
+ fVertexPool.putBack(vertices * vertexStride);
+}
+
+GrAppliedClip GrOpFlushState::detachAppliedClip() {
+ return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
+}
diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h
index 22d0e81..bc39866 100644
--- a/src/gpu/GrOpFlushState.h
+++ b/src/gpu/GrOpFlushState.h
@@ -10,6 +10,7 @@
#include "GrAppliedClip.h"
#include "GrBufferAllocPool.h"
+#include "GrDeferredUpload.h"
#include "SkArenaAlloc.h"
#include "ops/GrMeshDrawOp.h"
@@ -18,74 +19,76 @@
class GrGpuRTCommandBuffer;
class GrResourceProvider;
+// TODO: Store uploads on GrOpFlushState rather than GrDrawOp and remove this.
+class GrDrawOp::FlushStateAccess {
+private:
+ friend class GrOpFlushState;
+
+ explicit FlushStateAccess(GrDrawOp* op) : fOp(op) {}
+
+ void addInlineUpload(GrDeferredTextureUploadFn&& upload, GrDeferredUploadToken token) {
+ fOp->fInlineUploads.emplace_back(std::move(upload), token);
+ }
+
+ GrDrawOp* fOp;
+};
+
+// TODO: Store draw related data on GrOpFlushState rather than GrMeshDrawOp and remove this.
+class GrMeshDrawOp::FlushStateAccess {
+private:
+ friend class GrOpFlushState;
+ using QueuedDraw = GrMeshDrawOp::QueuedDraw;
+
+ explicit FlushStateAccess(GrMeshDrawOp* op) : fOp(op) {}
+
+ void addMesh(const GrMesh& mesh) { fOp->fMeshes.push_back(mesh); }
+
+ QueuedDraw* lastDraw() {
+ return fOp->fQueuedDraws.empty() ? nullptr : &fOp->fQueuedDraws.back();
+ }
+
+ QueuedDraw* addDraw() { return &fOp->fQueuedDraws.push_back(); }
+
+ GrDeferredUploadToken lastUploadToken() const {
+ if (fOp->fInlineUploads.empty()) {
+ return GrDeferredUploadToken::AlreadyFlushedToken();
+ }
+ return fOp->fInlineUploads.back().fUploadBeforeToken;
+ }
+
+ void setBaseDrawToken(GrDeferredUploadToken token) { fOp->fBaseDrawToken = token; }
+
+ GrMeshDrawOp* fOp;
+};
+
/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
-class GrOpFlushState {
+class GrOpFlushState final : public GrDeferredUploadTarget, public GrMeshDrawOp::Target {
public:
GrOpFlushState(GrGpu*, GrResourceProvider*);
- ~GrOpFlushState() { this->reset(); }
-
- /** Inserts an upload to be executed after all ops in the flush prepared their draws but before
- the draws are executed to the backend 3D API. */
- void addASAPUpload(GrDeferredTextureUploadFn&& upload) {
- fAsapUploads.emplace_back(std::move(upload));
- }
-
- const GrCaps& caps() const;
- GrResourceProvider* resourceProvider() const { return fResourceProvider; }
-
- /** Has the token been flushed to the backend 3D API. */
- bool hasDrawBeenFlushed(GrDeferredUploadToken token) const {
- return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
- }
+ ~GrOpFlushState() final { this->reset(); }
/** Issue a token to an operation that is being enqueued. */
- GrDeferredUploadToken issueDrawToken() {
- return GrDeferredUploadToken(++fLastIssuedToken.fSequenceNumber);
- }
+ GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; }
/** Call every time a draw that was issued a token is flushed */
- void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
-
- /** Gets the next draw token that will be issued. */
- GrDeferredUploadToken nextDrawToken() const {
- return GrDeferredUploadToken(fLastIssuedToken.fSequenceNumber + 1);
- }
-
- /** The last token flushed to all the way to the backend API. */
- GrDeferredUploadToken nextTokenToFlush() const {
- return GrDeferredUploadToken(fLastFlushedToken.fSequenceNumber + 1);
- }
-
- void* makeVertexSpace(size_t vertexSize, int vertexCount,
- const GrBuffer** buffer, int* startVertex);
- uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
-
- void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
- const GrBuffer** buffer, int* startVertex, int* actualVertexCount);
- uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
- const GrBuffer** buffer, int* startIndex,
- int* actualIndexCount);
+ void flushToken() { ++fLastFlushedToken; }
/** This is called after each op has a chance to prepare its draws and before the draws are
issued. */
void preIssueDraws() {
fVertexPool.unmap();
fIndexPool.unmap();
- int uploadCount = fAsapUploads.count();
+ int uploadCount = fASAPUploads.count();
for (int i = 0; i < uploadCount; i++) {
- this->doUpload(fAsapUploads[i]);
+ this->doUpload(fASAPUploads[i]);
}
- fAsapUploads.reset();
+ fASAPUploads.reset();
}
void doUpload(GrDeferredTextureUploadFn&);
- void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
-
- void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
-
GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
// Helper function used by Ops that are only called via RenderTargetOpLists
GrGpuRTCommandBuffer* rtCommandBuffer();
@@ -99,184 +102,65 @@
fPipelines.reset();
}
- /** Additional data required on a per-op basis when executing GrDrawOps. */
- struct DrawOpArgs {
+ /** Additional data required on a per-op basis when executing GrOps. */
+ struct OpArgs {
GrRenderTarget* renderTarget() const { return fProxy->priv().peekRenderTarget(); }
+ GrOp* fOp;
// TODO: do we still need the dst proxy here?
GrRenderTargetProxy* fProxy;
GrAppliedClip* fAppliedClip;
GrXferProcessor::DstProxy fDstProxy;
};
- void setDrawOpArgs(DrawOpArgs* opArgs) { fOpArgs = opArgs; }
+ void setOpArgs(OpArgs* opArgs) { fOpArgs = opArgs; }
- const DrawOpArgs& drawOpArgs() const {
+ const OpArgs& drawOpArgs() const {
SkASSERT(fOpArgs);
+ SkASSERT(fOpArgs->fOp);
return *fOpArgs;
}
- GrAppliedClip detachAppliedClip() {
- SkASSERT(fOpArgs);
- return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip();
- }
+ /** Overrides of GrDeferredUploadTarget. */
- template <typename... Args>
- GrPipeline* allocPipeline(Args&&... args) {
- return fPipelines.make<GrPipeline>(std::forward<Args>(args)...);
- }
+ GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final;
+ GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&&) final;
+ GrDeferredUploadToken nextDrawToken() const final { return fLastIssuedToken.next(); }
+ GrDeferredUploadToken nextTokenToFlush() const override { return fLastFlushedToken.next(); }
+
+ /** Overrides of GrMeshDrawOp::Target. */
+
+ void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) final;
+ void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
+ int* startVertex) final;
+ uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) final;
+ void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
+ const GrBuffer**, int* startVertex, int* actualVertexCount) final;
+ uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount, const GrBuffer**,
+ int* startIndex, int* actualIndexCount) final;
+ void putBackIndices(int indexCount) final;
+ void putBackVertices(int vertices, size_t vertexStride) final;
+ GrRenderTargetProxy* proxy() const final { return fOpArgs->fProxy; }
+ GrAppliedClip detachAppliedClip() final;
+ const GrXferProcessor::DstProxy& dstProxy() const final { return fOpArgs->fDstProxy; }
+ GrDeferredUploadTarget* deferredUploadTarget() final { return this; }
+ const GrCaps& caps() const final;
+ GrResourceProvider* resourceProvider() const final { return fResourceProvider; }
private:
+ /** GrMeshDrawOp::Target override. */
+ SkArenaAlloc* pipelineArena() override { return &fPipelines; }
+
GrGpu* fGpu;
GrResourceProvider* fResourceProvider;
GrGpuCommandBuffer* fCommandBuffer;
GrVertexBufferAllocPool fVertexPool;
GrIndexBufferAllocPool fIndexPool;
- SkSTArray<4, GrDeferredTextureUploadFn> fAsapUploads;
+ SkSTArray<4, GrDeferredTextureUploadFn> fASAPUploads;
GrDeferredUploadToken fLastIssuedToken;
GrDeferredUploadToken fLastFlushedToken;
- DrawOpArgs* fOpArgs;
+ OpArgs* fOpArgs;
SkArenaAlloc fPipelines{sizeof(GrPipeline) * 100};
};
-/**
- * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the
- * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
- * that there are no draws that have yet to be flushed that rely on the old texture contents. In
- * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
- * new (wrong) texture data. In that case they should schedule an inline upload.
- *
- * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
- * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
- * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
- * token. The target provides a facility for testing whether the draw corresponding to the token
- * has been flushed. If it has not been flushed then the op must perform an inline upload instead.
- * When scheduling an inline upload the op provides the token of the draw that the upload must occur
- * before. The upload will then occur between the draw that requires the new data but after the
- * token that requires the old data.
- *
- * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp,
- * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not
- * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the
- * GrDrawOp level.
- */
-
-/**
- * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws
- * that render their op.
- */
-class GrDrawOp::Target {
-public:
- Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {}
-
- /** Returns the token of the draw that this upload will occur before. */
- GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&& upload) {
- fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
- return fOp->fInlineUploads.back().fUploadBeforeToken;
- }
-
- /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
- are done first during a flush, this will be the first token since the most recent
- flush. */
- GrDeferredUploadToken addAsapUpload(GrDeferredTextureUploadFn&& upload) {
- fState->addASAPUpload(std::move(upload));
- return fState->nextTokenToFlush();
- }
-
- bool hasDrawBeenFlushed(GrDeferredUploadToken token) const {
- return fState->hasDrawBeenFlushed(token);
- }
-
- /** Gets the next draw token that will be issued by this target. This can be used by an op
- to record that the next draw it issues will use a resource (e.g. texture) while preparing
- that draw. */
- GrDeferredUploadToken nextDrawToken() const { return fState->nextDrawToken(); }
-
- const GrCaps& caps() const { return fState->caps(); }
-
- GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
-
-protected:
- GrDrawOp* op() { return fOp; }
- GrOpFlushState* state() { return fState; }
- const GrOpFlushState* state() const { return fState; }
-
-private:
- GrOpFlushState* fState;
- GrDrawOp* fOp;
-};
-
-/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex
- draws. */
-class GrMeshDrawOp::Target : public GrDrawOp::Target {
-public:
- Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {}
-
- void draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline, const GrMesh& mesh);
-
- void* makeVertexSpace(size_t vertexSize, int vertexCount,
- const GrBuffer** buffer, int* startVertex) {
- return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
- }
-
- uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
- return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
- }
-
- void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount, int fallbackVertexCount,
- const GrBuffer** buffer, int* startVertex,
- int* actualVertexCount) {
- return this->state()->makeVertexSpaceAtLeast(vertexSize, minVertexCount,
- fallbackVertexCount, buffer, startVertex,
- actualVertexCount);
- }
-
- uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
- const GrBuffer** buffer, int* startIndex,
- int* actualIndexCount) {
- return this->state()->makeIndexSpaceAtLeast(minIndexCount, fallbackIndexCount, buffer,
- startIndex, actualIndexCount);
- }
-
- /** Helpers for ops which over-allocate and then return data to the pool. */
- void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
- void putBackVertices(int vertices, size_t vertexStride) {
- this->state()->putBackVertexSpace(vertices * vertexStride);
- }
-
- GrRenderTargetProxy* proxy() const { return this->state()->drawOpArgs().fProxy; }
-
- const GrAppliedClip* clip() const { return this->state()->drawOpArgs().fAppliedClip; }
-
- GrAppliedClip detachAppliedClip() { return this->state()->detachAppliedClip(); }
-
- const GrXferProcessor::DstProxy& dstProxy() const {
- return this->state()->drawOpArgs().fDstProxy;
- }
-
- template <typename... Args>
- GrPipeline* allocPipeline(Args&&... args) {
- return this->state()->allocPipeline(std::forward<Args>(args)...);
- }
-
- /**
- * Helper that makes a pipeline targeting the op's render target that incorporates the op's
- * GrAppliedClip.
- * */
- GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet,
- GrAppliedClip&& clip) {
- GrPipeline::InitArgs pipelineArgs;
- pipelineArgs.fFlags = pipelineFlags;
- pipelineArgs.fProxy = this->proxy();
- pipelineArgs.fDstProxy = this->dstProxy();
- pipelineArgs.fCaps = &this->caps();
- pipelineArgs.fResourceProvider = this->resourceProvider();
- return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip));
- }
-
-private:
- GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
- typedef GrDrawOp::Target INHERITED;
-};
-
#endif
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 33240ea..af870ca 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -75,15 +75,16 @@
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
TRACE_EVENT0("skia", fRecordedOps[i].fOp->name());
#endif
- GrOpFlushState::DrawOpArgs opArgs = {
+ GrOpFlushState::OpArgs opArgs = {
+ fRecordedOps[i].fOp.get(),
fTarget.get()->asRenderTargetProxy(),
fRecordedOps[i].fAppliedClip,
fRecordedOps[i].fDstProxy
};
- flushState->setDrawOpArgs(&opArgs);
+ flushState->setOpArgs(&opArgs);
fRecordedOps[i].fOp->prepare(flushState);
- flushState->setDrawOpArgs(nullptr);
+ flushState->setOpArgs(nullptr);
}
}
@@ -163,15 +164,16 @@
TRACE_EVENT0("skia", fRecordedOps[i].fOp->name());
#endif
- GrOpFlushState::DrawOpArgs opArgs {
+ GrOpFlushState::OpArgs opArgs {
+ fRecordedOps[i].fOp.get(),
fTarget.get()->asRenderTargetProxy(),
fRecordedOps[i].fAppliedClip,
fRecordedOps[i].fDstProxy
};
- flushState->setDrawOpArgs(&opArgs);
+ flushState->setOpArgs(&opArgs);
fRecordedOps[i].fOp->execute(flushState);
- flushState->setDrawOpArgs(nullptr);
+ flushState->setOpArgs(nullptr);
}
finish_command_buffer(commandBuffer.get());
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 852258f..cf00309 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -52,8 +52,15 @@
// Loop over the ops that haven't yet generated their geometry
for (int i = 0; i < fRecordedOps.count(); ++i) {
if (fRecordedOps[i]) {
- // We do not call flushState->setDrawOpArgs as this op list does not support GrDrawOps.
+ GrOpFlushState::OpArgs opArgs = {
+ fRecordedOps[i].get(),
+ nullptr,
+ nullptr,
+ GrXferProcessor::DstProxy()
+ };
+ flushState->setOpArgs(&opArgs);
fRecordedOps[i]->prepare(flushState);
+ flushState->setOpArgs(nullptr);
}
}
}
@@ -69,8 +76,15 @@
flushState->setCommandBuffer(commandBuffer.get());
for (int i = 0; i < fRecordedOps.count(); ++i) {
- // We do not call flushState->setDrawOpArgs as this op list does not support GrDrawOps.
+ GrOpFlushState::OpArgs opArgs = {
+ fRecordedOps[i].get(),
+ nullptr,
+ nullptr,
+ GrXferProcessor::DstProxy()
+ };
+ flushState->setOpArgs(&opArgs);
fRecordedOps[i]->execute(flushState);
+ flushState->setOpArgs(nullptr);
}
commandBuffer->submit();
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 591afb2..f0a9300 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -235,9 +235,9 @@
size_t byteCount;
void* blobVertices;
int subRunGlyphCount;
- blob->regenInOp(target, fFontCache, &helper, args.fRun, args.fSubRun, &glyphCache,
- vertexStride, args.fViewMatrix, args.fX, args.fY, args.fColor,
- &blobVertices, &byteCount, &subRunGlyphCount);
+ blob->regenInOp(target->deferredUploadTarget(), fFontCache, &helper, args.fRun,
+ args.fSubRun, &glyphCache, vertexStride, args.fViewMatrix, args.fX, args.fY,
+ args.fColor, &blobVertices, &byteCount, &subRunGlyphCount);
// now copy all vertices
if (args.fClipRect.isEmpty()) {
diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h
index 88edfe7..f4a7102 100644
--- a/src/gpu/ops/GrDrawOp.h
+++ b/src/gpu/ops/GrDrawOp.h
@@ -16,11 +16,12 @@
class GrAppliedClip;
/**
- * Base class for GrOps that draw. These ops have a GrPipeline installed by GrOpList.
+ * Base class for GrOps that draw. These ops can draw into an op list's GrRenderTarget.
*/
class GrDrawOp : public GrOp {
public:
- class Target;
+ /** Provides GrOpFlushState with privileged access to GrDrawOp. */
+ class FlushStateAccess;
GrDrawOp(uint32_t classID) : INHERITED(classID) {}
diff --git a/src/gpu/ops/GrMeshDrawOp.cpp b/src/gpu/ops/GrMeshDrawOp.cpp
index 2e12953..a00af15 100644
--- a/src/gpu/ops/GrMeshDrawOp.cpp
+++ b/src/gpu/ops/GrMeshDrawOp.cpp
@@ -13,10 +13,7 @@
GrMeshDrawOp::GrMeshDrawOp(uint32_t classID)
: INHERITED(classID), fBaseDrawToken(GrDeferredUploadToken::AlreadyFlushedToken()) {}
-void GrMeshDrawOp::onPrepare(GrOpFlushState* state) {
- Target target(state, this);
- this->onPrepareDraws(&target);
-}
+void GrMeshDrawOp::onPrepare(GrOpFlushState* state) { this->onPrepareDraws(state); }
void* GrMeshDrawOp::PatternHelper::init(Target* target, size_t vertexStride,
const GrBuffer* indexBuffer, int verticesPerRepetition,
@@ -85,30 +82,3 @@
fQueuedDraws.reset();
fInlineUploads.reset();
}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void GrMeshDrawOp::Target::draw(const GrGeometryProcessor* gp, const GrPipeline* pipeline,
- const GrMesh& mesh) {
- GrMeshDrawOp* op = this->meshDrawOp();
- op->fMeshes.push_back(mesh);
- if (!op->fQueuedDraws.empty()) {
- // If the last draw shares a geometry processor and pipeline and there are no intervening
- // uploads, add this mesh to it.
- GrMeshDrawOp::QueuedDraw& lastDraw = op->fQueuedDraws.back();
- if (lastDraw.fGeometryProcessor == gp && lastDraw.fPipeline == pipeline &&
- (op->fInlineUploads.empty() ||
- op->fInlineUploads.back().fUploadBeforeToken != this->nextDrawToken())) {
- ++lastDraw.fMeshCnt;
- return;
- }
- }
- GrMeshDrawOp::QueuedDraw& draw = op->fQueuedDraws.push_back();
- GrDeferredUploadToken token = this->state()->issueDrawToken();
- draw.fGeometryProcessor.reset(gp);
- draw.fPipeline = pipeline;
- draw.fMeshCnt = 1;
- if (op->fQueuedDraws.count() == 1) {
- op->fBaseDrawToken = token;
- }
-}
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index 64faaa8..232adb2 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -23,7 +23,10 @@
*/
class GrMeshDrawOp : public GrDrawOp {
public:
+ /** Abstract interface that represents a destination for a GrMeshDrawOp. */
class Target;
+ /** Provides GrOpFlushState with privileged access to GrMeshDrawOp. */
+ class FlushStateAccess;
protected:
GrMeshDrawOp(uint32_t classID);
@@ -90,4 +93,93 @@
typedef GrDrawOp INHERITED;
};
+class GrMeshDrawOp::Target {
+public:
+ virtual ~Target() {}
+
+ /** Adds a draw of a mesh. */
+ virtual void draw(const GrGeometryProcessor*, const GrPipeline*, const GrMesh&) = 0;
+
+ /**
+ * Makes space for vertex data. The returned pointer is the location where vertex data
+ * should be written. On return the buffer that will hold the data as well as an offset into
+ * the buffer (in 'vertexSize' units) where the data will be placed.
+ */
+ virtual void* makeVertexSpace(size_t vertexSize, int vertexCount, const GrBuffer**,
+ int* startVertex) = 0;
+
+ /**
+ * Makes space for index data. The returned pointer is the location where index data
+ * should be written. On return the buffer that will hold the data as well as an offset into
+ * the buffer (in uint16_t units) where the data will be placed.
+ */
+ virtual uint16_t* makeIndexSpace(int indexCount, const GrBuffer**, int* startIndex) = 0;
+
+ /**
+ * This is similar to makeVertexSpace. It allows the caller to use up to 'actualVertexCount'
+ * vertices in the returned pointer, which may exceed 'minVertexCount'.
+ * 'fallbackVertexCount' is the maximum number of vertices that should be allocated if a new
+ * buffer is allocated on behalf of this request.
+ */
+ virtual void* makeVertexSpaceAtLeast(size_t vertexSize, int minVertexCount,
+ int fallbackVertexCount, const GrBuffer**,
+ int* startVertex, int* actualVertexCount) = 0;
+
+ /**
+ * This is similar to makeIndexSpace. It allows the caller to use up to 'actualIndexCount'
+ * indices in the returned pointer, which may exceed 'minIndexCount'.
+ * 'fallbackIndexCount' is the maximum number of indices that should be allocated if a new
+ * buffer is allocated on behalf of this request.
+ */
+ virtual uint16_t* makeIndexSpaceAtLeast(int minIndexCount, int fallbackIndexCount,
+ const GrBuffer**, int* startIndex,
+ int* actualIndexCount) = 0;
+
+ /** Helpers for ops which over-allocate and then return excess data to the pool. */
+ virtual void putBackIndices(int indices) = 0;
+ virtual void putBackVertices(int vertices, size_t vertexStride) = 0;
+
+ /**
+ * Allocate space for a pipeline. The target ensures this pipeline lifetime is at least
+ * as long as any deferred execution of draws added via draw().
+ * @tparam Args
+ * @param args
+ * @return
+ */
+ template <typename... Args>
+ GrPipeline* allocPipeline(Args&&... args) {
+ return this->pipelineArena()->make<GrPipeline>(std::forward<Args>(args)...);
+ }
+
+ /**
+ * Helper that makes a pipeline targeting the op's render target that incorporates the op's
+ * GrAppliedClip.
+ * */
+ GrPipeline* makePipeline(uint32_t pipelineFlags, GrProcessorSet&& processorSet,
+ GrAppliedClip&& clip) {
+ GrPipeline::InitArgs pipelineArgs;
+ pipelineArgs.fFlags = pipelineFlags;
+ pipelineArgs.fProxy = this->proxy();
+ pipelineArgs.fDstProxy = this->dstProxy();
+ pipelineArgs.fCaps = &this->caps();
+ pipelineArgs.fResourceProvider = this->resourceProvider();
+ return this->allocPipeline(pipelineArgs, std::move(processorSet), std::move(clip));
+ }
+
+ virtual GrRenderTargetProxy* proxy() const = 0;
+
+ virtual GrAppliedClip detachAppliedClip() = 0;
+
+ virtual const GrXferProcessor::DstProxy& dstProxy() const = 0;
+
+ virtual GrResourceProvider* resourceProvider() const = 0;
+
+ virtual const GrCaps& caps() const = 0;
+
+ virtual GrDeferredUploadTarget* deferredUploadTarget() = 0;
+
+private:
+ virtual SkArenaAlloc* pipelineArena() = 0;
+};
+
#endif
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 0aaab9c..d308498 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -383,10 +383,9 @@
}
}
- atlas->setLastUseToken(shapeData->fID, target->nextDrawToken());
+ atlas->setLastUseToken(shapeData->fID, target->deferredUploadTarget()->nextDrawToken());
- this->writePathVertices(target,
- atlas,
+ this->writePathVertices(atlas,
offset,
args.fColor,
vertexStride,
@@ -489,9 +488,11 @@
// add to atlas
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
- if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) {
+ auto uploadTarget = target->deferredUploadTarget();
+ if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) {
this->flush(target, flushInfo);
- if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) {
+ if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(),
+ &atlasLocation)) {
return false;
}
}
@@ -589,10 +590,11 @@
// add to atlas
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
- if (!atlas->addToAtlas(&id, target, dst.width(), dst.height(), dst.addr(),
+ auto uploadTarget = target->deferredUploadTarget();
+ if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
&atlasLocation)) {
this->flush(target, flushInfo);
- if (!atlas->addToAtlas(&id, target, dst.width(), dst.height(), dst.addr(),
+ if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
&atlasLocation)) {
return false;
}
@@ -622,8 +624,7 @@
return true;
}
- void writePathVertices(GrDrawOp::Target* target,
- GrDrawOpAtlas* atlas,
+ void writePathVertices(GrDrawOpAtlas* atlas,
intptr_t offset,
GrColor color,
size_t vertexStride,
diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp
index 1cf704a..25575be 100644
--- a/src/gpu/text/GrAtlasGlyphCache.cpp
+++ b/src/gpu/text/GrAtlasGlyphCache.cpp
@@ -443,7 +443,7 @@
}
}
-bool GrAtlasTextStrike::addGlyphToAtlas(GrDrawOp::Target* target,
+bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
GrGlyph* glyph,
SkGlyphCache* cache,
GrMaskFormat expectedMaskFormat) {
diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h
index 717c48e..20bc32a 100644
--- a/src/gpu/text/GrAtlasGlyphCache.h
+++ b/src/gpu/text/GrAtlasGlyphCache.h
@@ -65,7 +65,7 @@
// happen.
// TODO we can handle some of these cases if we really want to, but the long term solution is to
// get the actual glyph image itself when we get the glyph metrics.
- bool addGlyphToAtlas(GrDrawOp::Target*, GrGlyph*, SkGlyphCache*,
+ bool addGlyphToAtlas(GrDeferredUploadTarget*, GrGlyph*, SkGlyphCache*,
GrMaskFormat expectedMaskFormat);
// testing
@@ -168,9 +168,9 @@
}
// add to texture atlas that matches this format
- bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id, GrDrawOp::Target* target,
- GrMaskFormat format, int width, int height, const void* image,
- SkIPoint16* loc) {
+ bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
+ GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height,
+ const void* image, SkIPoint16* loc) {
fPreserveStrike = strike;
return this->getAtlas(format)->addToAtlas(id, target, width, height, image, loc);
}
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 0a90e20..79f2bf3 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -255,10 +255,10 @@
* SkAutoGlyphCache is passed to multiple calls of regenInOp then it can save the cost of
* multiple detach/attach operations of SkGlyphCache.
*/
- void regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache,
- GrBlobRegenHelper* helper, int run, int subRun, SkAutoGlyphCache*,
- size_t vertexStride, const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
- GrColor color, void** vertices, size_t* byteCount, int* glyphCount);
+ void regenInOp(GrDeferredUploadTarget*, GrAtlasGlyphCache* fontCache, GrBlobRegenHelper* helper,
+ int run, int subRun, SkAutoGlyphCache*, size_t vertexStride,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
+ void** vertices, size_t* byteCount, int* glyphCount);
const Key& key() const { return fKey; }
@@ -493,7 +493,7 @@
}; // Run
template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
- void regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache, GrBlobRegenHelper* helper,
+ void regenInOp(GrDeferredUploadTarget*, GrAtlasGlyphCache* fontCache, GrBlobRegenHelper* helper,
Run* run, Run::SubRunInfo* info, SkAutoGlyphCache*, int glyphCount,
size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const;
diff --git a/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp b/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
index c551a2a..e081158 100644
--- a/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
+++ b/src/gpu/text/GrAtlasTextBlob_regenInOp.cpp
@@ -136,7 +136,7 @@
}
template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
-void GrAtlasTextBlob::regenInOp(GrDrawOp::Target* target, GrAtlasGlyphCache* fontCache,
+void GrAtlasTextBlob::regenInOp(GrDeferredUploadTarget* target, GrAtlasGlyphCache* fontCache,
GrBlobRegenHelper* helper, Run* run, Run::SubRunInfo* info,
SkAutoGlyphCache* lazyCache, int glyphCount, size_t vertexStride,
GrColor color, SkScalar transX, SkScalar transY) const {
@@ -236,12 +236,10 @@
#define REGEN_ARGS target, fontCache, helper, &run, &info, lazyCache, \
*glyphCount, vertexStride, color, transX, transY
-void GrAtlasTextBlob::regenInOp(GrDrawOp::Target* target,
- GrAtlasGlyphCache* fontCache,
- GrBlobRegenHelper* helper,
- int runIndex, int subRunIndex, SkAutoGlyphCache* lazyCache,
- size_t vertexStride, const SkMatrix& viewMatrix,
- SkScalar x, SkScalar y, GrColor color,
+void GrAtlasTextBlob::regenInOp(GrDeferredUploadTarget* target, GrAtlasGlyphCache* fontCache,
+ GrBlobRegenHelper* helper, int runIndex, int subRunIndex,
+ SkAutoGlyphCache* lazyCache, size_t vertexStride,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
void** vertices, size_t* byteCount, int* glyphCount) {
Run& run = fRuns[runIndex];
Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex];