8b1bff2967
Consolidates all the different buffer implementations into a single GrBuffer class. This will allow us to add new buffer types, use DSA in OpenGL, track buffer bindings by unique ID, cache buffers without respect to the type of data they have been used for previously, etc. This change is strictly a refactor; it introduces no change in functionality. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1825393002 Review URL: https://codereview.chromium.org/1825393002
195 lines
6.9 KiB
C++
195 lines
6.9 KiB
C++
/*
|
|
* Copyright 2015 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef GrBatchBuffer_DEFINED
|
|
#define GrBatchBuffer_DEFINED
|
|
|
|
#include "GrBufferAllocPool.h"
|
|
#include "batches/GrVertexBatch.h"
|
|
|
|
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:
|
|
GrBatchFlushState(GrGpu*, GrResourceProvider*);
|
|
|
|
~GrBatchFlushState() { this->reset(); }
|
|
|
|
void advanceToken() { ++fCurrentToken; }
|
|
|
|
void advanceLastFlushedToken() { ++fLastFlushedToken; }
|
|
|
|
/** Inserts an upload to be executred 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));
|
|
}
|
|
|
|
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; }
|
|
|
|
/** The current token advances once for every contiguous set of uninterrupted draws prepared
|
|
by a batch. */
|
|
GrBatchToken currentToken() const { return fCurrentToken; }
|
|
|
|
/** The last token flushed to all the way to the backend API. */
|
|
GrBatchToken lastFlushedToken() const { return fLastFlushedToken; }
|
|
|
|
/** 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; }
|
|
|
|
void* makeVertexSpace(size_t vertexSize, int vertexCount,
|
|
const GrBuffer** buffer, int* startVertex);
|
|
uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
|
|
|
|
/** This is called after each batch has a chance to prepare its draws and before the draws
|
|
are issued. */
|
|
void preIssueDraws() {
|
|
fVertexPool.unmap();
|
|
fIndexPool.unmap();
|
|
int uploadCount = fAsapUploads.count();
|
|
for (int i = 0; i < uploadCount; i++) {
|
|
fAsapUploads[i]->upload(&fUploader);
|
|
}
|
|
fAsapUploads.reset();
|
|
}
|
|
|
|
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() {
|
|
fVertexPool.reset();
|
|
fIndexPool.reset();
|
|
}
|
|
|
|
private:
|
|
GrGpu* fGpu;
|
|
GrBatchUploader::TextureUploader fUploader;
|
|
|
|
GrResourceProvider* fResourceProvider;
|
|
|
|
GrVertexBufferAllocPool fVertexPool;
|
|
GrIndexBufferAllocPool fIndexPool;
|
|
|
|
SkTArray<SkAutoTUnref<GrBatchUploader>, true> fAsapUploads;
|
|
|
|
GrBatchToken fCurrentToken;
|
|
|
|
GrBatchToken fLastFlushedToken;
|
|
};
|
|
|
|
/**
|
|
* GrDrawBatch instances use this object to allocate space for their geometry and to issue the draws
|
|
* that render their batch.
|
|
*/
|
|
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));
|
|
}
|
|
}
|
|
|
|
bool hasTokenBeenFlushed(GrBatchToken token) const {
|
|
return fState->hasTokenBeenFlushed(token);
|
|
}
|
|
GrBatchToken currentToken() const { return fState->currentToken(); }
|
|
GrBatchToken asapToken() const { return fState->asapToken(); }
|
|
|
|
const GrCaps& caps() const { return fState->caps(); }
|
|
|
|
GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
|
|
|
|
protected:
|
|
GrDrawBatch* batch() { return fBatch; }
|
|
GrBatchFlushState* state() { return fState; }
|
|
|
|
private:
|
|
GrBatchFlushState* fState;
|
|
GrDrawBatch* fBatch;
|
|
};
|
|
|
|
/** Extension of GrDrawBatch::Target for use by GrVertexBatch. Adds the ability to create vertex
|
|
draws. */
|
|
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* 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);
|
|
}
|
|
|
|
/** Helpers for batches 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);
|
|
}
|
|
|
|
private:
|
|
GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); }
|
|
typedef GrDrawBatch::Target INHERITED;
|
|
};
|
|
|
|
#endif
|