FBO probing at Context startup is very expensive. This patch removes the
test of whether FBOs work at all, and adds parameters to the GrGLInterface so that values can be passed into the Context creation routines instead of executing the probes. The GrGLInterface now defaults to run FBO tests on Android (since hardware varies), but assumes success on desktop and software platforms. git-svn-id: http://skia.googlecode.com/svn/trunk@1582 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
353c252a2f
commit
747bf293d4
@ -50,11 +50,11 @@ GR_API GrGLInterface* GrGLGetGLInterface();
|
||||
GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface);
|
||||
|
||||
/*
|
||||
* This is called when GrGLSetGLInterface() hasn't been called before creating a
|
||||
* GrGpuGL object. It provides a default implementation. The actual implementation
|
||||
* depends on which GrGLDefaultInterface_*.cpp has been linked. There are some
|
||||
* platform-specific implementations provided as well as
|
||||
* GrGLDefaultInterface_none.cpp which does nothing (effectively requiring an
|
||||
* This is called when GrGLSetGLInterface() hasn't been called before creating
|
||||
* a GrGpuGL object. It provides a default implementation. The actual
|
||||
* implementation depends on which GrGLDefaultInterface_*.cpp has been linked.
|
||||
* There are some platform-specific implementations provided as well as
|
||||
* GrGLDefaultInterface_none.cpp which does nothing (effectively requiring an
|
||||
* explicit GrGLSetGLInterface call by the host).
|
||||
*/
|
||||
void GrGLSetDefaultGLInterface();
|
||||
@ -221,6 +221,16 @@ struct GrGLInterface {
|
||||
// exported: GLES{1|2} or Desktop.
|
||||
GrGLBinding fBindingsExported;
|
||||
|
||||
/// Does this GL support NPOT textures on FBOs?
|
||||
/// boolean value, or -1 to probe (slowly) at context creation.
|
||||
int fNPOTRenderTargetSupport;
|
||||
|
||||
/// Some GL implementations (PowerVR SGX devices like the iPhone 4)
|
||||
/// have restrictions on the size of small render targets.
|
||||
/// -1 to probe (slowly) at context creation.
|
||||
int fMinRenderTargetHeight;
|
||||
int fMinRenderTargetWidth;
|
||||
|
||||
GrGLActiveTextureProc fActiveTexture;
|
||||
GrGLAttachShaderProc fAttachShader;
|
||||
GrGLBindAttribLocationProc fBindAttribLocation;
|
||||
|
@ -189,6 +189,79 @@ static bool fbo_test(int w, int h) {
|
||||
return status == GR_GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
static bool probe_for_npot_render_target_support(bool hasNPOTTextureSupport) {
|
||||
|
||||
/* Experimentation has found that some GLs that support NPOT textures
|
||||
do not support FBOs with a NPOT texture. They report "unsupported" FBO
|
||||
status. I don't know how to explicitly query for this. Do an
|
||||
experiment. Note they may support NPOT with a renderbuffer but not a
|
||||
texture. Presumably, the implementation bloats the renderbuffer
|
||||
internally to the next POT.
|
||||
*/
|
||||
if (hasNPOTTextureSupport) {
|
||||
return fbo_test(200, 200);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int probe_for_min_render_target_height(bool hasNPOTRenderTargetSupport,
|
||||
int maxRenderTargetSize) {
|
||||
/* The iPhone 4 has a restriction that for an FBO with texture color
|
||||
attachment with height <= 8 then the width must be <= height. Here
|
||||
we look for such a limitation.
|
||||
*/
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("Small height FBO texture experiments\n");
|
||||
}
|
||||
int minRenderTargetHeight = GR_INVAL_GLINT;
|
||||
for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? ++i : i *= 2) {
|
||||
GrGLuint w = maxRenderTargetSize;
|
||||
GrGLuint h = i;
|
||||
if (fbo_test(w, h)) {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: PASSED\n", w, h);
|
||||
}
|
||||
minRenderTargetHeight = i;
|
||||
break;
|
||||
} else {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: FAILED\n", w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
GrAssert(GR_INVAL_GLINT != minRenderTargetHeight);
|
||||
|
||||
return minRenderTargetHeight;
|
||||
}
|
||||
|
||||
static int probe_for_min_render_target_width(bool hasNPOTRenderTargetSupport,
|
||||
int maxRenderTargetSize) {
|
||||
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("Small width FBO texture experiments\n");
|
||||
}
|
||||
int minRenderTargetWidth = GR_INVAL_GLINT;
|
||||
for (GrGLuint i = 1; i <= 256; hasNPOTRenderTargetSupport ? i *= 2 : ++i) {
|
||||
GrGLuint w = i;
|
||||
GrGLuint h = maxRenderTargetSize;
|
||||
if (fbo_test(w, h)) {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: PASSED\n", w, h);
|
||||
}
|
||||
minRenderTargetWidth = i;
|
||||
break;
|
||||
} else {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: FAILED\n", w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
GrAssert(GR_INVAL_GLINT != minRenderTargetWidth);
|
||||
|
||||
return minRenderTargetWidth;
|
||||
}
|
||||
|
||||
|
||||
GrGpuGL::GrGpuGL() {
|
||||
|
||||
if (gPrintStartupSpew) {
|
||||
@ -394,31 +467,14 @@ GrGpuGL::GrGpuGL() {
|
||||
fAALineSupport = GR_GL_SUPPORT_DESKTOP;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Experiments to determine limitations that can't be queried. TODO: Make
|
||||
// these a preprocess that generate some compile time constants.
|
||||
// Experiments to determine limitations that can't be queried.
|
||||
// TODO: Make these a preprocess that generate some compile time constants.
|
||||
// TODO: probe once at startup, rather than once per context creation.
|
||||
|
||||
// sanity check to make sure we can at least create an FBO from a POT texture
|
||||
|
||||
bool simpleFBOSuccess = fbo_test(128, 128);
|
||||
if (gPrintStartupSpew) {
|
||||
if (!simpleFBOSuccess) {
|
||||
GrPrintf("FBO Sanity Test: FAILED\n");
|
||||
} else {
|
||||
GrPrintf("FBO Sanity Test: PASSED\n");
|
||||
}
|
||||
}
|
||||
GrAssert(simpleFBOSuccess);
|
||||
|
||||
/* Experimentation has found that some GLs that support NPOT textures
|
||||
do not support FBOs with a NPOT texture. They report "unsupported" FBO
|
||||
status. I don't know how to explicitly query for this. Do an
|
||||
experiment. Note they may support NPOT with a renderbuffer but not a
|
||||
texture. Presumably, the implementation bloats the renderbuffer
|
||||
internally to the next POT.
|
||||
*/
|
||||
bool fNPOTRenderTargetSupport = false;
|
||||
if (fNPOTTextureSupport) {
|
||||
fNPOTRenderTargetSupport = fbo_test(200, 200);
|
||||
fNPOTRenderTargetSupport = GrGLGetGLInterface()->fNPOTRenderTargetSupport;
|
||||
if (fNPOTRenderTargetSupport < 0) {
|
||||
fNPOTRenderTargetSupport =
|
||||
probe_for_npot_render_target_support(fNPOTTextureSupport);
|
||||
}
|
||||
|
||||
if (gPrintStartupSpew) {
|
||||
@ -441,55 +497,24 @@ GrGpuGL::GrGpuGL() {
|
||||
|
||||
GR_GL_GetIntegerv(GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
|
||||
GR_GL_GetIntegerv(GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
|
||||
// Our render targets are always created with textures as the color
|
||||
// Our render targets are always created with textures as the color
|
||||
// attachment, hence this min:
|
||||
fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
|
||||
|
||||
/* The iPhone 4 has a restriction that for an FBO with texture color
|
||||
attachment with height <= 8 then the width must be <= height. Here
|
||||
we look for such a limitation.
|
||||
*/
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("Small height FBO texture experiments\n");
|
||||
fMinRenderTargetHeight = GrGLGetGLInterface()->fMinRenderTargetHeight;
|
||||
if (fMinRenderTargetHeight < 0) {
|
||||
fMinRenderTargetHeight =
|
||||
probe_for_min_render_target_height(fNPOTRenderTargetSupport,
|
||||
fMaxRenderTargetSize);
|
||||
}
|
||||
fMinRenderTargetHeight = GR_INVAL_GLINT;
|
||||
for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
|
||||
GrGLuint w = fMaxRenderTargetSize;
|
||||
GrGLuint h = i;
|
||||
if (fbo_test(w, h)) {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: PASSED\n", w, h);
|
||||
}
|
||||
fMinRenderTargetHeight = i;
|
||||
break;
|
||||
} else {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: FAILED\n", w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
GrAssert(GR_INVAL_GLINT != fMinRenderTargetHeight);
|
||||
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("Small width FBO texture experiments\n");
|
||||
fMinRenderTargetWidth = GrGLGetGLInterface()->fMinRenderTargetWidth;
|
||||
if (fMinRenderTargetWidth < 0) {
|
||||
fMinRenderTargetWidth =
|
||||
probe_for_min_render_target_width(fNPOTRenderTargetSupport,
|
||||
fMaxRenderTargetSize);
|
||||
}
|
||||
fMinRenderTargetWidth = GR_INVAL_GLINT;
|
||||
for (GrGLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
|
||||
GrGLuint w = i;
|
||||
GrGLuint h = fMaxRenderTargetSize;
|
||||
if (fbo_test(w, h)) {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: PASSED\n", w, h);
|
||||
}
|
||||
fMinRenderTargetWidth = i;
|
||||
break;
|
||||
} else {
|
||||
if (gPrintStartupSpew) {
|
||||
GrPrintf("\t[%d, %d]: FAILED\n", w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
GrAssert(GR_INVAL_GLINT != fMinRenderTargetWidth);
|
||||
|
||||
}
|
||||
|
||||
GrGpuGL::~GrGpuGL() {
|
||||
|
@ -19,7 +19,9 @@
|
||||
void GrGLSetDefaultGLInterface() {
|
||||
static GrGLInterface cmd_buffer_interface = {
|
||||
kES2_GrGLBinding,
|
||||
|
||||
-1, // fNPOTRenderTargetSupport
|
||||
-1, // fMinRenderTargetHeight
|
||||
-1, // fMinRenderTargetWidth
|
||||
glActiveTexture,
|
||||
glAttachShader,
|
||||
glBindAttribLocation,
|
||||
@ -135,4 +137,3 @@ void GrGLSetDefaultGLInterface() {
|
||||
host_StubGL_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,10 @@ void GrGLSetDefaultGLInterface() {
|
||||
static GrGLInterface gDefaultInterface;
|
||||
static bool gDefaultInterfaceInit;
|
||||
if (!gDefaultInterfaceInit) {
|
||||
gDefaultInterface.fNPOTRenderTargetSupport = 1;
|
||||
gDefaultInterface.fMinRenderTargetHeight = 1;
|
||||
gDefaultInterface.fMinRenderTargetWidth = 1;
|
||||
|
||||
gDefaultInterface.fActiveTexture = glActiveTexture;
|
||||
gDefaultInterface.fAttachShader = glAttachShader;
|
||||
gDefaultInterface.fBindAttribLocation = glBindAttribLocation;
|
||||
|
@ -38,6 +38,9 @@ void GrGLSetDefaultGLInterface() {
|
||||
// We must have array and element_array buffer objects.
|
||||
return;
|
||||
}
|
||||
gDefaultInterface.fNPOTRenderTargetSupport = 1;
|
||||
gDefaultInterface.fMinRenderTargetHeight = 1;
|
||||
gDefaultInterface.fMinRenderTargetWidth = 1;
|
||||
|
||||
gDefaultInterface.fActiveTexture = glActiveTexture;
|
||||
GR_GL_GET_PROC(AttachShader);
|
||||
|
@ -40,6 +40,10 @@ void GrGLSetDefaultGLInterface() {
|
||||
return;
|
||||
}
|
||||
|
||||
gDefaultInterface.fNPOTRenderTargetSupport = 1;
|
||||
gDefaultInterface.fMinRenderTargetHeight = 1;
|
||||
gDefaultInterface.fMinRenderTargetWidth = 1;
|
||||
|
||||
gDefaultInterface.fActiveTexture = glActiveTexture;
|
||||
GR_GL_GET_PROC(AttachShader);
|
||||
GR_GL_GET_PROC(BindAttribLocation);
|
||||
|
@ -32,7 +32,7 @@ void GrGLSetDefaultGLInterface() {
|
||||
static GrGLInterface gDefaultInterface;
|
||||
static bool gDefaultInterfaceInit;
|
||||
if (!gDefaultInterfaceInit) {
|
||||
|
||||
|
||||
// wglGetProcAddress requires a context.
|
||||
if (NULL != wglGetCurrentContext()) {
|
||||
int major, minor;
|
||||
@ -45,7 +45,11 @@ void GrGLSetDefaultGLInterface() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Functions that are part of GL 1.1 will return NULL in
|
||||
gDefaultInterface.fNPOTRenderTargetSupport = 1;
|
||||
gDefaultInterface.fMinRenderTargetHeight = 1;
|
||||
gDefaultInterface.fMinRenderTargetWidth = 1;
|
||||
|
||||
// Functions that are part of GL 1.1 will return NULL in
|
||||
// wglGetProcAddress
|
||||
gDefaultInterface.fBlendFunc = glBlendFunc;
|
||||
gDefaultInterface.fClear = glClear;
|
||||
|
Loading…
Reference in New Issue
Block a user