Re: [AD] [ alleg-Bugs-3152695 ] text rending is broken with OpenGL

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


On Thu, 2011-01-06 at 23:47 +0000, SourceForge.net wrote:
> Bugs item #3152695, was opened at 2011-01-06 23:47
> Summary: text rending is broken with OpenGL
> 
> Initial Comment:
> Under Windows, when forced texture compression is enabled (many
> low-end devices like my EEE PC have it on by default to save memory),
> font rendering doesn't work. Haven't investigate a lot yet, but likely
> glTexSubImage2D fails due to changed alignment requirements.
> 

Attached is a patch which fixes this. The problem is present on at least
two test PCs (one with an ATI card, one with an Intel card) so might be
wide-spread. The patch simply (unconditionally) makes glyphs in a font
sheet aligned to 4 pixel boundaries and also gives them a size which is
a multiple of 4 pixels.

With D3D and proper OpenGL drivers there is no problem. It also might be
Windows only. So could add a check to only do this when compiling for
Windows (although it would be nice to confirm it's Windows only first)
and add a runtime check to only do it when the bitmap is an OpenGL
bitmap. But aligning to 4-pixels seemed harmless enough to me to leave
that out for now.

-- 
Elias Pschernig <elias.pschernig@xxxxxxxxxx>
diff --git a/addons/ttf/ttf.c b/addons/ttf/ttf.c
index 6218d84..4b635a2 100644
--- a/addons/ttf/ttf.c
+++ b/addons/ttf/ttf.c
@@ -9,6 +9,18 @@
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
+/* Some low-end drivers enable automatic S3TC compression, which
+ * requires glTexSubImage2D to only work on multiples of aligned
+ * 4x4 pixel blocks with some buggy OpenGL drivers.
+ * There's not much we can do about that in general - if the user
+ * locks a portion of a bitmap not conformin to this it will fail
+ * with such a driver.
+ * 
+ * However in many programs this is no problem at all safe for rendering
+ * glyphs and simply aligning to 4 pixels here fixes it.
+ */
+#define ALIGN_TO_4_PIXEL
+
 ALLEGRO_DEBUG_CHANNEL("font")
 
 typedef struct ALLEGRO_TTF_GLYPH_DATA
@@ -114,9 +126,17 @@ static ALLEGRO_BITMAP* create_glyph_cache(ALLEGRO_FONT const *f, int w,
 
     p_cache = _al_vector_ref_back(&data->cache_bitmaps);
     cache = *p_cache;
+    
+    #ifdef ALIGN_TO_4_PIXEL
+    w = (w + 3) & ~3;
+    h = (h + 3) & ~3;
+    #endif
 
     if (data->cache_pos_x + w > al_get_bitmap_width(cache)) {
         data->cache_pos_y += data->cache_line_height + 2;
+        #ifdef ALIGN_TO_4_PIXEL
+        data->cache_pos_y = (data->cache_pos_y + 3) & ~3;
+        #endif
         data->cache_pos_x = 0;
         data->cache_line_height = 0;
     }
@@ -128,6 +148,9 @@ static ALLEGRO_BITMAP* create_glyph_cache(ALLEGRO_FONT const *f, int w,
     ret = al_create_sub_bitmap(cache, data->cache_pos_x,
         data->cache_pos_y, w, h);
     data->cache_pos_x += w + 2;
+    #ifdef ALIGN_TO_4_PIXEL
+      data->cache_pos_x = (data->cache_pos_x + 3) & ~3;
+      #endif
     if (h > data->cache_line_height)
         data->cache_line_height = h;
     return ret;
@@ -181,6 +204,22 @@ static int render_glyph(ALLEGRO_FONT const *f,
          * If it does, we can simplify this.
          */
         al_put_pixel(0, 0, al_map_rgba(0, 0, 0, 0));
+        #ifdef ALIGN_TO_4_PIXEL
+        {
+           /* clear the extra borders we added */
+           int i;
+           int bw = al_get_bitmap_width(glyph->bitmap);
+           int bh = al_get_bitmap_height(glyph->bitmap);
+           for (i = 0; i < (bh - h); i++) {
+              memset((unsigned char *)lr->data +
+                 (bh - 1 - i) * lr->pitch, 0, 4 * bw);
+           }
+           for (i = 0; i < bh; i++) {
+              memset((unsigned char *)lr->data +
+                 i * lr->pitch + 4 * w, 0, 4 * (bw - w));
+           }
+        }
+        #endif
         row = face->glyph->bitmap.buffer;
 
         if (glyph->monochrome) {
diff --git a/src/opengl/ogl_bitmap.c b/src/opengl/ogl_bitmap.c
index 4f6e31d..94bbfcb 100644
--- a/src/opengl/ogl_bitmap.c
+++ b/src/opengl/ogl_bitmap.c
@@ -949,8 +949,15 @@ static void ogl_unlock_region(ALLEGRO_BITMAP *bitmap)
             ogl_bitmap->lock_buffer);
          e = glGetError();
          if (e) {
+            GLint tex_internalformat;
             ALLEGRO_ERROR("glTexSubImage2D for format %s failed (%s).\n",
                _al_format_name(lock_format), error_string(e));
+            glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
+               GL_TEXTURE_INTERNAL_FORMAT, &tex_internalformat);
+
+            ALLEGRO_DEBUG("x/y/w/h: %d/%d/%d/%d, internal format: %d\n",
+               bitmap->lock_x, gl_y, bitmap->lock_w, bitmap->lock_h,
+               tex_internalformat);
          }
       }
    }


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