[AD] Potential Optimization

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


Currently when held bitmap drawing is on Allegro sets the display
transformation to identity then transforms bitmaps manually. This in
itself isn't the problem but with the patch attached the display
keeps the transform and Allegro only does a local transform on bitmaps.
This allow primitives including al_draw_prim to function normally with
held drawing on -- you can mix primitives and bitmaps
without changing the transform. This allows a more natural flow where each
widget/game element can draw itself, mixing text, graphics and primitives
while keeping everything cached as much as possible.

Basically what I've done is write a very simple set of functions to
replace al_draw_*_bitmap. It just caches vertices and uses al_draw_prim.
This avoids a lot of overhead that al_draw_*_bitmap has in
doing transformations (look in src/bitmap_draw.c to see only some of the
transforms that happen for each bitmap.) On top of that it allows me to
cache fonts efficiently -- instead of just having each
string drawn with held drawing, I now al_hold_bitmap_drawing(true) at the
start of each frame and at the end I al_hold_bitmap_drawing(false).
Anywhere I use shaders, transforms, or blending I can
toggle the held drawing state. What this means most of the time is I only
do a single drawing call for all the text on screen.

I'm working on a Raspberry Pi port which is the slowest device I own.
Before this change I was getting 20 FPS in my menu and after I have 50, so
it's a significant change. There are maybe 25-30 strings
on that screen, all short, so changing the bound texture just that many
times has a huge impact. Along with the new bitmap drawing using
al_draw_prim the game runs at or close to 60 FPS most of the time
(perhaps more because vsync is on), while before it maxed out at 30.

I haven't checked the tests yet but I should do that. Here's the patch.


diff --git a/src/bitmap_draw.c b/src/bitmap_draw.c
index cd01dfd..7cf74db 100644
--- a/src/bitmap_draw.c
+++ b/src/bitmap_draw.c
@@ -23,6 +23,7 @@

 static ALLEGRO_COLOR solid_white = {1, 1, 1, 1};

+static ALLEGRO_BITMAP *cache_bitmap;

 static void _bitmap_drawer(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR tint,
    float sx, float sy, float sw, float sh, int flags)
@@ -65,6 +66,7 @@ static void
_draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap,
    float sx, float sy, float sw, float sh, float dx, float dy,
    int flags)
 {
+   ALLEGRO_DISPLAY *disp = _al_get_bitmap_display(bitmap);
    ALLEGRO_TRANSFORM backup;
    ALLEGRO_TRANSFORM t;
    ALLEGRO_BITMAP *parent = bitmap;
@@ -72,6 +74,14 @@ static void
_draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap,
    float const orig_sh = sh;
    ASSERT(bitmap);

+   ALLEGRO_BITMAP *real = bitmap;
+   while (al_is_sub_bitmap(real))
+      real = al_get_parent_bitmap(real);
+   if (disp && real != cache_bitmap && disp->cache_enabled) {
+      disp->vt->flush_vertex_cache(disp);
+      cache_bitmap = real;
+   }
+
    al_copy_transform(&backup, al_get_current_transform());
    al_identity_transform(&t);

@@ -112,11 +122,13 @@ static void
_draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap,
    al_scale_transform(&t, xscale, yscale);
    al_rotate_transform(&t, angle);
    al_translate_transform(&t, dx, dy);
-   al_compose_transform(&t, &backup);

    al_use_transform(&t);
    _bitmap_drawer(parent, tint, sx, sy, sw, sh, flags);
    al_use_transform(&backup);
+
+   if (disp && !disp->cache_enabled)
+      disp->vt->flush_vertex_cache(disp);
 }


