[AD] al_convert_bitmap

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


The attached patch adds the ability to convert between memory and video
bitmaps. It has two new functions:

al_convert_bitmap: like al_clone_bitmap, but modifies the bitmap
in-place)

al_convert_all_video_bitmaps: converts all video bitmaps which have
silently been converted to memory bitmaps because there was no display
to actual video bitmaps

I first implemented this with a very small patch, simply making
ALLEGRO_BITMAP big enough to hold either the OpenGL or D3D version with
some static asserts to ensure it. But since that felt a bit messy I then
changed ALLEGRO_BITMAP to have an .extra field which OpenGL/D3D now use
to allocate their additional required storage, with no more driver
specific bitmap structs. This however made the patch grow huge :P

-- 
Elias Pschernig <elias.pschernig@xxxxxxxxxx>
diff --git a/addons/primitives/prim_opengl.c b/addons/primitives/prim_opengl.c
index ed5288c..d37dec3 100644
--- a/addons/primitives/prim_opengl.c
+++ b/addons/primitives/prim_opengl.c
@@ -323,16 +323,19 @@ int _al_draw_prim_opengl(ALLEGRO_BITMAP* target, ALLEGRO_BITMAP* texture, const
 
    int num_primitives = 0;
    ALLEGRO_DISPLAY *ogl_disp = target->display;
-   ALLEGRO_BITMAP_OGL *ogl_target = (ALLEGRO_BITMAP_OGL *)target;
+   ALLEGRO_BITMAP *opengl_target = target;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
    const void* vtx;
    int stride = decl ? decl->stride : (int)sizeof(ALLEGRO_VERTEX);
    int num_vtx;
    
    if (target->parent) {
-       ogl_target = (ALLEGRO_BITMAP_OGL *)target->parent;
+       opengl_target = target->parent;
    }
+   extra = opengl_target->extra;
   
-   if ((!ogl_target->is_backbuffer && ogl_disp->ogl_extras->opengl_target != ogl_target) || al_is_bitmap_locked(target)) {
+   if ((!extra->is_backbuffer && ogl_disp->ogl_extras->opengl_target !=
+      opengl_target) || al_is_bitmap_locked(target)) {
       return _al_draw_prim_soft(texture, vtxs, decl, start, end, type);
    }
 
@@ -461,7 +464,8 @@ int _al_draw_prim_indexed_opengl(ALLEGRO_BITMAP *target, ALLEGRO_BITMAP* texture
 
    int num_primitives = 0;
    ALLEGRO_DISPLAY *ogl_disp = target->display;
-   ALLEGRO_BITMAP_OGL *ogl_target = (ALLEGRO_BITMAP_OGL *)target;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
+   ALLEGRO_BITMAP *ogl_target = target;
    const void* vtx;
    const void* idx = indices;
    GLenum idx_size;
@@ -472,10 +476,11 @@ int _al_draw_prim_indexed_opengl(ALLEGRO_BITMAP *target, ALLEGRO_BITMAP* texture
 #endif
 
    if (target->parent) {
-       ogl_target = (ALLEGRO_BITMAP_OGL *)target->parent;
+       ogl_target = target->parent;
    }
+   extra = ogl_target->extra;
 
-   if ((!ogl_target->is_backbuffer && ogl_disp->ogl_extras->opengl_target != ogl_target) || al_is_bitmap_locked(target)) {
+   if ((!extra->is_backbuffer && ogl_disp->ogl_extras->opengl_target != ogl_target) || al_is_bitmap_locked(target)) {
       return _al_draw_prim_indexed_soft(texture, decl, vtxs, indices, num_vtx, type);
    }
    
diff --git a/docs/src/refman/graphics.txt b/docs/src/refman/graphics.txt
index 3cf9f96..c7d75fc 100644
--- a/docs/src/refman/graphics.txt
+++ b/docs/src/refman/graphics.txt
@@ -288,11 +288,34 @@ See also: [al_create_bitmap]
 
 ### API: al_clone_bitmap
 
-Create a new bitmap with [al_create_bitmap], and copy the pixel data from the
-old bitmap across.
+Create a new bitmap with [al_create_bitmap], and copy the pixel data
+from the old bitmap across.
 
 See also: [al_create_bitmap], [al_set_new_bitmap_format],
-[al_set_new_bitmap_flags]
+[al_set_new_bitmap_flags], [al_convert_bitmap]
+
+### API: al_convert_bitmap
+
+Converts the bitmap to the current bitmap flags and format. The bitmap
+will be as if it was created with al_create_bitmap but retain its
+contents.
+
+If the bitmap has sub-bitmaps, you alst must call al_convert_bitmap on
+all its sub-bitmaps. If the bitmap is a sub-bitmap, you must also call
+al_convert_bitmap on the parent.
+
+See also: [al_create_bitmap], [al_set_new_bitmap_format],
+[al_set_new_bitmap_flags], [al_clone_bitmap]
+
+### API: al_convert_all_video_bitmaps
+
+If you create a video bitmap when there is no current display (for
+example because you have not called al_create_display in the current
+thread) the video bitmap will be created successfully, but really be
+a memory bitmap. This function converts all such bitmaps to proper
+video bitmaps belonging to the current display.
+
+See also:  [al_convert_bitmap]
 
 ### API: al_destroy_bitmap
 
diff --git a/include/allegro5/bitmap.h b/include/allegro5/bitmap.h
index e4051e5..4a354f1 100644
--- a/include/allegro5/bitmap.h
+++ b/include/allegro5/bitmap.h
@@ -178,6 +178,8 @@ AL_FUNC(bool, al_is_sub_bitmap, (ALLEGRO_BITMAP *bitmap));
 
 /* Miscellaneous */
 AL_FUNC(ALLEGRO_BITMAP *, al_clone_bitmap, (ALLEGRO_BITMAP *bitmap));
+AL_FUNC(void, al_convert_bitmap, (ALLEGRO_BITMAP *bitmap));
+AL_FUNC(void, al_convert_all_video_bitmaps, (void));
 AL_FUNC(bool, al_is_bitmap_locked, (ALLEGRO_BITMAP *bitmap));
 
 /* Blending */
diff --git a/include/allegro5/internal/aintern_bitmap.h b/include/allegro5/internal/aintern_bitmap.h
index 3089884..7c12c70 100644
--- a/include/allegro5/internal/aintern_bitmap.h
+++ b/include/allegro5/internal/aintern_bitmap.h
@@ -65,11 +65,10 @@ struct ALLEGRO_BITMAP
    /* A memory copy of the bitmap data. May be NULL for an empty bitmap. */
    unsigned char *memory;
 
-   /* Size of the bitmap object. Used only by functions to convert bitmap
-      storage type. Can be missleading. */
-   size_t size;
-
    bool preserve_texture;
+   
+   /* Extra data for display bitmaps, like texture id and so on. */
+   void *extra;
 };
 
 struct ALLEGRO_BITMAP_INTERFACE
@@ -149,6 +148,8 @@ bool _al_transform_is_translation(const ALLEGRO_TRANSFORM* trans,
    float *dx, float *dy);
 
 void _al_init_iio_table(void);
+void _al_init_to_be_converted_bitmaps(void);
+void _al_cleanup_to_be_converted_bitmaps(void);
 
 #ifdef __cplusplus
 }
diff --git a/include/allegro5/internal/aintern_direct3d.h b/include/allegro5/internal/aintern_direct3d.h
index 0202b80..cdf7f19 100644
--- a/include/allegro5/internal/aintern_direct3d.h
+++ b/include/allegro5/internal/aintern_direct3d.h
@@ -9,10 +9,8 @@
 extern "C" {
 #endif
 
-typedef struct ALLEGRO_BITMAP_D3D
+typedef struct ALLEGRO_BITMAP_EXTRA_D3D
 {
-   ALLEGRO_BITMAP bitmap; /* This must be the first member. */
-
    /* Driver specifics. */
 
    unsigned int texture_w;
@@ -31,7 +29,7 @@ typedef struct ALLEGRO_BITMAP_D3D
    IDirect3DSurface9 *render_target;
 
    bool modified;
-} ALLEGRO_BITMAP_D3D;
+} ALLEGRO_BITMAP_EXTRA_D3D;
 
 typedef struct ALLEGRO_DISPLAY_D3D
 {
@@ -47,7 +45,8 @@ typedef struct ALLEGRO_DISPLAY_D3D
    bool reset_done;
    bool reset_success;
 
-   ALLEGRO_BITMAP_D3D backbuffer_bmp;
+   ALLEGRO_BITMAP backbuffer_bmp;
+   ALLEGRO_BITMAP_EXTRA_D3D backbuffer_bmp_extra;
 
    bool device_lost;
 
diff --git a/include/allegro5/internal/aintern_opengl.h b/include/allegro5/internal/aintern_opengl.h
index 9766197..2ef8d26 100644
--- a/include/allegro5/internal/aintern_opengl.h
+++ b/include/allegro5/internal/aintern_opengl.h
@@ -25,8 +25,6 @@ enum {
 
 #define ALLEGRO_MAX_OPENGL_FBOS 8
 
-struct ALLEGRO_BITMAP_OGL;
-
 enum {
    FBO_INFO_UNUSED      = 0,
    FBO_INFO_TRANSIENT   = 1,  /* may be destroyed for another bitmap */
@@ -37,14 +35,12 @@ typedef struct ALLEGRO_FBO_INFO
 {
    int fbo_state;
    GLuint fbo;
-   struct ALLEGRO_BITMAP_OGL *owner;
+   ALLEGRO_BITMAP *owner;
    double last_use_time;
 } ALLEGRO_FBO_INFO;
 
-typedef struct ALLEGRO_BITMAP_OGL
+typedef struct ALLEGRO_BITMAP_EXTRA_OPENGL
 {
-   ALLEGRO_BITMAP bitmap; /* This must be the first member. */
-
    /* Driver specifics. */
 
    int true_w;
@@ -65,8 +61,7 @@ typedef struct ALLEGRO_BITMAP_OGL
 
    float left, top, right, bottom; /* Texture coordinates. */
    bool is_backbuffer; /* This is not a real bitmap, but the backbuffer. */
-} ALLEGRO_BITMAP_OGL;
-
+} ALLEGRO_BITMAP_EXTRA_OPENGL;
 
 typedef struct OPENGL_INFO {
    uint32_t version;       /* OpenGL version */
@@ -91,9 +86,9 @@ typedef struct ALLEGRO_OGL_EXTRAS
    /* Various info about OpenGL implementation. */
    OPENGL_INFO ogl_info;
 
-   ALLEGRO_BITMAP_OGL *opengl_target;
+   ALLEGRO_BITMAP *opengl_target;
 
-   ALLEGRO_BITMAP_OGL *backbuffer;
+   ALLEGRO_BITMAP *backbuffer;
 
    /* True if display resources are shared among displays. */
    bool is_shared;
@@ -160,9 +155,9 @@ ALLEGRO_FBO_INFO *_al_ogl_persist_fbo(ALLEGRO_DISPLAY *display,
 void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap);
 void _al_ogl_setup_bitmap_clipping(const ALLEGRO_BITMAP *bitmap);
 ALLEGRO_BITMAP *_al_ogl_get_backbuffer(ALLEGRO_DISPLAY *d);
-ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp);
-void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP_OGL *b);
-bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP_OGL *b, int w, int h);
+ALLEGRO_BITMAP* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp);
+void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP *b);
+bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP *b, int w, int h);
 
 struct ALLEGRO_DISPLAY_INTERFACE;
 
