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); } } _______________________________________________ Allegro-developers mailing list Allegro-developers@gna.org https://mail.gna.org/listinfo/allegro-developers