Add optional per-gl-func client callback.

Review URL: http://codereview.appspot.com/4964055/



git-svn-id: http://skia.googlecode.com/svn/trunk@2207 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-09-01 13:28:16 +00:00
Родитель 9399cac0a1
Коммит 56bfc5acc2
8 изменённых файлов: 132 добавлений и 55 удалений

Просмотреть файл

@ -68,6 +68,15 @@
* However, this can cause a performance decrease on Chrome cmd buffer because
* it will create a new allocation and memset the whole thing to zero (for
* security reasons). Defaults to 1 (enabled).
*
* GR_GL_PER_GL_FUNC_CALLBACK: When set to 1 the GrGLInterface object provides
* a function pointer that is called just before every gl function. The ptr must
* be valid (i.e. there is no NULL check). However, by default the callback will
* be set to a function that does nothing. The signature of the function is:
* void function(const GrGLInterface*)
* It is not extern "C".
* The GrGLInterface field fCallback specifies the function ptr and there is an
* additional field fCallbackData of type intptr_t for client data.
*/
#if !defined(GR_GL_LOG_CALLS)
@ -98,6 +107,10 @@
#define GR_GL_USE_BUFFER_DATA_NULL_HINT 1
#endif
#if !defined(GR_GL_PER_GL_FUNC_CALLBACK)
#define GR_GL_PER_GL_FUNC_CALLBACK 0
#endif
#if(GR_GL_NO_CONSTANT_ATTRIBUTES) && (GR_GL_ATTRIBUTE_MATRICES)
#error "Cannot combine GR_GL_NO_CONSTANT_ATTRIBUTES and GR_GL_ATTRIBUTE_MATRICES"
#endif
@ -175,13 +188,37 @@ extern void GrGLClearErr(const GrGLInterface* gl);
#define GR_GL_LOG_CALLS_IMPL(X)
#endif
#if GR_GL_PER_GL_FUNC_CALLBACK
#define GR_GL_CALLBACK_IMPL(IFACE) (IFACE)->fCallback(IFACE)
#else
#define GR_GL_CALLBACK_IMPL(IFACE)
#endif
#define GR_GL_CALL(IFACE, X) \
GR_GL_CALL_NOERRCHECK(IFACE, X) \
GR_GL_CHECK_ERROR_IMPL(IFACE, X)
do { \
GR_GL_CALL_NOERRCHECK(IFACE, X); \
GR_GL_CHECK_ERROR_IMPL(IFACE, X); \
} while (false)
#define GR_GL_CALL_NOERRCHECK(IFACE, X) \
IFACE->f##X; \
GR_GL_LOG_CALLS_IMPL(X);
do { \
GR_GL_CALLBACK_IMPL(IFACE); \
(IFACE)->f##X; \
GR_GL_LOG_CALLS_IMPL(X); \
} while (false)
#define GR_GL_CALL_RET(IFACE, RET, X) \
do { \
GR_GL_CALL_RET_NOERRCHECK(IFACE, RET, X); \
GR_GL_CHECK_ERROR_IMPL(IFACE, X); \
} while (false)
#define GR_GL_CALL_RET_NOERRCHECK(IFACE, RET, X) \
do { \
GR_GL_CALLBACK_IMPL(IFACE); \
(RET) = (IFACE)->f##X; \
GR_GL_LOG_CALLS_IMPL(X); \
} while (false)
#define GR_GL_GET_ERROR(IFACE) (IFACE)->fGetError()

Просмотреть файл

@ -21,4 +21,7 @@
// with NULL.
#define GR_GL_USE_BUFFER_DATA_NULL_HINT 0
// chrome uses this to set the context on each GL call.
#define GR_GL_PER_GL_FUNC_CALLBACK 1
#endif

Просмотреть файл

