static void ogl_unlock_region_nonbb_nonfbo(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y) { const int lock_format = bitmap->locked_region.format; unsigned char *start_ptr; GLenum e; if (bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY) { ALLEGRO_DEBUG("Unlocking non-backbuffer non-FBO WRITEONLY\n"); start_ptr = ogl_bitmap->lock_buffer; } else { ALLEGRO_DEBUG("Unlocking non-backbuffer non-FBO READWRITE\n"); glPixelStorei(GL_UNPACK_ROW_LENGTH, ogl_bitmap->true_w); start_ptr = (unsigned char *)bitmap->lock_data + (bitmap->lock_h - 1) * bitmap->locked_region.pitch; } glTexSubImage2D(GL_TEXTURE_2D, 0, bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h, get_glformat(lock_format, 2), get_glformat(lock_format, 1), start_ptr); e = glGetError(); if (e) { ALLEGRO_ERROR("glTexSubImage2D for format %s failed (%s).\n", _al_pixel_format_name(lock_format), _al_gl_error_string(e)); } }
static void ogl_unlock_region_nonbb_fbo_writeonly(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y, int orig_format) { const int lock_format = bitmap->locked_region.format; const int orig_pixel_size = al_get_pixel_size(orig_format); const int dst_pitch = bitmap->lock_w * orig_pixel_size; unsigned char * const tmpbuf = al_malloc(dst_pitch * bitmap->lock_h); GLenum e; _al_convert_bitmap_data( ogl_bitmap->lock_buffer, bitmap->locked_region.format, -bitmap->locked_region.pitch, tmpbuf, orig_format, dst_pitch, 0, 0, 0, 0, bitmap->lock_w, bitmap->lock_h); glTexSubImage2D(GL_TEXTURE_2D, 0, bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h, get_glformat(orig_format, 2), get_glformat(orig_format, 1), tmpbuf); e = glGetError(); if (e) { ALLEGRO_ERROR("glTexSubImage2D for format %d failed (%s).\n", lock_format, _al_gl_error_string(e)); } al_free(tmpbuf); }
static bool ogl_lock_region_backbuffer( ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int x, int gl_y, int w, int h, int format, int flags) { const int pixel_size = al_get_pixel_size(format); const int pitch = ogl_pitch(w, pixel_size); GLenum e; ogl_bitmap->lock_buffer = al_malloc(pitch * h); if (ogl_bitmap->lock_buffer == NULL) { return false; } if (!(flags & ALLEGRO_LOCK_WRITEONLY)) { glReadPixels(x, gl_y, w, h, get_glformat(format, 2), get_glformat(format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n", _al_pixel_format_name(format), _al_gl_error_string(e)); al_free(ogl_bitmap->lock_buffer); ogl_bitmap->lock_buffer = NULL; return false; } } bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1); bitmap->locked_region.format = format; bitmap->locked_region.pitch = -pitch; bitmap->locked_region.pixel_size = pixel_size; return true; }
static void ogl_lock_region_nonbb_readwrite_nonfbo( ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int x, int gl_y, int w, int h, int format) { /* No FBO - fallback to reading the entire texture */ const int pixel_size = al_get_pixel_size(format); const int pitch = ogl_pitch(ogl_bitmap->true_w, pixel_size); GLenum e; (void) w; ogl_bitmap->lock_buffer = al_malloc(pitch * ogl_bitmap->true_h); glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture); glGetTexImage(GL_TEXTURE_2D, 0, get_glformat(format, 2), get_glformat(format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glGetTexImage for format %s failed (%s).\n", _al_format_name(format), _al_gl_error_string(e)); } bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (gl_y + h - 1) + pixel_size * x; bitmap->locked_region.format = format; bitmap->locked_region.pitch = -pitch; bitmap->locked_region.pixel_size = pixel_size; }
static void ogl_lock_region_nonbb_readwrite_fbo( ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int x, int gl_y, int w, int h, int format) { const int pixel_size = al_get_pixel_size(format); const int pitch = ogl_pitch(w, pixel_size); GLint old_fbo; GLenum e; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &old_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ogl_bitmap->fbo_info->fbo); ogl_bitmap->lock_buffer = al_malloc(pitch * h); glReadPixels(x, gl_y, w, h, get_glformat(format, 2), get_glformat(format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n", _al_format_name(format), _al_gl_error_string(e)); } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fbo); bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1); bitmap->locked_region.format = format; bitmap->locked_region.pitch = -pitch; bitmap->locked_region.pixel_size = pixel_size; }
static void ogl_unlock_region_backbuffer(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y) { const int lock_format = bitmap->locked_region.format; bool popmatrix = false; GLenum e; GLint program = 0; ALLEGRO_DISPLAY *display = al_get_current_display(); if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { // FIXME: This is a hack where we temporarily disable the active shader. // It will only work on Desktop OpenGL in non-strict mode where we even // can switch back to the fixed pipeline. The correct way would be to not // use any OpenGL 2 functions (like glDrawPixels). Probably we will want // separate OpenGL <= 2 (including OpenGL ES 1) and OpenGL >= 3 (including // OpenGL ES >= 2) drivers at some point. glGetIntegerv(GL_CURRENT_PROGRAM, &program); glUseProgram(0); } /* glWindowPos2i may not be available. */ if (al_get_opengl_version() >= _ALLEGRO_OPENGL_VERSION_1_4) { glWindowPos2i(bitmap->lock_x, gl_y); } else { /* glRasterPos is affected by the current modelview and projection * matrices (so maybe we actually need to reset both of them?). * The coordinate is also clipped; the small offset was required to * prevent it being culled on one of my machines. --pw * * Consider using glWindowPos2fMESAemulate from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushMatrix(); glLoadIdentity(); glRasterPos2f(bitmap->lock_x, bitmap->lock_y + bitmap->lock_h - 1e-4f); popmatrix = true; } glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDrawPixels(bitmap->lock_w, bitmap->lock_h, get_glformat(lock_format, 2), get_glformat(lock_format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glDrawPixels for format %s failed (%s).\n", _al_pixel_format_name(lock_format), _al_gl_error_string(e)); } if (popmatrix) { glPopMatrix(); } if (program != 0) { glUseProgram(program); } }
static void ogl_unlock_region_backbuffer(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y) { const int lock_format = bitmap->locked_region.format; bool popmatrix = false; GLenum e; /* glWindowPos2i may not be available. */ if (al_get_opengl_version() >= _ALLEGRO_OPENGL_VERSION_1_4) { glWindowPos2i(bitmap->lock_x, gl_y); } else { /* glRasterPos is affected by the current modelview and projection * matrices (so maybe we actually need to reset both of them?). * The coordinate is also clipped; the small offset was required to * prevent it being culled on one of my machines. --pw * * Consider using glWindowPos2fMESAemulate from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushMatrix(); glLoadIdentity(); glRasterPos2f(bitmap->lock_x, bitmap->lock_y + bitmap->lock_h - 1e-4f); popmatrix = true; } glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDrawPixels(bitmap->lock_w, bitmap->lock_h, get_glformat(lock_format, 2), get_glformat(lock_format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glDrawPixels for format %s failed (%s).\n", _al_format_name(lock_format), _al_gl_error_string(e)); } if (popmatrix) { glPopMatrix(); } }
static void ogl_unlock_region_nonbb_fbo_readwrite(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y) { const int lock_format = bitmap->locked_region.format; GLenum e; GLint tex_internalformat; glTexSubImage2D(GL_TEXTURE_2D, 0, bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h, get_glformat(lock_format, 2), get_glformat(lock_format, 1), ogl_bitmap->lock_buffer); e = glGetError(); if (e) { ALLEGRO_ERROR("glTexSubImage2D for format %s failed (%s).\n", _al_pixel_format_name(lock_format), _al_gl_error_string(e)); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &tex_internalformat); ALLEGRO_DEBUG("x/y/w/h: %d/%d/%d/%d, internal format: %d\n", bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h, tex_internalformat); } }