static ALLEGRO_FBO_INFO *ogl_new_fbo(ALLEGRO_DISPLAY *display) { ALLEGRO_FBO_INFO *info; GLint e; info = ogl_find_unused_fbo(display); ASSERT(info->fbo_state != FBO_INFO_PERSISTENT); if (info->fbo_state == FBO_INFO_TRANSIENT) { ALLEGRO_BITMAP_EXTRA_OPENGL *extra = info->owner->extra; extra->fbo_info = NULL; ALLEGRO_DEBUG("Deleting FBO: %u\n", info->fbo); if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) { glDeleteFramebuffers(1, &info->fbo); } else { glDeleteFramebuffersEXT(1, &info->fbo); } _al_ogl_reset_fbo_info(info); } else { /* FBO_INFO_UNUSED */ } if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) { glGenFramebuffers(1, &info->fbo); } else { glGenFramebuffersEXT(1, &info->fbo); } e = glGetError(); if (e) { ALLEGRO_ERROR("glGenFramebuffersEXT failed\n"); _al_ogl_reset_fbo_info(info); return NULL; } ALLEGRO_DEBUG("Created FBO: %u\n", info->fbo); return info; }
static void use_fbo_for_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap, ALLEGRO_FBO_INFO *info) { ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra; GLint e; if (info->fbo_state == FBO_INFO_UNUSED) info->fbo_state = FBO_INFO_TRANSIENT; info->owner = bitmap; info->last_use_time = al_get_time(); ogl_bitmap->fbo_info = info; /* Bind to the FBO. */ _al_ogl_bind_framebuffer(info->fbo); /* Attach the texture. */ if (ANDROID_PROGRAMMABLE_PIPELINE(al_get_current_display())) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ogl_bitmap->texture, 0); } else { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ogl_bitmap->texture, 0); } e = glGetError(); if (e) { ALLEGRO_DEBUG("glFrameBufferTexture2DEXT failed! fbo=%d texture=%d (%s)", info->fbo, ogl_bitmap->texture, _al_gl_error_string(e)); } /* See comment about unimplemented functions on Android above */ if (UNLESS_ANDROID_OR_RPI( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)) { /* For some reason, we cannot use the FBO with this * texture. So no reason to keep re-trying, output a log * message and switch to (extremely slow) software mode. */ ALLEGRO_ERROR("Could not use FBO for bitmap with format %s.\n", _al_pixel_format_name(al_get_bitmap_format(bitmap))); ALLEGRO_ERROR("*** SWITCHING TO SOFTWARE MODE ***\n"); _al_ogl_bind_framebuffer(0); glDeleteFramebuffersEXT(1, &info->fbo); _al_ogl_reset_fbo_info(info); ogl_bitmap->fbo_info = NULL; } else { display->ogl_extras->opengl_target = bitmap; } }
ALLEGRO_FBO_INFO *_al_ogl_persist_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_FBO_INFO *transient_fbo_info) { ALLEGRO_OGL_EXTRAS *extras = display->ogl_extras; int i; ASSERT(transient_fbo_info->fbo_state == FBO_INFO_TRANSIENT); for (i = 0; i < ALLEGRO_MAX_OPENGL_FBOS; i++) { if (transient_fbo_info == &extras->fbos[i]) { ALLEGRO_FBO_INFO *new_info = al_malloc(sizeof(ALLEGRO_FBO_INFO)); *new_info = *transient_fbo_info; new_info->fbo_state = FBO_INFO_PERSISTENT; _al_ogl_reset_fbo_info(transient_fbo_info); ALLEGRO_DEBUG("Persistent FBO: %u\n", new_info->fbo); return new_info; } } ALLEGRO_ERROR("Could not find FBO %u in pool\n", transient_fbo_info->fbo); return transient_fbo_info; }
static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap) { ALLEGRO_BITMAP_OGL *ogl_bitmap; if (bitmap->parent) bitmap = bitmap->parent; ogl_bitmap = (void *)bitmap; /* We can't return here. Target's FBO can be taken away by locking * a lot of bitmaps consecutively. * Also affects ex_multiwin; resizing one window affects the other. */ if (false && display->ogl_extras->opengl_target == ogl_bitmap) return; #if !defined ALLEGRO_GP2XWIZ if (!ogl_bitmap->is_backbuffer) { ALLEGRO_FBO_INFO *info = NULL; /* When a bitmap is set as target bitmap, we try to create an FBO for it. */ if (ogl_bitmap->fbo_info == NULL && !(bitmap->flags & ALLEGRO_FORCE_LOCKING)) { #ifdef ALLEGRO_IPHONE /* 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 * on iphone. */ if (true) #else if (al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object || al_get_opengl_extension_list()->ALLEGRO_GL_OES_framebuffer_object) #endif { info = ogl_find_unused_fbo(display); ASSERT(info->fbo_state != FBO_INFO_PERSISTENT); if (info->fbo_state == FBO_INFO_TRANSIENT) { info->owner->fbo_info = NULL; ALLEGRO_DEBUG("Deleting FBO: %u\n", info->fbo); glDeleteFramebuffersEXT(1, &info->fbo); _al_ogl_reset_fbo_info(info); } glGenFramebuffersEXT(1, &info->fbo); ALLEGRO_DEBUG("Created FBO: %u\n", info->fbo); } } else { info = ogl_bitmap->fbo_info; } 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 if (info->fbo_state == FBO_INFO_UNUSED) info->fbo_state = FBO_INFO_TRANSIENT; info->owner = ogl_bitmap; info->last_use_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); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { /* For some reason, we cannot use the FBO with this * texture. So no reason to keep re-trying, output a log * message and switch to (extremely slow) software mode. */ ALLEGRO_ERROR("Could not use FBO for bitmap with format %s.\n", _al_pixel_format_name(bitmap->format)); ALLEGRO_ERROR("*** SWITCHING TO SOFTWARE MODE ***\n"); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &info->fbo); _al_ogl_reset_fbo_info(info); ogl_bitmap->fbo_info = NULL; } else { display->ogl_extras->opengl_target = ogl_bitmap; glViewport(0, 0, bitmap->w, bitmap->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, bitmap->w, bitmap->h, 0, -1, 1); } } } else { display->ogl_extras->opengl_target = ogl_bitmap; // TODO: Might as well have a vtable entry here #ifdef ALLEGRO_IPHONE _al_iphone_setup_opengl_view(display); #else if (display->ogl_extras->extension_list->ALLEGRO_GL_EXT_framebuffer_object || display->ogl_extras->extension_list->ALLEGRO_GL_OES_framebuffer_object) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } glViewport(0, 0, display->w, display->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* We use upside down coordinates compared to OpenGL, so the bottommost * coordinate is display->h not 0. */ glOrtho(0, display->w, display->h, 0, -1, 1); #endif } #else ALLEGRO_DISPLAY_GP2XWIZ_OGL *wiz_disp = (ALLEGRO_DISPLAY_GP2XWIZ_OGL *)display; display->ogl_extras->opengl_target = ogl_bitmap; if (!ogl_bitmap->is_backbuffer) { /* FIXME: implement */ } else { eglMakeCurrent(wiz_disp->egl_display, wiz_disp->egl_surface, wiz_disp->egl_surface, wiz_disp->egl_context); glViewport(0, 0, display->w, display->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* We use upside down coordinates compared to OpenGL, so the bottommost * coordinate is display->h not 0. */ glOrtho(0, display->w, display->h, 0, -1, 1); } #endif }