/* Copy bitmap->memory to texture memory */ static void d3d_sync_bitmap_texture(ALLEGRO_BITMAP *bitmap, int x, int y, int width, int height) { D3DLOCKED_RECT locked_rect; RECT rect; ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap; LPDIRECT3DTEXTURE9 texture; rect.left = x; rect.top = y; rect.right = x + width; rect.bottom = y + height; if (_al_d3d_render_to_texture_supported()) texture = d3d_bmp->system_texture; else texture = d3d_bmp->video_texture; if (texture->LockRect(0, &locked_rect, &rect, 0) == D3D_OK) { _al_convert_bitmap_data(bitmap->memory, bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format), locked_rect.pBits, bitmap->format, locked_rect.Pitch, x, y, 0, 0, width, height); /* Copy an extra row and column so the texture ends nicely */ if (rect.bottom > bitmap->h) { _al_convert_bitmap_data( bitmap->memory, bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format), locked_rect.pBits, bitmap->format, locked_rect.Pitch, 0, bitmap->h-1, 0, height, width, 1); } if (rect.right > bitmap->w) { _al_convert_bitmap_data( bitmap->memory, bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format), locked_rect.pBits, bitmap->format, locked_rect.Pitch, bitmap->w-1, 0, width, 0, 1, height); } if (rect.bottom > bitmap->h && rect.right > bitmap->w) { _al_convert_bitmap_data( bitmap->memory, bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format), locked_rect.pBits, bitmap->format, locked_rect.Pitch, bitmap->w-1, bitmap->h-1, width, height, 1, 1); } texture->UnlockRect(0); } else { ALLEGRO_ERROR("d3d_sync_bitmap_texture: Couldn't lock texture to upload.\n"); } }
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 void d3d_unlock_region(ALLEGRO_BITMAP *bitmap) { ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap; d3d_bmp->modified = true; if (bitmap->locked_region.format != 0 && bitmap->locked_region.format != bitmap->format) { if (!(bitmap->lock_flags & ALLEGRO_LOCK_READONLY)) { _al_convert_bitmap_data( bitmap->locked_region.data, bitmap->locked_region.format, bitmap->locked_region.pitch, d3d_bmp->locked_rect.pBits, bitmap->format, d3d_bmp->locked_rect.Pitch, 0, 0, 0, 0, bitmap->lock_w, bitmap->lock_h); } al_free(bitmap->locked_region.data); } if (d3d_bmp->is_backbuffer) { ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)bitmap->display; d3d_disp->render_target->UnlockRect(); } else { LPDIRECT3DTEXTURE9 texture; if (_al_d3d_render_to_texture_supported()) texture = d3d_bmp->system_texture; else texture = d3d_bmp->video_texture; texture->UnlockRect(0); if (bitmap->lock_flags & ALLEGRO_LOCK_READONLY) return; d3d_do_upload(d3d_bmp, bitmap->lock_x, bitmap->lock_y, bitmap->lock_w, bitmap->lock_h, false); } }
/* Function: al_clone_bitmap */ ALLEGRO_BITMAP *al_clone_bitmap(ALLEGRO_BITMAP *bitmap) { ALLEGRO_BITMAP *clone; ALLEGRO_LOCKED_REGION *dst_region; ALLEGRO_LOCKED_REGION *src_region; ASSERT(bitmap); clone = al_create_bitmap(bitmap->w, bitmap->h); if (!clone) return NULL; if (!(src_region = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY))) return NULL; if (!(dst_region = al_lock_bitmap(clone, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY))) { al_unlock_bitmap(bitmap); return NULL; } _al_convert_bitmap_data( src_region->data, src_region->format, src_region->pitch, dst_region->data, dst_region->format, dst_region->pitch, 0, 0, 0, 0, bitmap->w, bitmap->h); al_unlock_bitmap(bitmap); al_unlock_bitmap(clone); return clone; }
static bool transfer_bitmap_data(ALLEGRO_BITMAP *src, ALLEGRO_BITMAP *dst) { ALLEGRO_LOCKED_REGION *dst_region; ALLEGRO_LOCKED_REGION *src_region; int src_format = al_get_bitmap_format(src); int dst_format = al_get_bitmap_format(dst); bool src_compressed = _al_pixel_format_is_compressed(src_format); bool dst_compressed = _al_pixel_format_is_compressed(dst_format); int copy_w = src->w; int copy_h = src->h; if (src_compressed && dst_compressed && src_format == dst_format) { int block_width = al_get_pixel_block_width(src_format); int block_height = al_get_pixel_block_height(src_format); if (!(src_region = al_lock_bitmap_blocked(src, ALLEGRO_LOCK_READONLY))) return false; if (!(dst_region = al_lock_bitmap_blocked(dst, ALLEGRO_LOCK_WRITEONLY))) { al_unlock_bitmap(src); return false; } copy_w = _al_get_least_multiple(copy_w, block_width); copy_h = _al_get_least_multiple(copy_h, block_height); ALLEGRO_DEBUG("Taking fast clone path.\n"); } else { int lock_format = ALLEGRO_PIXEL_FORMAT_ANY; /* Go through a non-compressed intermediate */ if (src_compressed && !dst_compressed) { lock_format = dst_format; } else if (!src_compressed && dst_compressed) { lock_format = src_format; } if (!(src_region = al_lock_bitmap(src, lock_format, ALLEGRO_LOCK_READONLY))) return false; if (!(dst_region = al_lock_bitmap(dst, lock_format, ALLEGRO_LOCK_WRITEONLY))) { al_unlock_bitmap(src); return false; } } _al_convert_bitmap_data( src_region->data, src_region->format, src_region->pitch, dst_region->data, dst_region->format, dst_region->pitch, 0, 0, 0, 0, copy_w, copy_h); al_unlock_bitmap(src); al_unlock_bitmap(dst); return true; }
static void _al_draw_bitmap_region_memory_fast(ALLEGRO_BITMAP *bitmap, int sx, int sy, int sw, int sh, int dx, int dy, int flags) { ALLEGRO_LOCKED_REGION *src_region; ALLEGRO_LOCKED_REGION *dst_region; ALLEGRO_BITMAP *dest = al_get_target_bitmap(); int dw = sw, dh = sh; ASSERT(_al_pixel_format_is_real(bitmap->format)); ASSERT(_al_pixel_format_is_real(dest->format)); ASSERT(bitmap->parent == NULL); /* Currently the only flags are for flipping, which is handled as negative * scaling. */ ASSERT(flags == 0); (void)flags; CLIPPER(bitmap, sx, sy, sw, sh, dest, dx, dy, dw, dh, 1, 1, flags) if (!(src_region = al_lock_bitmap_region(bitmap, sx, sy, sw, sh, bitmap->format, ALLEGRO_LOCK_READONLY))) { return; } if (!(dst_region = al_lock_bitmap_region(dest, dx, dy, sw, sh, dest->format, ALLEGRO_LOCK_WRITEONLY))) { al_unlock_bitmap(bitmap); return; } /* will detect if no conversion is needed */ _al_convert_bitmap_data( src_region->data, bitmap->format, src_region->pitch, dst_region->data, dest->format, dst_region->pitch, 0, 0, 0, 0, sw, sh); al_unlock_bitmap(bitmap); al_unlock_bitmap(dest); }
/* Copy texture memory to bitmap->memory */ static void d3d_sync_bitmap_memory(ALLEGRO_BITMAP *bitmap) { D3DLOCKED_RECT locked_rect; ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap; LPDIRECT3DTEXTURE9 texture; if (_al_d3d_render_to_texture_supported()) texture = d3d_bmp->system_texture; else texture = d3d_bmp->video_texture; if (texture->LockRect(0, &locked_rect, NULL, 0) == D3D_OK) { _al_convert_bitmap_data(locked_rect.pBits, bitmap->format, locked_rect.Pitch, bitmap->memory, bitmap->format, al_get_pixel_size(bitmap->format)*bitmap->w, 0, 0, 0, 0, bitmap->w, bitmap->h); texture->UnlockRect(0); } else { ALLEGRO_ERROR("d3d_sync_bitmap_memory: Couldn't lock texture.\n"); } }
/* Function: al_unlock_bitmap */ void al_unlock_bitmap(ALLEGRO_BITMAP *bitmap) { /* For sub-bitmaps */ if (bitmap->parent) { bitmap = bitmap->parent; } if (!(bitmap->flags & ALLEGRO_MEMORY_BITMAP)) { bitmap->vt->unlock_region(bitmap); } else { if (bitmap->locked_region.format != 0 && bitmap->locked_region.format != bitmap->format) { if (!(bitmap->lock_flags & ALLEGRO_LOCK_READONLY)) { _al_convert_bitmap_data( bitmap->locked_region.data, bitmap->locked_region.format, bitmap->locked_region.pitch, bitmap->memory, bitmap->format, bitmap->pitch, 0, 0, bitmap->lock_x, bitmap->lock_y, bitmap->lock_w, bitmap->lock_h); } al_free(bitmap->locked_region.data); } } bitmap->locked = false; }
static ALLEGRO_LOCKED_REGION *d3d_lock_region(ALLEGRO_BITMAP *bitmap, int x, int y, int w, int h, int format, int flags) { ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap; if (d3d_bmp->display->device_lost) return NULL; RECT rect; DWORD Flags = flags & ALLEGRO_LOCK_READONLY ? D3DLOCK_READONLY : 0; int f = _al_get_real_pixel_format(al_get_current_display(), format); if (f < 0) { return NULL; } rect.left = x; rect.right = x + w; rect.top = y; rect.bottom = y + h; if (d3d_bmp->is_backbuffer) { ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)bitmap->display; if (d3d_disp->render_target->LockRect(&d3d_bmp->locked_rect, &rect, Flags) != D3D_OK) { ALLEGRO_ERROR("LockRect failed in d3d_lock_region.\n"); return NULL; } } else { LPDIRECT3DTEXTURE9 texture; if (_al_d3d_render_to_texture_supported()) { /* * Sync bitmap->memory with texture */ bitmap->locked = false; _al_d3d_sync_bitmap(bitmap); bitmap->locked = true; texture = d3d_bmp->system_texture; } else { texture = d3d_bmp->video_texture; } if (texture->LockRect(0, &d3d_bmp->locked_rect, &rect, Flags) != D3D_OK) { ALLEGRO_ERROR("LockRect failed in d3d_lock_region.\n"); return NULL; } } if (format == ALLEGRO_PIXEL_FORMAT_ANY || bitmap->format == format || f == bitmap->format) { bitmap->locked_region.data = d3d_bmp->locked_rect.pBits; bitmap->locked_region.format = bitmap->format; bitmap->locked_region.pitch = d3d_bmp->locked_rect.Pitch; bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format); } else { bitmap->locked_region.pitch = al_get_pixel_size(f) * w; bitmap->locked_region.data = al_malloc(bitmap->locked_region.pitch*h); bitmap->locked_region.format = f; bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format); if (!(bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY)) { _al_convert_bitmap_data( d3d_bmp->locked_rect.pBits, bitmap->format, d3d_bmp->locked_rect.Pitch, bitmap->locked_region.data, f, bitmap->locked_region.pitch, 0, 0, 0, 0, w, h); } } return &bitmap->locked_region; }
/* Function: al_lock_bitmap_region */ ALLEGRO_LOCKED_REGION *al_lock_bitmap_region(ALLEGRO_BITMAP *bitmap, int x, int y, int width, int height, int format, int flags) { ASSERT(x >= 0); ASSERT(y >= 0); ASSERT(width >= 0); ASSERT(height >= 0); /* For sub-bitmaps */ if (bitmap->parent) { x += bitmap->xofs; y += bitmap->yofs; bitmap = bitmap->parent; } if (bitmap->locked) return NULL; ASSERT(x+width <= bitmap->w); ASSERT(y+height <= bitmap->h); bitmap->lock_x = x; bitmap->lock_y = y; bitmap->lock_w = width; bitmap->lock_h = height; bitmap->lock_flags = flags; if (bitmap->flags & ALLEGRO_MEMORY_BITMAP) { int f = _al_get_real_pixel_format(al_get_current_display(), format); if (f < 0) { return NULL; } ASSERT(bitmap->memory); if (format == ALLEGRO_PIXEL_FORMAT_ANY || bitmap->format == format || f == bitmap->format) { bitmap->locked_region.data = bitmap->memory + bitmap->pitch * y + x * al_get_pixel_size(bitmap->format); bitmap->locked_region.format = bitmap->format; bitmap->locked_region.pitch = bitmap->pitch; bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format); } else { bitmap->locked_region.pitch = al_get_pixel_size(f) * width; bitmap->locked_region.data = al_malloc(bitmap->locked_region.pitch*height); bitmap->locked_region.format = f; bitmap->locked_region.pixel_size = al_get_pixel_size(f); if (!(bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY)) { _al_convert_bitmap_data( bitmap->memory, bitmap->format, bitmap->pitch, bitmap->locked_region.data, f, bitmap->locked_region.pitch, x, y, 0, 0, width, height); } } } else { if (!bitmap->vt->lock_region(bitmap, x, y, width, height, format, flags)) { return NULL; } } bitmap->locked = true; return &bitmap->locked_region; }