diff --git a/src/display.c b/src/display.c
index 4d16a73..fa6e6d4 100644
--- a/src/display.c
+++ b/src/display.c
@@ -499,31 +499,10 @@ void al_hold_bitmap_drawing(bool hold)
    ALLEGRO_DISPLAY *current_display = al_get_current_display();

    if (current_display) {
-      if (hold && !current_display->cache_enabled) {
-         /*
-          * Set the hardware transformation to identity, but keep the bitmap
-          * transform the same as it was. Relies on the fact that when
bitmap
-          * holding is turned on, al_use_transform does not update the
hardware
-          * transformation.
-          */
-         ALLEGRO_TRANSFORM old, ident;
-         al_copy_transform(&old, al_get_current_transform());
-         al_identity_transform(&ident);
-
-         al_use_transform(&ident);
-         current_display->cache_enabled = hold;
-         al_use_transform(&old);
-      }
-      else {
-         current_display->cache_enabled = hold;
-      }
+      current_display->cache_enabled = hold;

       if (!hold) {
          current_display->vt->flush_vertex_cache(current_display);
-         /*
-          * Reset the hardware transform to match the stored transform.
-          */
-         al_use_transform(al_get_current_transform());
       }
    }
 }
diff --git a/src/opengl/ogl_bitmap.c b/src/opengl/ogl_bitmap.c
index 2b65738..e2e9290 100644
--- a/src/opengl/ogl_bitmap.c
+++ b/src/opengl/ogl_bitmap.c
@@ -208,12 +208,9 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap = bitmap->extra;
    ALLEGRO_OGL_BITMAP_VERTEX *verts;
    ALLEGRO_DISPLAY *disp = al_get_current_display();
-
+
    (void)flags;

-   if (disp->num_cache_vertices != 0 && ogl_bitmap->texture !=
disp->cache_texture) {
-      disp->vt->flush_vertex_cache(disp);
-   }
    disp->cache_texture = ogl_bitmap->texture;

    verts = disp->vt->prepare_vertex_cache(disp, 6);
@@ -241,7 +238,7 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    verts[0].g = tint.g;
    verts[0].b = tint.b;
    verts[0].a = tint.a;
-
+
    verts[1].x = 0;
    verts[1].y = 0;
    verts[1].tx = tex_l;
@@ -250,7 +247,7 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    verts[1].g = tint.g;
    verts[1].b = tint.b;
    verts[1].a = tint.a;
-
+
    verts[2].x = dw;
    verts[2].y = dh;
    verts[2].tx = tex_r;
@@ -259,7 +256,7 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    verts[2].g = tint.g;
    verts[2].b = tint.b;
    verts[2].a = tint.a;
-
+
    verts[4].x = dw;
    verts[4].y = 0;
    verts[4].tx = tex_r;
@@ -268,7 +265,7 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    verts[4].g = tint.g;
    verts[4].b = tint.b;
    verts[4].a = tint.a;
-
+
    if (disp->cache_enabled) {
       /* If drawing is batched, we apply transformations manually. */
       transform_vertex(&verts[0].x, &verts[0].y);
@@ -278,9 +275,6 @@ static void draw_quad(ALLEGRO_BITMAP *bitmap,
    }
    verts[3] = verts[1];
    verts[5] = verts[2];
-
-   if (!disp->cache_enabled)
-      disp->vt->flush_vertex_cache(disp);
 }
 #undef SWAP

diff --git a/src/opengl/ogl_draw.c b/src/opengl/ogl_draw.c
index a752680..d17de5d 100644
--- a/src/opengl/ogl_draw.c
+++ b/src/opengl/ogl_draw.c
@@ -357,7 +357,7 @@ static void ogl_flush_vertex_cache(ALLEGRO_DISPLAY *disp)
    GLuint current_texture;
    ALLEGRO_OGL_EXTRAS *o = disp->ogl_extras;
    (void)o; /* not used in all ports */
-
+
    if (!disp->vertex_cache)
       return;
    if (disp->num_cache_vertices == 0)
diff --git a/src/transformations.c b/src/transformations.c
index b0e9e29..cd9d306 100644
--- a/src/transformations.c
+++ b/src/transformations.c
@@ -57,15 +57,9 @@ void al_use_transform(const ALLEGRO_TRANSFORM *trans)
       target->inverse_transform_dirty = true;
    }

-   /*
-    * When the drawing is held, we apply the transformations in software,
-    * so the hardware transformation has to be kept at identity.
-    */
-   if (!al_is_bitmap_drawing_held()) {
-      display = _al_get_bitmap_display(target);
-      if (display) {
-         display->vt->update_transformation(display, target);
-      }
+   display = _al_get_bitmap_display(target);
+   if (display) {
+      display->vt->update_transformation(display, target);
    }
 }








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