Add support for glMapBufferRange. Use glMapBufferRange and glMapBufferSubData.
BUG=skia:2402 R=robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/243413002 git-svn-id: http://skia.googlecode.com/svn/trunk@14533 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
daf48e02ad
commit
f9deb8a15d
@ -111,6 +111,7 @@ extern "C" {
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEndQueryProc)(GrGLenum target);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFinishProc)();
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFlushProc)();
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFlushMappedBufferRangeProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferRenderbufferProc)(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferTexture2DProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFramebufferTexture2DMultisampleProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level, GrGLsizei samples);
|
||||
@ -150,6 +151,7 @@ extern "C" {
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLineWidthProc)(GrGLfloat width);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLLinkProgramProc)(GrGLuint program);
|
||||
typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapBufferProc)(GrGLenum target, GrGLenum access);
|
||||
typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapBufferRangeProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access);
|
||||
typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapBufferSubDataProc)(GrGLuint target, GrGLintptr offset, GrGLsizeiptr size, GrGLenum access);
|
||||
typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLenum access);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPixelStoreiProc)(GrGLenum pname, GrGLint param);
|
||||
|
@ -192,6 +192,7 @@ public:
|
||||
GLPtr<GrGLEndQueryProc> fEndQuery;
|
||||
GLPtr<GrGLFinishProc> fFinish;
|
||||
GLPtr<GrGLFlushProc> fFlush;
|
||||
GLPtr<GrGLFlushMappedBufferRangeProc> fFlushMappedBufferRange;
|
||||
GLPtr<GrGLFramebufferRenderbufferProc> fFramebufferRenderbuffer;
|
||||
GLPtr<GrGLFramebufferTexture2DProc> fFramebufferTexture2D;
|
||||
GLPtr<GrGLFramebufferTexture2DMultisampleProc> fFramebufferTexture2DMultisample;
|
||||
@ -231,6 +232,7 @@ public:
|
||||
GLPtr<GrGLLineWidthProc> fLineWidth;
|
||||
GLPtr<GrGLLinkProgramProc> fLinkProgram;
|
||||
GLPtr<GrGLMapBufferProc> fMapBuffer;
|
||||
GLPtr<GrGLMapBufferRangeProc> fMapBufferRange;
|
||||
GLPtr<GrGLMapBufferSubDataProc> fMapBufferSubData;
|
||||
GLPtr<GrGLMapTexSubImage2DProc> fMapTexSubImage2D;
|
||||
GLPtr<GrGLMatrixLoadfProc> fMatrixLoadf;
|
||||
|
@ -303,7 +303,7 @@ bool GrBufferAllocPool::createBlock(size_t requestSize) {
|
||||
// threshold (since we don't expect it is likely that we will see more vertex data)
|
||||
// b) If the hint is not set we lock if the buffer size is greater than the threshold.
|
||||
bool attemptLock = block.fBuffer->isCPUBacked();
|
||||
if (!attemptLock && fGpu->caps()->bufferLockSupport()) {
|
||||
if (!attemptLock && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
|
||||
if (fFrequentResetHint) {
|
||||
attemptLock = requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD;
|
||||
} else {
|
||||
@ -351,7 +351,7 @@ void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
|
||||
SkASSERT(flushSize <= buffer->sizeInBytes());
|
||||
VALIDATE(true);
|
||||
|
||||
if (fGpu->caps()->bufferLockSupport() &&
|
||||
if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
|
||||
flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
|
||||
void* data = buffer->lock();
|
||||
if (NULL != data) {
|
||||
|
@ -1016,13 +1016,14 @@ void GrDrawTargetCaps::reset() {
|
||||
fShaderDerivativeSupport = false;
|
||||
fGeometryShaderSupport = false;
|
||||
fDualSourceBlendingSupport = false;
|
||||
fBufferLockSupport = false;
|
||||
fPathRenderingSupport = false;
|
||||
fDstReadInShaderSupport = false;
|
||||
fDiscardRenderTargetSupport = false;
|
||||
fReuseScratchTextures = true;
|
||||
fGpuTracingSupport = false;
|
||||
|
||||
fMapBufferFlags = kNone_MapFlags;
|
||||
|
||||
fMaxRenderTargetSize = 0;
|
||||
fMaxTextureSize = 0;
|
||||
fMaxSampleCount = 0;
|
||||
@ -1040,13 +1041,14 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
|
||||
fShaderDerivativeSupport = other.fShaderDerivativeSupport;
|
||||
fGeometryShaderSupport = other.fGeometryShaderSupport;
|
||||
fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
|
||||
fBufferLockSupport = other.fBufferLockSupport;
|
||||
fPathRenderingSupport = other.fPathRenderingSupport;
|
||||
fDstReadInShaderSupport = other.fDstReadInShaderSupport;
|
||||
fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
|
||||
fReuseScratchTextures = other.fReuseScratchTextures;
|
||||
fGpuTracingSupport = other.fGpuTracingSupport;
|
||||
|
||||
fMapBufferFlags = other.fMapBufferFlags;
|
||||
|
||||
fMaxRenderTargetSize = other.fMaxRenderTargetSize;
|
||||
fMaxTextureSize = other.fMaxTextureSize;
|
||||
fMaxSampleCount = other.fMaxSampleCount;
|
||||
@ -1056,6 +1058,26 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
static SkString map_flags_to_string(uint32_t flags) {
|
||||
SkString str;
|
||||
if (GrDrawTargetCaps::kNone_MapFlags == flags) {
|
||||
str = "none";
|
||||
} else {
|
||||
SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags);
|
||||
SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag);
|
||||
str = "can_map";
|
||||
|
||||
if (GrDrawTargetCaps::kSubset_MapFlag & flags) {
|
||||
str.append(" partial");
|
||||
} else {
|
||||
str.append(" full");
|
||||
}
|
||||
SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag);
|
||||
}
|
||||
SkASSERT(0 == flags); // Make sure we handled all the flags.
|
||||
return str;
|
||||
}
|
||||
|
||||
SkString GrDrawTargetCaps::dump() const {
|
||||
SkString r;
|
||||
static const char* gNY[] = {"NO", "YES"};
|
||||
@ -1068,7 +1090,6 @@ SkString GrDrawTargetCaps::dump() const {
|
||||
r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
|
||||
r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
|
||||
r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
|
||||
r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
|
||||
r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
|
||||
r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
|
||||
r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]);
|
||||
@ -1078,6 +1099,8 @@ SkString GrDrawTargetCaps::dump() const {
|
||||
r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
|
||||
r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
|
||||
|
||||
r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str());
|
||||
|
||||
static const char* kConfigNames[] = {
|
||||
"Unknown", // kUnknown_GrPixelConfig
|
||||
"Alpha8", // kAlpha_8_GrPixelConfig,
|
||||
|
@ -37,12 +37,25 @@ public:
|
||||
bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
|
||||
bool geometryShaderSupport() const { return fGeometryShaderSupport; }
|
||||
bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
|
||||
bool bufferLockSupport() const { return fBufferLockSupport; }
|
||||
bool pathRenderingSupport() const { return fPathRenderingSupport; }
|
||||
bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
|
||||
bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
|
||||
bool gpuTracingSupport() const { return fGpuTracingSupport; }
|
||||
|
||||
/**
|
||||
* Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
|
||||
* textures allows partial mappings or full mappings.
|
||||
*/
|
||||
enum MapFlags {
|
||||
kNone_MapFlags = 0x0, //<! Cannot map the resource.
|
||||
|
||||
kCanMap_MapFlag = 0x1, //<! The resource can be mapped. Must be set for any of
|
||||
// the other flags to have meaning.k
|
||||
kSubset_MapFlag = 0x2, //<! The resource can be partially mapped.
|
||||
};
|
||||
|
||||
uint32_t mapBufferFlags() const { return fMapBufferFlags; }
|
||||
|
||||
// Scratch textures not being reused means that those scratch textures
|
||||
// that we upload to (i.e., don't have a render target) will not be
|
||||
// recycled in the texture cache. This is to prevent ghosting by drivers
|
||||
@ -69,13 +82,14 @@ protected:
|
||||
bool fShaderDerivativeSupport : 1;
|
||||
bool fGeometryShaderSupport : 1;
|
||||
bool fDualSourceBlendingSupport : 1;
|
||||
bool fBufferLockSupport : 1;
|
||||
bool fPathRenderingSupport : 1;
|
||||
bool fDstReadInShaderSupport : 1;
|
||||
bool fDiscardRenderTargetSupport: 1;
|
||||
bool fReuseScratchTextures : 1;
|
||||
bool fGpuTracingSupport : 1;
|
||||
|
||||
uint32_t fMapBufferFlags;
|
||||
|
||||
int fMaxRenderTargetSize;
|
||||
int fMaxTextureSize;
|
||||
int fMaxSampleCount;
|
||||
|
@ -173,6 +173,11 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
|
||||
GET_PROC(DeleteVertexArrays);
|
||||
}
|
||||
|
||||
if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_map_buffer_range")) {
|
||||
GET_PROC(MapBufferRange);
|
||||
GET_PROC(FlushMappedBufferRange);
|
||||
}
|
||||
|
||||
// First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
|
||||
// GL_ARB_framebuffer_object doesn't use ARB suffix.)
|
||||
if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
|
||||
|
@ -26,20 +26,22 @@ GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferTy
|
||||
, fLockPtr(NULL) {
|
||||
if (0 == desc.fID) {
|
||||
fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
|
||||
fGLSizeInBytes = 0;
|
||||
} else {
|
||||
fCPUData = NULL;
|
||||
// We assume that the GL buffer was created at the desc's size initially.
|
||||
fGLSizeInBytes = fDesc.fSizeInBytes;
|
||||
}
|
||||
VALIDATE();
|
||||
}
|
||||
|
||||
void GrGLBufferImpl::release(GrGpuGL* gpu) {
|
||||
VALIDATE();
|
||||
// make sure we've not been abandoned or already released
|
||||
if (NULL != fCPUData) {
|
||||
VALIDATE();
|
||||
sk_free(fCPUData);
|
||||
fCPUData = NULL;
|
||||
} else if (fDesc.fID && !fDesc.fIsWrapped) {
|
||||
VALIDATE();
|
||||
GL_CALL(gpu, DeleteBuffers(1, &fDesc.fID));
|
||||
if (GR_GL_ARRAY_BUFFER == fBufferType) {
|
||||
gpu->notifyVertexBufferDelete(fDesc.fID);
|
||||
@ -48,15 +50,19 @@ void GrGLBufferImpl::release(GrGpuGL* gpu) {
|
||||
gpu->notifyIndexBufferDelete(fDesc.fID);
|
||||
}
|
||||
fDesc.fID = 0;
|
||||
fGLSizeInBytes = 0;
|
||||
}
|
||||
fLockPtr = NULL;
|
||||
VALIDATE();
|
||||
}
|
||||
|
||||
void GrGLBufferImpl::abandon() {
|
||||
fDesc.fID = 0;
|
||||
fGLSizeInBytes = 0;
|
||||
fLockPtr = NULL;
|
||||
sk_free(fCPUData);
|
||||
fCPUData = NULL;
|
||||
VALIDATE();
|
||||
}
|
||||
|
||||
void GrGLBufferImpl::bind(GrGpuGL* gpu) const {
|
||||
@ -67,6 +73,7 @@ void GrGLBufferImpl::bind(GrGpuGL* gpu) const {
|
||||
SkASSERT(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType);
|
||||
gpu->bindIndexBufferAndDefaultVertexArray(fDesc.fID);
|
||||
}
|
||||
VALIDATE();
|
||||
}
|
||||
|
||||
void* GrGLBufferImpl::lock(GrGpuGL* gpu) {
|
||||
@ -74,17 +81,55 @@ void* GrGLBufferImpl::lock(GrGpuGL* gpu) {
|
||||
SkASSERT(!this->isLocked());
|
||||
if (0 == fDesc.fID) {
|
||||
fLockPtr = fCPUData;
|
||||
} else if (gpu->caps()->bufferLockSupport()) {
|
||||
this->bind(gpu);
|
||||
// Let driver know it can discard the old data
|
||||
GL_CALL(gpu, BufferData(fBufferType,
|
||||
(GrGLsizeiptr) fDesc.fSizeInBytes,
|
||||
NULL,
|
||||
fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
|
||||
GR_GL_CALL_RET(gpu->glInterface(),
|
||||
fLockPtr,
|
||||
MapBuffer(fBufferType, GR_GL_WRITE_ONLY));
|
||||
} else {
|
||||
switch (gpu->glCaps().mapBufferType()) {
|
||||
case GrGLCaps::kNone_MapBufferType:
|
||||
VALIDATE();
|
||||
return NULL;
|
||||
case GrGLCaps::kMapBuffer_MapBufferType:
|
||||
this->bind(gpu);
|
||||
// Let driver know it can discard the old data
|
||||
if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fDesc.fSizeInBytes != fGLSizeInBytes) {
|
||||
fGLSizeInBytes = fDesc.fSizeInBytes;
|
||||
GL_CALL(gpu,
|
||||
BufferData(fBufferType, fGLSizeInBytes, NULL,
|
||||
fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
|
||||
}
|
||||
GR_GL_CALL_RET(gpu->glInterface(), fLockPtr,
|
||||
MapBuffer(fBufferType, GR_GL_WRITE_ONLY));
|
||||
break;
|
||||
case GrGLCaps::kMapBufferRange_MapBufferType: {
|
||||
this->bind(gpu);
|
||||
// Make sure the GL buffer size agrees with fDesc before mapping.
|
||||
if (fDesc.fSizeInBytes != fGLSizeInBytes) {
|
||||
fGLSizeInBytes = fDesc.fSizeInBytes;
|
||||
GL_CALL(gpu,
|
||||
BufferData(fBufferType, fGLSizeInBytes, NULL,
|
||||
fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
|
||||
}
|
||||
static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT |
|
||||
GR_GL_MAP_WRITE_BIT;
|
||||
GR_GL_CALL_RET(gpu->glInterface(),
|
||||
fLockPtr,
|
||||
MapBufferRange(fBufferType, 0, fGLSizeInBytes, kAccess));
|
||||
break;
|
||||
}
|
||||
case GrGLCaps::kChromium_MapBufferType:
|
||||
this->bind(gpu);
|
||||
// Make sure the GL buffer size agrees with fDesc before mapping.
|
||||
if (fDesc.fSizeInBytes != fGLSizeInBytes) {
|
||||
fGLSizeInBytes = fDesc.fSizeInBytes;
|
||||
GL_CALL(gpu,
|
||||
BufferData(fBufferType, fGLSizeInBytes, NULL,
|
||||
fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
|
||||
}
|
||||
GR_GL_CALL_RET(gpu->glInterface(),
|
||||
fLockPtr,
|
||||
MapBufferSubData(fBufferType, 0, fGLSizeInBytes, GR_GL_WRITE_ONLY));
|
||||
break;
|
||||
}
|
||||
}
|
||||
VALIDATE();
|
||||
return fLockPtr;
|
||||
}
|
||||
|
||||
@ -92,9 +137,20 @@ void GrGLBufferImpl::unlock(GrGpuGL* gpu) {
|
||||
VALIDATE();
|
||||
SkASSERT(this->isLocked());
|
||||
if (0 != fDesc.fID) {
|
||||
SkASSERT(gpu->caps()->bufferLockSupport());
|
||||
this->bind(gpu);
|
||||
GL_CALL(gpu, UnmapBuffer(fBufferType));
|
||||
switch (gpu->glCaps().mapBufferType()) {
|
||||
case GrGLCaps::kNone_MapBufferType:
|
||||
SkDEBUGFAIL("Shouldn't get here.");
|
||||
return;
|
||||
case GrGLCaps::kMapBuffer_MapBufferType: // fall through
|
||||
case GrGLCaps::kMapBufferRange_MapBufferType:
|
||||
this->bind(gpu);
|
||||
GL_CALL(gpu, UnmapBuffer(fBufferType));
|
||||
break;
|
||||
case GrGLCaps::kChromium_MapBufferType:
|
||||
this->bind(gpu);
|
||||
GR_GL_CALL(gpu->glInterface(), UnmapBufferSubData(fLockPtr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
fLockPtr = NULL;
|
||||
}
|
||||
@ -127,7 +183,8 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB
|
||||
// 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.
|
||||
GL_CALL(gpu, BufferData(fBufferType, (GrGLsizeiptr) fDesc.fSizeInBytes, NULL, usage));
|
||||
fGLSizeInBytes = fDesc.fSizeInBytes;
|
||||
GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage));
|
||||
GL_CALL(gpu, BufferSubData(fBufferType, 0, (GrGLsizeiptr) srcSizeInBytes, src));
|
||||
}
|
||||
#else
|
||||
@ -147,10 +204,12 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB
|
||||
// Chromium's command buffer may turn a glBufferSubData where the size
|
||||
// exactly matches the buffer size into a glBufferData. So we tack 1
|
||||
// extra byte onto the glBufferData.
|
||||
GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes + 1, NULL, usage));
|
||||
fGLSizeInBytes = srcSizeInBytes + 1;
|
||||
GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage));
|
||||
GL_CALL(gpu, BufferSubData(fBufferType, 0, srcSizeInBytes, src));
|
||||
} else {
|
||||
GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes, src, usage));
|
||||
fGLSizeInBytes = srcSizeInBytes;
|
||||
GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, src, usage));
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
@ -161,5 +220,7 @@ void GrGLBufferImpl::validate() const {
|
||||
// The following assert isn't valid when the buffer has been abandoned:
|
||||
// SkASSERT((0 == fDesc.fID) == (NULL != fCPUData));
|
||||
SkASSERT(0 != fDesc.fID || !fDesc.fIsWrapped);
|
||||
SkASSERT(NULL == fCPUData || 0 == fGLSizeInBytes);
|
||||
SkASSERT(NULL == fLockPtr || fGLSizeInBytes == fDesc.fSizeInBytes);
|
||||
SkASSERT(NULL == fCPUData || NULL == fLockPtr || fCPUData == fLockPtr);
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ private:
|
||||
GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
|
||||
void* fCPUData;
|
||||
void* fLockPtr;
|
||||
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;
|
||||
};
|
||||
|
@ -24,6 +24,7 @@ void GrGLCaps::reset() {
|
||||
fMSFBOType = kNone_MSFBOType;
|
||||
fFBFetchType = kNone_FBFetchType;
|
||||
fInvalidateFBType = kNone_InvalidateFBType;
|
||||
fMapBufferType = kNone_MapBufferType;
|
||||
fMaxFragmentUniformVectors = 0;
|
||||
fMaxVertexAttributes = 0;
|
||||
fMaxFragmentTextureUnits = 0;
|
||||
@ -47,7 +48,6 @@ void GrGLCaps::reset() {
|
||||
fIsCoreProfile = false;
|
||||
fFullClearIsFree = false;
|
||||
fDropsTileOnZeroDivide = false;
|
||||
fMapSubSupport = false;
|
||||
}
|
||||
|
||||
GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
|
||||
@ -66,6 +66,7 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
|
||||
fMSFBOType = caps.fMSFBOType;
|
||||
fFBFetchType = caps.fFBFetchType;
|
||||
fInvalidateFBType = caps.fInvalidateFBType;
|
||||
fMapBufferType = caps.fMapBufferType;
|
||||
fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
|
||||
fBGRAFormatSupport = caps.fBGRAFormatSupport;
|
||||
fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
|
||||
@ -85,7 +86,6 @@ GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
|
||||
fIsCoreProfile = caps.fIsCoreProfile;
|
||||
fFullClearIsFree = caps.fFullClearIsFree;
|
||||
fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
|
||||
fMapSubSupport = caps.fMapSubSupport;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -290,12 +290,27 @@ bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
fBufferLockSupport = true; // we require VBO support and the desktop VBO extension includes
|
||||
// glMapBuffer.
|
||||
fMapSubSupport = false;
|
||||
fMapBufferFlags = kCanMap_MapFlag; // we require VBO support and the desktop VBO
|
||||
// extension includes glMapBuffer.
|
||||
if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_map_buffer_range")) {
|
||||
fMapBufferFlags |= kSubset_MapFlag;
|
||||
fMapBufferType = kMapBufferRange_MapBufferType;
|
||||
} else {
|
||||
fMapBufferType = kMapBuffer_MapBufferType;
|
||||
}
|
||||
} else {
|
||||
fBufferLockSupport = ctxInfo.hasExtension("GL_OES_mapbuffer");
|
||||
fMapSubSupport = ctxInfo.hasExtension("GL_CHROMIUM_map_sub");
|
||||
// Unextended GLES2 doesn't have any buffer mapping.
|
||||
fMapBufferFlags = kNone_MapBufferType;
|
||||
if (ctxInfo.hasExtension("GL_CHROMIUM_map_sub")) {
|
||||
fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
|
||||
fMapBufferType = kChromium_MapBufferType;
|
||||
} else if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_EXT_map_buffer_range")) {
|
||||
fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
|
||||
fMapBufferType = kMapBufferRange_MapBufferType;
|
||||
} else if (ctxInfo.hasExtension("GL_OES_mapbuffer")) {
|
||||
fMapBufferFlags = kCanMap_MapFlag;
|
||||
fMapBufferType = kMapBuffer_MapBufferType;
|
||||
}
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
@ -655,10 +670,23 @@ SkString GrGLCaps::dump() const {
|
||||
GR_STATIC_ASSERT(2 == kInvalidate_InvalidateFBType);
|
||||
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kInvalidateFBTypeStr) == kLast_InvalidateFBType + 1);
|
||||
|
||||
static const char* kMapBufferTypeStr[] = {
|
||||
"None",
|
||||
"MapBuffer",
|
||||
"MapBufferRange",
|
||||
"Chromium",
|
||||
};
|
||||
GR_STATIC_ASSERT(0 == kNone_MapBufferType);
|
||||
GR_STATIC_ASSERT(1 == kMapBuffer_MapBufferType);
|
||||
GR_STATIC_ASSERT(2 == kMapBufferRange_MapBufferType);
|
||||
GR_STATIC_ASSERT(3 == kChromium_MapBufferType);
|
||||
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMapBufferTypeStr) == kLast_MapBufferType + 1);
|
||||
|
||||
r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
|
||||
r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
|
||||
r.appendf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]);
|
||||
r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
|
||||
r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
|
||||
r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
|
||||
r.appendf("Max FS Texture Units: %d\n", fMaxFragmentTextureUnits);
|
||||
if (!fIsCoreProfile) {
|
||||
|
@ -86,6 +86,15 @@ public:
|
||||
kLast_InvalidateFBType = kInvalidate_InvalidateFBType
|
||||
};
|
||||
|
||||
enum MapBufferType {
|
||||
kNone_MapBufferType,
|
||||
kMapBuffer_MapBufferType, // glMapBuffer()
|
||||
kMapBufferRange_MapBufferType, // glMapBufferRange()
|
||||
kChromium_MapBufferType, // GL_CHROMIUM_map_sub
|
||||
|
||||
kLast_MapBufferType = kChromium_MapBufferType,
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a GrGLCaps that advertises no support for any extensions,
|
||||
* formats, etc. Call init to initialize from a GrGLContextInfo.
|
||||
@ -169,10 +178,8 @@ public:
|
||||
|
||||
InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
|
||||
|
||||
/**
|
||||
* Returs a string containeng the caps info.
|
||||
*/
|
||||
virtual SkString dump() const SK_OVERRIDE;
|
||||
/// What type of buffer mapping is supported?
|
||||
MapBufferType mapBufferType() const { return fMapBufferType; }
|
||||
|
||||
/**
|
||||
* Gets an array of legal stencil formats. These formats are not guaranteed
|
||||
@ -258,8 +265,10 @@ public:
|
||||
|
||||
bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
|
||||
|
||||
/// Is GL_CHROMIUM_map_sub supported?
|
||||
bool mapSubSupport() const { return fMapSubSupport; }
|
||||
/**
|
||||
* Returns a string containing the caps info.
|
||||
*/
|
||||
virtual SkString dump() const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -322,6 +331,7 @@ private:
|
||||
MSFBOType fMSFBOType;
|
||||
FBFetchType fFBFetchType;
|
||||
InvalidateFBType fInvalidateFBType;
|
||||
MapBufferType fMapBufferType;
|
||||
|
||||
bool fRGBA8RenderbufferSupport : 1;
|
||||
bool fBGRAFormatSupport : 1;
|
||||
@ -342,7 +352,6 @@ private:
|
||||
bool fIsCoreProfile : 1;
|
||||
bool fFullClearIsFree : 1;
|
||||
bool fDropsTileOnZeroDivide : 1;
|
||||
bool fMapSubSupport : 1;
|
||||
|
||||
typedef GrDrawTargetCaps INHERITED;
|
||||
};
|
||||
|
@ -186,8 +186,29 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* id
|
||||
}
|
||||
}
|
||||
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBufferRange(GrGLenum target, GrGLintptr offset,
|
||||
GrGLsizeiptr length, GrGLbitfield access) {
|
||||
GrGLuint id = 0;
|
||||
switch (target) {
|
||||
case GR_GL_ARRAY_BUFFER:
|
||||
id = gCurrArrayBuffer;
|
||||
break;
|
||||
case GR_GL_ELEMENT_ARRAY_BUFFER:
|
||||
id = gCurrElementArrayBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
if (id > 0) {
|
||||
// We just ignore the offset and length here.
|
||||
GrBufferObj* buffer = look_up(id);
|
||||
SkASSERT(!buffer->mapped());
|
||||
buffer->setMapped(true);
|
||||
return buffer->dataPtr();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
|
||||
GrGLuint id = 0;
|
||||
switch (target) {
|
||||
case GR_GL_ARRAY_BUFFER:
|
||||
@ -209,6 +230,11 @@ GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access)
|
||||
return NULL; // no buffer bound to target
|
||||
}
|
||||
|
||||
GrGLvoid GR_GL_FUNCTION_TYPE nullGLFlushMappedBufferRange(GrGLenum target,
|
||||
GrGLintptr offset,
|
||||
GrGLsizeiptr length) {}
|
||||
|
||||
|
||||
GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) {
|
||||
GrGLuint id = 0;
|
||||
switch (target) {
|
||||
@ -304,6 +330,7 @@ const GrGLInterface* GrGLCreateNullInterface() {
|
||||
functions->fEndQuery = noOpGLEndQuery;
|
||||
functions->fFinish = noOpGLFinish;
|
||||
functions->fFlush = noOpGLFlush;
|
||||
functions->fFlushMappedBufferRange = nullGLFlushMappedBufferRange;
|
||||
functions->fFrontFace = noOpGLFrontFace;
|
||||
functions->fGenBuffers = nullGLGenBuffers;
|
||||
functions->fGenerateMipmap = nullGLGenerateMipmap;
|
||||
@ -329,6 +356,8 @@ const GrGLInterface* GrGLCreateNullInterface() {
|
||||
functions->fInsertEventMarker = noOpGLInsertEventMarker;
|
||||
functions->fLineWidth = noOpGLLineWidth;
|
||||
functions->fLinkProgram = noOpGLLinkProgram;
|
||||
functions->fMapBuffer = nullGLMapBuffer;
|
||||
functions->fMapBufferRange = nullGLMapBufferRange;
|
||||
functions->fPixelStorei = nullGLPixelStorei;
|
||||
functions->fPopGroupMarker = noOpGLPopGroupMarker;
|
||||
functions->fPushGroupMarker = noOpGLPushGroupMarker;
|
||||
@ -368,6 +397,7 @@ const GrGLInterface* GrGLCreateNullInterface() {
|
||||
functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
|
||||
functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
|
||||
functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
|
||||
functions->fUnmapBuffer = nullGLUnmapBuffer;
|
||||
functions->fUseProgram = nullGLUseProgram;
|
||||
functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
|
||||
functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
|
||||
@ -387,10 +417,8 @@ const GrGLInterface* GrGLCreateNullInterface() {
|
||||
functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample;
|
||||
functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
|
||||
functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer;
|
||||
functions->fMapBuffer = nullGLMapBuffer;
|
||||
functions->fMatrixLoadf = noOpGLMatrixLoadf;
|
||||
functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
|
||||
functions->fUnmapBuffer = nullGLUnmapBuffer;
|
||||
functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed;
|
||||
|
||||
interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
|
||||
|
@ -601,6 +601,14 @@
|
||||
/* Vertex Buffer Object */
|
||||
#define GR_GL_WRITE_ONLY 0x88B9
|
||||
#define GR_GL_BUFFER_MAPPED 0x88BC
|
||||
|
||||
#define GR_GL_MAP_READ_BIT 0x0001
|
||||
#define GR_GL_MAP_WRITE_BIT 0x0002
|
||||
#define GR_GL_MAP_INVALIDATE_RANGE_BIT 0x0004
|
||||
#define GR_GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
|
||||
#define GR_GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
|
||||
#define GR_GL_MAP_UNSYNCHRONIZED_BIT 0x0020
|
||||
|
||||
/* Read Format */
|
||||
#define GR_GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
|
||||
|
@ -486,8 +486,8 @@ bool GrGLInterface::validate() const {
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // This can be enabled once Chromium is updated to set these functions pointers.
|
||||
if ((kGL_GrGLStandard == fStandard) || fExtensions.has("GL_ARB_invalidate_subdata")) {
|
||||
if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
|
||||
fExtensions.has("GL_ARB_invalidate_subdata")) {
|
||||
if (NULL == fFunctions.fInvalidateBufferData ||
|
||||
NULL == fFunctions.fInvalidateBufferSubData ||
|
||||
NULL == fFunctions.fInvalidateFramebuffer ||
|
||||
@ -496,7 +496,7 @@ bool GrGLInterface::validate() const {
|
||||
NULL == fFunctions.fInvalidateTexSubImage) {
|
||||
RETURN_FALSE_INTERFACE;
|
||||
}
|
||||
} else if (glVer >= GR_GL_VER(3,0)) {
|
||||
} else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
|
||||
// ES 3.0 adds the framebuffer functions but not the others.
|
||||
if (NULL == fFunctions.fInvalidateFramebuffer ||
|
||||
NULL == fFunctions.fInvalidateSubFramebuffer) {
|
||||
@ -512,7 +512,15 @@ bool GrGLInterface::validate() const {
|
||||
RETURN_FALSE_INTERFACE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// These functions are added to the 3.0 version of both GLES and GL.
|
||||
if (glVer >= GR_GL_VER(3,0) ||
|
||||
(kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) ||
|
||||
(kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) {
|
||||
if (NULL == fFunctions.fMapBufferRange ||
|
||||
NULL == fFunctions.fFlushMappedBufferRange) {
|
||||
RETURN_FALSE_INTERFACE;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ static GrGLInterface* create_es_interface(GrGLVersion version,
|
||||
functions->fGetShaderInfoLog = glGetShaderInfoLog;
|
||||
functions->fGetShaderiv = glGetShaderiv;
|
||||
functions->fGetString = glGetString;
|
||||
#if GL_ES_VERSION_30
|
||||
#if GL_ES_VERSION_3_0
|
||||
functions->fGetStringi = glGetStringi;
|
||||
#else
|
||||
functions->fGetStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
|
||||
@ -183,12 +183,24 @@ static GrGLInterface* create_es_interface(GrGLVersion version,
|
||||
functions->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
|
||||
functions->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
|
||||
functions->fRenderbufferStorage = glRenderbufferStorage;
|
||||
|
||||
#if GL_OES_mapbuffer
|
||||
functions->fMapBuffer = glMapBufferOES;
|
||||
functions->fUnmapBuffer = glUnmapBufferOES;
|
||||
#else
|
||||
functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
|
||||
functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
|
||||
|
||||
#endif
|
||||
|
||||
#if GL_ES_VERSION_3_0 || GL_EXT_map_buffer_range
|
||||
functions->fMapBufferRange = glMapBufferRange;
|
||||
functions->fFlushMappedBufferRange = glFlushMappedBufferRange;
|
||||
#else
|
||||
if (version >= GR_GL_VER(3,0) || extensions->has("GL_EXT_map_buffer_range")) {
|
||||
functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRange");
|
||||
functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRange");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (extensions->has("GL_EXT_debug_marker")) {
|
||||
|
@ -154,6 +154,14 @@ const GrGLInterface* GrGLCreateANGLEInterface() {
|
||||
functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
|
||||
functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
|
||||
|
||||
#if GL_ES_VERSION_3_0
|
||||
functions->fMapBufferRange = GET_PROC(glMapBufferRange);
|
||||
functions->fFlushMappedBufferRange = GET_PROC(glFlushMappedBufferRange);
|
||||
#else
|
||||
functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRange");
|
||||
functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRange");
|
||||
#endif
|
||||
|
||||
functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarkerEXT");
|
||||
functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarkerEXT");
|
||||
functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGroupMarkerEXT");
|
||||
|
@ -34,9 +34,15 @@ public:
|
||||
GrAlwaysAssert(!fMapped);
|
||||
}
|
||||
|
||||
void setMapped() { fMapped = true; }
|
||||
void setMapped(GrGLintptr offset, GrGLsizeiptr length) {
|
||||
fMapped = true;
|
||||
fMappedOffset = offset;
|
||||
fMappedLength = length;
|
||||
}
|
||||
void resetMapped() { fMapped = false; }
|
||||
bool getMapped() const { return fMapped; }
|
||||
GrGLsizei getMappedOffset() const { return fMappedOffset; }
|
||||
GrGLsizei getMappedLength() const { return fMappedLength; }
|
||||
|
||||
void setBound() { fBound = true; }
|
||||
void resetBound() { fBound = false; }
|
||||
@ -55,7 +61,9 @@ protected:
|
||||
private:
|
||||
|
||||
GrGLchar* fDataPtr;
|
||||
bool fMapped; // is the buffer object mapped via "glMapBuffer"?
|
||||
bool fMapped; // is the buffer object mapped via "glMapBuffer[Range]"?
|
||||
GrGLintptr fMappedOffset; // the offset of the buffer range that is mapped
|
||||
GrGLsizeiptr fMappedLength; // the size of the buffer range that is mapped
|
||||
bool fBound; // is the buffer object bound via "glBindBuffer"?
|
||||
GrGLsizeiptr fSize; // size in bytes
|
||||
GrGLint fUsage; // one of: GL_STREAM_DRAW,
|
||||
|
@ -622,11 +622,40 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* i
|
||||
}
|
||||
|
||||
// map a buffer to the caller's address space
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
|
||||
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBufferRange(GrGLenum target, GrGLintptr offset,
|
||||
GrGLsizeiptr length, GrGLbitfield access) {
|
||||
GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
|
||||
GR_GL_ELEMENT_ARRAY_BUFFER == target);
|
||||
// GR_GL_READ_ONLY == access || || GR_GL_READ_WRIT == access);
|
||||
|
||||
// We only expect read access and we expect that the buffer or range is always invalidated.
|
||||
GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
|
||||
GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
|
||||
|
||||
GrBufferObj *buffer = NULL;
|
||||
switch (target) {
|
||||
case GR_GL_ARRAY_BUFFER:
|
||||
buffer = GrDebugGL::getInstance()->getArrayBuffer();
|
||||
break;
|
||||
case GR_GL_ELEMENT_ARRAY_BUFFER:
|
||||
buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unexpected target to glMapBufferRange");
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL != buffer) {
|
||||
GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
|
||||
GrAlwaysAssert(!buffer->getMapped());
|
||||
buffer->setMapped(offset, length);
|
||||
return buffer->getDataPtr() + offset;
|
||||
}
|
||||
|
||||
GrAlwaysAssert(false);
|
||||
return NULL; // no buffer bound to the target
|
||||
}
|
||||
|
||||
GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
|
||||
GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
|
||||
|
||||
GrBufferObj *buffer = NULL;
|
||||
@ -642,14 +671,8 @@ GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access)
|
||||
break;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
GrAlwaysAssert(!buffer->getMapped());
|
||||
buffer->setMapped();
|
||||
return buffer->getDataPtr();
|
||||
}
|
||||
|
||||
GrAlwaysAssert(false);
|
||||
return NULL; // no buffer bound to the target
|
||||
return debugGLMapBufferRange(target, 0, buffer->getSize(),
|
||||
GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// remove a buffer from the caller's address space
|
||||
@ -672,7 +695,7 @@ GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
if (NULL != buffer) {
|
||||
GrAlwaysAssert(buffer->getMapped());
|
||||
buffer->resetMapped();
|
||||
return GR_GL_TRUE;
|
||||
@ -682,6 +705,34 @@ GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
|
||||
return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
GrGLvoid GR_GL_FUNCTION_TYPE debugGLFlushMappedBufferRange(GrGLenum target,
|
||||
GrGLintptr offset,
|
||||
GrGLsizeiptr length) {
|
||||
GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
|
||||
GR_GL_ELEMENT_ARRAY_BUFFER == target);
|
||||
|
||||
GrBufferObj *buffer = NULL;
|
||||
switch (target) {
|
||||
case GR_GL_ARRAY_BUFFER:
|
||||
buffer = GrDebugGL::getInstance()->getArrayBuffer();
|
||||
break;
|
||||
case GR_GL_ELEMENT_ARRAY_BUFFER:
|
||||
buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unexpected target to glUnmapBuffer");
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL != buffer) {
|
||||
GrAlwaysAssert(buffer->getMapped());
|
||||
GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
|
||||
} else {
|
||||
GrAlwaysAssert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
|
||||
GrGLenum value,
|
||||
GrGLint* params) {
|
||||
@ -706,17 +757,17 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
|
||||
switch (value) {
|
||||
case GR_GL_BUFFER_MAPPED:
|
||||
*params = GR_GL_FALSE;
|
||||
if (buffer)
|
||||
if (NULL != buffer)
|
||||
*params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
|
||||
break;
|
||||
case GR_GL_BUFFER_SIZE:
|
||||
*params = 0;
|
||||
if (buffer)
|
||||
if (NULL != buffer)
|
||||
*params = SkToInt(buffer->getSize());
|
||||
break;
|
||||
case GR_GL_BUFFER_USAGE:
|
||||
*params = GR_GL_STATIC_DRAW;
|
||||
if (buffer)
|
||||
if (NULL != buffer)
|
||||
*params = buffer->getUsage();
|
||||
break;
|
||||
default:
|
||||
@ -826,6 +877,7 @@ const GrGLInterface* GrGLCreateDebugInterface() {
|
||||
functions->fEndQuery = noOpGLEndQuery;
|
||||
functions->fFinish = noOpGLFinish;
|
||||
functions->fFlush = noOpGLFlush;
|
||||
functions->fFlushMappedBufferRange = debugGLFlushMappedBufferRange;
|
||||
functions->fFrontFace = noOpGLFrontFace;
|
||||
functions->fGenerateMipmap = debugGLGenerateMipmap;
|
||||
functions->fGenBuffers = debugGLGenBuffers;
|
||||
@ -850,6 +902,8 @@ const GrGLInterface* GrGLCreateDebugInterface() {
|
||||
functions->fGenVertexArrays = debugGLGenVertexArrays;
|
||||
functions->fLineWidth = noOpGLLineWidth;
|
||||
functions->fLinkProgram = noOpGLLinkProgram;
|
||||
functions->fMapBuffer = debugGLMapBuffer;
|
||||
functions->fMapBufferRange = debugGLMapBufferRange;
|
||||
functions->fPixelStorei = debugGLPixelStorei;
|
||||
functions->fQueryCounter = noOpGLQueryCounter;
|
||||
functions->fReadBuffer = noOpGLReadBuffer;
|
||||
@ -887,6 +941,7 @@ const GrGLInterface* GrGLCreateDebugInterface() {
|
||||
functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
|
||||
functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
|
||||
functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
|
||||
functions->fUnmapBuffer = debugGLUnmapBuffer;
|
||||
functions->fUseProgram = debugGLUseProgram;
|
||||
functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
|
||||
functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
|
||||
@ -909,10 +964,9 @@ const GrGLInterface* GrGLCreateDebugInterface() {
|
||||
functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
|
||||
functions->fResolveMultisampleFramebuffer =
|
||||
noOpGLResolveMultisampleFramebuffer;
|
||||
functions->fMapBuffer = debugGLMapBuffer;
|
||||
functions->fMatrixLoadf = noOpGLMatrixLoadf;
|
||||
functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
|
||||
functions->fUnmapBuffer = debugGLUnmapBuffer;
|
||||
|
||||
functions->fBindFragDataLocationIndexed =
|
||||
noOpGLBindFragDataLocationIndexed;
|
||||
|
||||
|
@ -132,6 +132,11 @@ const GrGLInterface* GrGLCreateNativeInterface() {
|
||||
functions->fUnmapBuffer = glUnmapBufferOES;
|
||||
#endif
|
||||
|
||||
#if GL_EXT_map_buffer_range || GL_ES_VERSION_3_0
|
||||
functions->fMapBufferRange = glMapBufferRange;
|
||||
functions->fFlushMappedBufferRange = glFlushMappedBufferRange;
|
||||
#endif
|
||||
|
||||
#if GL_APPLE_framebuffer_multisample
|
||||
functions->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleAPPLE;
|
||||
functions->fResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE;
|
||||
|
Loading…
Reference in New Issue
Block a user