From d7a2c1f5fd710581d6233de5c202d3f2627948e0 Mon Sep 17 00:00:00 2001 From: jvanverth Date: Mon, 7 Dec 2015 07:36:44 -0800 Subject: [PATCH] Add transfer buffer to GLCaps Adds a check for PBO/transfer buffer support to GrGLCaps, and uses that to pick the correct buffer type. BUG=skia:4604 Review URL: https://codereview.chromium.org/1503593002 --- src/gpu/gl/GrGLBufferImpl.cpp | 4 +++- src/gpu/gl/GrGLCaps.cpp | 13 ++++++++++++ src/gpu/gl/GrGLCaps.h | 12 +++++++++++ src/gpu/gl/GrGLDefines.h | 6 +++++- src/gpu/gl/GrGLGpu.cpp | 39 ++++++++++++++++++++++++++--------- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp index 07fc7a1584..2babce8028 100644 --- a/src/gpu/gl/GrGLBufferImpl.cpp +++ b/src/gpu/gl/GrGLBufferImpl.cpp @@ -111,7 +111,9 @@ bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInB 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_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); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index a768b37105..6c0ee19584 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -23,6 +23,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fInvalidateFBType = kNone_InvalidateFBType; fLATCAlias = kLATC_LATCAlias; fMapBufferType = kNone_MapBufferType; + fTransferBufferType = kNone_TransferBufferType; fMaxFragmentUniformVectors = 0; fMaxVertexAttributes = 0; fMaxFragmentTextureUnits = 0; @@ -370,6 +371,18 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, } } + if (kGL_GrGLStandard == standard) { + if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_pixel_buffer_object")) { + fTransferBufferType = kPBO_TransferBufferType; + } + } else { + if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_NV_pixel_buffer_object")) { + fTransferBufferType = kPBO_TransferBufferType; + } else if (ctxInfo.hasExtension("GL_CHROMIUM_pixel_transfer_buffer_object")) { + fTransferBufferType = kChromium_TransferBufferType; + } + } + // 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 (fGeometryBufferMapThreshold < 0) { diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 0ec6c85b47..026ae23fb7 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -90,6 +90,14 @@ public: kLast_MapBufferType = kChromium_MapBufferType, }; + enum TransferBufferType { + kNone_TransferBufferType, + kPBO_TransferBufferType, // ARB_pixel_buffer_object + kChromium_TransferBufferType, // CHROMIUM_pixel_transfer_buffer_object + + kLast_TransferBufferType = kChromium_TransferBufferType, + }; + /** * Initializes the GrGLCaps to the set of features supported in the current * OpenGL context accessible via ctxInfo. @@ -143,6 +151,9 @@ public: /// What type of buffer mapping is supported? MapBufferType mapBufferType() const { return fMapBufferType; } + /// What type of transfer buffer is supported? + TransferBufferType transferBufferType() const { return fTransferBufferType; } + /** * Gets an array of legal stencil formats. These formats are not guaranteed * to be supported by the driver but are legal GLenum names given the GL @@ -337,6 +348,7 @@ private: MSFBOType fMSFBOType; InvalidateFBType fInvalidateFBType; MapBufferType fMapBufferType; + TransferBufferType fTransferBufferType; LATCAlias fLATCAlias; bool fRGBA8RenderbufferSupport : 1; diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index 4570f4c94b..f0b56ae989 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -113,6 +113,9 @@ #define GR_GL_PIXEL_PACK_BUFFER 0x88EB #define GR_GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM 0x78EC +#define GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM 0x78ED + #define GR_GL_STREAM_DRAW 0x88E0 #define GR_GL_STREAM_READ 0x88E1 #define GR_GL_STATIC_DRAW 0x88E4 @@ -705,7 +708,8 @@ #define GR_GL_T2F_C4F_N3F_V3F 0x2A2C #define GR_GL_T4F_C4F_N3F_V4F 0x2A2D -/* Vertex Buffer Object */ +/* Buffer Object */ +#define GR_GL_READ_ONLY 0x88B8 #define GR_GL_WRITE_ONLY 0x88B9 #define GR_GL_BUFFER_MAPPED 0x88BC diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 5b6ae7cc18..ecaf09091b 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1479,19 +1479,30 @@ GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) { } } -GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType type) { +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 == type); + bool toGpu = (kCpuToGpu_TransferType == xferType); desc.fUsage = toGpu ? GrGLBufferImpl::kStreamDraw_Usage : GrGLBufferImpl::kStreamRead_Usage; desc.fSizeInBytes = size; - // TODO: check caps to see if we can create a PBO, and which kind GL_CALL(GenBuffers(1, &desc.fID)); if (desc.fID) { CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); - // make sure driver can allocate memory for this buffer - GrGLenum type = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; + // make sure driver can allocate memory for this bmapuffer + GrGLenum type; + if (GrGLCaps::kChromium_TransferBufferType == xferBufferType) { + type = toGpu ? GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM + : GR_GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM; + } else { + SkASSERT(GrGLCaps::kPBO_TransferBufferType == xferBufferType); + type = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUFFER; + } GL_ALLOC_CALL(this->glInterface(), BufferData(type, (GrGLsizeiptr) desc.fSizeInBytes, @@ -1650,6 +1661,8 @@ void GrGLGpu::bindBuffer(GrGLuint id, GrGLenum type) { this->bindVertexBuffer(id); } else if (GR_GL_ELEMENT_ARRAY_BUFFER == type) { this->bindIndexBufferAndDefaultVertexArray(id); + } else { + GR_GL_CALL(this->glInterface(), BindBuffer(type, id)); } } @@ -1679,6 +1692,8 @@ 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: @@ -1689,7 +1704,7 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize) { GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); } - GL_CALL_RET(mapPtr, MapBuffer(type, GR_GL_WRITE_ONLY)); + GL_CALL_RET(mapPtr, MapBuffer(type, readOnly ? GR_GL_READ_ONLY : GR_GL_WRITE_ONLY)); break; case GrGLCaps::kMapBufferRange_MapBufferType: { this->bindBuffer(id, type); @@ -1697,9 +1712,11 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage if (currentSize != requestedSize) { GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); } - static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT | - GR_GL_MAP_WRITE_BIT; - GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, kAccess)); + static const GrGLbitfield kWriteAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT | + GR_GL_MAP_WRITE_BIT; + GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, readOnly ? + GR_GL_MAP_READ_BIT : + kWriteAccess)); break; } case GrGLCaps::kChromium_MapBufferType: @@ -1708,7 +1725,9 @@ void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage if (currentSize != requestedSize) { GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); } - GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, GR_GL_WRITE_ONLY)); + GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, readOnly ? + GR_GL_READ_ONLY : + GR_GL_WRITE_ONLY)); break; } return mapPtr;