2015-08-17 19:55:38 +00:00
|
|
|
/*
|
|
|
|
* 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:
|
2015-11-10 18:19:50 +00:00
|
|
|
GrBatchFlushState(GrGpu*, GrResourceProvider*);
|
2015-08-17 19:55:38 +00:00
|
|
|
|
2015-10-02 18:27:14 +00:00
|
|
|
~GrBatchFlushState() { this->reset(); }
|
2015-08-17 19:55:38 +00:00
|
|
|
|
|
|
|
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,
|
2016-03-25 19:15:03 +00:00
|
|
|
const GrBuffer** buffer, int* startVertex);
|
|
|
|
uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex);
|
2015-08-17 19:55:38 +00:00
|
|
|
|
|
|
|
/** 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; }
|
|
|
|
|
2015-10-02 18:27:14 +00:00
|
|
|
void reset() {
|
|
|
|
fVertexPool.reset();
|
|
|
|
fIndexPool.reset();
|
|
|
|
}
|
|
|
|
|
2015-08-17 19:55:38 +00:00
|
|
|
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) {}
|
|
|
|
|
2016-03-17 18:35:45 +00:00
|
|
|
void initDraw(const GrPrimitiveProcessor* primProc) {
|
2015-08-17 19:55:38 +00:00
|
|
|
GrVertexBatch::DrawArray* draws = this->vertexBatch()->fDrawArrays.addToTail();
|
|
|
|
draws->fPrimitiveProcessor.reset(primProc);
|
|
|
|
this->state()->advanceToken();
|
|
|
|
}
|
|
|
|
|
2016-03-17 18:35:45 +00:00
|
|
|
void draw(const GrMesh& mesh) {
|
|
|
|
this->vertexBatch()->fDrawArrays.tail()->fDraws.push_back(mesh);
|
2015-08-17 19:55:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void* makeVertexSpace(size_t vertexSize, int vertexCount,
|
2016-03-25 19:15:03 +00:00
|
|
|
const GrBuffer** buffer, int* startVertex) {
|
2015-08-17 19:55:38 +00:00
|
|
|
return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
|
|
|
|
}
|
|
|
|
|
2016-03-25 19:15:03 +00:00
|
|
|
uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) {
|
2015-08-17 19:55:38 +00:00
|
|
|
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
|