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
This commit is contained in:
jvanverth 2015-12-07 07:36:44 -08:00 committed by Commit bot
parent 776d49b41b
commit d7a2c1f5fd
5 changed files with 62 additions and 12 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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;