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);
}
}
}