Doing away with the 32 bit per pixel memory buffer. Now passing the returned

pango memory buffer directly to OpenGL.  This simplifies the code.  Performance
did not seem to be better, but it certainly looks faster in theory.


git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@336 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
rambetter 2010-11-16 07:07:28 +00:00
parent c1dbb77342
commit 1c8129e946

View file

@ -208,7 +208,7 @@ gboolean WINAPI gtk_glwidget_make_current (GtkWidget *widget)
} }
// Think about rewriting this font stuff to use OpenGL display lists and bit maps. // Think about rewriting this font stuff to use OpenGL display lists and glBitmap().
// Bit maps together with display lists may offer a performance increase, but // Bit maps together with display lists may offer a performance increase, but
// they would not allow antialiased fonts. // they would not allow antialiased fonts.
static const char font_string[] = "Monospace"; static const char font_string[] = "Monospace";
@ -309,24 +309,21 @@ void gtk_glwidget_destroy_font()
// Google for "glDrawPixels clipping". // Google for "glDrawPixels clipping".
void gtk_glwidget_print_string(const char *s) void gtk_glwidget_print_string(const char *s)
{ {
// Much of this code is copied from the font-pangoft2.c example that comes with GtkGLExt. // The idea for this code initially came from the font-pangoft2.c example that comes with GtkGLExt.
PangoLayout *layout; PangoLayout *layout;
PangoRectangle ink_rect;
PangoRectangle log_rect; PangoRectangle log_rect;
FT_Bitmap bitmap; FT_Bitmap bitmap;
GLvoid *pixels; unsigned char *begin_bitmap_buffer;
guint32 *p;
GLfloat color[4]; GLfloat color[4];
guint32 rgb;
GLfloat alpha;
guint8 *row, *row_end;
int i;
GLint previous_unpack_alignment; GLint previous_unpack_alignment;
GLboolean previous_blend_enabled; GLboolean previous_blend_enabled;
GLint previous_blend_src; GLint previous_blend_func_src;
GLint previous_blend_dst; GLint previous_blend_func_dst;
GLfloat previous_red_bias;
GLfloat previous_green_bias;
GLfloat previous_blue_bias;
GLfloat previous_alpha_scale;
if (!_debug_font_created) { if (!_debug_font_created) {
Error("Programming error: gtk_glwidget_print_string() called but font does not exist; " Error("Programming error: gtk_glwidget_print_string() called but font does not exist; "
@ -336,90 +333,52 @@ void gtk_glwidget_print_string(const char *s)
layout = pango_layout_new(ft2_context); layout = pango_layout_new(ft2_context);
pango_layout_set_width(layout, -1); // -1 no wrapping. All text on one line. pango_layout_set_width(layout, -1); // -1 no wrapping. All text on one line.
pango_layout_set_text(layout, s, -1); // -1 null-terminated string. pango_layout_set_text(layout, s, -1); // -1 null-terminated string.
pango_layout_get_extents(layout, &ink_rect, &log_rect); pango_layout_get_extents(layout, NULL, &log_rect);
if (log_rect.width > 0 && log_rect.height > 0) { if (log_rect.width > 0 && log_rect.height > 0) {
bitmap.rows = font_ascent + font_descent; bitmap.rows = font_ascent + font_descent;
bitmap.width = PANGO_PIXELS_CEIL(log_rect.width); bitmap.width = PANGO_PIXELS_CEIL(log_rect.width);
bitmap.pitch = bitmap.width; bitmap.pitch = -bitmap.width; // Rendering it "upside down" for OpenGL.
bitmap.buffer = g_malloc(bitmap.rows * bitmap.width); begin_bitmap_buffer = (unsigned char *) g_malloc(bitmap.rows * bitmap.width);
memset(begin_bitmap_buffer, 0, bitmap.rows * bitmap.width);
bitmap.buffer = begin_bitmap_buffer + (bitmap.rows - 1) * bitmap.width; // See pitch above.
bitmap.num_grays = 0xff; bitmap.num_grays = 0xff;
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
memset(bitmap.buffer, 0, bitmap.rows * bitmap.width);
pango_ft2_render_layout_subpixel(&bitmap, layout, -log_rect.x, pango_ft2_render_layout_subpixel(&bitmap, layout, -log_rect.x,
y_offset_bitmap_render_pango_units); y_offset_bitmap_render_pango_units);
pixels = g_malloc(bitmap.rows * bitmap.width * 4);
p = (guint32 *) pixels;
qglGetFloatv(GL_CURRENT_COLOR, color); qglGetFloatv(GL_CURRENT_COLOR, color);
#if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN
rgb =
(((guint32) (color[0] * 255.0)) << 0) |
(((guint32) (color[1] * 255.0)) << 8) |
(((guint32) (color[2] * 255.0)) << 16);
#else
rgb =
(((guint32) (color[0] * 255.0)) << 24) |
(((guint32) (color[1] * 255.0)) << 16) |
(((guint32) (color[2] * 255.0)) << 8);
#endif
alpha = color[3];
row = bitmap.buffer + bitmap.rows * bitmap.width; // Past the end.
row_end = bitmap.buffer; // Beginning.
if (alpha == 1.0) {
do {
row -= bitmap.width;
for (i = 0; i < bitmap.width; i++) {
#if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN
*p++ = rgb | (((guint32) row[i]) << 24);
#else
*p++ = rgb | ((guint32) row[i]);
#endif
}
} while (row != row_end);
}
else { // Translucent. Much less efficient, so try to avoid.
do {
row -= bitmap.width;
for (i = 0; i < bitmap.width; i++) {
#if !defined(GL_VERSION_1_2) && G_BYTE_ORDER == G_LITTLE_ENDIAN
*p++ = rgb | (((guint32) (alpha * row[i])) << 24);
#else
*p++ = rgb | ((guint32) (alpha * row[i]));
#endif
}
} while (row != row_end);
}
// Save state. I didn't see any OpenGL push/pop operations for these. // Save state. I didn't see any OpenGL push/pop operations for these.
// Question: Is saving/restoring this state necessary? // Question: Is saving/restoring this state necessary? Being safe.
qglGetIntegerv(GL_UNPACK_ALIGNMENT, &previous_unpack_alignment); qglGetIntegerv(GL_UNPACK_ALIGNMENT, &previous_unpack_alignment);
previous_blend_enabled = qglIsEnabled(GL_BLEND); previous_blend_enabled = qglIsEnabled(GL_BLEND);
qglGetIntegerv(GL_BLEND_SRC, &previous_blend_src); qglGetIntegerv(GL_BLEND_SRC, &previous_blend_func_src);
qglGetIntegerv(GL_BLEND_DST, &previous_blend_dst); qglGetIntegerv(GL_BLEND_DST, &previous_blend_func_dst);
qglGetFloatv(GL_RED_BIAS, &previous_red_bias);
qglGetFloatv(GL_GREEN_BIAS, &previous_green_bias);
qglGetFloatv(GL_BLUE_BIAS, &previous_blue_bias);
qglGetFloatv(GL_ALPHA_SCALE, &previous_alpha_scale);
qglPixelStorei(GL_UNPACK_ALIGNMENT, 4); qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
qglEnable(GL_BLEND); qglEnable(GL_BLEND);
qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qglPixelTransferf(GL_RED_BIAS, color[0]);
qglPixelTransferf(GL_GREEN_BIAS, color[1]);
qglPixelTransferf(GL_BLUE_BIAS, color[2]);
qglPixelTransferf(GL_ALPHA_SCALE, color[3]);
#if !defined(GL_VERSION_1_2)
qglDrawPixels(bitmap.width, bitmap.rows, qglDrawPixels(bitmap.width, bitmap.rows,
GL_RGBA, GL_UNSIGNED_BYTE, pixels); GL_ALPHA, GL_UNSIGNED_BYTE, begin_bitmap_buffer);
#else g_free(begin_bitmap_buffer);
qglDrawPixels(bitmap.width, bitmap.rows,
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pixels);
#endif
// Restore state in reverse order of how we set it. // Restore state in reverse order of how we set it.
qglBlendFunc(previous_blend_src, previous_blend_dst); qglPixelTransferf(GL_ALPHA_SCALE, previous_alpha_scale);
qglPixelTransferf(GL_BLUE_BIAS, previous_blue_bias);
qglPixelTransferf(GL_GREEN_BIAS, previous_green_bias);
qglPixelTransferf(GL_RED_BIAS, previous_red_bias);
qglBlendFunc(previous_blend_func_src, previous_blend_func_dst);
if (!previous_blend_enabled) { qglDisable(GL_BLEND); } if (!previous_blend_enabled) { qglDisable(GL_BLEND); }
qglPixelStorei(GL_UNPACK_ALIGNMENT, previous_unpack_alignment); qglPixelStorei(GL_UNPACK_ALIGNMENT, previous_unpack_alignment);
g_free(bitmap.buffer);
g_free(pixels);
} }
g_object_unref(G_OBJECT(layout)); g_object_unref(G_OBJECT(layout));