@ -53,6 +53,10 @@ float gl_version_as_float(const GrGLInterface*);
* also an implementation that does nothing. You can link in any of the provided
* implementations or your own implementation that sets up the GL function
* pointers for your specific platform.
*
* By defining GR_GL_PER_GL_CALL_IFACE_CALLBACK to 1 the client can specify a
* callback function that will be called prior to each GL function call. See
* comments in GrGLConfig.h
*/
struct GrGLInterface;
@ -217,6 +221,12 @@ extern "C" {
typedef GrGLvoid (GR_GL_FUNCTION_TYPE *GrGLBindFragDataLocationIndexedProc)(GrGLuint program, GrGLuint colorNumber, GrGLuint index, const GrGLchar * name);
} // extern "C"
#if GR_GL_PER_GL_FUNC_CALLBACK
typedef void (*GrGLInterfaceCallbackProc)(const GrGLInterface*);
typedef intptr_t GrGLInterfaceCallbackData;
#endif
enum GrGLCapability {
kProbe_GrGLCapability = -1
};
@ -388,6 +398,12 @@ struct GR_API GrGLInterface : public GrRefCnt {
// Dual Source Blending
GrGLBindFragDataLocationIndexedProc fBindFragDataLocationIndexed;
// Per-GL func callback
#if GR_GL_PER_GL_FUNC_CALLBACK
GrGLInterfaceCallbackProc fCallback;
GrGLInterfaceCallbackData fCallbackData;
#endif
private:
bool validateShaderFunctions() const;
bool validateFixedFunctions() const;

Просмотреть файл

@ -59,7 +59,9 @@ void* GrGLIndexBuffer::lock() {
NULL,
this->dynamic() ? GR_GL_DYNAMIC_DRAW :
GR_GL_STATIC_DRAW));
fLockPtr = GL_CALL(MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
GR_GL_CALL_RET(GPUGL->glInterface(),
fLockPtr,
MapBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
GR_GL_WRITE_ONLY));
return fLockPtr;

Просмотреть файл

