| Index: src/gpu/GrBatchFlushState.h
|
| diff --git a/src/gpu/GrBatchFlushState.h b/src/gpu/GrBatchFlushState.h
|
| index be9d790597671b242b3aba2f5df94f883bbc9575..0b2e2bd239450eb1584a69142b391a8c531cd43f 100644
|
| --- a/src/gpu/GrBatchFlushState.h
|
| +++ b/src/gpu/GrBatchFlushState.h
|
| @@ -13,34 +13,6 @@
|
|
|
| class GrResourceProvider;
|
|
|
| -/** Simple class that performs the upload on behalf of a GrBatchUploader. */
|
| -class GrBatchUploader::TextureUploader {
|
| -public:
|
| - TextureUploader(GrGpu* gpu) : fGpu(gpu) { SkASSERT(gpu); }
|
| -
|
| - /**
|
| - * Updates the pixels in a rectangle of a texture.
|
| - *
|
| - * @param left left edge of the rectangle to write (inclusive)
|
| - * @param top top edge of the rectangle to write (inclusive)
|
| - * @param width width of rectangle to write in pixels.
|
| - * @param height height of rectangle to write in pixels.
|
| - * @param config the pixel config of the source buffer
|
| - * @param buffer memory to read pixels from
|
| - * @param rowBytes number of bytes between consecutive rows. Zero
|
| - * means rows are tightly packed.
|
| - */
|
| - bool writeTexturePixels(GrTexture* texture,
|
| - int left, int top, int width, int height,
|
| - GrPixelConfig config, const void* buffer,
|
| - size_t rowBytes) {
|
| - return fGpu->writePixels(texture, left, top, width, height, config, buffer, rowBytes);
|
| - }
|
| -
|
| -private:
|
| - GrGpu* fGpu;
|
| -};
|
| -
|
| /** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
|
| class GrBatchFlushState {
|
| public:
|
| @@ -48,32 +20,37 @@ public:
|
|
|
| ~GrBatchFlushState() { this->reset(); }
|
|
|
| - void advanceToken() { ++fCurrentToken; }
|
| -
|
| - void advanceLastFlushedToken() { ++fLastFlushedToken; }
|
| -
|
| - /** Inserts an upload to be executred after all batches in the flush prepared their draws
|
| + /** Inserts an upload to be executed after all batches in the flush prepared their draws
|
| but before the draws are executed to the backend 3D API. */
|
| - void addASAPUpload(GrBatchUploader* upload) {
|
| - fAsapUploads.push_back().reset(SkRef(upload));
|
| + void addASAPUpload(GrDrawBatch::DeferredUploadFn&& upload) {
|
| + fAsapUploads.emplace_back(std::move(upload));
|
| }
|
|
|
| const GrCaps& caps() const { return *fGpu->caps(); }
|
| GrResourceProvider* resourceProvider() const { return fResourceProvider; }
|
|
|
| /** Has the token been flushed to the backend 3D API. */
|
| - bool hasTokenBeenFlushed(GrBatchToken token) const { return fLastFlushedToken >= token; }
|
| + bool hasDrawBeenFlushed(GrBatchDrawToken token) const {
|
| + return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
|
| + }
|
| +
|
| + /** Issue a token to an operation that is being enqueued. */
|
| + GrBatchDrawToken issueDrawToken() {
|
| + return GrBatchDrawToken(++fLastIssuedToken.fSequenceNumber);
|
| + }
|
|
|
| - /** The current token advances once for every contiguous set of uninterrupted draws prepared
|
| - by a batch. */
|
| - GrBatchToken currentToken() const { return fCurrentToken; }
|
| + /** Call every time a draw that was issued a token is flushed */
|
| + void flushToken() { ++fLastFlushedToken.fSequenceNumber; }
|
|
|
| - /** The last token flushed to all the way to the backend API. */
|
| - GrBatchToken lastFlushedToken() const { return fLastFlushedToken; }
|
| + /** Gets the next draw token that will be issued. */
|
| + GrBatchDrawToken nextDrawToken() const {
|
| + return GrBatchDrawToken(fLastIssuedToken.fSequenceNumber + 1);
|
| + }
|
|
|
| - /** This is a magic token that can be used to indicate that an upload should occur before
|
| - any draws for any batch in the current flush execute. */
|
| - GrBatchToken asapToken() const { return fLastFlushedToken + 1; }
|
| + /** The last token flushed to all the way to the backend API. */
|
| + GrBatchDrawToken nextTokenToFlush() const {
|
| + return GrBatchDrawToken(fLastFlushedToken.fSequenceNumber + 1);
|
| + }
|
|
|
| void* makeVertexSpace(size_t vertexSize, int vertexCount,
|
| const GrBuffer** buffer, int* startVertex);
|
| @@ -85,18 +62,28 @@ public:
|
| fVertexPool.unmap();
|
| fIndexPool.unmap();
|
| int uploadCount = fAsapUploads.count();
|
| +
|
| for (int i = 0; i < uploadCount; i++) {
|
| - fAsapUploads[i]->upload(&fUploader);
|
| + this->doUpload(fAsapUploads[i]);
|
| }
|
| fAsapUploads.reset();
|
| }
|
|
|
| + void doUpload(GrDrawBatch::DeferredUploadFn& upload) {
|
| + GrDrawBatch::WritePixelsFn wp = [this] (GrSurface* surface,
|
| + int left, int top, int width, int height,
|
| + GrPixelConfig config, const void* buffer,
|
| + size_t rowBytes) -> bool {
|
| + return this->fGpu->writePixels(surface, left, top, width, height, config, buffer,
|
| + rowBytes);
|
| + };
|
| + upload(wp);
|
| + }
|
| +
|
| void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
|
|
|
| void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
|
|
|
| - GrBatchUploader::TextureUploader* uploader() { return &fUploader; }
|
| -
|
| GrGpu* gpu() { return fGpu; }
|
|
|
| void reset() {
|
| @@ -105,22 +92,44 @@ public:
|
| }
|
|
|
| private:
|
| - GrGpu* fGpu;
|
| - GrBatchUploader::TextureUploader fUploader;
|
|
|
| - GrResourceProvider* fResourceProvider;
|
| + GrGpu* fGpu;
|
| +
|
| + GrResourceProvider* fResourceProvider;
|
|
|
| - GrVertexBufferAllocPool fVertexPool;
|
| - GrIndexBufferAllocPool fIndexPool;
|
| + GrVertexBufferAllocPool fVertexPool;
|
| + GrIndexBufferAllocPool fIndexPool;
|
|
|
| - SkTArray<SkAutoTUnref<GrBatchUploader>, true> fAsapUploads;
|
| + SkSTArray<4, GrDrawBatch::DeferredUploadFn> fAsapUploads;
|
|
|
| - GrBatchToken fCurrentToken;
|
| + GrBatchDrawToken fLastIssuedToken;
|
|
|
| - GrBatchToken fLastFlushedToken;
|
| + GrBatchDrawToken fLastFlushedToken;
|
| };
|
|
|
| /**
|
| + * A word about uploads and tokens: Batches 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.
|
| + *
|
| + * Batches, in conjunction with helpers such as GrBatchAtlas, 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 batch must perform an inline upload
|
| + * instead. When scheduling an inline upload the batch 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 GrDrawBatch, GrVertexBatch,
|
| + * GrDrawBatch::Target, and GrVertexBatch::Target. However, the interface at the GrDrawBatch
|
| + * level is not complete and isn't useful. We should push it down to GrVertexBatch until it
|
| + * is required at the GrDrawBatch level.
|
| + */
|
| +
|
| +/**
|
| * GrDrawBatch instances use this object to allocate space for their geometry and to issue the draws
|
| * that render their batch.
|
| */
|
| @@ -128,19 +137,28 @@ class GrDrawBatch::Target {
|
| public:
|
| Target(GrBatchFlushState* state, GrDrawBatch* batch) : fState(state), fBatch(batch) {}
|
|
|
| - void upload(GrBatchUploader* upload) {
|
| - if (this->asapToken() == upload->lastUploadToken()) {
|
| - fState->addASAPUpload(upload);
|
| - } else {
|
| - fBatch->fInlineUploads.push_back().reset(SkRef(upload));
|
| - }
|
| + /** Returns the token of the draw that this upload will occur before. */
|
| + GrBatchDrawToken addInlineUpload(DeferredUploadFn&& upload) {
|
| + fBatch->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
|
| + return fBatch->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. */
|
| + GrBatchDrawToken addAsapUpload(DeferredUploadFn&& upload) {
|
| + fState->addASAPUpload(std::move(upload));
|
| + return fState->nextTokenToFlush();
|
| }
|
|
|
| - bool hasTokenBeenFlushed(GrBatchToken token) const {
|
| - return fState->hasTokenBeenFlushed(token);
|
| + bool hasDrawBeenFlushed(GrBatchDrawToken token) const {
|
| + return fState->hasDrawBeenFlushed(token);
|
| }
|
| - GrBatchToken currentToken() const { return fState->currentToken(); }
|
| - GrBatchToken asapToken() const { return fState->asapToken(); }
|
| +
|
| + /** Gets the next draw token that will be issued by this target. This can be used by a batch
|
| + to record that the next draw it issues will use a resource (e.g. texture) while preparing
|
| + that draw. */
|
| + GrBatchDrawToken nextDrawToken() const { return fState->nextDrawToken(); }
|
|
|
| const GrCaps& caps() const { return fState->caps(); }
|
|
|
| @@ -161,15 +179,7 @@ class GrVertexBatch::Target : public GrDrawBatch::Target {
|
| public:
|
| Target(GrBatchFlushState* state, GrVertexBatch* batch) : INHERITED(state, batch) {}
|
|
|
| - void initDraw(const GrPrimitiveProcessor* primProc) {
|
| - GrVertexBatch::DrawArray* draws = this->vertexBatch()->fDrawArrays.addToTail();
|
| - draws->fPrimitiveProcessor.reset(primProc);
|
| - this->state()->advanceToken();
|
| - }
|
| -
|
| - void draw(const GrMesh& mesh) {
|
| - this->vertexBatch()->fDrawArrays.tail()->fDraws.push_back(mesh);
|
| - }
|
| + void draw(const GrGeometryProcessor* gp, const GrMesh& mesh);
|
|
|
| void* makeVertexSpace(size_t vertexSize, int vertexCount,
|
| const GrBuffer** buffer, int* startVertex) {
|
|
|