[AD] Conserving OpenGL FBOs |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
I've got a patch that is supposed to use fbos from a pool (of 8 right
now). I don't get any slowdown in ex_bitmap_target, and my game, which
was getting an X error about out of resources, is working now... so I
think this patch is at least partially right. I'd like to have someone
review it if possible before I commit it though. It's attached. Would
appreciate any comments.
Thanks,
Trent
Index: include/allegro5/internal/aintern_opengl.h
===================================================================
--- include/allegro5/internal/aintern_opengl.h (revision 14537)
+++ include/allegro5/internal/aintern_opengl.h (working copy)
@@ -23,7 +23,18 @@
_ALLEGRO_OPENGL_VERSION_4_0 = 0x04000000
};
+#define ALLEGRO_MAX_OPENGL_FBOS 8
+struct ALLEGRO_BITMAP_OGL;
+
+typedef struct ALLEGRO_FBO_INFO
+{
+ bool used;
+ GLuint fbo;
+ struct ALLEGRO_BITMAP_OGL *owner;
+ double creation_time;
+} ALLEGRO_FBO_INFO;
+
typedef struct ALLEGRO_BITMAP_OGL
{
ALLEGRO_BITMAP bitmap; /* This must be the first member. */
@@ -41,7 +52,7 @@
NativeWindowType pbuf_native_wnd;
bool changed;
#else
- GLuint fbo; /* 0 means, no fbo yet. */
+ ALLEGRO_FBO_INFO *fbo_info;
#endif
unsigned char *lock_buffer;
@@ -81,6 +92,8 @@
/* True if display resources are shared among displays. */
bool is_shared;
+ ALLEGRO_FBO_INFO fbos[ALLEGRO_MAX_OPENGL_FBOS];
+
GLuint program_object; // Shader object
/* Shader variable addresses. If the user is using the programmable pipeline,
Index: src/opengl/ogl_display.c
===================================================================
--- src/opengl/ogl_display.c (revision 14537)
+++ src/opengl/ogl_display.c (working copy)
@@ -28,34 +28,56 @@
#include "allegro5/internal/aintern_iphone.h"
#endif
+#include <float.h>
+
ALLEGRO_DEBUG_CHANNEL("opengl")
+static ALLEGRO_FBO_INFO *ogl_find_unused_fbo(ALLEGRO_DISPLAY *display)
+{
+ ALLEGRO_OGL_EXTRAS *extras = display->ogl_extras;
+ double min_time = DBL_MAX;
+ int min_time_index = -1;
+ int i;
+
+ for (i = 0; i < ALLEGRO_MAX_OPENGL_FBOS; i++) {
+ if (!extras->fbos[i].used)
+ return &extras->fbos[i];
+ if (extras->fbos[i].creation_time < min_time) {
+ min_time = extras->fbos[i].creation_time;
+ min_time_index = i;
+ }
+ }
+
+ return &extras->fbos[min_time_index];
+}
+
static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
{
ALLEGRO_BITMAP_OGL *ogl_bitmap;
+ ALLEGRO_FBO_INFO *info;
+ GLuint delete_fbo = 0;
+ #ifdef ALLEGRO_IPHONE
+ #define glGenFramebuffersEXT glGenFramebuffersOES
+ #define glBindFramebufferEXT glBindFramebufferOES
+ #define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES
+ #define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0_OES
+ #define glCheckFramebufferStatusEXT glCheckFramebufferStatusOES
+ #define glFramebufferTexture2DEXT glFramebufferTexture2DOES
+ #define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE_OES
+ #define glDeleteFramebuffersEXT glDeleteFramebuffersOES
+ #define glOrtho glOrthof
+ #endif
+
if (bitmap->parent) bitmap = bitmap->parent;
ogl_bitmap = (void *)bitmap;
#if !defined ALLEGRO_GP2XWIZ
if (!ogl_bitmap->is_backbuffer) {
- // FIXME: ...
- #ifdef ALLEGRO_IPHONE
- #define glGenFramebuffersEXT glGenFramebuffersOES
- #define glBindFramebufferEXT glBindFramebufferOES
- #define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES
- #define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0_OES
- #define glCheckFramebufferStatusEXT glCheckFramebufferStatusOES
- #define glFramebufferTexture2DEXT glFramebufferTexture2DOES
- #define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE_OES
- #define glDeleteFramebuffersEXT glDeleteFramebuffersOES
- #define glOrtho glOrthof
- #endif
-
/* When a bitmap is set as target bitmap, we try to create an FBO for it.
*/
- if (ogl_bitmap->fbo == 0 && !(bitmap->flags & ALLEGRO_FORCE_LOCKING)) {
+ if (ogl_bitmap->fbo_info == NULL && !(bitmap->flags & ALLEGRO_FORCE_LOCKING)) {
/* FIXME This is quite a hack but I don't know how the Allegro extension
* manager works to fix this properly (getting extensions properly reported
@@ -67,18 +89,33 @@
if (al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object ||
al_get_opengl_extension_list()->ALLEGRO_GL_OES_framebuffer_object) {
#endif
- glGenFramebuffersEXT(1, &ogl_bitmap->fbo);
+ info = ogl_find_unused_fbo(display);
+ if (info->used) {
+ info->owner->fbo_info = NULL;
+ delete_fbo = info->fbo;
+ memset(info, 0, sizeof(*info));
+ }
+
+ glGenFramebuffersEXT(1, &info->fbo);
}
}
+ else {
+ info = ogl_bitmap->fbo_info;
+ }
- if (ogl_bitmap->fbo) {
+ if (info && info->fbo) {
/* Bind to the FBO. */
#ifndef ALLEGRO_IPHONE
ASSERT(display->ogl_extras->extension_list->ALLEGRO_GL_EXT_framebuffer_object ||
display->ogl_extras->extension_list->ALLEGRO_GL_OES_framebuffer_object);
#endif
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ogl_bitmap->fbo);
+ info->used = true;
+ info->owner = ogl_bitmap;
+ info->creation_time = al_get_time();
+ ogl_bitmap->fbo_info = info;
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, info->fbo);
+
/* Attach the texture. */
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, ogl_bitmap->texture, 0);
@@ -92,8 +129,9 @@
_al_format_name(bitmap->format));
ALLEGRO_ERROR("*** SWITCHING TO SOFTWARE MODE ***\n");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glDeleteFramebuffersEXT(1, &ogl_bitmap->fbo);
- ogl_bitmap->fbo = 0;
+ glDeleteFramebuffersEXT(1, &info->fbo);
+ memset(info, 0, sizeof(*info));
+ ogl_bitmap->fbo_info = NULL;
}
else {
display->ogl_extras->opengl_target = ogl_bitmap;
@@ -163,6 +201,10 @@
glOrtho(0, display->w, display->h, 0, -1, 1);
}
#endif
+
+ if (delete_fbo != 0) {
+ glDeleteFramebuffersEXT(1, &delete_fbo);
+ }
}
void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
Index: src/opengl/ogl_bitmap.c
===================================================================
--- src/opengl/ogl_bitmap.c (revision 14537)
+++ src/opengl/ogl_bitmap.c (working copy)
@@ -346,7 +346,7 @@
/* In general, we can't modify the texture while it's
* FBO bound - so we temporarily disable the FBO.
*/
- if (ogl_target->fbo)
+ if (ogl_target->fbo_info)
_al_ogl_set_target_bitmap(disp, bitmap);
/* We need to do clipping because glCopyTexSubImage2D
@@ -378,7 +378,7 @@
sx, bitmap->h - sy - sh,
sw, sh);
/* Fix up FBO again after the copy. */
- if (ogl_target->fbo)
+ if (ogl_target->fbo_info)
_al_ogl_set_target_bitmap(disp, target);
return;
}
@@ -679,7 +679,7 @@
GLint current_fbo;
/* Create an FBO if there isn't one. */
- if (!ogl_bitmap->fbo) {
+ if (!ogl_bitmap->fbo_info) {
ALLEGRO_STATE state;
al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP);
bitmap->locked = false; // hack :(
@@ -689,7 +689,7 @@
}
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, ¤t_fbo);
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, ogl_bitmap->fbo);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, ogl_bitmap->fbo_info->fbo);
pitch = ogl_pitch(w, pixel_size);
ogl_bitmap->lock_buffer = al_malloc(pitch * h);
@@ -999,17 +999,16 @@
_al_set_current_display_only(bitmap->display);
}
+ if (ogl_bitmap->fbo_info) {
+ if (ogl_bitmap->fbo_info->fbo) {
#if !defined ALLEGRO_GP2XWIZ && !defined ALLEGRO_IPHONE
- if (ogl_bitmap->fbo) {
- glDeleteFramebuffersEXT(1, &ogl_bitmap->fbo);
- ogl_bitmap->fbo = 0;
- }
+ glDeleteFramebuffersEXT(1, &ogl_bitmap->fbo_info->fbo);
#elif defined ALLEGRO_IPHONE
- if (ogl_bitmap->fbo) {
- glDeleteFramebuffersOES(1, &ogl_bitmap->fbo);
- ogl_bitmap->fbo = 0;
+ glDeleteFramebuffersOES(1, &ogl_bitmap->fbo_info->fbo);
+#endif
+ }
+ memset(ogl_bitmap->fbo_info, 0, sizeof(ALLEGRO_FBO_INFO));
}
-#endif
if (ogl_bitmap->texture) {
glDeleteTextures(1, &ogl_bitmap->texture);
@@ -1149,7 +1148,7 @@
ogl_bmp->texture = ogl_parent->texture;
#if !defined ALLEGRO_GP2XWIZ
- ogl_bmp->fbo = ogl_parent->fbo;
+ ogl_bmp->fbo_info = ogl_parent->fbo_info;
#endif
ogl_bmp->left = x / (float)ogl_parent->true_w;
@@ -1182,9 +1181,10 @@
#if !defined ALLEGRO_GP2XWIZ && !defined ALLEGRO_IPHONE
ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL)) return;
- if (ogl_bitmap->fbo) {
- glDeleteFramebuffersEXT(1, &ogl_bitmap->fbo);
- ogl_bitmap->fbo = 0;
+ if (ogl_bitmap->fbo_info) {
+ glDeleteFramebuffersEXT(1, &ogl_bitmap->fbo_info->fbo);
+ memset(ogl_bitmap->fbo_info, 0, sizeof(ALLEGRO_FBO_INFO));
+ ogl_bitmap->fbo_info = NULL;
}
#else
(void)bitmap;
@@ -1198,7 +1198,7 @@
#if !defined ALLEGRO_GP2XWIZ
ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL)) return 0;
- return ogl_bitmap->fbo;
+ return ogl_bitmap->fbo_info == NULL ? 0 : ogl_bitmap->fbo_info->fbo;
#else
(void)bitmap;
return 0;