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
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index cbfcc6e..aa8c6db 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -189,6 +189,79 @@
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 @@
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 @@
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() {
diff --git a/gpu/src/android/GrGLDefaultInterface_android.cpp b/gpu/src/android/GrGLDefaultInterface_android.cpp
index e52277e..38e7708 100644
--- a/gpu/src/android/GrGLDefaultInterface_android.cpp
+++ b/gpu/src/android/GrGLDefaultInterface_android.cpp
@@ -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 @@
host_StubGL_initialized = true;
}
}
-
diff --git a/gpu/src/mac/GrGLDefaultInterface_mac.cpp b/gpu/src/mac/GrGLDefaultInterface_mac.cpp
index fb5b182..a49f238 100644
--- a/gpu/src/mac/GrGLDefaultInterface_mac.cpp
+++ b/gpu/src/mac/GrGLDefaultInterface_mac.cpp
@@ -23,6 +23,10 @@
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;
diff --git a/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp b/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp
index 0350c30..6852eb7 100644
--- a/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp
+++ b/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp
@@ -38,6 +38,9 @@
// 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);
diff --git a/gpu/src/unix/GrGLDefaultInterface_unix.cpp b/gpu/src/unix/GrGLDefaultInterface_unix.cpp
index 3e9b975..f58b215 100644
--- a/gpu/src/unix/GrGLDefaultInterface_unix.cpp
+++ b/gpu/src/unix/GrGLDefaultInterface_unix.cpp
@@ -40,6 +40,10 @@
return;
}
+ gDefaultInterface.fNPOTRenderTargetSupport = 1;
+ gDefaultInterface.fMinRenderTargetHeight = 1;
+ gDefaultInterface.fMinRenderTargetWidth = 1;
+
gDefaultInterface.fActiveTexture = glActiveTexture;
GR_GL_GET_PROC(AttachShader);
GR_GL_GET_PROC(BindAttribLocation);
diff --git a/gpu/src/win/GrGLDefaultInterface_win.cpp b/gpu/src/win/GrGLDefaultInterface_win.cpp
index 428abb1..7f680a67 100644
--- a/gpu/src/win/GrGLDefaultInterface_win.cpp
+++ b/gpu/src/win/GrGLDefaultInterface_win.cpp
@@ -32,7 +32,7 @@
static GrGLInterface gDefaultInterface;
static bool gDefaultInterfaceInit;
if (!gDefaultInterfaceInit) {
-
+
// wglGetProcAddress requires a context.
if (NULL != wglGetCurrentContext()) {
int major, minor;
@@ -45,7 +45,11 @@
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;