diff --git a/src/bitmap.c b/src/bitmap.c
index 10c1df2..d984cff 100644
--- a/src/bitmap.c
+++ b/src/bitmap.c
@@ -31,6 +31,25 @@ ALLEGRO_DEBUG_CHANNEL("bitmap")
 
 static ALLEGRO_COLOR solid_white = {1, 1, 1, 1};
 
+struct TO_BE_CONVERTED_LIST {
+   ALLEGRO_MUTEX *mutex;
+   _AL_VECTOR bitmaps;
+};
+
+static struct TO_BE_CONVERTED_LIST to_be_converted;
+
+void _al_init_to_be_converted_bitmaps(void)
+{
+   to_be_converted.mutex = al_create_mutex();
+   _al_vector_init(&to_be_converted.bitmaps, sizeof(ALLEGRO_BITMAP *));
+}
+
+void _al_cleanup_to_be_converted_bitmaps(void)
+{
+   _al_vector_free(&to_be_converted.bitmaps);
+   al_destroy_mutex(to_be_converted.mutex);
+}
+
 /* Creates a memory bitmap.
  */
 static ALLEGRO_BITMAP *_al_create_memory_bitmap(int w, int h)
@@ -43,14 +62,23 @@ static ALLEGRO_BITMAP *_al_create_memory_bitmap(int w, int h)
 
    bitmap = al_malloc(sizeof *bitmap);
    memset(bitmap, 0, sizeof(*bitmap));
-   bitmap->size = sizeof(*bitmap);
 
    pitch = w * al_get_pixel_size(format);
 
    bitmap->vt = NULL;
    bitmap->format = format;
-   bitmap->flags = (al_get_new_bitmap_flags() | ALLEGRO_MEMORY_BITMAP) &
-      ~ALLEGRO_VIDEO_BITMAP;
+
+   /* If this is really a video bitmap, we add it to the list of to
+    * be converted bitmaps.
+    */
+   bitmap->flags = (al_get_new_bitmap_flags() | ALLEGRO_MEMORY_BITMAP);
+   if (bitmap->flags & ALLEGRO_VIDEO_BITMAP) {
+      ALLEGRO_BITMAP **back;
+      al_lock_mutex(to_be_converted.mutex);
+      back = _al_vector_alloc_back(&to_be_converted.bitmaps);
+      *back = bitmap;
+      al_unlock_mutex(to_be_converted.mutex);
+   }
    bitmap->w = w;
    bitmap->h = h;
    bitmap->pitch = pitch;
@@ -100,10 +128,6 @@ static ALLEGRO_BITMAP *do_create_bitmap(int w, int h)
       return NULL;
    }
 
-   /* XXX the ogl_display driver sets some of these variables. It's not clear
-    * who should be responsible for setting what.
-    * The pitch must be set by the driver.
-    */
    bitmap->display = current_display;
    bitmap->w = w;
    bitmap->h = h;
@@ -659,17 +683,15 @@ ALLEGRO_BITMAP *al_create_sub_bitmap(ALLEGRO_BITMAP *parent,
       y += parent->yofs;
       parent = parent->parent;
    }
-
+   
    if (parent->display && parent->display->vt &&
-         parent->display->vt->create_sub_bitmap)
-   {
+         parent->display->vt->create_sub_bitmap) {
       bitmap = parent->display->vt->create_sub_bitmap(
          parent->display, parent, x, y, w, h);
    }
    else {
       bitmap = al_malloc(sizeof *bitmap);
       memset(bitmap, 0, sizeof *bitmap);
-      bitmap->size = sizeof *bitmap;
       bitmap->vt = parent->vt;
    }
 
@@ -709,37 +731,118 @@ bool al_is_sub_bitmap(ALLEGRO_BITMAP *bitmap)
 }
 
 
-/* Function: al_clone_bitmap
- */
-ALLEGRO_BITMAP *al_clone_bitmap(ALLEGRO_BITMAP *bitmap)
+static void transfer_bitmap_data(ALLEGRO_BITMAP *src, ALLEGRO_BITMAP *dst)
 {
-   ALLEGRO_BITMAP *clone = al_create_bitmap(bitmap->w, bitmap->h);
    ALLEGRO_LOCKED_REGION *dst_region;
    ALLEGRO_LOCKED_REGION *src_region;
 
-   if (!clone)
-      return NULL;
-
-   if (!(src_region = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY)))
-      return NULL;
+   if (!(src_region = al_lock_bitmap(src, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY)))
+      return;
 
-   if (!(dst_region = al_lock_bitmap(clone, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY))) {
-      al_unlock_bitmap(bitmap);
-      return NULL;
+   if (!(dst_region = al_lock_bitmap(dst, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY))) {
+      al_unlock_bitmap(src);
+      return;
    }
 
    _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);
+      0, 0, 0, 0, src->w, src->h);
+
+   al_unlock_bitmap(src);
+   al_unlock_bitmap(dst);
+}
 
-   al_unlock_bitmap(bitmap);
-   al_unlock_bitmap(clone);
 
+/* Function: al_clone_bitmap
+ */
+ALLEGRO_BITMAP *al_clone_bitmap(ALLEGRO_BITMAP *bitmap)
+{
+   ALLEGRO_BITMAP *clone = al_create_bitmap(bitmap->w, bitmap->h);
+   if (!clone)
+      return NULL;
+   transfer_bitmap_data(bitmap, clone);
    return clone;
 }
 
 
+/* Function: al_convert_bitmap
+ */
+void al_convert_bitmap(ALLEGRO_BITMAP *bitmap)
+{
+   ALLEGRO_BITMAP temp = *bitmap;
+   ALLEGRO_BITMAP *clone;
+   bool want_memory = al_get_new_bitmap_flags() & ALLEGRO_MEMORY_BITMAP;
+   bool is_memory = bitmap->flags & ALLEGRO_MEMORY_BITMAP;
+
+   if (bitmap->parent) {
+      bool parent_mem = bitmap->parent->flags & ALLEGRO_MEMORY_BITMAP;
+      if (parent_mem != is_memory)
+         al_convert_bitmap(bitmap->parent);
+      clone = al_create_sub_bitmap(bitmap->parent,
+         bitmap->xofs, bitmap->yofs, bitmap->w, bitmap->h);
+   }
+   else {
+      clone = al_clone_bitmap(bitmap);
+   }
+
+   /* If we convert from a display bitmap, we need to manually remove
+    * the bitmap pointer from the display list.
+    */
+   if (!is_memory && want_memory && bitmap->display) {
+      _al_vector_find_and_delete(&bitmap->display->bitmaps, &bitmap);
+   }
+   
+   /* If we convert to a display bitmap, we need to manually remove
+    * the created pointer for the clone.
+    */
+   if (!want_memory && clone->display) {
+      _al_vector_find_and_delete(&clone->display->bitmaps, &clone);
+   }
+
+   /* Preserve bitmap state. */
+   clone->cl = bitmap->cl;
+   clone->ct = bitmap->ct;
+   clone->cr_excl = bitmap->cr_excl;
+   clone->cb_excl = bitmap->cb_excl;
+   clone->transform = bitmap->transform;
+   clone->inverse_transform = bitmap->inverse_transform;
+   clone->inverse_transform_dirty = bitmap->inverse_transform_dirty;
+   *bitmap = *clone; /* We get the new bitmap's extra pointer. */
+
+   *clone = temp; /* So everything can be deleted properly. */
+   al_destroy_bitmap(clone);
+}
+
+
+/* Function: al_convert_all_video_bitmaps
+ */
+void al_convert_all_video_bitmaps(void)
+{
+   ALLEGRO_STATE backup;
+   ALLEGRO_DISPLAY *display = al_get_current_display();
+   if (!display) return;
+   
+   al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);
+   al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
+
+   al_lock_mutex(to_be_converted.mutex);
+   
+   while (!_al_vector_is_empty(&to_be_converted.bitmaps)) {
+      ALLEGRO_BITMAP **back;
+      back = _al_vector_ref_back(&to_be_converted.bitmaps);
+      al_convert_bitmap(*back);
+
+      _al_vector_delete_at(&to_be_converted.bitmaps,
+         _al_vector_size(&to_be_converted.bitmaps) - 1);
+   }
+
+   al_unlock_mutex(to_be_converted.mutex);
+   
+   al_restore_state(&backup);
+}
+
+
 /* Function: al_is_bitmap_locked
  */
 bool al_is_bitmap_locked(ALLEGRO_BITMAP *bitmap)
@@ -749,140 +852,49 @@ bool al_is_bitmap_locked(ALLEGRO_BITMAP *bitmap)
 
 
 /* Converts a memory bitmap to a display bitmap preserving its contents.
- * The created bitmap belongs to the current display. A converted sub
- * bitmap is invalid until its parent is converted.
- * WARNING: This function will fail for any memory bitmap not previously
- * processed by _al_convert_to_memory_bitmap().
+ * The created bitmap belongs to the current display.
+ * 
+ * If this is called for a sub-bitmap, the parent also is converted.
  */
 void _al_convert_to_display_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP *tmp;
