ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap, int x, int y, int w, int h, int format, int flags) { ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra; const GLint gl_y = bitmap->h - y - h; ALLEGRO_DISPLAY *disp; ALLEGRO_DISPLAY *old_disp = NULL; ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); GLenum e; bool ok; bool restore_fbo = false; if (format == ALLEGRO_PIXEL_FORMAT_ANY) { /* Never pick compressed formats with ANY, as it interacts weirdly with * existing code (e.g. al_get_pixel_size() etc) */ int bitmap_format = al_get_bitmap_format(bitmap); if (_al_pixel_format_is_compressed(bitmap_format)) { // XXX Get a good format from the driver? format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE; } else { format = bitmap_format; } } disp = al_get_current_display(); format = _al_get_real_pixel_format(disp, format); /* Change OpenGL context if necessary. */ if (!disp || (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false && _al_get_bitmap_display(bitmap) != disp)) { old_disp = disp; _al_set_current_display_only(_al_get_bitmap_display(bitmap)); } ok = true; /* Set up the pixel store state. We will need to match it when unlocking. * There may be other pixel store state we should be setting. * See also pitfalls 7 & 8 from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); { const int pixel_size = al_get_pixel_size(format); const int pixel_alignment = ogl_pixel_alignment(pixel_size); glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment); e = glGetError(); if (e) { ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n", pixel_alignment, _al_gl_error_string(e)); ok = false; } } if (ok) { if (ogl_bitmap->is_backbuffer) { ALLEGRO_DEBUG("Locking backbuffer\n"); ok = ogl_lock_region_backbuffer(bitmap, ogl_bitmap, x, gl_y, w, h, format, flags); } else if (flags & ALLEGRO_LOCK_WRITEONLY) { ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n"); ok = ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap, x, gl_y, w, h, format); } else { ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n"); ok = ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap, x, gl_y, w, h, format, &restore_fbo); } } glPopClientAttrib(); /* Restore state after switching FBO. */ if (restore_fbo) { if (!old_target) { /* Old target was NULL; release the context. */ _al_set_current_display_only(NULL); } else if (!_al_get_bitmap_display(old_target)) { /* Old target was memory bitmap; leave the current display alone. */ } else if (old_target != bitmap) { /* Old target was another OpenGL bitmap. */ _al_ogl_setup_fbo(_al_get_bitmap_display(old_target), old_target); } } ASSERT(al_get_target_bitmap() == old_target); if (old_disp != NULL) { _al_set_current_display_only(old_disp); } if (ok) { return &bitmap->locked_region; } ALLEGRO_ERROR("Failed to lock region\n"); ASSERT(ogl_bitmap->lock_buffer == NULL); return NULL; }
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap, int x, int y, int w, int h, int format, int flags) { ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra; const GLint gl_y = bitmap->h - y - h; ALLEGRO_DISPLAY *disp; ALLEGRO_DISPLAY *old_disp = NULL; GLenum e; if (format == ALLEGRO_PIXEL_FORMAT_ANY) { format = bitmap->format; } disp = al_get_current_display(); format = _al_get_real_pixel_format(disp, format); /* Change OpenGL context if necessary. */ if (!disp || (bitmap->display->ogl_extras->is_shared == false && bitmap->display != disp)) { old_disp = disp; _al_set_current_display_only(bitmap->display); } /* Set up the pixel store state. We will need to match it when unlocking. * There may be other pixel store state we should be setting. * See also pitfalls 7 & 8 from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); { const int pixel_size = al_get_pixel_size(format); const int pixel_alignment = ogl_pixel_alignment(pixel_size); glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment); e = glGetError(); if (e) { ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n", pixel_alignment, _al_gl_error_string(e)); } } if (ogl_bitmap->is_backbuffer) { ALLEGRO_DEBUG("Locking backbuffer\n"); ogl_lock_region_backbuffer(bitmap, ogl_bitmap, x, gl_y, w, h, format, flags); } else if (flags & ALLEGRO_LOCK_WRITEONLY) { ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n"); ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap, x, gl_y, w, h, format); } else { ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n"); ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap, x, gl_y, w, h, format); } glPopClientAttrib(); if (old_disp != NULL) { _al_set_current_display_only(old_disp); } return &bitmap->locked_region; }