diff options
author | robertphillips <robertphillips@google.com> | 2016-03-25 04:55:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-25 04:55:59 -0700 |
commit | f8c3ba40cf4f42b2c2ba1b473c28d7733383223e (patch) | |
tree | 00c671765311aaa35c8a9d6fa0a6b84907c871b9 /src | |
parent | f299e7105435829c47e94f4cf6e408cad675bc77 (diff) |
Revert of Consolidate GPU buffer implementations (patchset #10 id:180001 of https://codereview.chromium.org/1825393002/ )
Reason for revert:
Lots of Android redness
Original issue's description:
> Consolidate GPU buffer implementations
>
> 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
>
> Committed: https://skia.googlesource.com/skia/+/8b1bff29675afd25843439eade634a57f68fe16f
TBR=bsalomon@google.com,egdaniel@google.com,jvanverth@google.com,cdalton@nvidia.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Review URL: https://codereview.chromium.org/1831133004
Diffstat (limited to 'src')
65 files changed, 1400 insertions, 790 deletions
diff --git a/src/gpu/GrBatchAtlas.cpp b/src/gpu/GrBatchAtlas.cpp index 9f3c4dd983..db1b13471f 100644 --- a/src/gpu/GrBatchAtlas.cpp +++ b/src/gpu/GrBatchAtlas.cpp @@ -9,6 +9,7 @@ #include "GrBatchFlushState.h" #include "GrRectanizer.h" #include "GrTracing.h" +#include "GrVertexBuffer.h" //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrBatchFlushState.cpp b/src/gpu/GrBatchFlushState.cpp index f01d88852e..52261a1839 100644 --- a/src/gpu/GrBatchFlushState.cpp +++ b/src/gpu/GrBatchFlushState.cpp @@ -20,11 +20,11 @@ GrBatchFlushState::GrBatchFlushState(GrGpu* gpu, GrResourceProvider* resourcePro , fLastFlushedToken(0) {} void* GrBatchFlushState::makeVertexSpace(size_t vertexSize, int vertexCount, - const GrBuffer** buffer, int* startVertex) { + const GrVertexBuffer** buffer, int* startVertex) { return fVertexPool.makeSpace(vertexSize, vertexCount, buffer, startVertex); } uint16_t* GrBatchFlushState::makeIndexSpace(int indexCount, - const GrBuffer** buffer, int* startIndex) { + const GrIndexBuffer** buffer, int* startIndex) { return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex)); } diff --git a/src/gpu/GrBatchFlushState.h b/src/gpu/GrBatchFlushState.h index be9d790597..1f82453c2e 100644 --- a/src/gpu/GrBatchFlushState.h +++ b/src/gpu/GrBatchFlushState.h @@ -76,8 +76,8 @@ public: 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); + const GrVertexBuffer** buffer, int* startVertex); + uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex); /** This is called after each batch has a chance to prepare its draws and before the draws are issued. */ @@ -172,11 +172,11 @@ public: } void* makeVertexSpace(size_t vertexSize, int vertexCount, - const GrBuffer** buffer, int* startVertex) { + const GrVertexBuffer** buffer, int* startVertex) { return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex); } - uint16_t* makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) { + uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex) { return this->state()->makeIndexSpace(indexCount, buffer, startIndex); } diff --git a/src/gpu/GrBuffer.h b/src/gpu/GrBuffer.h deleted file mode 100644 index 4fadba6aa7..0000000000 --- a/src/gpu/GrBuffer.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrBuffer_DEFINED -#define GrBuffer_DEFINED - -#include "GrGpuResource.h" - -class GrGpu; - -class GrBuffer : public GrGpuResource { -public: - /** - * Computes a scratch key for a buffer with a "dynamic" access pattern. (Buffers with "static" - * and "stream" access patterns are disqualified by nature from being cached and reused.) - */ - static void ComputeScratchKeyForDynamicBuffer(GrBufferType type, size_t size, - GrScratchKey* key) { - static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType(); - GrScratchKey::Builder builder(key, kType, 1 + (sizeof(size_t) + 3) / 4); - // TODO: There's not always reason to cache a buffer by type. In some (all?) APIs it's just - // a chunk of memory we can use/reuse for any type of data. We really only need to - // differentiate between the "read" types (e.g. kGpuToCpu_BufferType) and "draw" types. - builder[0] = type; - builder[1] = (uint32_t)size; - if (sizeof(size_t) > 4) { - builder[2] = (uint32_t)((uint64_t)size >> 32); - } - } - - GrBufferType type() const { return fType; } - - GrAccessPattern accessPattern() const { return fAccessPattern; } - - /** - * Returns true if the buffer is a wrapper around a CPU array. If true it - * indicates that map will always succeed and will be free. - */ - bool isCPUBacked() const { return fCPUBacked; } - - /** - * Maps the buffer to be written by the CPU. - * - * The previous content of the buffer is invalidated. It is an error - * to draw from the buffer while it is mapped. It may fail if the backend - * doesn't support mapping the buffer. If the buffer is CPU backed then - * it will always succeed and is a free operation. Once a buffer is mapped, - * subsequent calls to map() are ignored. - * - * Note that buffer mapping does not go through GrContext and therefore is - * not serialized with other operations. - * - * @return a pointer to the data or nullptr if the map fails. - */ - void* map() { - if (!fMapPtr) { - this->onMap(); - } - return fMapPtr; - } - - /** - * Unmaps the buffer. - * - * The pointer returned by the previous map call will no longer be valid. - */ - void unmap() { - SkASSERT(fMapPtr); - this->onUnmap(); - fMapPtr = nullptr; - } - - /** - * Returns the same ptr that map() returned at time of map or nullptr if the - * is not mapped. - * - * @return ptr to mapped buffer data or nullptr if buffer is not mapped. - */ - void* mapPtr() const { return fMapPtr; } - - /** - Queries whether the buffer has been mapped. - - @return true if the buffer is mapped, false otherwise. - */ - bool isMapped() const { return SkToBool(fMapPtr); } - - /** - * Updates the buffer data. - * - * The size of the buffer will be preserved. The src data will be - * placed at the beginning of the buffer and any remaining contents will - * be undefined. srcSizeInBytes must be <= to the buffer size. - * - * The buffer must not be mapped. - * - * Note that buffer updates do not go through GrContext and therefore are - * not serialized with other operations. - * - * @return returns true if the update succeeds, false otherwise. - */ - bool updateData(const void* src, size_t srcSizeInBytes) { - SkASSERT(!this->isMapped()); - SkASSERT(srcSizeInBytes <= fGpuMemorySize); - return this->onUpdateData(src, srcSizeInBytes); - } - -protected: - GrBuffer(GrGpu* gpu, GrBufferType type, size_t gpuMemorySize, GrAccessPattern accessPattern, - bool cpuBacked) - : INHERITED(gpu, kCached_LifeCycle), - fMapPtr(nullptr), - fType(type), - fGpuMemorySize(gpuMemorySize), // TODO: Zero for cpu backed buffers? - fAccessPattern(accessPattern), - fCPUBacked(cpuBacked) { - if (!fCPUBacked && SkIsPow2(fGpuMemorySize) && kDynamic_GrAccessPattern == fAccessPattern) { - GrScratchKey key; - ComputeScratchKeyForDynamicBuffer(fType, fGpuMemorySize, &key); - this->setScratchKey(key); - } - } - - void* fMapPtr; - -private: - virtual size_t onGpuMemorySize() const { return fGpuMemorySize; } - - virtual void onMap() = 0; - virtual void onUnmap() = 0; - virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) = 0; - - GrBufferType fType; - size_t fGpuMemorySize; - GrAccessPattern fAccessPattern; - bool fCPUBacked; - - typedef GrGpuResource INHERITED; -}; - -#endif diff --git a/src/gpu/GrBufferAllocPool.cpp b/src/gpu/GrBufferAllocPool.cpp index ac34b5cfcc..73b70bf861 100644 --- a/src/gpu/GrBufferAllocPool.cpp +++ b/src/gpu/GrBufferAllocPool.cpp @@ -8,12 +8,13 @@ #include "GrBufferAllocPool.h" -#include "GrBuffer.h" #include "GrCaps.h" #include "GrContext.h" #include "GrGpu.h" +#include "GrIndexBuffer.h" #include "GrResourceProvider.h" #include "GrTypes.h" +#include "GrVertexBuffer.h" #include "SkTraceEvent.h" @@ -40,7 +41,7 @@ do { } while (false) GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, - GrBufferType bufferType, + BufferType bufferType, size_t blockSize) : fBlocks(8) { @@ -52,12 +53,12 @@ GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu, fBytesInUse = 0; - fBufferMapThreshold = gpu->caps()->bufferMapThreshold(); + fGeometryBufferMapThreshold = gpu->caps()->geometryBufferMapThreshold(); } void GrBufferAllocPool::deleteBlocks() { if (fBlocks.count()) { - GrBuffer* buffer = fBlocks.back().fBuffer; + GrGeometryBuffer* buffer = fBlocks.back().fBuffer; if (buffer->isMapped()) { UNMAP_BUFFER(fBlocks.back()); } @@ -108,7 +109,7 @@ void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { if (fBufferPtr) { SkASSERT(!fBlocks.empty()); if (fBlocks.back().fBuffer->isMapped()) { - GrBuffer* buf = fBlocks.back().fBuffer; + GrGeometryBuffer* buf = fBlocks.back().fBuffer; SkASSERT(buf->mapPtr() == fBufferPtr); } else { SkASSERT(fCpuData == fBufferPtr); @@ -144,7 +145,7 @@ void GrBufferAllocPool::validate(bool unusedBlockAllowed) const { void* GrBufferAllocPool::makeSpace(size_t size, size_t alignment, - const GrBuffer** buffer, + const GrGeometryBuffer** buffer, size_t* offset) { VALIDATE(); @@ -251,7 +252,7 @@ bool GrBufferAllocPool::createBlock(size_t requestSize) { // threshold. bool attemptMap = block.fBuffer->isCPUBacked(); if (!attemptMap && GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) { - attemptMap = size > fBufferMapThreshold; + attemptMap = size > fGeometryBufferMapThreshold; } if (attemptMap) { @@ -294,7 +295,7 @@ void* GrBufferAllocPool::resetCpuData(size_t newSize) { void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) { - GrBuffer* buffer = block.fBuffer; + GrGeometryBuffer* buffer = block.fBuffer; SkASSERT(buffer); SkASSERT(!buffer->isMapped()); SkASSERT(fCpuData == fBufferPtr); @@ -302,7 +303,7 @@ void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) VALIDATE(true); if (GrCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() && - flushSize > fBufferMapThreshold) { + flushSize > fGeometryBufferMapThreshold) { void* data = buffer->map(); if (data) { memcpy(data, fBufferPtr, flushSize); @@ -314,24 +315,30 @@ void GrBufferAllocPool::flushCpuData(const BufferBlock& block, size_t flushSize) VALIDATE(true); } -GrBuffer* GrBufferAllocPool::getBuffer(size_t size) { +GrGeometryBuffer* GrBufferAllocPool::getBuffer(size_t size) { GrResourceProvider* rp = fGpu->getContext()->resourceProvider(); + static const GrResourceProvider::BufferUsage kUsage = GrResourceProvider::kDynamic_BufferUsage; // Shouldn't have to use this flag (https://bug.skia.org/4156) static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag; - return rp->createBuffer(fBufferType, size, kDynamic_GrAccessPattern, kFlags); + if (kIndex_BufferType == fBufferType) { + return rp->createIndexBuffer(size, kUsage, kFlags); + } else { + SkASSERT(kVertex_BufferType == fBufferType); + return rp->createVertexBuffer(size, kUsage, kFlags); + } } //////////////////////////////////////////////////////////////////////////////// GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu) - : GrBufferAllocPool(gpu, kVertex_GrBufferType, MIN_VERTEX_BUFFER_SIZE) { + : GrBufferAllocPool(gpu, kVertex_BufferType, MIN_VERTEX_BUFFER_SIZE) { } void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, int vertexCount, - const GrBuffer** buffer, + const GrVertexBuffer** buffer, int* startVertex) { SkASSERT(vertexCount >= 0); @@ -339,11 +346,13 @@ void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, SkASSERT(startVertex); size_t offset = 0; // assign to suppress warning + const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning void* ptr = INHERITED::makeSpace(vertexSize * vertexCount, vertexSize, - buffer, + &geomBuffer, &offset); + *buffer = (const GrVertexBuffer*) geomBuffer; SkASSERT(0 == offset % vertexSize); *startVertex = static_cast<int>(offset / vertexSize); return ptr; @@ -352,11 +361,11 @@ void* GrVertexBufferAllocPool::makeSpace(size_t vertexSize, //////////////////////////////////////////////////////////////////////////////// GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu) - : GrBufferAllocPool(gpu, kIndex_GrBufferType, MIN_INDEX_BUFFER_SIZE) { + : GrBufferAllocPool(gpu, kIndex_BufferType, MIN_INDEX_BUFFER_SIZE) { } void* GrIndexBufferAllocPool::makeSpace(int indexCount, - const GrBuffer** buffer, + const GrIndexBuffer** buffer, int* startIndex) { SkASSERT(indexCount >= 0); @@ -364,11 +373,13 @@ void* GrIndexBufferAllocPool::makeSpace(int indexCount, SkASSERT(startIndex); size_t offset = 0; // assign to suppress warning + const GrGeometryBuffer* geomBuffer = nullptr; // assign to suppress warning void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t), sizeof(uint16_t), - buffer, + &geomBuffer, &offset); + *buffer = (const GrIndexBuffer*) geomBuffer; SkASSERT(0 == offset % sizeof(uint16_t)); *startIndex = static_cast<int>(offset / sizeof(uint16_t)); return ptr; diff --git a/src/gpu/GrBufferAllocPool.h b/src/gpu/GrBufferAllocPool.h index 071b00b064..a3d8e45364 100644 --- a/src/gpu/GrBufferAllocPool.h +++ b/src/gpu/GrBufferAllocPool.h @@ -11,9 +11,8 @@ #include "SkTArray.h" #include "SkTDArray.h" #include "SkTypes.h" -#include "GrTypesPriv.h" -class GrBuffer; +class GrGeometryBuffer; class GrGpu; /** @@ -48,6 +47,16 @@ public: protected: /** + * Used to determine what type of buffers to create. We could make the + * createBuffer a virtual except that we want to use it in the cons for + * pre-allocated buffers. + */ + enum BufferType { + kVertex_BufferType, + kIndex_BufferType, + }; + + /** * Constructor * * @param gpu The GrGpu used to create the buffers. @@ -57,7 +66,7 @@ protected: * reasonable minimum. */ GrBufferAllocPool(GrGpu* gpu, - GrBufferType bufferType, + BufferType bufferType, size_t bufferSize = 0); virtual ~GrBufferAllocPool(); @@ -83,15 +92,15 @@ protected: */ void* makeSpace(size_t size, size_t alignment, - const GrBuffer** buffer, + const GrGeometryBuffer** buffer, size_t* offset); - GrBuffer* getBuffer(size_t size); + GrGeometryBuffer* getBuffer(size_t size); private: struct BufferBlock { - size_t fBytesFree; - GrBuffer* fBuffer; + size_t fBytesFree; + GrGeometryBuffer* fBuffer; }; bool createBlock(size_t requestSize); @@ -106,14 +115,16 @@ private: GrGpu* fGpu; size_t fMinBlockSize; - GrBufferType fBufferType; + BufferType fBufferType; SkTArray<BufferBlock> fBlocks; void* fCpuData; void* fBufferPtr; - size_t fBufferMapThreshold; + size_t fGeometryBufferMapThreshold; }; +class GrVertexBuffer; + /** * A GrBufferAllocPool of vertex buffers */ @@ -149,13 +160,15 @@ public: */ void* makeSpace(size_t vertexSize, int vertexCount, - const GrBuffer** buffer, + const GrVertexBuffer** buffer, int* startVertex); private: typedef GrBufferAllocPool INHERITED; }; +class GrIndexBuffer; + /** * A GrBufferAllocPool of index buffers */ @@ -187,7 +200,7 @@ public: * @return pointer to first index. */ void* makeSpace(int indexCount, - const GrBuffer** buffer, + const GrIndexBuffer** buffer, int* startIndex); private: diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index 857e789808..784e401328 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -116,7 +116,7 @@ GrCaps::GrCaps(const GrContextOptions& options) { fSuppressPrints = options.fSuppressPrints; fImmediateFlush = options.fImmediateMode; fDrawPathMasksToCompressedTextureSupport = options.fDrawPathToCompressedTexture; - fBufferMapThreshold = options.fBufferMapThreshold; + fGeometryBufferMapThreshold = options.fGeometryBufferMapThreshold; fUseDrawInsteadOfPartialRenderTargetWrite = options.fUseDrawInsteadOfPartialRenderTargetWrite; fUseDrawInsteadOfAllRenderTargetWrites = false; diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 39c1e32d07..08938ec0af 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -19,6 +19,7 @@ #include "GrRenderTargetPriv.h" #include "GrSurfacePriv.h" #include "GrTexture.h" +#include "GrVertexBuffer.h" #include "gl/GrGLRenderTarget.h" #include "SkStrokeRec.h" diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index c863b455b3..9a6dbc9e71 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -13,8 +13,11 @@ #include "GrContext.h" #include "GrPathProcessor.h" #include "GrPrimitiveProcessor.h" +#include "GrIndexBuffer.h" #include "GrPathRendering.h" #include "GrPipelineBuilder.h" +#include "GrPipeline.h" +#include "GrVertexBuffer.h" #include "GrXferProcessor.h" #include "batches/GrDrawBatch.h" diff --git a/src/gpu/GrGeometryBuffer.h b/src/gpu/GrGeometryBuffer.h new file mode 100644 index 0000000000..56a6cae3fb --- /dev/null +++ b/src/gpu/GrGeometryBuffer.h @@ -0,0 +1,124 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef GrGeometryBuffer_DEFINED +#define GrGeometryBuffer_DEFINED + +#include "GrGpuResource.h" + +class GrGpu; + +/** + * Parent class for vertex and index buffers + */ +class GrGeometryBuffer : public GrGpuResource { +public: + + + /** + *Retrieves whether the buffer was created with the dynamic flag + * + * @return true if the buffer was created with the dynamic flag + */ + bool dynamic() const { return fDynamic; } + + /** + * Returns true if the buffer is a wrapper around a CPU array. If true it + * indicates that map will always succeed and will be free. + */ + bool isCPUBacked() const { return fCPUBacked; } + + /** + * Maps the buffer to be written by the CPU. + * + * The previous content of the buffer is invalidated. It is an error + * to draw from the buffer while it is mapped. It is an error to call map + * on an already mapped buffer. It may fail if the backend doesn't support + * mapping the buffer. If the buffer is CPU backed then it will always + * succeed and is a free operation. Must be matched by an unmap() call. + * Currently only one map at a time is supported (no nesting of + * map/unmap). + * + * Note that buffer mapping does not go through GrContext and therefore is + * not serialized with other operations. + * + * @return a pointer to the data or nullptr if the map fails. + */ + void* map() { return (fMapPtr = this->onMap()); } + + /** + * Unmaps the buffer. + * + * The pointer returned by the previous map call will no longer be valid. + */ + void unmap() { + SkASSERT(fMapPtr); + this->onUnmap(); + fMapPtr = nullptr; + } + + /** + * Returns the same ptr that map() returned at time of map or nullptr if the + * is not mapped. + * + * @return ptr to mapped buffer data or nullptr if buffer is not mapped. + */ + void* mapPtr() const { return fMapPtr; } + + /** + Queries whether the buffer has been mapped. + + @return true if the buffer is mapped, false otherwise. + */ + bool isMapped() const { return SkToBool(fMapPtr); } + + /** + * Updates the buffer data. + * + * The size of the buffer will be preserved. The src data will be + * placed at the beginning of the buffer and any remaining contents will + * be undefined. srcSizeInBytes must be <= to the buffer size. + * + * The buffer must not be mapped. + * + * Note that buffer updates do not go through GrContext and therefore are + * not serialized with other operations. + * + * @return returns true if the update succeeds, false otherwise. + */ + bool updateData(const void* src, size_t srcSizeInBytes) { + SkASSERT(!this->isMapped()); + SkASSERT(srcSizeInBytes <= fGpuMemorySize); + return this->onUpdateData(src, srcSizeInBytes); + } + +protected: + GrGeometryBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked) + : INHERITED(gpu, kCached_LifeCycle) + , fMapPtr(nullptr) + , fGpuMemorySize(gpuMemorySize) + , fDynamic(dynamic) + , fCPUBacked(cpuBacked) {} + +private: + virtual size_t onGpuMemorySize() const { return fGpuMemorySize; } + + virtual void* onMap() = 0; + virtual void onUnmap() = 0; + virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) = 0; + + void* fMapPtr; + size_t fGpuMemorySize; + bool fDynamic; + bool fCPUBacked; + + typedef GrGpuResource INHERITED; +}; + +#endif diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 35c04caa23..177fbabc59 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -8,10 +8,10 @@ #include "GrGpu.h" -#include "GrBuffer.h" #include "GrCaps.h" #include "GrContext.h" #include "GrGpuResourcePriv.h" +#include "GrIndexBuffer.h" #include "GrMesh.h" #include "GrPathRendering.h" #include "GrPipeline.h" @@ -20,6 +20,8 @@ #include "GrRenderTargetPriv.h" #include "GrStencilAttachment.h" #include "GrSurfacePriv.h" +#include "GrTransferBuffer.h" +#include "GrVertexBuffer.h" #include "SkTypes.h" GrMesh& GrMesh::operator =(const GrMesh& di) { @@ -236,13 +238,28 @@ GrRenderTarget* GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTextureDe return this->onWrapBackendTextureAsRenderTarget(desc, ownership); } -GrBuffer* GrGpu::createBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) { +GrVertexBuffer* GrGpu::createVertexBuffer(size_t size, bool dynamic) { this->handleDirtyContext(); - GrBuffer* buffer = this->onCreateBuffer(type, size, accessPattern); + GrVertexBuffer* vb = this->onCreateVertexBuffer(size, dynamic); if (!this->caps()->reuseScratchBuffers()) { - buffer->resourcePriv().removeScratchKey(); + vb->resourcePriv().removeScratchKey(); } - return buffer; + return vb; +} + +GrIndexBuffer* GrGpu::createIndexBuffer(size_t size, bool dynamic) { + this->handleDirtyContext(); + GrIndexBuffer* ib = this->onCreateIndexBuffer(size, dynamic); + if (!this->caps()->reuseScratchBuffers()) { + ib->resourcePriv().removeScratchKey(); + } + return ib; +} + +GrTransferBuffer* GrGpu::createTransferBuffer(size_t size, TransferType type) { + this->handleDirtyContext(); + GrTransferBuffer* tb = this->onCreateTransferBuffer(size, type); + return tb; } void GrGpu::clear(const SkIRect& rect, @@ -399,13 +416,13 @@ bool GrGpu::writePixels(GrSurface* surface, bool GrGpu::transferPixels(GrSurface* surface, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) { - SkASSERT(transferBuffer); + SkASSERT(buffer); this->handleDirtyContext(); if (this->onTransferPixels(surface, left, top, width, height, config, - transferBuffer, offset, rowBytes)) { + buffer, offset, rowBytes)) { fStats.incTransfersToTexture(); return true; } diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index a49b2c28fd..4e9b247ca3 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -20,9 +20,9 @@ #include "SkTArray.h" class GrBatchTracker; -class GrBuffer; class GrContext; class GrGLContext; +class GrIndexBuffer; class GrMesh; class GrNonInstancedVertices; class GrPath; @@ -36,6 +36,8 @@ class GrRenderTarget; class GrStencilAttachment; class GrSurface; class GrTexture; +class GrTransferBuffer; +class GrVertexBuffer; class GrGpu : public SkRefCnt { public: @@ -127,11 +129,39 @@ public: GrRenderTarget* wrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&, GrWrapOwnership); /** - * Creates a buffer. + * Creates a vertex buffer. * - * @return the buffer if successful, otherwise nullptr. + * @param size size in bytes of the vertex buffer + * @param dynamic hints whether the data will be frequently changed + * by either GrVertexBuffer::map() or + * GrVertexBuffer::updateData(). + * + * @return The vertex buffer if successful, otherwise nullptr. + */ + GrVertexBuffer* createVertexBuffer(size_t size, bool dynamic); + + /** + * Creates an index buffer. + * + * @param size size in bytes of the index buffer + * @param dynamic hints whether the data will be frequently changed + * by either GrIndexBuffer::map() or + * GrIndexBuffer::updateData(). + * + * @return The index buffer if successful, otherwise nullptr. + */ + GrIndexBuffer* createIndexBuffer(size_t size, bool dynamic); + + /** + * Creates a transfer buffer. + * + * @param size size in bytes of the index buffer + * @param toGpu true if used to transfer from the cpu to the gpu + * otherwise to be used to transfer from the gpu to the cpu + * + * @return The transfer buffer if successful, otherwise nullptr. */ - GrBuffer* createBuffer(GrBufferType, size_t size, GrAccessPattern); + GrTransferBuffer* createTransferBuffer(size_t size, TransferType type); /** * Resolves MSAA. @@ -268,22 +298,22 @@ public: size_t rowBytes); /** - * Updates the pixels in a rectangle of a surface using a buffer + * Updates the pixels in a rectangle of a surface using a GrTransferBuffer * - * @param surface The surface to write to. - * @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 transferBuffer GrBuffer to read pixels from (type must be "kCpuToGpu") - * @param offset offset from the start of the buffer - * @param rowBytes number of bytes between consecutive rows. Zero - * means rows are tightly packed. + * @param surface The surface to write to. + * @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 GrTransferBuffer to read pixels from + * @param offset offset from the start of the buffer + * @param rowBytes number of bytes between consecutive rows. Zero + * means rows are tightly packed. */ bool transferPixels(GrSurface* surface, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes); /** @@ -528,7 +558,9 @@ private: GrWrapOwnership) = 0; virtual GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&, GrWrapOwnership) = 0; - virtual GrBuffer* onCreateBuffer(GrBufferType, size_t size, GrAccessPattern) = 0; + virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0; + virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) = 0; + virtual GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) = 0; // overridden by backend-specific derived class to perform the clear. virtual void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) = 0; @@ -570,7 +602,7 @@ private: // overridden by backend-specific derived class to perform the surface write virtual bool onTransferPixels(GrSurface*, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) = 0; // overridden by backend-specific derived class to perform the resolve diff --git a/src/gpu/GrIndexBuffer.h b/src/gpu/GrIndexBuffer.h new file mode 100644 index 0000000000..2e3b437adf --- /dev/null +++ b/src/gpu/GrIndexBuffer.h @@ -0,0 +1,51 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#ifndef GrIndexBuffer_DEFINED +#define GrIndexBuffer_DEFINED + +#include "GrGeometryBuffer.h" + + +class GrIndexBuffer : public GrGeometryBuffer { +public: + static void ComputeScratchKey(size_t size, bool dynamic, GrScratchKey* key) { + static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType(); + + GrScratchKey::Builder builder(key, kType, 2); + + builder[0] = SkToUInt(size); + builder[1] = dynamic ? 1 : 0; + } + + /** + * Retrieves the maximum number of quads that could be rendered + * from the index buffer (using kTriangles_GrPrimitiveType). + * @return the maximum number of quads using full size of index buffer. + */ + int maxQuads() const { + return static_cast<int>(this->gpuMemorySize() / (sizeof(uint16_t) * 6)); + } +protected: + GrIndexBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked) + : INHERITED(gpu, gpuMemorySize, dynamic, cpuBacked) { + // We currently only make buffers scratch if they're both pow2 sized and not cpuBacked. + if (!cpuBacked && SkIsPow2(gpuMemorySize)) { + GrScratchKey key; + ComputeScratchKey(gpuMemorySize, dynamic, &key); + this->setScratchKey(key); + } + } + +private: + typedef GrGeometryBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/GrMesh.h b/src/gpu/GrMesh.h index 964e0b4a8e..5ff23dcfd0 100644 --- a/src/gpu/GrMesh.h +++ b/src/gpu/GrMesh.h @@ -8,8 +8,8 @@ #ifndef GrMesh_DEFINED #define GrMesh_DEFINED -#include "GrBuffer.h" -#include "GrGpuResourceRef.h" +#include "GrIndexBuffer.h" +#include "GrVertexBuffer.h" class GrNonInstancedMesh { public: @@ -20,8 +20,8 @@ public: int indexCount() const { return fIndexCount; } bool isIndexed() const { return fIndexCount > 0; } - const GrBuffer* vertexBuffer() const { return fVertexBuffer.get(); } - const GrBuffer* indexBuffer() const { return fIndexBuffer.get(); } + const GrVertexBuffer* vertexBuffer() const { return fVertexBuffer.get(); } + const GrIndexBuffer* indexBuffer() const { return fIndexBuffer.get(); } protected: GrPrimitiveType fPrimitiveType; @@ -29,8 +29,8 @@ protected: int fStartIndex; int fVertexCount; int fIndexCount; - GrPendingIOResource<const GrBuffer, kRead_GrIOType> fVertexBuffer; - GrPendingIOResource<const GrBuffer, kRead_GrIOType> fIndexBuffer; + GrPendingIOResource<const GrVertexBuffer, kRead_GrIOType> fVertexBuffer; + GrPendingIOResource<const GrIndexBuffer, kRead_GrIOType> fIndexBuffer; friend class GrMesh; }; @@ -46,7 +46,7 @@ public: GrMesh(const GrMesh& di) { (*this) = di; } GrMesh& operator =(const GrMesh& di); - void init(GrPrimitiveType primType, const GrBuffer* vertexBuffer, int startVertex, + void init(GrPrimitiveType primType, const GrVertexBuffer* vertexBuffer, int startVertex, int vertexCount) { SkASSERT(vertexBuffer); SkASSERT(vertexCount); @@ -65,8 +65,8 @@ public: } void initIndexed(GrPrimitiveType primType, - const GrBuffer* vertexBuffer, - const GrBuffer* indexBuffer, + const GrVertexBuffer* vertexBuffer, + const GrIndexBuffer* indexBuffer, int startVertex, int startIndex, int vertexCount, @@ -95,8 +95,8 @@ public: the number of instances supported by the index buffer. To be used with nextInstances() to draw in max-sized batches.*/ void initInstanced(GrPrimitiveType primType, - const GrBuffer* vertexBuffer, - const GrBuffer* indexBuffer, + const GrVertexBuffer* vertexBuffer, + const GrIndexBuffer* indexBuffer, int startVertex, int verticesPerInstance, int indicesPerInstance, diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 9388f323c8..d0be27d9b0 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -1211,8 +1211,8 @@ static const int kNumRRectsInIndexBuffer = 256; GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); -static const GrBuffer* ref_rrect_index_buffer(bool strokeOnly, - GrResourceProvider* resourceProvider) { +static const GrIndexBuffer* ref_rrect_index_buffer(bool strokeOnly, + GrResourceProvider* resourceProvider) { GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); if (strokeOnly) { @@ -1286,7 +1286,7 @@ private: // drop out the middle quad if we're stroked int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPerRRect; - SkAutoTUnref<const GrBuffer> indexBuffer( + SkAutoTUnref<const GrIndexBuffer> indexBuffer( ref_rrect_index_buffer(fStroked, target->resourceProvider())); InstancedHelper helper; @@ -1434,7 +1434,7 @@ private: // drop out the middle quad if we're stroked int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPerRRect; - SkAutoTUnref<const GrBuffer> indexBuffer( + SkAutoTUnref<const GrIndexBuffer> indexBuffer( ref_rrect_index_buffer(fStroked, target->resourceProvider())); InstancedHelper helper; diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index a73bf752b0..79146d0911 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -7,14 +7,15 @@ #include "GrResourceProvider.h" -#include "GrBuffer.h" #include "GrGpu.h" +#include "GrIndexBuffer.h" #include "GrPathRendering.h" #include "GrRenderTarget.h" #include "GrRenderTargetPriv.h" #include "GrResourceCache.h" #include "GrResourceKey.h" #include "GrStencilAttachment.h" +#include "GrVertexBuffer.h" GR_DECLARE_STATIC_UNIQUE_KEY(gQuadIndexBufferKey); @@ -24,16 +25,16 @@ GrResourceProvider::GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSin fQuadIndexBufferKey = gQuadIndexBufferKey; } -const GrBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern, - int patternSize, - int reps, - int vertCount, - const GrUniqueKey& key) { +const GrIndexBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* pattern, + int patternSize, + int reps, + int vertCount, + const GrUniqueKey& key) { size_t bufferSize = patternSize * reps * sizeof(uint16_t); // This is typically used in GrBatchs, so we assume kNoPendingIO. - GrBuffer* buffer = this->createBuffer(kIndex_GrBufferType, bufferSize, kStatic_GrAccessPattern, - kNoPendingIO_Flag); + GrIndexBuffer* buffer = this->createIndexBuffer(bufferSize, kStatic_BufferUsage, + kNoPendingIO_Flag); if (!buffer) { return nullptr; } @@ -62,7 +63,7 @@ const GrBuffer* GrResourceProvider::createInstancedIndexBuffer(const uint16_t* p return buffer; } -const GrBuffer* GrResourceProvider::createQuadIndexBuffer() { +const GrIndexBuffer* GrResourceProvider::createQuadIndexBuffer() { static const int kMaxQuads = 1 << 12; // max possible: (1 << 14) - 1; GR_STATIC_ASSERT(4 * kMaxQuads <= 65535); static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 }; @@ -88,31 +89,72 @@ GrPathRange* GrResourceProvider::createGlyphs(const SkTypeface* tf, const SkDesc return this->gpu()->pathRendering()->createGlyphs(tf, desc, stroke); } -GrBuffer* GrResourceProvider::createBuffer(GrBufferType type, size_t size, - GrAccessPattern accessPattern, uint32_t flags) { +GrIndexBuffer* GrResourceProvider::createIndexBuffer(size_t size, BufferUsage usage, + uint32_t flags) { if (this->isAbandoned()) { return nullptr; } - if (kDynamic_GrAccessPattern == accessPattern) { + bool noPendingIO = SkToBool(flags & kNoPendingIO_Flag); + bool dynamic = kDynamic_BufferUsage == usage; + if (dynamic) { // bin by pow2 with a reasonable min static const uint32_t MIN_SIZE = 1 << 12; size = SkTMax(MIN_SIZE, GrNextPow2(SkToUInt(size))); GrScratchKey key; - GrBuffer::ComputeScratchKeyForDynamicBuffer(type, size, &key); + GrIndexBuffer::ComputeScratchKey(size, true, &key); uint32_t scratchFlags = 0; - if (flags & kNoPendingIO_Flag) { + if (noPendingIO) { scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; } else { scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; } GrGpuResource* resource = this->cache()->findAndRefScratchResource(key, size, scratchFlags); if (resource) { - return static_cast<GrBuffer*>(resource); + return static_cast<GrIndexBuffer*>(resource); } } - return this->gpu()->createBuffer(type, size, accessPattern); + return this->gpu()->createIndexBuffer(size, dynamic); +} + +GrVertexBuffer* GrResourceProvider::createVertexBuffer(size_t size, BufferUsage usage, + uint32_t flags) { + if (this->isAbandoned()) { + return nullptr; + } + + bool noPendingIO = SkToBool(flags & kNoPendingIO_Flag); + bool dynamic = kDynamic_BufferUsage == usage; + if (dynamic) { + // bin by pow2 with a reasonable min + static const uint32_t MIN_SIZE = 1 << 12; + size = SkTMax(MIN_SIZE, GrNextPow2(SkToUInt(size))); + + GrScratchKey key; + GrVertexBuffer::ComputeScratchKey(size, true, &key); + uint32_t scratchFlags = 0; + if (noPendingIO) { + scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag; + } else { + scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag; + } + GrGpuResource* resource = this->cache()->findAndRefScratchResource(key, size, scratchFlags); + if (resource) { + return static_cast<GrVertexBuffer*>(resource); + } + } + return this->gpu()->createVertexBuffer(size, dynamic); +} + +GrTransferBuffer* GrResourceProvider::createTransferBuffer(size_t size, TransferType type, + uint32_t flags) { + if (this->isAbandoned()) { + return nullptr; + } + + //bool noPendingIO = SkToBool(flags & kNoPendingIO_Flag); + return this->gpu()->createTransferBuffer(size, type); } GrBatchAtlas* GrResourceProvider::createAtlas(GrPixelConfig config, diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h index 7b51726d10..3dfc9ba863 100644 --- a/src/gpu/GrResourceProvider.h +++ b/src/gpu/GrResourceProvider.h @@ -9,16 +9,18 @@ #define GrResourceProvider_DEFINED #include "GrBatchAtlas.h" -#include "GrBuffer.h" +#include "GrIndexBuffer.h" #include "GrTextureProvider.h" #include "GrPathRange.h" class GrBatchAtlas; +class GrIndexBuffer; class GrPath; class GrRenderTarget; class GrSingleOwner; class GrStencilAttachment; class GrStrokeInfo; +class GrVertexBuffer; class SkDescriptor; class SkPath; class SkTypeface; @@ -43,7 +45,7 @@ public: /** * Either finds and refs, or creates an index buffer for instanced drawing with a specific * pattern if the index buffer is not found. If the return is non-null, the caller owns - * a ref on the returned GrBuffer. + * a ref on the returned GrIndexBuffer. * * @param pattern the pattern of indices to repeat * @param patternSize size in bytes of the pattern @@ -53,12 +55,12 @@ public: * * @return The index buffer if successful, otherwise nullptr. */ - const GrBuffer* findOrCreateInstancedIndexBuffer(const uint16_t* pattern, - int patternSize, - int reps, - int vertCount, - const GrUniqueKey& key) { - if (GrBuffer* buffer = this->findAndRefTByUniqueKey<GrBuffer>(key)) { + const GrIndexBuffer* findOrCreateInstancedIndexBuffer(const uint16_t* pattern, + int patternSize, + int reps, + int vertCount, + const GrUniqueKey& key) { + if (GrIndexBuffer* buffer = this->findAndRefTByUniqueKey<GrIndexBuffer>(key)) { return buffer; } return this->createInstancedIndexBuffer(pattern, patternSize, reps, vertCount, key); @@ -67,13 +69,13 @@ public: /** * Returns an index buffer that can be used to render quads. * Six indices per quad: 0, 1, 2, 0, 2, 3, etc. - * The max number of quads is the buffer's index capacity divided by 6. + * The max number of quads can be queried using GrIndexBuffer::maxQuads(). * Draw with kTriangles_GrPrimitiveType * @ return the quad index buffer */ - const GrBuffer* refQuadIndexBuffer() { - if (GrBuffer* buffer = - this->findAndRefTByUniqueKey<GrBuffer>(fQuadIndexBufferKey)) { + const GrIndexBuffer* refQuadIndexBuffer() { + if (GrIndexBuffer* buffer = + this->findAndRefTByUniqueKey<GrIndexBuffer>(fQuadIndexBufferKey)) { return buffer; } return this->createQuadIndexBuffer(); @@ -102,7 +104,16 @@ public: kNoPendingIO_Flag = kNoPendingIO_ScratchTextureFlag, }; - GrBuffer* createBuffer(GrBufferType, size_t size, GrAccessPattern, uint32_t flags); + enum BufferUsage { + /** Caller intends to specify the buffer data rarely with respect to the number of draws + that read the data. */ + kStatic_BufferUsage, + /** Caller intends to respecify the buffer data frequently between draws. */ + kDynamic_BufferUsage, + }; + GrIndexBuffer* createIndexBuffer(size_t size, BufferUsage, uint32_t flags); + GrVertexBuffer* createVertexBuffer(size_t size, BufferUsage, uint32_t flags); + GrTransferBuffer* createTransferBuffer(size_t size, TransferType, uint32_t flags); GrTexture* createApproxTexture(const GrSurfaceDesc& desc, uint32_t flags) { SkASSERT(0 == flags || kNoPendingIO_Flag == flags); @@ -146,13 +157,13 @@ public: GrWrapOwnership = kBorrow_GrWrapOwnership); private: - const GrBuffer* createInstancedIndexBuffer(const uint16_t* pattern, - int patternSize, - int reps, - int vertCount, - const GrUniqueKey& key); + const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern, + int patternSize, + int reps, + int vertCount, + const GrUniqueKey& key); - const GrBuffer* createQuadIndexBuffer(); + const GrIndexBuffer* createQuadIndexBuffer(); GrUniqueKey fQuadIndexBufferKey; diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp index 093bef7086..af77c205b5 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -9,6 +9,7 @@ #include "GrSoftwarePathRenderer.h" #include "GrContext.h" #include "GrSWMaskHelper.h" +#include "GrVertexBuffer.h" #include "batches/GrRectBatchFactory.h" //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrTest.cpp b/src/gpu/GrTest.cpp index 2b6463d853..c9b26e284a 100644 --- a/src/gpu/GrTest.cpp +++ b/src/gpu/GrTest.cpp @@ -345,7 +345,11 @@ private: return nullptr; } - GrBuffer* onCreateBuffer(GrBufferType, size_t, GrAccessPattern) override { return nullptr; } + GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override { return nullptr; } + + GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override { return nullptr; } + + GrTransferBuffer* onCreateTransferBuffer(size_t, TransferType) override { return nullptr; } void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override {} @@ -372,7 +376,7 @@ private: bool onTransferPixels(GrSurface* surface, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) override { return false; } @@ -406,7 +410,7 @@ GrContext* GrContext::CreateMockContext() { void GrContext::initMockContext() { GrContextOptions options; - options.fBufferMapThreshold = 0; + options.fGeometryBufferMapThreshold = 0; SkASSERT(nullptr == fGpu); fGpu = new MockGpu(this, options); SkASSERT(fGpu); diff --git a/src/gpu/GrTransferBuffer.h b/src/gpu/GrTransferBuffer.h new file mode 100755 index 0000000000..bd80666fd6 --- /dev/null +++ b/src/gpu/GrTransferBuffer.h @@ -0,0 +1,76 @@ + +/* + * 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 GrTransferBuffer_DEFINED +#define GrTransferBuffer_DEFINED + +#include "GrGpuResource.h" + +class GrTransferBuffer : public GrGpuResource { +public: + /** + * Maps the buffer to be written by the CPU. + * + * The previous content of the buffer is invalidated. It is an error + * to transfer to or from the buffer while it is mapped. It is an error to + * call map on an already mapped buffer. Must be matched by an unmap() call. + * Currently only one map at a time is supported (no nesting of map/unmap). + * + * Note that buffer mapping does not go through GrContext and therefore is + * not serialized with other operations. + * + * @return a pointer to the data or nullptr if the map fails. + */ + void* map() { return (fMapPtr = this->onMap()); } + + /** + * Unmaps the buffer. + * + * The pointer returned by the previous map call will no longer be valid. + */ + void unmap() { + SkASSERT(fMapPtr); + this->onUnmap(); + fMapPtr = nullptr; + } + + /** + * Returns the same ptr that map() returned at time of map or nullptr if the + * is not mapped. + * + * @return ptr to mapped buffer data or nullptr if buffer is not mapped. + */ + void* mapPtr() const { return fMapPtr; } + + /** + Queries whether the buffer has been mapped. + + @return true if the buffer is mapped, false otherwise. + */ + bool isMapped() const { return SkToBool(fMapPtr); } + +protected: + GrTransferBuffer(GrGpu* gpu, size_t gpuMemorySize) + : INHERITED(gpu, kUncached_LifeCycle) + , fGpuMemorySize(gpuMemorySize) { + } + +private: + virtual size_t onGpuMemorySize() const { return fGpuMemorySize; } + + virtual void* onMap() = 0; + virtual void onUnmap() = 0; + + void* fMapPtr; + size_t fGpuMemorySize; + + typedef GrGpuResource INHERITED; +}; + +#endif diff --git a/src/gpu/GrVertexBuffer.h b/src/gpu/GrVertexBuffer.h new file mode 100644 index 0000000000..3c62cd61ca --- /dev/null +++ b/src/gpu/GrVertexBuffer.h @@ -0,0 +1,42 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#ifndef GrVertexBuffer_DEFINED +#define GrVertexBuffer_DEFINED + +#include "GrGeometryBuffer.h" + +class GrVertexBuffer : public GrGeometryBuffer { +public: + static void ComputeScratchKey(size_t size, bool dynamic, GrScratchKey* key) { + static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType(); + + GrScratchKey::Builder builder(key, kType, 2); + + builder[0] = SkToUInt(size); + builder[1] = dynamic ? 1 : 0; + } + +protected: + GrVertexBuffer(GrGpu* gpu, size_t gpuMemorySize, bool dynamic, bool cpuBacked) + : INHERITED(gpu, gpuMemorySize, dynamic, cpuBacked) { + // We currently only make buffers scratch if they're both pow2 sized and not cpuBacked. + if (!cpuBacked && SkIsPow2(gpuMemorySize)) { + GrScratchKey key; + ComputeScratchKey(gpuMemorySize, dynamic, &key); + this->setScratchKey(key); + } + } + +private: + typedef GrGeometryBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/batches/GrAAConvexPathRenderer.cpp b/src/gpu/batches/GrAAConvexPathRenderer.cpp index ba19a0db85..f6be366697 100644 --- a/src/gpu/batches/GrAAConvexPathRenderer.cpp +++ b/src/gpu/batches/GrAAConvexPathRenderer.cpp @@ -814,7 +814,7 @@ private: continue; } - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, tess.numPts(), &vertexBuffer, @@ -824,7 +824,7 @@ private: return; } - const GrBuffer* indexBuffer; + const GrIndexBuffer* indexBuffer; int firstIndex; uint16_t* idxs = target->makeIndexSpace(tess.numIndices(), &indexBuffer, &firstIndex); @@ -900,7 +900,7 @@ private: continue; } - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; size_t vertexStride = quadProcessor->getVertexStride(); @@ -912,7 +912,7 @@ private: return; } - const GrBuffer* indexBuffer; + const GrIndexBuffer* indexBuffer; int firstIndex; uint16_t *idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp index 6a8ec2ff85..7e96b86550 100644 --- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp @@ -10,13 +10,13 @@ #include "GrBatchFlushState.h" #include "GrBatchTest.h" -#include "GrBuffer.h" #include "GrContext.h" #include "GrPipelineBuilder.h" #include "GrResourceProvider.h" #include "GrSurfacePriv.h" #include "GrSWMaskHelper.h" #include "GrTexturePriv.h" +#include "GrVertexBuffer.h" #include "batches/GrVertexBatch.h" #include "effects/GrDistanceFieldGeoProc.h" @@ -177,8 +177,8 @@ private: } struct FlushInfo { - SkAutoTUnref<const GrBuffer> fVertexBuffer; - SkAutoTUnref<const GrBuffer> fIndexBuffer; + SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; + SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; int fVertexOffset; int fInstancesToFlush; }; @@ -217,7 +217,7 @@ private: size_t vertexStride = dfProcessor->getVertexStride(); SkASSERT(vertexStride == 2 * sizeof(SkPoint) + sizeof(GrColor)); - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; void* vertices = target->makeVertexSpace(vertexStride, kVerticesPerQuad * instanceCount, &vertexBuffer, @@ -492,8 +492,7 @@ private: void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { GrMesh mesh; - int maxInstancesPerDraw = - static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6); + int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads(); mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad, kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw); diff --git a/src/gpu/batches/GrAAFillRectBatch.cpp b/src/gpu/batches/GrAAFillRectBatch.cpp index 890a18b576..9ec8ffdc4a 100644 --- a/src/gpu/batches/GrAAFillRectBatch.cpp +++ b/src/gpu/batches/GrAAFillRectBatch.cpp @@ -28,7 +28,7 @@ static const int kNumAAFillRectsInIndexBuffer = 256; static const int kVertsPerAAFillRect = 8; static const int kIndicesPerAAFillRect = 30; -const GrBuffer* get_index_buffer(GrResourceProvider* resourceProvider) { +const GrIndexBuffer* get_index_buffer(GrResourceProvider* resourceProvider) { GR_DEFINE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); static const uint16_t gFillAARectIdx[] = { @@ -191,7 +191,7 @@ public: out->setUnknownSingleComponent(); } - static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) { + static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* rp) { return get_index_buffer(rp); } diff --git a/src/gpu/batches/GrAAHairLinePathRenderer.cpp b/src/gpu/batches/GrAAHairLinePathRenderer.cpp index 2cc91f9740..7d45ed71f9 100644 --- a/src/gpu/batches/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/batches/GrAAHairLinePathRenderer.cpp @@ -9,14 +9,15 @@ #include "GrBatchFlushState.h" #include "GrBatchTest.h" -#include "GrBuffer.h" #include "GrCaps.h" #include "GrContext.h" #include "GrDefaultGeoProcFactory.h" +#include "GrIndexBuffer.h" #include "GrPathUtils.h" #include "GrPipelineBuilder.h" #include "GrProcessor.h" #include "GrResourceProvider.h" +#include "GrVertexBuffer.h" #include "SkGeometry.h" #include "SkStroke.h" #include "SkTemplates.h" @@ -64,7 +65,7 @@ static const int kQuadNumVertices = 5; static const int kQuadsNumInIdxBuffer = 256; GR_DECLARE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey); -static const GrBuffer* ref_quads_index_buffer(GrResourceProvider* resourceProvider) { +static const GrIndexBuffer* ref_quads_index_buffer(GrResourceProvider* resourceProvider) { GR_DEFINE_STATIC_UNIQUE_KEY(gQuadsIndexBufferKey); return resourceProvider->findOrCreateInstancedIndexBuffer( kQuadIdxBufPattern, kIdxsPerQuad, kQuadsNumInIdxBuffer, kQuadNumVertices, @@ -98,7 +99,7 @@ static const int kLineSegsNumInIdxBuffer = 256; GR_DECLARE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey); -static const GrBuffer* ref_lines_index_buffer(GrResourceProvider* resourceProvider) { +static const GrIndexBuffer* ref_lines_index_buffer(GrResourceProvider* resourceProvider) { GR_DEFINE_STATIC_UNIQUE_KEY(gLinesIndexBufferKey); return resourceProvider->findOrCreateInstancedIndexBuffer( kLineSegIdxBufPattern, kIdxsPerLineSeg, kLineSegsNumInIdxBuffer, kLineSegNumVertices, @@ -857,11 +858,11 @@ void AAHairlineBatch::onPrepareDraws(Target* target) const { // do lines first if (lineCount) { - SkAutoTUnref<const GrBuffer> linesIndexBuffer( + SkAutoTUnref<const GrIndexBuffer> linesIndexBuffer( ref_lines_index_buffer(target->resourceProvider())); target->initDraw(lineGP); - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; size_t vertexStride = lineGP->getVertexStride(); @@ -890,10 +891,10 @@ void AAHairlineBatch::onPrepareDraws(Target* target) const { } if (quadCount || conicCount) { - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; - SkAutoTUnref<const GrBuffer> quadsIndexBuffer( + SkAutoTUnref<const GrIndexBuffer> quadsIndexBuffer( ref_quads_index_buffer(target->resourceProvider())); size_t vertexStride = sizeof(BezierVertex); diff --git a/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp index 1cd8daf881..120ecc76ee 100644 --- a/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp +++ b/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp @@ -164,7 +164,7 @@ private: if (vertexCount == 0 || indexCount == 0) { return; } - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; GrMesh mesh; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, @@ -175,7 +175,7 @@ private: } memcpy(verts, vertices, vertexCount * vertexStride); - const GrBuffer* indexBuffer; + const GrIndexBuffer* indexBuffer; int firstIndex; uint16_t* idxs = target->makeIndexSpace(indexCount, &indexBuffer, &firstIndex); if (!idxs) { diff --git a/src/gpu/batches/GrAAStrokeRectBatch.cpp b/src/gpu/batches/GrAAStrokeRectBatch.cpp index 2ce5eca7a6..54bc495a4d 100644 --- a/src/gpu/batches/GrAAStrokeRectBatch.cpp +++ b/src/gpu/batches/GrAAStrokeRectBatch.cpp @@ -123,7 +123,8 @@ private: static const int kBevelVertexCnt = 24; static const int kNumBevelRectsInIndexBuffer = 256; - static const GrBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider, bool miterStroke); + static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvider, + bool miterStroke); GrColor color() const { return fBatch.fColor; } bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } @@ -205,7 +206,7 @@ void AAStrokeRectBatch::onPrepareDraws(Target* target) const { int indicesPerInstance = this->miterStroke() ? kMiterIndexCnt : kBevelIndexCnt; int instanceCount = fGeoData.count(); - const SkAutoTUnref<const GrBuffer> indexBuffer( + const SkAutoTUnref<const GrIndexBuffer> indexBuffer( GetIndexBuffer(target->resourceProvider(), this->miterStroke())); InstancedHelper helper; void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, @@ -234,8 +235,8 @@ void AAStrokeRectBatch::onPrepareDraws(Target* target) const { helper.recordDraw(target); } -const GrBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resourceProvider, - bool miterStroke) { +const GrIndexBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resourceProvider, + bool miterStroke) { if (miterStroke) { static const uint16_t gMiterIndices[] = { diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp index 654643d339..8b89039406 100644 --- a/src/gpu/batches/GrAtlasTextBatch.cpp +++ b/src/gpu/batches/GrAtlasTextBatch.cpp @@ -119,7 +119,7 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { target->initDraw(gp); int glyphCount = this->numGlyphs(); - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; void* vertices = target->makeVertexSpace(vertexStride, glyphCount * kVerticesPerGlyph, @@ -181,8 +181,7 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { void GrAtlasTextBatch::flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { GrMesh mesh; - int maxGlyphsPerDraw = - static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6); + int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads(); mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->fGlyphsToFlush, diff --git a/src/gpu/batches/GrAtlasTextBatch.h b/src/gpu/batches/GrAtlasTextBatch.h index 01d799233e..435fb59d49 100644 --- a/src/gpu/batches/GrAtlasTextBatch.h +++ b/src/gpu/batches/GrAtlasTextBatch.h @@ -99,8 +99,8 @@ private: void initBatchTracker(const GrXPOverridesForBatch& overrides) override; struct FlushInfo { - SkAutoTUnref<const GrBuffer> fVertexBuffer; - SkAutoTUnref<const GrBuffer> fIndexBuffer; + SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; + SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; int fGlyphsToFlush; int fVertexOffset; }; diff --git a/src/gpu/batches/GrDefaultPathRenderer.cpp b/src/gpu/batches/GrDefaultPathRenderer.cpp index 0a3dcd6a14..acaff173c6 100644 --- a/src/gpu/batches/GrDefaultPathRenderer.cpp +++ b/src/gpu/batches/GrDefaultPathRenderer.cpp @@ -313,7 +313,7 @@ private: } // allocate vertex / index buffers - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, maxVertices, @@ -324,7 +324,7 @@ private: return; } - const GrBuffer* indexBuffer = nullptr; + const GrIndexBuffer* indexBuffer = nullptr; int firstIndex = 0; void* indices = nullptr; diff --git a/src/gpu/batches/GrDrawVerticesBatch.cpp b/src/gpu/batches/GrDrawVerticesBatch.cpp index 20d9f79290..c76ba7d1ec 100644 --- a/src/gpu/batches/GrDrawVerticesBatch.cpp +++ b/src/gpu/batches/GrDrawVerticesBatch.cpp @@ -106,7 +106,7 @@ void GrDrawVerticesBatch::onPrepareDraws(Target* target) const { int instanceCount = fGeoData.count(); - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex); @@ -116,7 +116,7 @@ void GrDrawVerticesBatch::onPrepareDraws(Target* target) const { return; } - const GrBuffer* indexBuffer = nullptr; + const GrIndexBuffer* indexBuffer = nullptr; int firstIndex = 0; uint16_t* indices = nullptr; diff --git a/src/gpu/batches/GrNinePatch.cpp b/src/gpu/batches/GrNinePatch.cpp index 17ab6c1c30..3ca004d46c 100644 --- a/src/gpu/batches/GrNinePatch.cpp +++ b/src/gpu/batches/GrNinePatch.cpp @@ -96,7 +96,7 @@ private: size_t vertexStride = gp->getVertexStride(); int instanceCount = fGeoData.count(); - SkAutoTUnref<const GrBuffer> indexBuffer( + SkAutoTUnref<const GrIndexBuffer> indexBuffer( target->resourceProvider()->refQuadIndexBuffer()); InstancedHelper helper; void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, diff --git a/src/gpu/batches/GrNonAAFillRectBatch.cpp b/src/gpu/batches/GrNonAAFillRectBatch.cpp index 5e9d1769b5..09643444d0 100644 --- a/src/gpu/batches/GrNonAAFillRectBatch.cpp +++ b/src/gpu/batches/GrNonAAFillRectBatch.cpp @@ -26,7 +26,7 @@ public: out->setKnownSingleComponent(0xff); } - static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) { + static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* rp) { return rp->refQuadIndexBuffer(); } diff --git a/src/gpu/batches/GrNonAAStrokeRectBatch.cpp b/src/gpu/batches/GrNonAAStrokeRectBatch.cpp index 3e5311f7b9..a87ab11383 100644 --- a/src/gpu/batches/GrNonAAStrokeRectBatch.cpp +++ b/src/gpu/batches/GrNonAAStrokeRectBatch.cpp @@ -130,7 +130,7 @@ private: vertexCount = kVertsPerStrokeRect; } - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; void* verts = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, diff --git a/src/gpu/batches/GrPLSPathRenderer.cpp b/src/gpu/batches/GrPLSPathRenderer.cpp index 28ad2069bf..348681f43f 100644 --- a/src/gpu/batches/GrPLSPathRenderer.cpp +++ b/src/gpu/batches/GrPLSPathRenderer.cpp @@ -873,7 +873,7 @@ public: } if (triVertices.count()) { - const GrBuffer* triVertexBuffer; + const GrVertexBuffer* triVertexBuffer; int firstTriVertex; size_t triStride = triangleProcessor->getVertexStride(); PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace( @@ -892,7 +892,7 @@ public: } if (quadVertices.count()) { - const GrBuffer* quadVertexBuffer; + const GrVertexBuffer* quadVertexBuffer; int firstQuadVertex; size_t quadStride = quadProcessor->getVertexStride(); PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace( @@ -916,7 +916,7 @@ public: SkPath::FillType::kEvenOdd_FillType, invert, this->usesLocalCoords())); - const GrBuffer* rectVertexBuffer; + const GrVertexBuffer* rectVertexBuffer; size_t finishStride = finishProcessor->getVertexStride(); int firstRectVertex; static const int kRectVertexCount = 6; diff --git a/src/gpu/batches/GrTInstanceBatch.h b/src/gpu/batches/GrTInstanceBatch.h index fdd0662d06..22d4f52792 100644 --- a/src/gpu/batches/GrTInstanceBatch.h +++ b/src/gpu/batches/GrTInstanceBatch.h @@ -34,7 +34,7 @@ * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, * const GrXPOverridesForBatch& overrides) * - * const GrBuffer* GetIndexBuffer(GrResourceProvider*) + * const GrIndexBuffer* GetIndexBuffer(GrResourceProvider*) * * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, * const GrXPOverridesForBatch& overrides) @@ -101,7 +101,7 @@ private: size_t vertexStride = gp->getVertexStride(); int instanceCount = fGeoData.count(); - SkAutoTUnref<const GrBuffer> indexBuffer( + SkAutoTUnref<const GrIndexBuffer> indexBuffer( Impl::GetIndexBuffer(target->resourceProvider())); InstancedHelper helper; void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp index 4ba01884dc..c00e8ecbe6 100644 --- a/src/gpu/batches/GrTessellatingPathRenderer.cpp +++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp @@ -45,7 +45,7 @@ private: } }; -bool cache_match(GrBuffer* vertexBuffer, SkScalar tol, int* actualCount) { +bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { if (!vertexBuffer) { return false; } @@ -68,8 +68,8 @@ public: } SkPoint* lock(int vertexCount) override { size_t size = vertexCount * sizeof(SkPoint); - fVertexBuffer.reset(fResourceProvider->createBuffer( - kVertex_GrBufferType, size, kStatic_GrAccessPattern, 0)); + fVertexBuffer.reset(fResourceProvider->createVertexBuffer( + size, GrResourceProvider::kStatic_BufferUsage, 0)); if (!fVertexBuffer.get()) { return nullptr; } @@ -89,9 +89,9 @@ public: } fVertices = nullptr; } - GrBuffer* vertexBuffer() { return fVertexBuffer.get(); } + GrVertexBuffer* vertexBuffer() { return fVertexBuffer.get(); } private: - SkAutoTUnref<GrBuffer> fVertexBuffer; + SkAutoTUnref<GrVertexBuffer> fVertexBuffer; GrResourceProvider* fResourceProvider; bool fCanMapVB; SkPoint* fVertices; @@ -158,7 +158,8 @@ private: fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]); builder.finish(); GrResourceProvider* rp = target->resourceProvider(); - SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key)); + SkAutoTUnref<GrVertexBuffer> cachedVertexBuffer( + rp->findAndRefTByUniqueKey<GrVertexBuffer>(key)); int actualCount; SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; SkScalar tol = GrPathUtils::scaleToleranceToSrc( @@ -225,7 +226,7 @@ private: this->draw(target, gp.get()); } - void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrBuffer* vb, + void drawVertices(Target* target, const GrGeometryProcessor* gp, const GrVertexBuffer* vb, int firstVertex, int count) const { SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); diff --git a/src/gpu/batches/GrTestBatch.h b/src/gpu/batches/GrTestBatch.h index c28f98d716..3efa3578d5 100644 --- a/src/gpu/batches/GrTestBatch.h +++ b/src/gpu/batches/GrTestBatch.h @@ -10,6 +10,7 @@ #include "GrBatchFlushState.h" #include "GrGeometryProcessor.h" +#include "GrVertexBuffer.h" #include "batches/GrVertexBatch.h" diff --git a/src/gpu/batches/GrVertexBatch.cpp b/src/gpu/batches/GrVertexBatch.cpp index fc7a1e4fae..17bcf8e3af 100644 --- a/src/gpu/batches/GrVertexBatch.cpp +++ b/src/gpu/batches/GrVertexBatch.cpp @@ -17,14 +17,14 @@ void GrVertexBatch::onPrepare(GrBatchFlushState* state) { } void* GrVertexBatch::InstancedHelper::init(Target* target, GrPrimitiveType primType, - size_t vertexStride, const GrBuffer* indexBuffer, + size_t vertexStride, const GrIndexBuffer* indexBuffer, int verticesPerInstance, int indicesPerInstance, int instancesToDraw) { SkASSERT(target); if (!indexBuffer) { return nullptr; } - const GrBuffer* vertexBuffer; + const GrVertexBuffer* vertexBuffer; int firstVertex; int vertexCount = verticesPerInstance * instancesToDraw; void* vertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex); @@ -49,7 +49,7 @@ void GrVertexBatch::InstancedHelper::recordDraw(Target* target) { void* GrVertexBatch::QuadHelper::init(Target* target, size_t vertexStride, int quadsToDraw) { - SkAutoTUnref<const GrBuffer> quadIndexBuffer( + SkAutoTUnref<const GrIndexBuffer> quadIndexBuffer( target->resourceProvider()->refQuadIndexBuffer()); if (!quadIndexBuffer) { SkDebugf("Could not get quad index buffer."); diff --git a/src/gpu/batches/GrVertexBatch.h b/src/gpu/batches/GrVertexBatch.h index 2af4dd1cad..16ba603962 100644 --- a/src/gpu/batches/GrVertexBatch.h +++ b/src/gpu/batches/GrVertexBatch.h @@ -35,7 +35,7 @@ protected: /** Returns the allocated storage for the vertices. The caller should populate the before vertices before calling issueDraws(). */ void* init(Target*, GrPrimitiveType, size_t vertexStride, - const GrBuffer*, int verticesPerInstance, int indicesPerInstance, + const GrIndexBuffer*, int verticesPerInstance, int indicesPerInstance, int instancesToDraw); /** Call after init() to issue draws to the batch target.*/ diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp index 344c125f7e..51507b1e66 100644 --- a/src/gpu/effects/GrDashingEffect.cpp +++ b/src/gpu/effects/GrDashingEffect.cpp @@ -17,6 +17,7 @@ #include "GrInvariantOutput.h" #include "GrProcessor.h" #include "GrStrokeInfo.h" +#include "GrVertexBuffer.h" #include "SkGr.h" #include "batches/GrVertexBatch.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" diff --git a/src/gpu/gl/GrGLBuffer.cpp b/src/gpu/gl/GrGLBuffer.cpp deleted file mode 100644 index ad56ceb729..0000000000 --- a/src/gpu/gl/GrGLBuffer.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrGLBuffer.h" -#include "GrGLGpu.h" -#include "SkTraceMemoryDump.h" - -#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) -#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), RET, X) - -#if GR_GL_CHECK_ALLOC_WITH_GET_ERROR - #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) -#else - #define CLEAR_ERROR_BEFORE_ALLOC(iface) - #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) - #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR -#endif - -#ifdef SK_DEBUG -#define VALIDATE() this->validate() -#else -#define VALIDATE() do {} while(false) -#endif - -GrGLBuffer* GrGLBuffer::Create(GrGLGpu* gpu, GrBufferType type, size_t size, - GrAccessPattern accessPattern) { - static const int kIsVertexOrIndex = (1 << kVertex_GrBufferType) | (1 << kIndex_GrBufferType); - bool cpuBacked = gpu->glCaps().useNonVBOVertexAndIndexDynamicData() && - kDynamic_GrAccessPattern == accessPattern && - ((kIsVertexOrIndex >> type) & 1); - SkAutoTUnref<GrGLBuffer> buffer(new GrGLBuffer(gpu, type, size, accessPattern, cpuBacked)); - if (!cpuBacked && 0 == buffer->fBufferID) { - return nullptr; - } - return buffer.release(); -} - -// GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a client's vertex buffer -// objects are implemented as client-side-arrays on tile-deferred architectures. -#define DYNAMIC_DRAW_PARAM GR_GL_STREAM_DRAW - -inline static void get_target_and_usage(GrBufferType type, GrAccessPattern accessPattern, - const GrGLCaps& caps, GrGLenum* target, GrGLenum* usage) { - static const GrGLenum nonXferTargets[] = { - GR_GL_ARRAY_BUFFER, - GR_GL_ELEMENT_ARRAY_BUFFER - }; - GR_STATIC_ASSERT(0 == kVertex_GrBufferType); - GR_STATIC_ASSERT(1 == kIndex_GrBufferType); - - static const GrGLenum drawUsages[] = { - DYNAMIC_DRAW_PARAM, // TODO: Do we really want to use STREAM_DRAW here on non-Chromium? - GR_GL_STATIC_DRAW, - GR_GL_STREAM_DRAW - }; - static const GrGLenum readUsages[] = { - GR_GL_DYNAMIC_READ, - GR_GL_STATIC_READ, - GR_GL_STREAM_READ - }; - GR_STATIC_ASSERT(0 == kDynamic_GrAccessPattern); - GR_STATIC_ASSERT(1 == kStatic_GrAccessPattern); - GR_STATIC_ASSERT(2 == kStream_GrAccessPattern); - GR_STATIC_ASSERT(SK_ARRAY_COUNT(drawUsages) == 1 + kLast_GrAccessPattern); - GR_STATIC_ASSERT(SK_ARRAY_COUNT(readUsages) == 1 + kLast_GrAccessPattern); - - SkASSERT(accessPattern >= 0 && accessPattern <= kLast_GrAccessPattern); - - switch (type) { - case kVertex_GrBufferType: - case kIndex_GrBufferType: - *target = nonXferTargets[type]; - *usage = drawUsages[accessPattern]; - break; - case kXferCpuToGpu_GrBufferType: - if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferType()) { - *target = GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM; - } else { - SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBufferType()); - *target = GR_GL_PIXEL_UNPACK_BUFFER; - } - *usage = drawUsages[accessPattern]; - break; - case kXferGpuToCpu_GrBufferType: - if (GrGLCaps::kChromium_TransferBufferType == caps.transferBufferType()) { - *target = GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; - } else { - SkASSERT(GrGLCaps::kPBO_TransferBufferType == caps.transferBufferType()); - *target = GR_GL_PIXEL_PACK_BUFFER; - } - *usage = readUsages[accessPattern]; - break; - default: - SkFAIL("Unexpected buffer type."); - break; - } -} - -GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, GrBufferType type, size_t size, GrAccessPattern accessPattern, - bool cpuBacked) - : INHERITED(gpu, type, size, accessPattern, cpuBacked), - fCPUData(nullptr), - fTarget(0), - fBufferID(0), - fSizeInBytes(size), - fUsage(0), - fGLSizeInBytes(0) { - if (cpuBacked) { - if (gpu->caps()->mustClearUploadedBufferData()) { - fCPUData = sk_calloc_throw(fSizeInBytes); - } else { - fCPUData = sk_malloc_flags(fSizeInBytes, SK_MALLOC_THROW); - } - } else { - GL_CALL(GenBuffers(1, &fBufferID)); - fSizeInBytes = size; - get_target_and_usage(type, accessPattern, gpu->glCaps(), &fTarget, &fUsage); - if (fBufferID) { - gpu->bindBuffer(fBufferID, fTarget); - CLEAR_ERROR_BEFORE_ALLOC(gpu->glInterface()); - // make sure driver can allocate memory for this buffer - GL_ALLOC_CALL(gpu->glInterface(), BufferData(fTarget, - (GrGLsizeiptr) fSizeInBytes, - nullptr, // data ptr - fUsage)); - if (CHECK_ALLOC_ERROR(gpu->glInterface()) != GR_GL_NO_ERROR) { - gpu->releaseBuffer(fBufferID, fTarget); - fBufferID = 0; - } else { - fGLSizeInBytes = fSizeInBytes; - } - } - } - VALIDATE(); - this->registerWithCache(); -} - -inline GrGLGpu* GrGLBuffer::glGpu() const { - SkASSERT(!this->wasDestroyed()); - return static_cast<GrGLGpu*>(this->getGpu()); -} - -inline const GrGLCaps& GrGLBuffer::glCaps() const { - return this->glGpu()->glCaps(); -} - -void GrGLBuffer::onRelease() { - if (!this->wasDestroyed()) { - VALIDATE(); - // make sure we've not been abandoned or already released - if (fCPUData) { - SkASSERT(!fBufferID); - sk_free(fCPUData); - fCPUData = nullptr; - } else if (fBufferID) { - this->glGpu()->releaseBuffer(fBufferID, fTarget); - fBufferID = 0; - fGLSizeInBytes = 0; - } - fMapPtr = nullptr; - VALIDATE(); - } - - INHERITED::onRelease(); -} - -void GrGLBuffer::onAbandon() { - fBufferID = 0; - fGLSizeInBytes = 0; - fMapPtr = nullptr; - sk_free(fCPUData); - fCPUData = nullptr; - VALIDATE(); - INHERITED::onAbandon(); -} - -void GrGLBuffer::onMap() { - if (this->wasDestroyed()) { - return; - } - - VALIDATE(); - SkASSERT(!this->isMapped()); - - if (0 == fBufferID) { - fMapPtr = fCPUData; - VALIDATE(); - return; - } - - bool readOnly = (kXferGpuToCpu_GrBufferType == this->type()); - - // Handling dirty context is done in the bindBuffer call - switch (this->glCaps().mapBufferType()) { - case GrGLCaps::kNone_MapBufferType: - break; - case GrGLCaps::kMapBuffer_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Let driver know it can discard the old data - if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GL_CALL_RET(fMapPtr, MapBuffer(fTarget, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); - break; - case GrGLCaps::kMapBufferRange_MapBufferType: { - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Make sure the GL buffer size agrees with fDesc before mapping. - if (fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT; - // TODO: allow the client to specify invalidation in the transfer buffer case. - if (kXferCpuToGpu_GrBufferType != this->type()) { - writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; - } - GL_CALL_RET(fMapPtr, MapBufferRange(fTarget, 0, fSizeInBytes, - readOnly ? GR_GL_MAP_READ_BIT : writeAccess)); - break; - } - case GrGLCaps::kChromium_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - // Make sure the GL buffer size agrees with fDesc before mapping. - if (fGLSizeInBytes != fSizeInBytes) { - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - } - GL_CALL_RET(fMapPtr, MapBufferSubData(fTarget, 0, fSizeInBytes, - readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); - break; - } - fGLSizeInBytes = fSizeInBytes; - VALIDATE(); -} - -void GrGLBuffer::onUnmap() { - if (this->wasDestroyed()) { - return; - } - - VALIDATE(); - SkASSERT(this->isMapped()); - if (0 == fBufferID) { - fMapPtr = nullptr; - return; - } - // bind buffer handles the dirty context - switch (this->glCaps().mapBufferType()) { - case GrGLCaps::kNone_MapBufferType: - SkDEBUGFAIL("Shouldn't get here."); - return; - case GrGLCaps::kMapBuffer_MapBufferType: // fall through - case GrGLCaps::kMapBufferRange_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - GL_CALL(UnmapBuffer(fTarget)); - break; - case GrGLCaps::kChromium_MapBufferType: - this->glGpu()->bindBuffer(fBufferID, fTarget); - GL_CALL(UnmapBufferSubData(fMapPtr)); - break; - } - fMapPtr = nullptr; -} - -bool GrGLBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { - if (this->wasDestroyed()) { - return false; - } - - SkASSERT(!this->isMapped()); - SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTarget); - VALIDATE(); - if (srcSizeInBytes > fSizeInBytes) { - return false; - } - if (0 == fBufferID) { - memcpy(fCPUData, src, srcSizeInBytes); - return true; - } - SkASSERT(srcSizeInBytes <= fSizeInBytes); - // bindbuffer handles dirty context - this->glGpu()->bindBuffer(fBufferID, fTarget); - -#if GR_GL_USE_BUFFER_DATA_NULL_HINT - if (fSizeInBytes == srcSizeInBytes) { - GL_CALL(BufferData(fTarget, (GrGLsizeiptr) srcSizeInBytes, src, fUsage)); - } else { - // Before we call glBufferSubData we give the driver a hint using - // glBufferData with nullptr. This makes the old buffer contents - // inaccessible to future draws. The GPU may still be processing - // draws that reference the old contents. With this hint it can - // assign a different allocation for the new contents to avoid - // flushing the gpu past draws consuming the old contents. - // TODO I think we actually want to try calling bufferData here - GL_CALL(BufferData(fTarget, fSizeInBytes, nullptr, fUsage)); - GL_CALL(BufferSubData(fTarget, 0, (GrGLsizeiptr) srcSizeInBytes, src)); - } - fGLSizeInBytes = fSizeInBytes; -#else - // Note that we're cheating on the size here. Currently no methods - // allow a partial update that preserves contents of non-updated - // portions of the buffer (map() does a glBufferData(..size, nullptr..)) - GL_CALL(BufferData(fTarget, srcSizeInBytes, src, fUsage)); - fGLSizeInBytes = srcSizeInBytes; -#endif - VALIDATE(); - return true; -} - -void GrGLBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, - const SkString& dumpName) const { - SkString buffer_id; - buffer_id.appendU32(this->bufferID()); - traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", - buffer_id.c_str()); -} - -#ifdef SK_DEBUG - -void GrGLBuffer::validate() const { - SkASSERT(GR_GL_ARRAY_BUFFER == fTarget || GR_GL_ELEMENT_ARRAY_BUFFER == fTarget || - GR_GL_PIXEL_PACK_BUFFER == fTarget || GR_GL_PIXEL_UNPACK_BUFFER == fTarget || - GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fTarget || - GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fTarget); - // The following assert isn't valid when the buffer has been abandoned: - // SkASSERT((0 == fDesc.fID) == (fCPUData)); - SkASSERT(0 != fBufferID || 0 == fGLSizeInBytes); - SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fSizeInBytes); - SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr); -} - -#endif diff --git a/src/gpu/gl/GrGLBuffer.h b/src/gpu/gl/GrGLBuffer.h deleted file mode 100644 index 90d2c43dfa..0000000000 --- a/src/gpu/gl/GrGLBuffer.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrGLBuffer_DEFINED -#define GrGLBuffer_DEFINED - -#include "GrBuffer.h" -#include "gl/GrGLTypes.h" - -class GrGLGpu; -class GrGLCaps; - -class GrGLBuffer : public GrBuffer { -public: - static GrGLBuffer* Create(GrGLGpu*, GrBufferType, size_t size, GrAccessPattern); - - ~GrGLBuffer() { - // either release or abandon should have been called by the owner of this object. - SkASSERT(0 == fBufferID); - } - - GrGLenum target() const { return fTarget; } - GrGLuint bufferID() const { return fBufferID; } - size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); } - -protected: - GrGLBuffer(GrGLGpu*, GrBufferType, size_t size, GrAccessPattern, bool cpuBacked); - - void onAbandon() override; - void onRelease() override; - void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, - const SkString& dumpName) const override; - -private: - GrGLGpu* glGpu() const; - const GrGLCaps& glCaps() const; - - void onMap() override; - void onUnmap() override; - bool onUpdateData(const void* src, size_t srcSizeInBytes) override; - -#ifdef SK_DEBUG - void validate() const; -#endif - - void* fCPUData; - GrGLenum fTarget; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER, e.g. - GrGLuint fBufferID; - size_t fSizeInBytes; - GrGLenum fUsage; - size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object - // smaller or larger than the size in fDesc. - - typedef GrBuffer INHERITED; -}; - -#endif diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp new file mode 100644 index 0000000000..2babce8028 --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.cpp @@ -0,0 +1,122 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLBufferImpl.h" +#include "GrGLGpu.h" + +#define GL_CALL(GPU, X) GR_GL_CALL(GPU->glInterface(), X) + +#ifdef SK_DEBUG +#define VALIDATE() this->validate() +#else +#define VALIDATE() do {} while(false) +#endif + +GrGLBufferImpl::GrGLBufferImpl(GrGLGpu* gpu, const Desc& desc, GrGLenum bufferType) + : fDesc(desc) + , fBufferType(bufferType) + , fMapPtr(nullptr) { + if (0 == desc.fID) { + if (gpu->caps()->mustClearUploadedBufferData()) { + fCPUData = sk_calloc_throw(desc.fSizeInBytes); + } else { + fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW); + } + fGLSizeInBytes = 0; + } else { + fCPUData = nullptr; + // We assume that the GL buffer was created at the desc's size initially. + fGLSizeInBytes = fDesc.fSizeInBytes; + } + VALIDATE(); +} + +void GrGLBufferImpl::release(GrGLGpu* gpu) { + VALIDATE(); + // make sure we've not been abandoned or already released + if (fCPUData) { + sk_free(fCPUData); + fCPUData = nullptr; + } else if (fDesc.fID) { + gpu->releaseBuffer(fDesc.fID, fBufferType); + fDesc.fID = 0; + fGLSizeInBytes = 0; + } + fMapPtr = nullptr; + VALIDATE(); +} + +void GrGLBufferImpl::abandon() { + fDesc.fID = 0; + fGLSizeInBytes = 0; + fMapPtr = nullptr; + sk_free(fCPUData); + fCPUData = nullptr; + VALIDATE(); +} + +void* GrGLBufferImpl::map(GrGLGpu* gpu) { + VALIDATE(); + SkASSERT(!this->isMapped()); + if (0 == fDesc.fID) { + fMapPtr = fCPUData; + } else { + fMapPtr = gpu->mapBuffer(fDesc.fID, fBufferType, fDesc.fUsage, fGLSizeInBytes, + fDesc.fSizeInBytes); + fGLSizeInBytes = fDesc.fSizeInBytes; + } + VALIDATE(); + return fMapPtr; +} + +void GrGLBufferImpl::unmap(GrGLGpu* gpu) { + VALIDATE(); + SkASSERT(this->isMapped()); + if (0 != fDesc.fID) { + gpu->unmapBuffer(fDesc.fID, fBufferType, fMapPtr); + } + fMapPtr = nullptr; +} + +bool GrGLBufferImpl::isMapped() const { + VALIDATE(); + return SkToBool(fMapPtr); +} + +bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes) { + SkASSERT(!this->isMapped()); + SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); + VALIDATE(); + if (srcSizeInBytes > fDesc.fSizeInBytes) { + return false; + } + if (0 == fDesc.fID) { + memcpy(fCPUData, src, srcSizeInBytes); + return true; + } + gpu->bufferData(fDesc.fID, fBufferType, fDesc.fUsage, fDesc.fSizeInBytes, src, + srcSizeInBytes); +#if GR_GL_USE_BUFFER_DATA_NULL_HINT + fGLSizeInBytes = fDesc.fSizeInBytes; +#else + fGLSizeInBytes = srcSizeInBytes; +#endif + VALIDATE(); + return true; +} + +void GrGLBufferImpl::validate() const { + SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType || + GR_GL_PIXEL_PACK_BUFFER == fBufferType || GR_GL_PIXEL_UNPACK_BUFFER == fBufferType || + GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM == fBufferType || + GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == fBufferType); + // The following assert isn't valid when the buffer has been abandoned: + // SkASSERT((0 == fDesc.fID) == (fCPUData)); + SkASSERT(nullptr == fCPUData || 0 == fGLSizeInBytes); + SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fDesc.fSizeInBytes); + SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr); +} diff --git a/src/gpu/gl/GrGLBufferImpl.h b/src/gpu/gl/GrGLBufferImpl.h new file mode 100644 index 0000000000..a8f2cced37 --- /dev/null +++ b/src/gpu/gl/GrGLBufferImpl.h @@ -0,0 +1,69 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLBufferImpl_DEFINED +#define GrGLBufferImpl_DEFINED + +#include "SkTypes.h" +#include "gl/GrGLTypes.h" + +class GrGLGpu; + +/** + * This class serves as the implementation of GrGL*Buffer classes. It was written to avoid code + * duplication in those classes. + */ +class GrGLBufferImpl : SkNoncopyable { +public: + enum Usage { + kStaticDraw_Usage = 0, + kDynamicDraw_Usage, + kStreamDraw_Usage, + kStreamRead_Usage, + + kLast_Usage = kStreamRead_Usage + }; + static const int kUsageCount = kLast_Usage + 1; + + struct Desc { + GrGLuint fID; // set to 0 to indicate buffer is CPU-backed and not a VBO. + size_t fSizeInBytes; + Usage fUsage; + }; + + GrGLBufferImpl(GrGLGpu*, const Desc&, GrGLenum bufferType); + ~GrGLBufferImpl() { + // either release or abandon should have been called by the owner of this object. + SkASSERT(0 == fDesc.fID); + } + + void abandon(); + void release(GrGLGpu* gpu); + + GrGLuint bufferID() const { return fDesc.fID; } + size_t baseOffset() const { return reinterpret_cast<size_t>(fCPUData); } + GrGLenum bufferType() const { return fBufferType; } + + void* map(GrGLGpu* gpu); + void unmap(GrGLGpu* gpu); + bool isMapped() const; + bool updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes); + +private: + void validate() const; + + Desc fDesc; + GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER, e.g. + void* fCPUData; + void* fMapPtr; + size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object + // smaller or larger than the size in fDesc. + + typedef SkNoncopyable INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 51974d4c02..50a74febe7 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -400,14 +400,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, // On many GPUs, map memory is very expensive, so we effectively disable it here by setting the // threshold to the maximum unless the client gives us a hint that map memory is cheap. - if (fBufferMapThreshold < 0) { + if (fGeometryBufferMapThreshold < 0) { // We think mapping on Chromium will be cheaper once we know ahead of time how much space // we will use for all GrBatchs. Right now we might wind up mapping a large buffer and using // a small subset. #if 0 - fBufferMapThreshold = kChromium_GrGLDriver == ctxInfo.driver() ? 0 : SK_MaxS32; + fGeometryBufferMapThreshold = kChromium_GrGLDriver == ctxInfo.driver() ? 0 : SK_MaxS32; #else - fBufferMapThreshold = SK_MaxS32; + fGeometryBufferMapThreshold = SK_MaxS32; #endif } diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index c97e605ba8..ff4c457250 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -122,9 +122,7 @@ #define GR_GL_STREAM_DRAW 0x88E0 #define GR_GL_STREAM_READ 0x88E1 #define GR_GL_STATIC_DRAW 0x88E4 -#define GR_GL_STATIC_READ 0x88E5 #define GR_GL_DYNAMIC_DRAW 0x88E8 -#define GR_GL_DYNAMIC_READ 0x88E9 #define GR_GL_BUFFER_SIZE 0x8764 #define GR_GL_BUFFER_USAGE 0x8765 diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 6b591494b9..3a293610f2 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -6,7 +6,6 @@ */ #include "GrGLGpu.h" -#include "GrGLBuffer.h" #include "GrGLGLSL.h" #include "GrGLStencilAttachment.h" #include "GrGLTextureRenderTarget.h" @@ -844,7 +843,7 @@ bool GrGLGpu::onWritePixels(GrSurface* surface, bool GrGLGpu::onTransferPixels(GrSurface* surface, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) { GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); @@ -860,14 +859,16 @@ bool GrGLGpu::onTransferPixels(GrSurface* surface, this->setScratchTextureUnit(); GL_CALL(BindTexture(glTex->target(), glTex->textureID())); - SkASSERT(kXferCpuToGpu_GrBufferType == transferBuffer->type()); - SkASSERT(!transferBuffer->isMapped()); - const GrGLBuffer* glBuffer = reinterpret_cast<const GrGLBuffer*>(transferBuffer); - this->bindBuffer(glBuffer->bufferID(), glBuffer->target()); + SkASSERT(!buffer->isMapped()); + GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer); + // bind the transfer buffer + SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || + GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType()); + GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); bool success = false; GrMipLevel mipLevel; - mipLevel.fPixels = transferBuffer; + mipLevel.fPixels = buffer; mipLevel.fRowBytes = rowBytes; SkSTArray<1, GrMipLevel> texels; texels.push_back(mipLevel); @@ -1932,8 +1933,111 @@ GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen // objects are implemented as client-side-arrays on tile-deferred architectures. #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW -GrBuffer* GrGLGpu::onCreateBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) { - return GrGLBuffer::Create(this, type, size, accessPattern); +GrVertexBuffer* GrGLGpu::onCreateVertexBuffer(size_t size, bool dynamic) { + GrGLVertexBuffer::Desc desc; + desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl::kStaticDraw_Usage; + desc.fSizeInBytes = size; + + if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { + desc.fID = 0; + GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); + return vertexBuffer; + } else { + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + fHWGeometryState.setVertexBufferID(this, desc.fID); + CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); + // make sure driver can allocate memory for this buffer + GL_ALLOC_CALL(this->glInterface(), + BufferData(GR_GL_ARRAY_BUFFER, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + this->notifyVertexBufferDelete(desc.fID); + return nullptr; + } + GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); + return vertexBuffer; + } + return nullptr; + } +} + +GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) { + GrGLIndexBuffer::Desc desc; + desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl::kStaticDraw_Usage; + desc.fSizeInBytes = size; + + if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { + desc.fID = 0; + GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); + return indexBuffer; + } else { + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID); + CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); + // make sure driver can allocate memory for this buffer + GL_ALLOC_CALL(this->glInterface(), + BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + this->notifyIndexBufferDelete(desc.fID); + return nullptr; + } + GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); + return indexBuffer; + } + return nullptr; + } +} + +GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType xferType) { + GrGLCaps::TransferBufferType xferBufferType = this->ctxInfo().caps()->transferBufferType(); + if (GrGLCaps::kNone_TransferBufferType == xferBufferType) { + return nullptr; + } + + GrGLTransferBuffer::Desc desc; + bool toGpu = (kCpuToGpu_TransferType == xferType); + desc.fUsage = toGpu ? GrGLBufferImpl::kStreamDraw_Usage : GrGLBufferImpl::kStreamRead_Usage; + + desc.fSizeInBytes = size; + desc.fID = 0; + GL_CALL(GenBuffers(1, &desc.fID)); + if (desc.fID) { + CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); + // make sure driver can allocate memory for this bmapuffer + GrGLenum target; + if (GrGLCaps::kChromium_TransferBufferType == xferBufferType) { + target = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM + : GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; + } else { + SkASSERT(GrGLCaps::kPBO_TransferBufferType == xferBufferType); + target = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; + } + GL_CALL(BindBuffer(target, desc.fID)); + GL_ALLOC_CALL(this->glInterface(), + BufferData(target, + (GrGLsizeiptr) desc.fSizeInBytes, + nullptr, // data ptr + (toGpu ? GR_GL_STREAM_DRAW : GR_GL_STREAM_READ))); + if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { + GL_CALL(DeleteBuffers(1, &desc.fID)); + return nullptr; + } + GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, target); + return transferBuffer; + } + + return nullptr; } void GrGLGpu::flushScissor(const GrScissorState& scissorState, @@ -2018,18 +2122,18 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso void GrGLGpu::setupGeometry(const GrPrimitiveProcessor& primProc, const GrNonInstancedMesh& mesh, size_t* indexOffsetInBytes) { - const GrGLBuffer* vbuf; - vbuf = static_cast<const GrGLBuffer*>(mesh.vertexBuffer()); + GrGLVertexBuffer* vbuf; + vbuf = (GrGLVertexBuffer*) mesh.vertexBuffer(); SkASSERT(vbuf); SkASSERT(!vbuf->isMapped()); - const GrGLBuffer* ibuf = nullptr; + GrGLIndexBuffer* ibuf = nullptr; if (mesh.isIndexed()) { SkASSERT(indexOffsetInBytes); *indexOffsetInBytes = 0; - ibuf = static_cast<const GrGLBuffer*>(mesh.indexBuffer()); + ibuf = (GrGLIndexBuffer*)mesh.indexBuffer(); SkASSERT(ibuf); SkASSERT(!ibuf->isMapped()); @@ -2119,6 +2223,113 @@ void GrGLGpu::releaseBuffer(GrGLuint id, GrGLenum type) { } } +static GrGLenum get_gl_usage(GrGLBufferImpl::Usage usage) { + static const GrGLenum grToGL[] = { + GR_GL_STATIC_DRAW, // GrGLBufferImpl::kStaticDraw_Usage + DYNAMIC_USAGE_PARAM, // GrGLBufferImpl::kDynamicDraw_Usage + GR_GL_STREAM_DRAW, // GrGLBufferImpl::kStreamDraw_Usage + GR_GL_STREAM_READ, // GrGLBufferImpl::kStreamRead_Usage + }; + static_assert(SK_ARRAY_COUNT(grToGL) == GrGLBufferImpl::kUsageCount, "array_size_mismatch"); + + return grToGL[usage]; +} + +void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, + size_t currentSize, size_t requestedSize) { + void* mapPtr = nullptr; + GrGLenum glUsage = get_gl_usage(usage); + bool readOnly = (GrGLBufferImpl::kStreamRead_Usage == usage); + + // Handling dirty context is done in the bindBuffer call + switch (this->glCaps().mapBufferType()) { + case GrGLCaps::kNone_MapBufferType: + break; + case GrGLCaps::kMapBuffer_MapBufferType: + this->bindBuffer(id, type); + // Let driver know it can discard the old data + if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GL_CALL_RET(mapPtr, MapBuffer(type, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); + break; + case GrGLCaps::kMapBufferRange_MapBufferType: { + this->bindBuffer(id, type); + // Make sure the GL buffer size agrees with fDesc before mapping. + if (currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GrGLbitfield writeAccess = GR_GL_MAP_WRITE_BIT; + // TODO: allow the client to specify invalidation in the stream draw case + if (GrGLBufferImpl::kStreamDraw_Usage != usage) { + writeAccess |= GR_GL_MAP_INVALIDATE_BUFFER_BIT; + } + GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, readOnly ? + GR_GL_MAP_READ_BIT : + writeAccess)); + break; + } + case GrGLCaps::kChromium_MapBufferType: + this->bindBuffer(id, type); + // Make sure the GL buffer size agrees with fDesc before mapping. + if (currentSize != requestedSize) { + GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); + } + GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, readOnly ? + GR_GL_READ_ONLY : + GR_GL_WRITE_ONLY)); + break; + } + return mapPtr; +} + +void GrGLGpu::bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, + size_t currentSize, const void* src, size_t srcSizeInBytes) { + SkASSERT(srcSizeInBytes <= currentSize); + // bindbuffer handles dirty context + this->bindBuffer(id, type); + GrGLenum glUsage = get_gl_usage(usage); + +#if GR_GL_USE_BUFFER_DATA_NULL_HINT + if (currentSize == srcSizeInBytes) { + GL_CALL(BufferData(type, (GrGLsizeiptr) srcSizeInBytes, src, glUsage)); + } else { + // Before we call glBufferSubData we give the driver a hint using + // glBufferData with nullptr. This makes the old buffer contents + // inaccessible to future draws. The GPU may still be processing + // draws that reference the old contents. With this hint it can + // assign a different allocation for the new contents to avoid + // flushing the gpu past draws consuming the old contents. + // TODO I think we actually want to try calling bufferData here + GL_CALL(BufferData(type, currentSize, nullptr, glUsage)); + GL_CALL(BufferSubData(type, 0, (GrGLsizeiptr) srcSizeInBytes, src)); + } +#else + // Note that we're cheating on the size here. Currently no methods + // allow a partial update that preserves contents of non-updated + // portions of the buffer (map() does a glBufferData(..size, nullptr..)) + GL_CALL(BufferData(type, srcSizeInBytes, src, glUsage)); +#endif +} + +void GrGLGpu::unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr) { + // bind buffer handles the dirty context + switch (this->glCaps().mapBufferType()) { + case GrGLCaps::kNone_MapBufferType: + SkDEBUGFAIL("Shouldn't get here."); + return; + case GrGLCaps::kMapBuffer_MapBufferType: // fall through + case GrGLCaps::kMapBufferRange_MapBufferType: + this->bindBuffer(id, type); + GL_CALL(UnmapBuffer(type)); + break; + case GrGLCaps::kChromium_MapBufferType: + this->bindBuffer(id, type); + GL_CALL(UnmapBufferSubData(mapPtr)); + break; + } +} + void GrGLGpu::disableScissor() { if (kNo_TriState != fHWScissorSettings.fEnabled) { GL_CALL(Disable(GR_GL_SCISSOR_TEST)); @@ -4140,8 +4351,8 @@ void GrGLGpu::resetShaderCacheForTesting() const { /////////////////////////////////////////////////////////////////////////////// GrGLAttribArrayState* GrGLGpu::HWGeometryState::bindArrayAndBuffersToDraw( GrGLGpu* gpu, - const GrGLBuffer* vbuffer, - const GrGLBuffer* ibuffer) { + const GrGLVertexBuffer* vbuffer, + const GrGLIndexBuffer* ibuffer) { SkASSERT(vbuffer); GrGLuint vbufferID = vbuffer->bufferID(); GrGLuint* ibufferIDPtr = nullptr; diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index bc79d2f427..bcb3c193dc 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -10,12 +10,15 @@ #include "GrGLContext.h" #include "GrGLIRect.h" +#include "GrGLIndexBuffer.h" #include "GrGLPathRendering.h" #include "GrGLProgram.h" #include "GrGLRenderTarget.h" #include "GrGLStencilAttachment.h" #include "GrGLTexture.h" +#include "GrGLTransferBuffer.h" #include "GrGLVertexArray.h" +#include "GrGLVertexBuffer.h" #include "GrGpu.h" #include "GrPipelineBuilder.h" #include "GrTypes.h" @@ -23,7 +26,6 @@ #include "SkTArray.h" #include "SkTypes.h" -class GrGLBuffer; class GrPipeline; class GrNonInstancedMesh; class GrSwizzle; @@ -99,6 +101,15 @@ public: void releaseBuffer(GrGLuint id, GrGLenum type); + // sizes are in bytes + void* mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize, + size_t requestedSize); + + void unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr); + + void bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage, size_t currentSize, + const void* src, size_t srcSizeInBytes); + const GrGLContext* glContextForTesting() const override { return &this->glContext(); } @@ -138,7 +149,9 @@ private: GrGpuResource::LifeCycle lifeCycle, const SkTArray<GrMipLevel>& texels) override; - GrBuffer* onCreateBuffer(GrBufferType, size_t size, GrAccessPattern) override; + GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override; + GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override; + GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) override; GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override; GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&, GrWrapOwnership) override; @@ -195,7 +208,7 @@ private: bool onTransferPixels(GrSurface*, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) override; void onResolveRenderTarget(GrRenderTarget* target) override; @@ -498,8 +511,8 @@ private: * returned GrGLAttribArrayState should be used to set vertex attribute arrays. */ GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGLGpu* gpu, - const GrGLBuffer* vbuffer, - const GrGLBuffer* ibuffer); + const GrGLVertexBuffer* vbuffer, + const GrGLIndexBuffer* ibuffer); /** Variants of the above that takes GL buffer IDs. Note that 0 does not imply that a buffer won't be bound. The "default buffer" will be bound, which is used for client-side diff --git a/src/gpu/gl/GrGLIndexBuffer.cpp b/src/gpu/gl/GrGLIndexBuffer.cpp new file mode 100644 index 0000000000..5a794ad824 --- /dev/null +++ b/src/gpu/gl/GrGLIndexBuffer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLIndexBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLIndexBuffer::GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc) + : INHERITED(gpu, desc.fSizeInBytes, GrGLBufferImpl::kDynamicDraw_Usage == desc.fUsage, + 0 == desc.fID) + , fImpl(gpu, desc, GR_GL_ELEMENT_ARRAY_BUFFER) { + this->registerWithCache(); +} + +void GrGLIndexBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLIndexBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLIndexBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLIndexBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +bool GrGLIndexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { + if (!this->wasDestroyed()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); + } else { + return false; + } +} + +void GrGLIndexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLIndexBuffer.h b/src/gpu/gl/GrGLIndexBuffer.h new file mode 100644 index 0000000000..628970a0fa --- /dev/null +++ b/src/gpu/gl/GrGLIndexBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLIndexBuffer_DEFINED +#define GrGLIndexBuffer_DEFINED + +#include "GrIndexBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLIndexBuffer : public GrIndexBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLIndexBuffer(GrGLGpu* gpu, const Desc& desc); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + bool onUpdateData(const void* src, size_t srcSizeInBytes) override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrIndexBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLTransferBuffer.cpp b/src/gpu/gl/GrGLTransferBuffer.cpp new file mode 100755 index 0000000000..b7ee766d92 --- /dev/null +++ b/src/gpu/gl/GrGLTransferBuffer.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLTransferBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLTransferBuffer::GrGLTransferBuffer(GrGLGpu* gpu, const Desc& desc, GrGLenum type) + : INHERITED(gpu, desc.fSizeInBytes) + , fImpl(gpu, desc, type) { + this->registerWithCache(); +} + +void GrGLTransferBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLTransferBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLTransferBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLTransferBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +void GrGLTransferBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLTransferBuffer.h b/src/gpu/gl/GrGLTransferBuffer.h new file mode 100755 index 0000000000..e01d4447df --- /dev/null +++ b/src/gpu/gl/GrGLTransferBuffer.h @@ -0,0 +1,48 @@ +/* + * 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 GrGLTransferBuffer_DEFINED +#define GrGLTransferBuffer_DEFINED + +#include "GrTransferBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLTransferBuffer : public GrTransferBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLTransferBuffer(GrGLGpu* gpu, const Desc& desc, GrGLenum type); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + GrGLenum bufferType() const { return fImpl.bufferType(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrTransferBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLVertexArray.h b/src/gpu/gl/GrGLVertexArray.h index 4a99d59058..f5a97672f3 100644 --- a/src/gpu/gl/GrGLVertexArray.h +++ b/src/gpu/gl/GrGLVertexArray.h @@ -13,6 +13,8 @@ #include "gl/GrGLTypes.h" #include "SkTArray.h" +class GrGLVertexBuffer; +class GrGLIndexBuffer; class GrGLGpu; /** diff --git a/src/gpu/gl/GrGLVertexBuffer.cpp b/src/gpu/gl/GrGLVertexBuffer.cpp new file mode 100644 index 0000000000..2294844fc4 --- /dev/null +++ b/src/gpu/gl/GrGLVertexBuffer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLVertexBuffer.h" +#include "GrGLGpu.h" +#include "SkTraceMemoryDump.h" + +GrGLVertexBuffer::GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc) + : INHERITED(gpu, desc.fSizeInBytes, GrGLBufferImpl::kDynamicDraw_Usage == desc.fUsage, + 0 == desc.fID) + , fImpl(gpu, desc, GR_GL_ARRAY_BUFFER) { + this->registerWithCache(); +} + +void GrGLVertexBuffer::onRelease() { + if (!this->wasDestroyed()) { + fImpl.release(this->getGpuGL()); + } + + INHERITED::onRelease(); +} + +void GrGLVertexBuffer::onAbandon() { + fImpl.abandon(); + INHERITED::onAbandon(); +} + +void* GrGLVertexBuffer::onMap() { + if (!this->wasDestroyed()) { + return fImpl.map(this->getGpuGL()); + } else { + return nullptr; + } +} + +void GrGLVertexBuffer::onUnmap() { + if (!this->wasDestroyed()) { + fImpl.unmap(this->getGpuGL()); + } +} + +bool GrGLVertexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) { + if (!this->wasDestroyed()) { + return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes); + } else { + return false; + } +} + +void GrGLVertexBuffer::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const { + SkString buffer_id; + buffer_id.appendU32(this->bufferID()); + traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_buffer", + buffer_id.c_str()); +} diff --git a/src/gpu/gl/GrGLVertexBuffer.h b/src/gpu/gl/GrGLVertexBuffer.h new file mode 100644 index 0000000000..93c6b2badd --- /dev/null +++ b/src/gpu/gl/GrGLVertexBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLVertexBuffer_DEFINED +#define GrGLVertexBuffer_DEFINED + +#include "GrVertexBuffer.h" +#include "GrGLBufferImpl.h" +#include "gl/GrGLInterface.h" + +class GrGLGpu; + +class GrGLVertexBuffer : public GrVertexBuffer { + +public: + typedef GrGLBufferImpl::Desc Desc; + + GrGLVertexBuffer(GrGLGpu* gpu, const Desc& desc); + + GrGLuint bufferID() const { return fImpl.bufferID(); } + size_t baseOffset() const { return fImpl.baseOffset(); } + +protected: + void onAbandon() override; + void onRelease() override; + void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, + const SkString& dumpName) const override; + +private: + void* onMap() override; + void onUnmap() override; + bool onUpdateData(const void* src, size_t srcSizeInBytes) override; + + GrGLGpu* getGpuGL() const { + SkASSERT(!this->wasDestroyed()); + return (GrGLGpu*)(this->getGpu()); + } + + GrGLBufferImpl fImpl; + + typedef GrVertexBuffer INHERITED; +}; + +#endif diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index 35aef7a29a..7cfddbab2a 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -29,7 +29,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* fUseDrawInsteadOfClear = false; //TODO: figure this out fMapBufferFlags = kNone_MapFlags; //TODO: figure this out - fBufferMapThreshold = SK_MaxS32; //TODO: figure this out + fGeometryBufferMapThreshold = SK_MaxS32; //TODO: figure this out fMaxRenderTargetSize = 4096; // minimum required by spec fMaxTextureSize = 4096; // minimum required by spec @@ -112,7 +112,7 @@ void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties, // Assuming since we will always map in the end to upload the data we might as well just map // from the get go. There is no hard data to suggest this is faster or slower. - fBufferMapThreshold = 0; + fGeometryBufferMapThreshold = 0; fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag; diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 5796f11d51..21e4ee358d 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -171,26 +171,18 @@ void GrVkGpu::submitCommandBuffer(SyncQueue sync) { } /////////////////////////////////////////////////////////////////////////////// -GrBuffer* GrVkGpu::onCreateBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) { - switch (type) { - case kVertex_GrBufferType: - SkASSERT(kDynamic_GrAccessPattern == accessPattern || - kStatic_GrAccessPattern == accessPattern); - return GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); - case kIndex_GrBufferType: - SkASSERT(kDynamic_GrAccessPattern == accessPattern || - kStatic_GrAccessPattern == accessPattern); - return GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern); - case kXferCpuToGpu_GrBufferType: - SkASSERT(kStream_GrAccessPattern == accessPattern); - return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type); - case kXferGpuToCpu_GrBufferType: - SkASSERT(kStream_GrAccessPattern == accessPattern); - return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type); - default: - SkFAIL("Unknown buffer type."); - return nullptr; - } +GrVertexBuffer* GrVkGpu::onCreateVertexBuffer(size_t size, bool dynamic) { + return GrVkVertexBuffer::Create(this, size, dynamic); +} + +GrIndexBuffer* GrVkGpu::onCreateIndexBuffer(size_t size, bool dynamic) { + return GrVkIndexBuffer::Create(this, size, dynamic); +} + +GrTransferBuffer* GrVkGpu::onCreateTransferBuffer(size_t size, TransferType type) { + GrVkBuffer::Type bufferType = kCpuToGpu_TransferType ? GrVkBuffer::kCopyRead_Type + : GrVkBuffer::kCopyWrite_Type; + return GrVkTransferBuffer::Create(this, size, bufferType); } //////////////////////////////////////////////////////////////////////////////// @@ -1225,9 +1217,8 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, false); GrVkTransferBuffer* transferBuffer = - static_cast<GrVkTransferBuffer*>(this->createBuffer(kXferGpuToCpu_GrBufferType, - rowBytes * height, - kStream_GrAccessPattern)); + reinterpret_cast<GrVkTransferBuffer*>(this->createTransferBuffer(rowBytes * height, + kGpuToCpu_TransferType)); bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); VkOffset3D offset = { diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index a9a8a41d97..a6911f773b 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -136,7 +136,9 @@ private: GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&, GrWrapOwnership) override { return NULL; } - GrBuffer* onCreateBuffer(GrBufferType, size_t size, GrAccessPattern) override; + GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override; + GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override; + GrTransferBuffer* onCreateTransferBuffer(size_t size, TransferType type) override; void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override; @@ -159,7 +161,7 @@ private: bool onTransferPixels(GrSurface*, int left, int top, int width, int height, - GrPixelConfig config, GrBuffer* transferBuffer, + GrPixelConfig config, GrTransferBuffer* buffer, size_t offset, size_t rowBytes) override { return false; } void onResolveRenderTarget(GrRenderTarget* target) override {} diff --git a/src/gpu/vk/GrVkIndexBuffer.cpp b/src/gpu/vk/GrVkIndexBuffer.cpp index 6cec856cd4..52f7bd59b7 100644 --- a/src/gpu/vk/GrVkIndexBuffer.cpp +++ b/src/gpu/vk/GrVkIndexBuffer.cpp @@ -10,8 +10,7 @@ GrVkIndexBuffer::GrVkIndexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, const GrVkBuffer::Resource* bufferResource) - : INHERITED(gpu, kIndex_GrBufferType, desc.fSizeInBytes, - desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false) + : INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, false) , GrVkBuffer(desc, bufferResource) { this->registerWithCache(); } @@ -48,9 +47,11 @@ void GrVkIndexBuffer::onAbandon() { INHERITED::onAbandon(); } -void GrVkIndexBuffer::onMap() { +void* GrVkIndexBuffer::onMap() { if (!this->wasDestroyed()) { - this->GrBuffer::fMapPtr = this->vkMap(this->getVkGpu()); + return this->vkMap(this->getVkGpu()); + } else { + return NULL; } } diff --git a/src/gpu/vk/GrVkIndexBuffer.h b/src/gpu/vk/GrVkIndexBuffer.h index 4bca5a6b5c..84bbbd3377 100644 --- a/src/gpu/vk/GrVkIndexBuffer.h +++ b/src/gpu/vk/GrVkIndexBuffer.h @@ -8,13 +8,13 @@ #ifndef GrVkIndexBuffer_DEFINED #define GrVkIndexBuffer_DEFINED -#include "GrBuffer.h" +#include "GrIndexBuffer.h" #include "GrVkBuffer.h" #include "vk/GrVkInterface.h" class GrVkGpu; -class GrVkIndexBuffer : public GrBuffer, public GrVkBuffer { +class GrVkIndexBuffer : public GrIndexBuffer, public GrVkBuffer { public: static GrVkIndexBuffer* Create(GrVkGpu* gpu, size_t size, bool dynamic); @@ -27,13 +27,13 @@ private: GrVkIndexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, const GrVkBuffer::Resource* resource); - void onMap() override; + void* onMap() override; void onUnmap() override; bool onUpdateData(const void* src, size_t srcSizeInBytes) override; GrVkGpu* getVkGpu() const; - typedef GrBuffer INHERITED; + typedef GrIndexBuffer INHERITED; }; #endif diff --git a/src/gpu/vk/GrVkTransferBuffer.cpp b/src/gpu/vk/GrVkTransferBuffer.cpp index 43fd3af9a9..3730627764 100644 --- a/src/gpu/vk/GrVkTransferBuffer.cpp +++ b/src/gpu/vk/GrVkTransferBuffer.cpp @@ -31,9 +31,7 @@ GrVkTransferBuffer* GrVkTransferBuffer::Create(GrVkGpu* gpu, size_t size, GrVkBu GrVkTransferBuffer::GrVkTransferBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, const GrVkBuffer::Resource* bufferResource) - : INHERITED(gpu, kCopyRead_Type == desc.fType ? - kXferCpuToGpu_GrBufferType : kXferGpuToCpu_GrBufferType, - desc.fSizeInBytes, kStream_GrAccessPattern, false) + : INHERITED(gpu, desc.fSizeInBytes) , GrVkBuffer(desc, bufferResource) { this->registerWithCache(); } diff --git a/src/gpu/vk/GrVkTransferBuffer.h b/src/gpu/vk/GrVkTransferBuffer.h index c6ca2147b3..f978df95fd 100644 --- a/src/gpu/vk/GrVkTransferBuffer.h +++ b/src/gpu/vk/GrVkTransferBuffer.h @@ -8,13 +8,13 @@ #ifndef GrVkTransferBuffer_DEFINED #define GrVkTransferBuffer_DEFINED -#include "GrBuffer.h" +#include "GrTransferBuffer.h" #include "GrVkBuffer.h" #include "vk/GrVkInterface.h" class GrVkGpu; -class GrVkTransferBuffer : public GrBuffer, public GrVkBuffer { +class GrVkTransferBuffer : public GrTransferBuffer, public GrVkBuffer { public: static GrVkTransferBuffer* Create(GrVkGpu* gpu, size_t size, GrVkBuffer::Type type); @@ -29,9 +29,11 @@ private: void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, const SkString& dumpName) const override; - void onMap() override { + void* onMap() override { if (!this->wasDestroyed()) { - this->GrBuffer::fMapPtr = this->vkMap(this->getVkGpu()); + return this->vkMap(this->getVkGpu()); + } else { + return nullptr; } } @@ -41,17 +43,12 @@ private: } } - bool onUpdateData(const void* src, size_t srcSizeInBytes) override { - SkFAIL("Not implemented for transfer buffers."); - return false; - } - GrVkGpu* getVkGpu() const { SkASSERT(!this->wasDestroyed()); return reinterpret_cast<GrVkGpu*>(this->getGpu()); } - typedef GrBuffer INHERITED; + typedef GrTransferBuffer INHERITED; }; #endif diff --git a/src/gpu/vk/GrVkVertexBuffer.cpp b/src/gpu/vk/GrVkVertexBuffer.cpp index 1d3eadb42c..46c6d28f23 100644 --- a/src/gpu/vk/GrVkVertexBuffer.cpp +++ b/src/gpu/vk/GrVkVertexBuffer.cpp @@ -10,8 +10,7 @@ GrVkVertexBuffer::GrVkVertexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, const GrVkBuffer::Resource* bufferResource) - : INHERITED(gpu, kVertex_GrBufferType, desc.fSizeInBytes, - desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false) + : INHERITED(gpu, desc.fSizeInBytes, desc.fDynamic, false) , GrVkBuffer(desc, bufferResource) { this->registerWithCache(); } @@ -47,9 +46,11 @@ void GrVkVertexBuffer::onAbandon() { INHERITED::onAbandon(); } -void GrVkVertexBuffer::onMap() { +void* GrVkVertexBuffer::onMap() { if (!this->wasDestroyed()) { - this->GrBuffer::fMapPtr = this->vkMap(this->getVkGpu()); + return this->vkMap(this->getVkGpu()); + } else { + return NULL; } } diff --git a/src/gpu/vk/GrVkVertexBuffer.h b/src/gpu/vk/GrVkVertexBuffer.h index 7786f6275c..82f00597b7 100644 --- a/src/gpu/vk/GrVkVertexBuffer.h +++ b/src/gpu/vk/GrVkVertexBuffer.h @@ -8,13 +8,13 @@ #ifndef GrVkVertexBuffer_DEFINED #define GrVkVertexBuffer_DEFINED -#include "GrBuffer.h" +#include "GrVertexBuffer.h" #include "GrVkBuffer.h" #include "vk/GrVkInterface.h" class GrVkGpu; -class GrVkVertexBuffer : public GrBuffer, public GrVkBuffer { +class GrVkVertexBuffer : public GrVertexBuffer, public GrVkBuffer { public: static GrVkVertexBuffer* Create(GrVkGpu* gpu, size_t size, bool dynamic); @@ -26,13 +26,13 @@ private: GrVkVertexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc, const GrVkBuffer::Resource* resource); - void onMap() override; + void* onMap() override; void onUnmap() override; bool onUpdateData(const void* src, size_t srcSizeInBytes) override; GrVkGpu* getVkGpu() const; - typedef GrBuffer INHERITED; + typedef GrVertexBuffer INHERITED; }; #endif |