-   ALLEGRO_BITMAP **vid;
    ALLEGRO_STATE backup;
-   ALLEGRO_DISPLAY *d = al_get_current_display();
 
    /* Do nothing if it is a display bitmap already. */
    if (!(bitmap->flags & ALLEGRO_MEMORY_BITMAP))
       return;
 
-   if (bitmap->parent) {
-      /* FIXME
-       * We cannot safely assume that the backbuffer and bitmaps use the same
-       * vtable.
-       */
-      bitmap->vt = al_get_backbuffer(d)->vt;
-      bitmap->display = d;
-      bitmap->flags &= !ALLEGRO_MEMORY_BITMAP;
-      return;
-   }
-
    ALLEGRO_DEBUG("converting memory bitmap %p to display bitmap\n", bitmap);
 
-   /* Allocate a temporary bitmap which will hold the data during the
-    * conversion process.
-    */
-   al_store_state(&backup, ALLEGRO_STATE_BITMAP | ALLEGRO_STATE_BLENDER);
-
+   al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);
    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
    al_set_new_bitmap_format(bitmap->format);
-   tmp = do_create_bitmap(bitmap->w, bitmap->h);
-
-   /* Preserve bitmap contents. */
-   al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
-   al_set_target_bitmap(tmp);
-   al_draw_bitmap(bitmap, 0, 0, 0);
-   tmp->cb_excl = bitmap->cb_excl;
-   tmp->cr_excl = bitmap->cr_excl;
-   tmp->cl = bitmap->cl;
-   tmp->ct = bitmap->ct;
-
+   al_convert_bitmap(bitmap);
    al_restore_state(&backup);
-
-   /* Free the memory bitmap's memory. */
-   al_free(bitmap->memory);
-
-   /* Put the contents back to the bitmap. */
-   ASSERT(tmp->size > sizeof(ALLEGRO_BITMAP));
-   ASSERT(bitmap->size > sizeof(ALLEGRO_BITMAP));
-   ASSERT(tmp->size == bitmap->size);
-   memcpy(bitmap, tmp, tmp->size);
-
-   vid = _al_vector_alloc_back(&d->bitmaps);
-   *vid = bitmap;
-
-   /* Remove the temporary bitmap from the display bitmap list, added
-    * automatically by al_create_bitmap()
-    */
-   _al_vector_find_and_delete(&d->bitmaps, &tmp);
-   al_free(tmp);
 }
 
 
 /* Converts a display bitmap to a memory bitmap preserving its contents.
- * Driver specific resources occupied by the display bitmap are freed.
- * A converted sub bitmap is invalid until its parent is converted.
+ * If this is called for a sub-bitmap, the parent also is converted.
  */
 void _al_convert_to_memory_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP *tmp;
    ALLEGRO_STATE backup;
-   size_t old_size;
 
    /* Do nothing if it is a memory bitmap already. */
    if (bitmap->flags & ALLEGRO_MEMORY_BITMAP)
       return;
 
-   if (bitmap->parent) {
-      _al_vector_find_and_delete(&bitmap->display->bitmaps, &bitmap);
-
-      //al_realloc(bitmap, sizeof(ALLEGRO_BITMAP));
-      bitmap->display = NULL;
-      bitmap->flags |= ALLEGRO_MEMORY_BITMAP;
-      return;
-   }
-
    ALLEGRO_DEBUG("converting display bitmap %p to memory bitmap\n", bitmap);
 
-   /* Allocate a temporary bitmap which will hold the data
-    * during the conversion process. */
-
-   al_store_state(&backup, ALLEGRO_STATE_BITMAP | ALLEGRO_STATE_BLENDER);
-
+   al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);
    al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
    al_set_new_bitmap_format(bitmap->format);
-   tmp = _al_create_memory_bitmap(bitmap->w, bitmap->h);
-
-   /* Preserve bitmap contents. */
-   al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
-   al_set_target_bitmap(tmp);
-   al_draw_bitmap(bitmap, 0, 0, 0);
-   tmp->cb_excl = bitmap->cb_excl;
-   tmp->cr_excl = bitmap->cr_excl;
-   tmp->cl = bitmap->cl;
-   tmp->ct = bitmap->ct;
-
+   al_convert_bitmap(bitmap);
    al_restore_state(&backup);
-
-   /* Destroy the display bitmap to free driver-specific resources. */
-   if (bitmap->vt)
-      bitmap->vt->destroy_bitmap(bitmap);
-
-   _al_vector_find_and_delete(&bitmap->display->bitmaps, &bitmap);
-
-   /* Do not shrink the bitmap object. This way we can convert back to the
-    * display bitmap.
-    */
-   /*al_realloc(bitmap, tmp->size);
-     bitmap->size = tmp->size*/
-
-   /* Put the contents back to the bitmap. */
-   old_size = bitmap->size;
-   memcpy(bitmap, tmp, tmp->size);
-   bitmap->size = old_size;
-
-   al_free(tmp);
 }
 