@ -13,6 +13,12 @@
#include <stdio.h>
#if GR_GL_PER_GL_FUNC_CALLBACK
namespace {
void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
}
#endif
static SkAutoTUnref<const GrGLInterface> gDefaultGLInterface;
void gl_version_from_string(int* major, int* minor,
@ -234,6 +240,11 @@ GrGLInterface::GrGLInterface() {
fMapBuffer = NULL;
fUnmapBuffer = NULL;
fBindFragDataLocationIndexed = NULL;
#if GR_GL_PER_GL_FUNC_CALLBACK
fCallback = GrGLDefaultInterfaceCallback;
fCallbackData = 0;
#endif
}

Просмотреть файл

@ -774,7 +774,8 @@ GrGLuint GrGLProgram::CompileShader(const GrGLInterface* gl,
SK_TRACE_EVENT1("GrGLProgram::CompileShader",
"stringCount", SkStringPrintf("%i", stringCnt).c_str());
GrGLuint shader = GR_GL_CALL(gl, CreateShader(type));
GrGLuint shader;
GR_GL_CALL_RET(gl, shader, CreateShader(type));
if (0 == shader) {
return 0;
}
@ -813,7 +814,7 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(
bool bindColorOut,
bool bindDualSrcOut,
CachedData* programData) const {
programData->fProgramID = GR_GL_CALL(gl, CreateProgram());
GR_GL_CALL_RET(gl, programData->fProgramID, CreateProgram());
if (!programData->fProgramID) {
return false;
}
@ -890,24 +891,24 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLInterface* gl,
const GrGLint& progID = programData->fProgramID;
if (kUseUniform == programData->fUniLocations.fViewMatrixUni) {
programData->fUniLocations.fViewMatrixUni =
GR_GL_CALL(gl, GetUniformLocation(progID, VIEW_MATRIX_NAME));
GR_GL_CALL_RET(gl, programData->fUniLocations.fViewMatrixUni,
GetUniformLocation(progID, VIEW_MATRIX_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
}
if (kUseUniform == programData->fUniLocations.fColorUni) {
programData->fUniLocations.fColorUni =
GR_GL_CALL(gl, GetUniformLocation(progID, COL_UNI_NAME));
GR_GL_CALL_RET(gl, programData->fUniLocations.fColorUni,
GetUniformLocation(progID, COL_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
}
if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
programData->fUniLocations.fColorFilterUni =
GR_GL_CALL(gl, GetUniformLocation(progID, COL_FILTER_UNI_NAME));
GR_GL_CALL_RET(gl, programData->fUniLocations.fColorFilterUni,
GetUniformLocation(progID, COL_FILTER_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
}
if (kUseUniform == programData->fUniLocations.fEdgesUni) {
programData->fUniLocations.fEdgesUni =
GR_GL_CALL(gl, GetUniformLocation(progID, EDGES_UNI_NAME));
GR_GL_CALL_RET(gl, programData->fUniLocations.fEdgesUni,
GetUniformLocation(progID, EDGES_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fEdgesUni);
} else {
programData->fUniLocations.fEdgesUni = kUnusedUniform;
@ -919,57 +920,54 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLInterface* gl,
if (kUseUniform == locations.fTextureMatrixUni) {
GrStringBuilder texMName;
tex_matrix_name(s, &texMName);
locations.fTextureMatrixUni =
GR_GL_CALL(gl, GetUniformLocation(progID, texMName.c_str()));
GR_GL_CALL_RET(gl, locations.fTextureMatrixUni,
GetUniformLocation(progID, texMName.c_str()));
GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
}
if (kUseUniform == locations.fSamplerUni) {
GrStringBuilder samplerName;
sampler_name(s, &samplerName);
locations.fSamplerUni =
GR_GL_CALL(gl, GetUniformLocation(progID,
samplerName.c_str()));
GR_GL_CALL_RET(gl, locations.fSamplerUni,
GetUniformLocation(progID,samplerName.c_str()));
GrAssert(kUnusedUniform != locations.fSamplerUni);
}
if (kUseUniform == locations.fNormalizedTexelSizeUni) {
GrStringBuilder texelSizeName;
normalized_texel_size_name(s, &texelSizeName);
locations.fNormalizedTexelSizeUni =
GR_GL_CALL(gl, GetUniformLocation(progID,
texelSizeName.c_str()));
GR_GL_CALL_RET(gl, locations.fNormalizedTexelSizeUni,
GetUniformLocation(progID, texelSizeName.c_str()));
GrAssert(kUnusedUniform != locations.fNormalizedTexelSizeUni);
}
if (kUseUniform == locations.fRadial2Uni) {
GrStringBuilder radial2ParamName;
radial2_param_name(s, &radial2ParamName);
locations.fRadial2Uni =
GR_GL_CALL(gl, GetUniformLocation(progID,
radial2ParamName.c_str()));
GR_GL_CALL_RET(gl, locations.fRadial2Uni,
GetUniformLocation(progID, radial2ParamName.c_str()));
GrAssert(kUnusedUniform != locations.fRadial2Uni);
}
if (kUseUniform == locations.fTexDomUni) {
GrStringBuilder texDomName;
tex_domain_name(s, &texDomName);
locations.fTexDomUni =
GR_GL_CALL(gl, GetUniformLocation(progID,
texDomName.c_str()));
GR_GL_CALL_RET(gl, locations.fTexDomUni,
GetUniformLocation(progID, texDomName.c_str()));
GrAssert(kUnusedUniform != locations.fTexDomUni);
}
GrStringBuilder kernelName, imageIncrementName;
convolve_param_names(s, &kernelName, &imageIncrementName);
if (kUseUniform == locations.fKernelUni) {
locations.fKernelUni = GR_GL_CALL(gl, GetUniformLocation(
progID, kernelName.c_str()));
GR_GL_CALL_RET(gl, locations.fKernelUni,
GetUniformLocation(progID, kernelName.c_str()));
GrAssert(kUnusedUniform != locations.fKernelUni);
}
if (kUseUniform == locations.fImageIncrementUni) {
locations.fImageIncrementUni = GR_GL_CALL(gl, GetUniformLocation(progID,
GR_GL_CALL_RET(gl, locations.fImageIncrementUni,
GetUniformLocation(progID,
imageIncrementName.c_str()));
GrAssert(kUnusedUniform != locations.fImageIncrementUni);
}

Просмотреть файл

@ -56,7 +56,9 @@ void* GrGLVertexBuffer::lock() {
GL_CALL(BufferData(GR_GL_ARRAY_BUFFER, this->sizeInBytes(), NULL,
this->dynamic() ? GR_GL_DYNAMIC_DRAW :
GR_GL_STATIC_DRAW));
fLockPtr = GL_CALL(MapBuffer(GR_GL_ARRAY_BUFFER, GR_GL_WRITE_ONLY));
GR_GL_CALL_RET(GPUGL->glInterface(),
fLockPtr,
MapBuffer(GR_GL_ARRAY_BUFFER, GR_GL_WRITE_ONLY));
return fLockPtr;
}
return NULL;

Просмотреть файл

@ -16,6 +16,7 @@ static const GrGLuint GR_MAX_GLUINT = ~0;
static const GrGLint GR_INVAL_GLINT = ~0;
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X)
// we use a spare texture unit to avoid
// mucking with the state of any of the stages.
@ -173,7 +174,8 @@ static bool fbo_test(const GrGLInterface* gl, int w, int h) {
GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D, testRTTex, 0));
GrGLenum status = GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GrGLenum status;
GR_GL_CALL_RET(gl, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GR_GL_CALL(gl, DeleteFramebuffers(1, &testFBO));
GR_GL_CALL(gl, DeleteTextures(1, &testRTTex));
@ -278,11 +280,15 @@ GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
GrGLClearErr(fGL);
const GrGLubyte* ext;
GL_CALL_RET(ext, GetString(GR_GL_EXTENSIONS));
if (gPrintStartupSpew) {
const GrGLubyte* vendor = GL_CALL(GetString(GR_GL_VENDOR));
const GrGLubyte* renderer = GL_CALL(GetString(GR_GL_RENDERER));
const GrGLubyte* version = GL_CALL(GetString(GR_GL_VERSION));
const GrGLubyte* ext = GL_CALL(GetString(GR_GL_EXTENSIONS));
const GrGLubyte* vendor;
const GrGLubyte* renderer;
const GrGLubyte* version;
GL_CALL_RET(vendor, GetString(GR_GL_VENDOR));
GL_CALL_RET(renderer, GetString(GR_GL_RENDERER));
GL_CALL_RET(version, GetString(GR_GL_VERSION));
GrPrintf("------------------------- create GrGpuGL %p --------------\n",
this);
GrPrintf("------ VENDOR %s\n", vendor);
@ -292,7 +298,7 @@ GrGpuGL::GrGpuGL(const GrGLInterface* gl, GrGLBinding glBinding)
}
fGLVersion = gl_version_as_float(gl);
fExtensionString = (const char*) GL_CALL(GetString(GR_GL_EXTENSIONS));
fExtensionString = (const char*) ext;
this->resetDirtyFlags();
@ -953,7 +959,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_RENDERBUFFER,
desc->fMSColorRenderbufferID));
GrGLenum status = GL_CALL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
goto FAILED;
}
@ -964,7 +970,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
GR_GL_COLOR_ATTACHMENT0,
GR_GL_TEXTURE_2D,
texID, 0));
status = GL_CALL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
goto FAILED;
}
@ -1220,8 +1226,8 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
GR_GL_DEPTH_ATTACHMENT,
GR_GL_RENDERBUFFER, 0));
#if GR_DEBUG
GrGLenum status =
GL_CALL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GrAssert(GR_GL_FRAMEBUFFER_COMPLETE == status);
#endif
}
@ -1245,7 +1251,8 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
GR_GL_RENDERBUFFER, 0));
}
GrGLenum status = GL_CALL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT,
@ -1495,7 +1502,8 @@ void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
++fStats.fRenderTargetChngCnt;
#endif
#if GR_DEBUG
GrGLenum status = GL_CALL(CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
GrPrintf("GrGpuGL::flushRenderTarget glCheckFramebufferStatus %x\n", status);
}