+
 void _al_convert_bitmap_data(
    void *src, int src_format, int src_pitch,
    void *dst, int dst_format, int dst_pitch,
diff --git a/src/iphone/iphone_display.c b/src/iphone/iphone_display.c
index cd9ca90..ec168af 100644
--- a/src/iphone/iphone_display.c
+++ b/src/iphone/iphone_display.c
@@ -115,9 +115,10 @@ void _al_iphone_translate_to_screen(ALLEGRO_DISPLAY *d, int *ox, int *oy)
 
 void _al_iphone_clip(ALLEGRO_BITMAP const *bitmap, int x_1, int y_1, int x_2, int y_2)
 {
-   ALLEGRO_BITMAP_OGL *oglb = (void *)(bitmap->parent ? bitmap->parent : bitmap);
-   int h = oglb->bitmap.h;
-   if (_screen_hack && oglb->is_backbuffer) {
+   ALLEGRO_BITMAP *oglb = (void *)(bitmap->parent ? bitmap->parent : bitmap);
+   ALLEGRO_BITMAP_EXTRA_OPENGL *e = oglb->extra;
+   int h = oglb->h;
+   if (_screen_hack && e->is_backbuffer) {
       _al_iphone_translate_to_screen(bitmap->display, &x_1, &y_1);
       _al_iphone_translate_to_screen(bitmap->display, &x_2, &y_2);
       if (x_1 > x_2) {
diff --git a/src/opengl/ogl_bitmap.c b/src/opengl/ogl_bitmap.c
index 64d2bd1..8fd4f2c 100644
--- a/src/opengl/ogl_bitmap.c
+++ b/src/opengl/ogl_bitmap.c
@@ -232,7 +232,7 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
 {
    float tex_l, tex_t, tex_r, tex_b, w, h, tex_w, tex_h;
    float dw = sw, dh = sh;
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    ALLEGRO_OGL_BITMAP_VERTEX *verts;
    ALLEGRO_DISPLAY *disp = al_get_current_display();
    
@@ -319,7 +319,7 @@ static void ogl_draw_bitmap_region(ALLEGRO_BITMAP *bitmap,
    // FIXME: hack
    // FIXME: need format conversion if they don't match
    ALLEGRO_BITMAP *target = al_get_target_bitmap();
-   ALLEGRO_BITMAP_OGL *ogl_target;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target;
    ALLEGRO_DISPLAY *disp = target->display;
 
    /* For sub-bitmaps */
@@ -327,11 +327,11 @@ static void ogl_draw_bitmap_region(ALLEGRO_BITMAP *bitmap,
       target = target->parent;
    }
 
-   ogl_target = (ALLEGRO_BITMAP_OGL *)target;
+   ogl_target = target->extra;
 
    if (!(bitmap->flags & ALLEGRO_MEMORY_BITMAP)) {
 #if !defined ALLEGRO_GP2XWIZ
-      ALLEGRO_BITMAP_OGL *ogl_source = (void *)bitmap;
+      ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_source = bitmap->extra;
       if (ogl_source->is_backbuffer) {
          /* Our source bitmap is the OpenGL backbuffer, the target
           * is an OpenGL texture.
@@ -392,7 +392,7 @@ static void ogl_draw_bitmap_region(ALLEGRO_BITMAP *bitmap,
       return;
 #endif
    }
-   if (disp->ogl_extras->opengl_target == ogl_target) {
+   if (disp->ogl_extras->opengl_target == target) {
       if (setup_blending(disp)) {
          draw_quad(bitmap, tint, sx, sy, sw, sh, flags);
          return;
@@ -417,7 +417,7 @@ static int pot(int x)
 // proxy textures, formats, limits ...
 static bool ogl_upload_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    int w = bitmap->w;
    int h = bitmap->h;
    bool post_generate_mipmap = false;
@@ -550,13 +550,13 @@ static bool ogl_upload_bitmap(ALLEGRO_BITMAP *bitmap)
 static void ogl_update_clipping_rectangle(ALLEGRO_BITMAP *bitmap)
 {
    ALLEGRO_DISPLAY *ogl_disp = al_get_current_display();
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP *target_bitmap = bitmap;
 
    if (bitmap->parent) {
-      ogl_bitmap = (ALLEGRO_BITMAP_OGL *)bitmap->parent;
+      target_bitmap = bitmap->parent;
    }
 
-   if (ogl_disp->ogl_extras->opengl_target == ogl_bitmap) {
+   if (ogl_disp->ogl_extras->opengl_target == target_bitmap) {
       _al_ogl_setup_bitmap_clipping(bitmap);
    }
 }
@@ -604,7 +604,7 @@ static bool exactly_15bpp(int pixel_format)
 static ALLEGRO_LOCKED_REGION *ogl_lock_region(ALLEGRO_BITMAP *bitmap,
    int x, int y, int w, int h, int format, int flags)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    int pixel_size;
    int pixel_alignment;
    int pitch;
@@ -787,7 +787,7 @@ static ALLEGRO_LOCKED_REGION *ogl_lock_region(ALLEGRO_BITMAP *bitmap,
  */
 static void ogl_unlock_region(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    const int lock_format = bitmap->locked_region.format;
    ALLEGRO_DISPLAY *disp;
    ALLEGRO_DISPLAY *old_disp = NULL;
@@ -1015,7 +1015,7 @@ Done:
 
 static void ogl_destroy_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    ALLEGRO_DISPLAY *disp;
    ALLEGRO_DISPLAY *old_disp = NULL;
 
@@ -1036,6 +1036,8 @@ static void ogl_destroy_bitmap(ALLEGRO_BITMAP *bitmap)
    if (old_disp) {
       _al_set_current_display_only(old_disp);
    }
+   
+   al_free(ogl_bitmap);
 }
 
 
@@ -1063,7 +1065,8 @@ static ALLEGRO_BITMAP_INTERFACE *ogl_bitmap_driver(void)
 
 ALLEGRO_BITMAP *_al_ogl_create_bitmap(ALLEGRO_DISPLAY *d, int w, int h)
 {
-   ALLEGRO_BITMAP_OGL *bitmap;
+   ALLEGRO_BITMAP *bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
    int format = al_get_new_bitmap_format();
    const int flags = al_get_new_bitmap_flags();
    int true_w;
@@ -1107,97 +1110,91 @@ ALLEGRO_BITMAP *_al_ogl_create_bitmap(ALLEGRO_DISPLAY *d, int w, int h)
 
    pitch = true_w * al_get_pixel_size(format);
 
-   bitmap = al_malloc(sizeof *bitmap);
+   bitmap = al_calloc(1, sizeof *bitmap);
    ASSERT(bitmap);
-   memset(bitmap, 0, sizeof *bitmap);
-   bitmap->bitmap.size = sizeof *bitmap;
-   bitmap->bitmap.vt = ogl_bitmap_driver();
-   bitmap->bitmap.w = w;
-   bitmap->bitmap.h = h;
-   bitmap->bitmap.pitch = pitch;
-   bitmap->bitmap.format = format;
-   bitmap->bitmap.flags = flags | _ALLEGRO_INTERNAL_OPENGL;
-   bitmap->bitmap.cl = 0;
-   bitmap->bitmap.ct = 0;
-   bitmap->bitmap.cr_excl = w;
-   bitmap->bitmap.cb_excl = h;
-   /* Back and front buffers should share a transform, which they do
-    * because our OpenGL driver returns the same pointer for both.
-    */
-   al_identity_transform(&bitmap->bitmap.transform);
+   bitmap->extra = al_calloc(1, sizeof(ALLEGRO_BITMAP_EXTRA_OPENGL));
+   ASSERT(bitmap->extra);
+   extra = bitmap->extra;
+   
+   bitmap->vt = ogl_bitmap_driver();
+   bitmap->pitch = pitch;
+   bitmap->format = format;
+   bitmap->flags = flags | _ALLEGRO_INTERNAL_OPENGL;
 
-   bitmap->true_w = true_w;
-   bitmap->true_h = true_h;
+   extra->true_w = true_w;
+   extra->true_h = true_h;
 
 #if !defined(ALLEGRO_IPHONE) && !defined(ALLEGRO_GP2XWIZ)
-   bitmap->bitmap.memory = NULL;
+   bitmap->memory = NULL;
 #else
    /* iPhone/Wiz ports still expect the buffer to be present. */
    {
       size_t bytes = pitch * true_h;
-      bitmap->bitmap.memory = al_malloc(bytes);
+      bitmap->memory = al_malloc(bytes);
 
       /* We never allow un-initialized memory for OpenGL bitmaps, if it
        * is uploaded to a floating point texture it can lead to Inf and
        * NaN values which break all subsequent blending.
        */
-      memset(bitmap->bitmap.memory, 0, bytes);
+      memset(bitmap->memory, 0, bytes);
    }
 #endif
 
-   return &bitmap->bitmap;
+   return bitmap;
 }
 
 
-
 ALLEGRO_BITMAP *_al_ogl_create_sub_bitmap(ALLEGRO_DISPLAY *d,
                                           ALLEGRO_BITMAP *parent,
                                           int x, int y, int w, int h)
 {
-   ALLEGRO_BITMAP_OGL* ogl_bmp;
-   ALLEGRO_BITMAP_OGL* ogl_parent = (void*)parent;
+   ALLEGRO_BITMAP *bmp;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *parent_extra = parent->extra;
    (void)d;
 
-   ogl_bmp = al_malloc(sizeof *ogl_bmp);
-   memset(ogl_bmp, 0, sizeof *ogl_bmp);
+   bmp = al_calloc(1, sizeof *bmp);
+   extra = al_calloc(1, sizeof *extra);
+   bmp->extra = extra;
 
-   ogl_bmp->true_w = ogl_parent->true_w;
-   ogl_bmp->true_h = ogl_parent->true_h;
-   ogl_bmp->texture = ogl_parent->texture;
+   extra->true_w = parent_extra->true_w;
+   extra->true_h = parent_extra->true_h;
+   extra->texture = parent_extra->texture;
 
 #if !defined ALLEGRO_GP2XWIZ
-   ogl_bmp->fbo_info = ogl_parent->fbo_info;
+   extra->fbo_info = parent_extra->fbo_info;
 #endif
 
-   ogl_bmp->left = x / (float)ogl_parent->true_w;
-   ogl_bmp->right = (x + w) / (float)ogl_parent->true_w;
-   ogl_bmp->top = (parent->h - y) / (float)ogl_parent->true_h;
-   ogl_bmp->bottom = (parent->h - y - h) / (float)ogl_parent->true_h;
+   extra->left = x / (float)parent_extra->true_w;
+   extra->right = (x + w) / (float)parent_extra->true_w;
+   extra->top = (parent->h - y) / (float)parent_extra->true_h;
+   extra->bottom = (parent->h - y - h) / (float)parent_extra->true_h;
 
-   ogl_bmp->is_backbuffer = ogl_parent->is_backbuffer;
+   extra->is_backbuffer = parent_extra->is_backbuffer;
 
-   ogl_bmp->bitmap.vt = parent->vt;
+   bmp->vt = parent->vt;
    
-   ogl_bmp->bitmap.flags |= _ALLEGRO_INTERNAL_OPENGL;
+   bmp->flags |= _ALLEGRO_INTERNAL_OPENGL;
 
-   return (void*)ogl_bmp;
+   return bmp;
 }
 
+
 /* Function: al_get_opengl_texture
  */
 GLuint al_get_opengl_texture(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra = bitmap->extra;
    if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL))
       return 0;
-   return ogl_bitmap->texture;
+   return extra->texture;
 }
 
 /* Function: al_remove_opengl_fbo
  */
 void al_remove_opengl_fbo(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
 
    if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL))
       return;
@@ -1229,7 +1226,7 @@ void al_remove_opengl_fbo(ALLEGRO_BITMAP *bitmap)
 GLuint al_get_opengl_fbo(ALLEGRO_BITMAP *bitmap)
 {
 #if !defined ALLEGRO_GP2XWIZ
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
 
    if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL))
       return 0;
@@ -1259,7 +1256,7 @@ void al_get_opengl_texture_size(ALLEGRO_BITMAP *bitmap, int *w, int *h)
     * texture sizes, so this will be the only way there to get the texture
     * size. On normal OpenGL also glGetTexLevelParameter could be used.
     */
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    if (!(bitmap->flags & _ALLEGRO_INTERNAL_OPENGL)) {
       *w = 0;
       *h = 0;
diff --git a/src/opengl/ogl_display.c b/src/opengl/ogl_display.c
index 42e30bb..14b965d 100644
--- a/src/opengl/ogl_display.c
+++ b/src/opengl/ogl_display.c
@@ -57,13 +57,13 @@ void _al_ogl_reset_fbo_info(ALLEGRO_FBO_INFO *info)
 
 bool _al_ogl_create_persistent_fbo(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap;
    ALLEGRO_FBO_INFO *info;
    GLint old_fbo;
 
    if (bitmap->parent)
       bitmap = bitmap->parent;
-   ogl_bitmap = (void *)bitmap;
+   ogl_bitmap = bitmap->extra;
 
    /* Don't continue if the bitmap does not belong to the current display. */
    if (bitmap->display->ogl_extras->is_shared == false &&
@@ -102,7 +102,7 @@ bool _al_ogl_create_persistent_fbo(ALLEGRO_BITMAP *bitmap)
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fbo);
 
    info->fbo_state = FBO_INFO_PERSISTENT;
-   info->owner = ogl_bitmap;
+   info->owner = bitmap;
    info->last_use_time = al_get_time();
    ogl_bitmap->fbo_info = info;
    ALLEGRO_DEBUG("Persistent FBO: %u\n", info->fbo);
@@ -155,11 +155,11 @@ static ALLEGRO_FBO_INFO *ogl_find_unused_fbo(ALLEGRO_DISPLAY *display)
 
 static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap;
 
    if (bitmap->parent)
       bitmap = bitmap->parent;
-   ogl_bitmap = (void *)bitmap;
+   ogl_bitmap = bitmap->extra;
 
 #if !defined ALLEGRO_GP2XWIZ
    if (!ogl_bitmap->is_backbuffer) {
@@ -184,7 +184,8 @@ static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
             ASSERT(info->fbo_state != FBO_INFO_PERSISTENT);
 
             if (info->fbo_state == FBO_INFO_TRANSIENT) {
-               info->owner->fbo_info = NULL;
+               ALLEGRO_BITMAP_EXTRA_OPENGL *extra = info->owner->extra;
+               extra->fbo_info = NULL;
                ALLEGRO_DEBUG("Deleting FBO: %u\n", info->fbo);
                glDeleteFramebuffersEXT(1, &info->fbo);
                _al_ogl_reset_fbo_info(info);
@@ -206,7 +207,7 @@ static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
 #endif
          if (info->fbo_state == FBO_INFO_UNUSED)
             info->fbo_state = FBO_INFO_TRANSIENT;
-         info->owner = ogl_bitmap;
+         info->owner = bitmap;
          info->last_use_time = al_get_time();
          ogl_bitmap->fbo_info = info;
 
@@ -230,7 +231,7 @@ static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
             ogl_bitmap->fbo_info = NULL;
          }
          else {
-            display->ogl_extras->opengl_target = ogl_bitmap;
+            display->ogl_extras->opengl_target = bitmap;
 
             glViewport(0, 0, bitmap->w, bitmap->h);
 
@@ -242,7 +243,7 @@ static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
       }
    }
    else {
-      display->ogl_extras->opengl_target = ogl_bitmap;
+      display->ogl_extras->opengl_target = bitmap;
 
 #ifndef ALLEGRO_IPHONE
       if (display->ogl_extras->extension_list->ALLEGRO_GL_EXT_framebuffer_object ||
@@ -302,14 +303,14 @@ static void setup_fbo(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
 
 void _al_ogl_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_OGL *ogl_bitmap = (void *)bitmap;
+   ALLEGRO_BITMAP *target = bitmap;
    if (bitmap->parent)
-      ogl_bitmap = (void *)bitmap->parent;
+      target = bitmap->parent;
 
    if (!bitmap->locked) {
       setup_fbo(display, bitmap);
 
-      if (display->ogl_extras->opengl_target == ogl_bitmap) {
+      if (display->ogl_extras->opengl_target == target) {
          _al_ogl_setup_bitmap_clipping(bitmap);
       }
    }
@@ -391,42 +392,43 @@ ALLEGRO_BITMAP *_al_ogl_get_backbuffer(ALLEGRO_DISPLAY *d)
 }
 
 
-bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP_OGL *b, int w, int h)
+bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP *b, int w, int h)
 {
    int pitch;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *extra = b->extra;
          
-   pitch = w * al_get_pixel_size(b->bitmap.format);
+   pitch = w * al_get_pixel_size(b->format);
 
-   b->bitmap.w = w;
-   b->bitmap.h = h;
-   b->bitmap.pitch = pitch;
-   b->bitmap.cl = 0;
-   b->bitmap.ct = 0;
-   b->bitmap.cr_excl = w;
-   b->bitmap.cb_excl = h;
+   b->w = w;
+   b->h = h;
+   b->pitch = pitch;
+   b->cl = 0;
+   b->ct = 0;
+   b->cr_excl = w;
+   b->cb_excl = h;
 
    /* There is no texture associated with the backbuffer so no need to care
     * about texture size limitations. */
-   b->true_w = w;
-   b->true_h = h;
+   extra->true_w = w;
+   extra->true_h = h;
 
    /* This code below appears to be unneccessary on platforms other than
     * OS X.
     */
 #ifdef ALLEGRO_MACOSX
-   b->bitmap.display->vt->set_projection(b->bitmap.display);
+   b->bitmap.display->vt->set_projection(b->display);
 #endif
 
 #if !defined(ALLEGRO_IPHONE) && !defined(ALLEGRO_GP2XWIZ)
-   b->bitmap.memory = NULL;
+   b->memory = NULL;
 #else
    /* iPhone/Wiz ports still expect the buffer to be present. */
    {
       /* FIXME: lazily manage memory */
       size_t bytes = pitch * h;
-      al_free(b->bitmap.memory);
-      b->bitmap.memory = al_malloc(bytes);
-      memset(b->bitmap.memory, 0, bytes);
+      al_free(b->memory);
+      b->memory = al_malloc(bytes);
+      memset(b->memory, 0, bytes);
    }
 #endif
 
@@ -434,9 +436,9 @@ bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP_OGL *b, int w, int h)
 }
 
 
-ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
+ALLEGRO_BITMAP* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
 {
-   ALLEGRO_BITMAP_OGL *ogl_backbuffer;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_backbuffer;
    ALLEGRO_BITMAP *backbuffer;
    ALLEGRO_STATE backup;
    int format;
@@ -477,6 +479,13 @@ ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
    al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
    backbuffer = _al_ogl_create_bitmap(disp, disp->w, disp->h);
    al_restore_state(&backup);
+   
+   backbuffer->w = disp->w;
+   backbuffer->h = disp->h;
+   backbuffer->cl = 0;
+   backbuffer->ct = 0;
+   backbuffer->cr_excl = disp->w;
+   backbuffer->cb_excl = disp->h;
 
    if (!backbuffer) {
       ALLEGRO_DEBUG("Backbuffer bitmap creation failed.\n");
@@ -487,19 +496,19 @@ ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
       "Created backbuffer bitmap (actual format: %s)\n",
       _al_format_name(backbuffer->format));
 
-   ogl_backbuffer = (ALLEGRO_BITMAP_OGL*)backbuffer;
+   ogl_backbuffer = backbuffer->extra;
    ogl_backbuffer->is_backbuffer = 1;
    backbuffer->display = disp;
 
    al_identity_transform(&disp->view_transform);
 
-   return ogl_backbuffer;
+   return backbuffer;
 }
 
 
-void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP_OGL *b)
+void _al_ogl_destroy_backbuffer(ALLEGRO_BITMAP *b)
 {
-   al_destroy_bitmap((ALLEGRO_BITMAP *)b);
+   al_destroy_bitmap(b);
 }
 
 
diff --git a/src/opengl/ogl_draw.c b/src/opengl/ogl_draw.c
index e0408e5..0f71e9c 100644
--- a/src/opengl/ogl_draw.c
+++ b/src/opengl/ogl_draw.c
@@ -165,15 +165,15 @@ static void ogl_clear(ALLEGRO_DISPLAY *d, ALLEGRO_COLOR *color)
 {
    ALLEGRO_DISPLAY *ogl_disp = (void *)d;
    ALLEGRO_BITMAP *target = al_get_target_bitmap();
-   ALLEGRO_BITMAP_OGL *ogl_target;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target;
    float r, g, b, a;
    
    if (target->parent) target = target->parent;
    
-   ogl_target = (void *)target;
+   ogl_target = target->extra;
 
    if ((!ogl_target->is_backbuffer &&
-      ogl_disp->ogl_extras->opengl_target != ogl_target) ||
+      ogl_disp->ogl_extras->opengl_target != target) ||
       target->locked) {
       _al_clear_memory(color);
       return;
@@ -190,12 +190,12 @@ static void ogl_draw_pixel(ALLEGRO_DISPLAY *d, float x, float y,
    ALLEGRO_COLOR *color)
 {
    ALLEGRO_BITMAP *target = al_get_target_bitmap();
-   ALLEGRO_BITMAP_OGL *ogl_target = (void *)target;
+   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_target = target->extra;
    GLfloat vert[2];
    GLfloat color_array[4];
 
    if ((!ogl_target->is_backbuffer &&
-      d->ogl_extras->opengl_target != ogl_target) ||
+      d->ogl_extras->opengl_target != target) ||
       target->locked || !set_opengl_blending(d))  {
       _al_draw_pixel_memory(target, x, y, color);
       return;
diff --git a/src/system.c b/src/system.c
index b8a8258..f5e6e93 100644
--- a/src/system.c
+++ b/src/system.c
@@ -280,6 +280,8 @@ bool al_install_system(int version, int (*atexit_ptr)(void (*)(void)))
    _al_init_pixels();
 
    _al_init_iio_table();
+   
+   _al_init_to_be_converted_bitmaps();
 
    if (atexit_ptr && atexit_virgin) {
       atexit_ptr(al_uninstall_system);
@@ -298,6 +300,7 @@ bool al_install_system(int version, int (*atexit_ptr)(void (*)(void)))
  */
 void al_uninstall_system(void)
 {
+   _al_cleanup_to_be_converted_bitmaps();
    _al_run_destructors(_al_dtor_list);
    _al_run_exit_funcs();
    _al_shutdown_destructors(_al_dtor_list);
diff --git a/src/win/d3d_bmp.cpp b/src/win/d3d_bmp.cpp
index 660e82e..ee5e536 100644
--- a/src/win/d3d_bmp.cpp
+++ b/src/win/d3d_bmp.cpp
@@ -35,10 +35,12 @@ ALLEGRO_DEBUG_CHANNEL("d3d")
 static ALLEGRO_BITMAP_INTERFACE *vt;
 static _AL_VECTOR created_bitmaps;
 
+// C++ needs to cast void pointers
+#define get_extra(b) ((ALLEGRO_BITMAP_EXTRA_D3D *)b->extra)
 
 void al_get_d3d_texture_size(ALLEGRO_BITMAP *bitmap, int *width, int *height)
 {
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
    *width = d3d_bmp->texture_w;
    *height = d3d_bmp->texture_h;
 }
@@ -46,7 +48,7 @@ void al_get_d3d_texture_size(ALLEGRO_BITMAP *bitmap, int *width, int *height)
 
 void _al_d3d_bmp_init(void)
 {
-   _al_vector_init(&created_bitmaps, sizeof(ALLEGRO_BITMAP_D3D *));
+   _al_vector_init(&created_bitmaps, sizeof(ALLEGRO_BITMAP *));
 }
 
 
@@ -70,7 +72,7 @@ static INLINE void transform_vertex(float* x, float* y)
  * Draw a textured quad
  */
 static void d3d_draw_textured_quad(
-   ALLEGRO_DISPLAY_D3D *disp, ALLEGRO_BITMAP_D3D *bmp, ALLEGRO_COLOR tint,
+   ALLEGRO_DISPLAY_D3D *disp, ALLEGRO_BITMAP *bmp, ALLEGRO_COLOR tint,
    float sx, float sy, float sw, float sh, int flags)
 {
    float right;
@@ -81,6 +83,7 @@ static void d3d_draw_textured_quad(
    float tv_end;
    int texture_w;
    int texture_h;
+   ALLEGRO_BITMAP_EXTRA_D3D *extra = get_extra(bmp);
 
    const float z = 0.0f;
    
@@ -94,8 +97,8 @@ static void d3d_draw_textured_quad(
    right  = sw;
    bottom = sh;
 
-   texture_w = bmp->texture_w;
-   texture_h = bmp->texture_h;
+   texture_w = extra->texture_w;
+   texture_h = extra->texture_h;
    tu_start = sx / texture_w;
    tv_start = sy / texture_h;
    tu_end = sw / texture_w + tu_start;
@@ -172,7 +175,7 @@ static void d3d_draw_textured_quad(
 static void d3d_sync_bitmap_memory(ALLEGRO_BITMAP *bitmap)
 {
    D3DLOCKED_RECT locked_rect;
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
    LPDIRECT3DTEXTURE9 texture;
 
    if (_al_d3d_render_to_texture_supported())
@@ -197,7 +200,7 @@ static void d3d_sync_bitmap_texture(ALLEGRO_BITMAP *bitmap,
 {
    D3DLOCKED_RECT locked_rect;
    RECT rect;
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
    LPDIRECT3DTEXTURE9 texture;
 
    rect.left = x;
@@ -252,10 +255,10 @@ static void d3d_sync_bitmap_texture(ALLEGRO_BITMAP *bitmap,
    }
 }
 
-static void d3d_do_upload(ALLEGRO_BITMAP_D3D *d3d_bmp, int x, int y, int width,
+static void d3d_do_upload(ALLEGRO_BITMAP *bmp, int x, int y, int width,
    int height, bool sync_from_memory)
 {
-   ALLEGRO_BITMAP *bmp = (ALLEGRO_BITMAP *)d3d_bmp;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bmp);
 
    if (sync_from_memory) {
       d3d_sync_bitmap_texture(bmp, x, y, width, height);
@@ -282,10 +285,10 @@ void _al_d3d_release_default_pool_textures(void)
    for (i = 0; i < created_bitmaps._size; i++) {
    	ALLEGRO_BITMAP **bptr = (ALLEGRO_BITMAP **)_al_vector_ref(&created_bitmaps, i);
 	ALLEGRO_BITMAP *albmp = *bptr;
-	ALLEGRO_BITMAP_D3D *d3d_bmp;
+	ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp;
 	if (albmp->flags & ALLEGRO_MEMORY_BITMAP)
 	   continue;
-	d3d_bmp = (ALLEGRO_BITMAP_D3D *)albmp;
+	d3d_bmp = get_extra(albmp);
 	if (!d3d_bmp->is_backbuffer && d3d_bmp->render_target) {
 		d3d_bmp->render_target->Release();
 		d3d_bmp->render_target = NULL;
@@ -363,7 +366,7 @@ static ALLEGRO_BITMAP *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface
    int flags)
 {
    ALLEGRO_BITMAP *bitmap;
-   ALLEGRO_BITMAP_D3D *d3d_bmp;
+   ALLEGRO_BITMAP_EXTRA_D3D *extra;
    D3DSURFACE_DESC desc;
    D3DLOCKED_RECT surf_locked_rect;
    D3DLOCKED_RECT sys_locked_rect;
@@ -389,7 +392,7 @@ static ALLEGRO_BITMAP *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface
    al_set_new_bitmap_flags(flags);
 
    bitmap = al_create_bitmap(desc.Width, desc.Height);
-   d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   extra = get_extra(bitmap);
 
    al_restore_state(&backup);
 
@@ -398,7 +401,7 @@ static ALLEGRO_BITMAP *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface
       return NULL;
    }
 
-   if (d3d_bmp->system_texture->LockRect(0, &sys_locked_rect, 0, 0) != D3D_OK) {
+   if (extra->system_texture->LockRect(0, &sys_locked_rect, 0, 0) != D3D_OK) {
       surface->UnlockRect();
       al_destroy_bitmap(bitmap);
       ALLEGRO_ERROR("d3d_create_bitmap_from_surface: Lock system texture failed.\n");
@@ -414,11 +417,11 @@ static ALLEGRO_BITMAP *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface
    }
 
    surface->UnlockRect();
-   d3d_bmp->system_texture->UnlockRect(0);
+   extra->system_texture->UnlockRect(0);
 
-   if (d3d_bmp->display->device->UpdateTexture(
-         (IDirect3DBaseTexture9 *)d3d_bmp->system_texture,
-         (IDirect3DBaseTexture9 *)d3d_bmp->video_texture) != D3D_OK) {
+   if (extra->display->device->UpdateTexture(
+         (IDirect3DBaseTexture9 *)extra->system_texture,
+         (IDirect3DBaseTexture9 *)extra->video_texture) != D3D_OK) {
       ALLEGRO_ERROR("d3d_create_bitmap_from_texture: Couldn't update texture.\n");
    }
 
@@ -428,7 +431,7 @@ static ALLEGRO_BITMAP *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface
 /* Copies video texture to system texture and bitmap->memory */
 static void _al_d3d_sync_bitmap(ALLEGRO_BITMAP *dest)
 {
-   ALLEGRO_BITMAP_D3D *d3d_dest;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_dest;
    LPDIRECT3DSURFACE9 system_texture_surface;
    LPDIRECT3DSURFACE9 video_texture_surface;
    UINT i;
@@ -440,7 +443,7 @@ static void _al_d3d_sync_bitmap(ALLEGRO_BITMAP *dest)
       return;
    }
 
-   d3d_dest = (ALLEGRO_BITMAP_D3D *)dest;
+   d3d_dest = get_extra(dest);
 
    if (d3d_dest->system_texture == NULL || d3d_dest->video_texture == NULL) {
       return;
@@ -499,17 +502,17 @@ void _al_d3d_prepare_bitmaps_for_reset(ALLEGRO_DISPLAY_D3D *disp)
    al_lock_mutex(_al_d3d_lost_device_mutex);
 
    for (i = 0; i < created_bitmaps._size; i++) {
-      ALLEGRO_BITMAP_D3D **bptr = (ALLEGRO_BITMAP_D3D **)_al_vector_ref(&created_bitmaps, i);
-      ALLEGRO_BITMAP_D3D *bmp = *bptr;
-      ALLEGRO_BITMAP *al_bmp = (ALLEGRO_BITMAP *)bmp;
-      if (bmp->display == disp) {
+      ALLEGRO_BITMAP **bptr = (ALLEGRO_BITMAP **)_al_vector_ref(&created_bitmaps, i);
+      ALLEGRO_BITMAP *bmp = *bptr;
+      ALLEGRO_BITMAP_EXTRA_D3D *extra = get_extra(bmp);
+      if ((void *)bmp->display == (void *)disp) {
          //d3d_sync_bitmap_memory(al_bmp);
-         if (!al_bmp->preserve_texture) {
-            bmp->modified = false;
+         if (!bmp->preserve_texture) {
+            extra->modified = false;
          }
-         else if (!bmp->is_backbuffer && bmp->modified && !(al_bmp->flags & ALLEGRO_MEMORY_BITMAP)) {
-            _al_d3d_sync_bitmap(al_bmp);
-            bmp->modified = false;
+         else if (!extra->is_backbuffer && extra->modified && !(bmp->flags & ALLEGRO_MEMORY_BITMAP)) {
+            _al_d3d_sync_bitmap(bmp);
+            extra->modified = false;
          }
       }
    }
@@ -525,19 +528,19 @@ bool _al_d3d_recreate_bitmap_textures(ALLEGRO_DISPLAY_D3D *disp)
    unsigned int i;
 
    for (i = 0; i < created_bitmaps._size; i++) {
-      ALLEGRO_BITMAP_D3D **bptr = (ALLEGRO_BITMAP_D3D **)_al_vector_ref(&created_bitmaps, i);
-      ALLEGRO_BITMAP_D3D *bmp = *bptr;
-      ALLEGRO_BITMAP *al_bmp = (ALLEGRO_BITMAP *)bmp;
-
-      if (bmp->display == disp) {
-	      if (!d3d_create_textures(disp, bmp->texture_w,
-		    bmp->texture_h,
-		    al_bmp->flags,
-		    &bmp->video_texture,
-		    &bmp->system_texture,
-		    al_bmp->format))
-		 return false;
-	      d3d_do_upload(bmp, 0, 0, al_bmp->w, al_bmp->h, true);
+      ALLEGRO_BITMAP **bptr = (ALLEGRO_BITMAP **)_al_vector_ref(&created_bitmaps, i);
+      ALLEGRO_BITMAP *bmp = *bptr;
+      ALLEGRO_BITMAP_EXTRA_D3D *extra = get_extra(bmp);
+
+      if ((void *)bmp->display == (void *)disp) {
+	      if (!d3d_create_textures(disp, extra->texture_w,
+            extra->texture_h,
+            bmp->flags,
+            &extra->video_texture,
+            &extra->system_texture,
+            bmp->format))
+            return false;
+	      d3d_do_upload(bmp, 0, 0, bmp->w, bmp->h, true);
       }
    }
 
@@ -553,27 +556,27 @@ void _al_d3d_refresh_texture_memory(void)
    unsigned int i;
 
    for (i = 0; i < created_bitmaps._size; i++) {
-      ALLEGRO_BITMAP_D3D **bptr = (ALLEGRO_BITMAP_D3D **)_al_vector_ref(&created_bitmaps, i);
-      ALLEGRO_BITMAP_D3D *bmp = *bptr;
-      ALLEGRO_BITMAP *al_bmp = (ALLEGRO_BITMAP *)bmp;
-      ALLEGRO_DISPLAY_D3D *bmps_display = (ALLEGRO_DISPLAY_D3D *)al_bmp->display;
-
-      d3d_create_textures(bmps_display, bmp->texture_w, bmp->texture_h,
-         al_bmp->flags,
-	 &bmp->video_texture, /*&bmp->system_texture*/0, al_bmp->format);
-      d3d_sync_bitmap_texture(al_bmp,
-	 0, 0, al_bmp->w, al_bmp->h);
+      ALLEGRO_BITMAP **bptr = (ALLEGRO_BITMAP **)_al_vector_ref(&created_bitmaps, i);
+      ALLEGRO_BITMAP *bmp = *bptr;
+      ALLEGRO_BITMAP_EXTRA_D3D *extra = get_extra(bmp);
+      ALLEGRO_DISPLAY_D3D *bmps_display = (ALLEGRO_DISPLAY_D3D *)bmp->display;
+
+      d3d_create_textures(bmps_display, extra->texture_w,
+         extra->texture_h, bmp->flags,
+	 &extra->video_texture, /*&bmp->system_texture*/0, bmp->format);
+      d3d_sync_bitmap_texture(bmp,
+	 0, 0, bmp->w, bmp->h);
       if (_al_d3d_render_to_texture_supported()) {
 	 bmps_display->device->UpdateTexture(
-	    (IDirect3DBaseTexture9 *)bmp->system_texture,
-	    (IDirect3DBaseTexture9 *)bmp->video_texture);
+	    (IDirect3DBaseTexture9 *)extra->system_texture,
+	    (IDirect3DBaseTexture9 *)extra->video_texture);
       }
    }
 }
 
 static bool d3d_upload_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
    int w = bitmap->w;
    int h = bitmap->h;
 
@@ -587,7 +590,7 @@ static bool d3d_upload_bitmap(ALLEGRO_BITMAP *bitmap)
       if (non_pow2 && non_square) {
          // Any shape and size
          d3d_bmp->texture_w = w;
-	 d3d_bmp->texture_h = h;
+         d3d_bmp->texture_h = h;
       }
       else if (non_pow2) {
          // Must be sqaure
@@ -608,7 +611,7 @@ static bool d3d_upload_bitmap(ALLEGRO_BITMAP *bitmap)
       if (d3d_bmp->video_texture == 0)
          if (!d3d_create_textures(d3d_bmp->display, d3d_bmp->texture_w,
                d3d_bmp->texture_h,
-               d3d_bmp->bitmap.flags,
+               bitmap->flags,
                &d3d_bmp->video_texture,
                &d3d_bmp->system_texture,
                bitmap->format)) {
@@ -619,12 +622,12 @@ static bool d3d_upload_bitmap(ALLEGRO_BITMAP *bitmap)
        * Keep track of created bitmaps, in case the display is lost
        * or resized.
        */
-      *(ALLEGRO_BITMAP_D3D **)_al_vector_alloc_back(&created_bitmaps) = d3d_bmp;
+      *(ALLEGRO_BITMAP **)_al_vector_alloc_back(&created_bitmaps) = bitmap;
 
       d3d_bmp->initialized = true;
    }
 
-   d3d_do_upload(d3d_bmp, 0, 0, w, h, false);
+   d3d_do_upload(bitmap, 0, 0, w, h, false);
 
    return true;
 }
@@ -635,8 +638,10 @@ static void d3d_draw_bitmap_region(
    float sx, float sy, float sw, float sh, int flags)
 {
    ALLEGRO_BITMAP *dest = al_get_target_bitmap();
-   ALLEGRO_BITMAP_D3D *d3d_dest = (ALLEGRO_BITMAP_D3D *)dest;
-   ALLEGRO_BITMAP_D3D *d3d_src = (ALLEGRO_BITMAP_D3D *)src;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_dest = get_extra(dest);
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_src = get_extra(src);
+   
+   ASSERT(src->parent == NULL);
 
    if (!_al_d3d_render_to_texture_supported() || !_al_d3d_supports_separate_alpha_blend(al_get_current_display())) {
       _al_draw_bitmap_region_memory(src, tint,
@@ -651,27 +656,19 @@ static void d3d_draw_bitmap_region(
    _al_d3d_set_bitmap_clip(dest);
 
    /* For sub-bitmaps */
-   if (src->parent) {
-      sx += src->xofs;
-      sy += src->yofs;
-      src = src->parent;
-      d3d_src = (ALLEGRO_BITMAP_D3D *)src;
-   }
    if (dest->parent) {
       dest = dest->parent;
-      d3d_dest = (ALLEGRO_BITMAP_D3D *)dest;
+      d3d_dest = get_extra(dest);
    }
 
    if (d3d_src->is_backbuffer) {
-      ALLEGRO_BITMAP_D3D *tmp_bmp = NULL;
-      tmp_bmp =
-         (ALLEGRO_BITMAP_D3D *)d3d_create_bitmap_from_surface(
-         ((ALLEGRO_BITMAP_D3D *)d3d_src)->display->render_target,
+      ALLEGRO_BITMAP *tmp_bmp = d3d_create_bitmap_from_surface(
+         d3d_src->display->render_target,
          src->flags);
       if (tmp_bmp) {
-         d3d_draw_bitmap_region((ALLEGRO_BITMAP *)tmp_bmp, tint,
+         d3d_draw_bitmap_region(tmp_bmp, tint,
             sx, sy, sw, sh, flags);
-         al_destroy_bitmap((ALLEGRO_BITMAP *)tmp_bmp);
+         al_destroy_bitmap(tmp_bmp);
       }
       return;
    }
@@ -679,7 +676,7 @@ static void d3d_draw_bitmap_region(
    _al_d3d_set_blender(d3d_dest->display);
 
    d3d_draw_textured_quad(
-      d3d_dest->display, d3d_src, tint,
+      d3d_dest->display, src, tint,
       sx, sy, sw, sh, flags);
 
    d3d_dest->modified = true;
@@ -687,7 +684,7 @@ static void d3d_draw_bitmap_region(
 
 static void d3d_destroy_bitmap(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
 
    if (!al_is_sub_bitmap(bitmap)) {
       if (d3d_bmp->video_texture) {
@@ -709,13 +706,15 @@ static void d3d_destroy_bitmap(ALLEGRO_BITMAP *bitmap)
    }
 
    _al_vector_find_and_delete(&created_bitmaps, &d3d_bmp);
+   
+   al_free(bitmap->extra);
 }
 
 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;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
 
    if (d3d_bmp->display->device_lost)
       return NULL;
@@ -783,7 +782,7 @@ static ALLEGRO_LOCKED_REGION *d3d_lock_region(ALLEGRO_BITMAP *bitmap,
 
 static void d3d_unlock_region(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
 
    d3d_bmp->modified = true;
 
@@ -810,7 +809,7 @@ static void d3d_unlock_region(ALLEGRO_BITMAP *bitmap)
       texture->UnlockRect(0);
       if (bitmap->lock_flags & ALLEGRO_LOCK_READONLY)
          return;
-      d3d_do_upload(d3d_bmp, bitmap->lock_x, bitmap->lock_y,
+      d3d_do_upload(bitmap, bitmap->lock_x, bitmap->lock_y,
          bitmap->lock_w, bitmap->lock_h, false);
    }
 }
diff --git a/src/win/d3d_disp.cpp b/src/win/d3d_disp.cpp
index 4fbcd7e..a227031 100644
--- a/src/win/d3d_disp.cpp
+++ b/src/win/d3d_disp.cpp
@@ -35,6 +35,9 @@
 
 #include "d3d.h"
 
+// C++ needs to cast void pointers
+#define get_extra(b) ((ALLEGRO_BITMAP_EXTRA_D3D *)b->extra)
+
 static const char* _al_d3d_module_name = "d3d9.dll";
 
 ALLEGRO_DEBUG_CHANNEL("d3d")
@@ -1927,18 +1930,19 @@ static bool d3d_create_display_internals(ALLEGRO_DISPLAY_D3D *d3d_display)
    d3d_reset_state(d3d_display);
 
    //d3d_display->backbuffer_bmp.render_target = d3d_display->render_target;
-   d3d_display->backbuffer_bmp.is_backbuffer = true;
-   d3d_display->backbuffer_bmp.bitmap.display = al_display;
-   d3d_display->backbuffer_bmp.bitmap.format = _al_deduce_color_format(&al_display->extra_settings);
-   d3d_display->backbuffer_bmp.bitmap.flags = 0;
-   d3d_display->backbuffer_bmp.bitmap.w = al_display->w;
-   d3d_display->backbuffer_bmp.bitmap.h = al_display->h;
-   d3d_display->backbuffer_bmp.bitmap.cl = 0;
-   d3d_display->backbuffer_bmp.bitmap.ct = 0;
-   d3d_display->backbuffer_bmp.bitmap.cr_excl = al_display->w;
-   d3d_display->backbuffer_bmp.bitmap.cb_excl = al_display->h;
-   d3d_display->backbuffer_bmp.bitmap.vt = (ALLEGRO_BITMAP_INTERFACE *)_al_bitmap_d3d_driver();
-   d3d_display->backbuffer_bmp.display = d3d_display;
+   d3d_display->backbuffer_bmp.extra = &d3d_display->backbuffer_bmp_extra;
+   d3d_display->backbuffer_bmp_extra.is_backbuffer = true;
+   d3d_display->backbuffer_bmp.display = al_display;
+   d3d_display->backbuffer_bmp.format = _al_deduce_color_format(&al_display->extra_settings);
+   d3d_display->backbuffer_bmp.flags = 0;
+   d3d_display->backbuffer_bmp.w = al_display->w;
+   d3d_display->backbuffer_bmp.h = al_display->h;
+   d3d_display->backbuffer_bmp.cl = 0;
+   d3d_display->backbuffer_bmp.ct = 0;
+   d3d_display->backbuffer_bmp.cr_excl = al_display->w;
+   d3d_display->backbuffer_bmp.cb_excl = al_display->h;
+   d3d_display->backbuffer_bmp.vt = (ALLEGRO_BITMAP_INTERFACE *)_al_bitmap_d3d_driver();
+   d3d_display->backbuffer_bmp_extra.display = d3d_display;
 
    /* Alpha blending is the default */
    d3d_display->device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
@@ -2289,7 +2293,8 @@ static void d3d_update_display_region(ALLEGRO_DISPLAY *al_display,
  */
 void _al_d3d_set_bitmap_clip(ALLEGRO_BITMAP *bitmap)
 {
-   ALLEGRO_DISPLAY_D3D *disp = ((ALLEGRO_BITMAP_D3D *)bitmap)->display;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(bitmap);
+   ALLEGRO_DISPLAY_D3D *disp = d3d_bmp->display;
    RECT rect;
 
    if (!disp)
@@ -2340,12 +2345,12 @@ static bool d3d_acknowledge_resize(ALLEGRO_DISPLAY *d)
       d->h = h;
    }
 
-   disp->backbuffer_bmp.bitmap.w = d->w;
-   disp->backbuffer_bmp.bitmap.h = d->h;
-   disp->backbuffer_bmp.bitmap.cl = 0;
-   disp->backbuffer_bmp.bitmap.ct = 0;
-   disp->backbuffer_bmp.bitmap.cr_excl = w;
-   disp->backbuffer_bmp.bitmap.cb_excl = h;
+   disp->backbuffer_bmp.w = d->w;
+   disp->backbuffer_bmp.h = d->h;
+   disp->backbuffer_bmp.cl = 0;
+   disp->backbuffer_bmp.ct = 0;
+   disp->backbuffer_bmp.cr_excl = w;
+   disp->backbuffer_bmp.cb_excl = h;
 
    disp->do_reset = true;
    while (!disp->reset_done) {
@@ -2439,18 +2444,18 @@ static bool d3d_resize_helper(ALLEGRO_DISPLAY *d, int width, int height)
        * changed to match the new size.
        */
       al_store_state(&backup, ALLEGRO_STATE_TARGET_BITMAP);
-      al_set_target_bitmap(&disp->backbuffer_bmp.bitmap);
-      disp->backbuffer_bmp.bitmap.w = width;
-      disp->backbuffer_bmp.bitmap.h = height;
+      al_set_target_bitmap(&disp->backbuffer_bmp);
+      disp->backbuffer_bmp.w = width;
+      disp->backbuffer_bmp.h = height;
       al_set_clipping_rectangle(0, 0, width, height);
-      _al_d3d_set_bitmap_clip(&disp->backbuffer_bmp.bitmap);
+      _al_d3d_set_bitmap_clip(&disp->backbuffer_bmp);
       al_restore_state(&backup);
 
       ret = true;
    }
 
-   disp->backbuffer_bmp.bitmap.w = width;
-   disp->backbuffer_bmp.bitmap.h = height;
+   disp->backbuffer_bmp.w = width;
+   disp->backbuffer_bmp.h = height;
 
    return ret;
 }
@@ -2480,15 +2485,14 @@ static bool d3d_resize_display(ALLEGRO_DISPLAY *d, int width, int height)
 ALLEGRO_BITMAP *_al_d3d_create_bitmap(ALLEGRO_DISPLAY *d,
    int w, int h)
 {
-   ALLEGRO_BITMAP_D3D *bitmap = (ALLEGRO_BITMAP_D3D*)al_malloc(sizeof *bitmap);
+   ALLEGRO_BITMAP *bitmap = (ALLEGRO_BITMAP *)al_malloc(sizeof *bitmap);
+   ALLEGRO_BITMAP_EXTRA_D3D *extra;
    int format;
    int flags;
 
    ASSERT(bitmap);
    (void)h;
 
-   bitmap->bitmap.size = sizeof *bitmap;
-
    format = al_get_new_bitmap_format();
    flags = al_get_new_bitmap_flags();
 
@@ -2506,56 +2510,61 @@ ALLEGRO_BITMAP *_al_d3d_create_bitmap(ALLEGRO_DISPLAY *d,
 
    ALLEGRO_INFO("Chose bitmap format %d\n", format);
 
-   bitmap->bitmap.vt = _al_bitmap_d3d_driver();
-   bitmap->bitmap.memory = NULL;
-   bitmap->bitmap.format = format;
-   bitmap->bitmap.flags = flags;
-   bitmap->bitmap.pitch = w * al_get_pixel_size(format);
-   al_identity_transform(&bitmap->bitmap.transform);
+   bitmap->vt = _al_bitmap_d3d_driver();
+   bitmap->memory = NULL;
+   bitmap->format = format;
+   bitmap->flags = flags;
+   bitmap->pitch = w * al_get_pixel_size(format);
+   al_identity_transform(&bitmap->transform);
 
-   bitmap->bitmap.memory = (unsigned char *)al_malloc(bitmap->bitmap.pitch * h);
+   bitmap->memory = (unsigned char *)al_malloc(bitmap->pitch * h);
 
-   bitmap->video_texture = 0;
-   bitmap->system_texture = 0;
-   bitmap->initialized = false;
-   bitmap->is_backbuffer = false;
-   bitmap->render_target = NULL;
-   bitmap->modified = true;
+   extra = (ALLEGRO_BITMAP_EXTRA_D3D *)al_calloc(1, sizeof *extra);
+   bitmap->extra = extra;
+   extra->video_texture = 0;
+   extra->system_texture = 0;
+   extra->initialized = false;
+   extra->is_backbuffer = false;
+   extra->render_target = NULL;
+   extra->modified = true;
 
-   bitmap->display = (ALLEGRO_DISPLAY_D3D *)d;
+   extra->display = (ALLEGRO_DISPLAY_D3D *)d;
 
-   return &bitmap->bitmap;
+   return bitmap;
 }
 
 static ALLEGRO_BITMAP *d3d_create_sub_bitmap(ALLEGRO_DISPLAY *display,
    ALLEGRO_BITMAP *parent, int x, int y, int width, int height)
 {
-   ALLEGRO_BITMAP_D3D *bitmap = (ALLEGRO_BITMAP_D3D*)al_malloc(sizeof *bitmap);
+   ALLEGRO_BITMAP *bitmap = (ALLEGRO_BITMAP *)al_malloc(sizeof *bitmap);
+   ALLEGRO_BITMAP_EXTRA_D3D *extra;
+   ALLEGRO_BITMAP_EXTRA_D3D *pextra = get_extra(parent);
+   extra = (ALLEGRO_BITMAP_EXTRA_D3D *)al_calloc(1, sizeof *extra);
+   bitmap->extra = extra;
 
    (void)x;
    (void)y;
    (void)width;
    (void)height;
 
-   bitmap->texture_w = 0;
-   bitmap->texture_h = 0;
-   bitmap->video_texture = ((ALLEGRO_BITMAP_D3D *)parent)->video_texture;
-   bitmap->system_texture = ((ALLEGRO_BITMAP_D3D *)parent)->system_texture;
-   bitmap->initialized = false;
-   bitmap->is_backbuffer = ((ALLEGRO_BITMAP_D3D *)parent)->is_backbuffer;
-   bitmap->display = (ALLEGRO_DISPLAY_D3D *)display;
-   bitmap->render_target = ((ALLEGRO_BITMAP_D3D *)parent)->render_target;
-   bitmap->modified = true;
-   al_identity_transform(&bitmap->bitmap.transform);
+   extra->texture_w = 0;
+   extra->texture_h = 0;
+   extra->video_texture = pextra->video_texture;
+   extra->system_texture = pextra->system_texture;
+   extra->initialized = false;
+   extra->is_backbuffer = pextra->is_backbuffer;
+   extra->display = (ALLEGRO_DISPLAY_D3D *)display;
+   extra->render_target = pextra->render_target;
+   extra->modified = true;
 
-   bitmap->bitmap.vt = parent->vt;
-   return (ALLEGRO_BITMAP *)bitmap;
+   bitmap->vt = parent->vt;
+   return bitmap;
 }
 
 static void d3d_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
 {
    ALLEGRO_BITMAP *target;
-   ALLEGRO_BITMAP_D3D *d3d_target;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_target;
    ALLEGRO_DISPLAY_D3D *d3d_display = (ALLEGRO_DISPLAY_D3D *)display;
    D3DVIEWPORT9 viewport;
    viewport.X = 0;
@@ -2572,14 +2581,17 @@ static void d3d_set_target_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitm
    else {
       target = bitmap;
    }
-   d3d_target = (ALLEGRO_BITMAP_D3D *)target;
+   d3d_target = get_extra(target);
 
    /* Release the previous target bitmap if it was not the backbuffer */
 
-   ALLEGRO_BITMAP_D3D *currtarget = (ALLEGRO_BITMAP_D3D *)al_get_target_bitmap();
-   if (currtarget && !currtarget->is_backbuffer && currtarget->render_target) {
-      currtarget->render_target->Release();
-      currtarget->render_target = NULL;
+   ALLEGRO_BITMAP *currtarget = al_get_target_bitmap();
+   if (currtarget) {
+      ALLEGRO_BITMAP_EXTRA_D3D *cextra = get_extra(currtarget);
+      if (!cextra->is_backbuffer && cextra->render_target) {
+         cextra->render_target->Release();
+         cextra->render_target = NULL;
+      }
    }
 
    /* Set the render target */
@@ -2679,14 +2691,16 @@ LPDIRECT3DDEVICE9 al_get_d3d_device(ALLEGRO_DISPLAY *display)
  */
 LPDIRECT3DTEXTURE9 al_get_d3d_system_texture(ALLEGRO_BITMAP *bitmap)
 {
-   return ((ALLEGRO_BITMAP_D3D *)bitmap)->system_texture;
+   ALLEGRO_BITMAP_EXTRA_D3D *e = get_extra(bitmap);
+   return e->system_texture;
 }
 
 /* Function: al_get_d3d_video_texture
  */
 LPDIRECT3DTEXTURE9 al_get_d3d_video_texture(ALLEGRO_BITMAP *bitmap)
 {
-   return ((ALLEGRO_BITMAP_D3D *)bitmap)->video_texture;
+   ALLEGRO_BITMAP_EXTRA_D3D *e = get_extra(bitmap);
+   return e->video_texture;
 }
 
 /* Function: al_get_d3d_texture_position
@@ -2779,7 +2793,7 @@ static void d3d_flush_vertex_cache(ALLEGRO_DISPLAY* disp)
 
    ALLEGRO_DISPLAY_D3D* d3d_disp = (ALLEGRO_DISPLAY_D3D*)disp;
    ALLEGRO_BITMAP* cache_bmp = (ALLEGRO_BITMAP*)disp->cache_texture;
-   ALLEGRO_BITMAP_D3D* d3d_bmp = (ALLEGRO_BITMAP_D3D*)cache_bmp;
+   ALLEGRO_BITMAP_EXTRA_D3D *d3d_bmp = get_extra(cache_bmp);
 
    if (cache_bmp->flags & ALLEGRO_MIN_LINEAR) {
       d3d_disp->device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
diff --git a/src/win/wgl_disp.c b/src/win/wgl_disp.c
index b559bd2..82af2d3 100644
--- a/src/win/wgl_disp.c
+++ b/src/win/wgl_disp.c
@@ -1372,8 +1372,10 @@ static bool wgl_resize_helper(ALLEGRO_DISPLAY *d, int width, int height)
       size_t i;
 
       target_bmp = al_get_target_bitmap();
-      if (target_bmp->vt)
-         was_backbuffer = ((ALLEGRO_BITMAP_OGL*)target_bmp)->is_backbuffer;
+      if (target_bmp->vt) {
+         ALLEGRO_BITMAP_EXTRA_OPENGL *extra = target_bmp->extra;
+         was_backbuffer = extra->is_backbuffer;
+      }
 
       /* Remeber display bitmaps. */
       _al_vector_init(&disp_bmps, sizeof(ALLEGRO_BITMAP*));


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/