From 8f1cfefbb223af8755b1013573d4088d476eae7c Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 7 Feb 2002 04:22:57 +0000 Subject: [PATCH] benchmark theme on startup 2002-02-06 Havoc Pennington * src/theme-viewer.c: benchmark theme on startup * src/theme-parser.c (parse_draw_op_element): fix "colorize != NULL" to "colorize_spec != NULL" and free pixbuf on color spec failure * src/theme.c (colorize_pixbuf): minor reformatting, raise function calls out of inner loop, clamp r/g/b values to uchar range before assigning to uchar (draw_op_as_pixbuf): cache the colorized pixbuf (meta_draw_op_free): free the cache pixbuf --- ChangeLog | 14 ++++++ src/theme-parser.c | 3 +- src/theme-viewer.c | 88 ++++++++++++++++++++++++++++++--- src/theme.c | 119 +++++++++++++++++++++++++++++---------------- src/theme.h | 2 + 5 files changed, 178 insertions(+), 48 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44fb320da..3fa129125 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-02-06 Havoc Pennington + + * src/theme-viewer.c: benchmark theme on startup + + * src/theme-parser.c (parse_draw_op_element): fix "colorize != + NULL" to "colorize_spec != NULL" and free pixbuf on color spec + failure + + * src/theme.c (colorize_pixbuf): minor reformatting, raise + function calls out of inner loop, clamp r/g/b values to uchar + range before assigning to uchar + (draw_op_as_pixbuf): cache the colorized pixbuf + (meta_draw_op_free): free the cache pixbuf + 2002-02-07 Anders Carlsson * src/theme-parser.c: (parse_draw_op_element): diff --git a/src/theme-parser.c b/src/theme-parser.c index 74a076f30..12f43c0ca 100644 --- a/src/theme-parser.c +++ b/src/theme-parser.c @@ -2071,9 +2071,10 @@ parse_draw_op_element (GMarkupParseContext *context, { colorize_spec = meta_color_spec_new_from_string (colorize, error); - if (colorize == NULL) + if (colorize_spec == NULL) { add_context_to_error (error, context); + g_object_unref (G_OBJECT (pixbuf)); return; } } diff --git a/src/theme-viewer.c b/src/theme-viewer.c index dd2ecdf9e..0f8a24ad9 100644 --- a/src/theme-viewer.c +++ b/src/theme-viewer.c @@ -28,13 +28,15 @@ #include #include -static int client_width = 200; -static int client_height = 200; +#define CLIENT_WIDTH 200 +#define CLIENT_HEIGHT 200 static MetaTheme *global_theme = NULL; static void run_position_expression_tests (void); static void run_position_expression_timings (void); +static void run_theme_benchmark (int client_width, + int client_height); static MetaFrameFlags get_flags (GtkWidget *widget) @@ -139,8 +141,8 @@ set_widget_to_frame_size (GtkWidget *widget) &right_width); gtk_widget_set_size_request (widget, - client_width + left_width + right_width, - client_height + top_height + bottom_height); + CLIENT_WIDTH + left_width + right_width, + CLIENT_HEIGHT + top_height + bottom_height); } static gboolean @@ -176,7 +178,7 @@ expose_handler (GtkWidget *widget, 0, 0, META_FRAME_TYPE_NORMAL, get_flags (widget), - client_width, client_height, + CLIENT_WIDTH, CLIENT_HEIGHT, layout, get_text_height (widget), button_states, @@ -189,7 +191,7 @@ expose_handler (GtkWidget *widget, widget->style->white_gc, TRUE, left_width, top_height, - client_width, client_height); + CLIENT_WIDTH, CLIENT_HEIGHT); g_object_unref (G_OBJECT (layout)); @@ -241,6 +243,8 @@ main (int argc, char **argv) global_theme->name, (end - start) / (double) CLOCKS_PER_SEC); + run_theme_benchmark (CLIENT_WIDTH, CLIENT_HEIGHT); + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size (GTK_WINDOW (window), 270, 270); @@ -285,6 +289,78 @@ main (int argc, char **argv) return 0; } +static void +run_theme_benchmark (int client_width, + int client_height) +{ + GtkWidget* widget; + GdkPixmap *pixmap; + int top_height, bottom_height, left_width, right_width; + MetaButtonState button_states[META_BUTTON_TYPE_LAST] = + { + META_BUTTON_STATE_NORMAL, + META_BUTTON_STATE_NORMAL, + META_BUTTON_STATE_NORMAL, + META_BUTTON_STATE_NORMAL + }; + PangoLayout *layout; + clock_t start; + clock_t end; + int i; +#define ITERATIONS 100 + + widget = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_realize (widget); + + meta_theme_get_frame_borders (global_theme, + META_FRAME_TYPE_NORMAL, + get_text_height (widget), + get_flags (widget), + &top_height, + &bottom_height, + &left_width, + &right_width); + + pixmap = gdk_pixmap_new (widget->window, + client_width + left_width + right_width, + client_height + top_height + bottom_height, + -1); + + layout = create_title_layout (widget); + + start = clock (); + + i = 0; + while (i < ITERATIONS) + { + meta_theme_draw_frame (global_theme, + widget, + pixmap, + NULL, + 0, 0, + META_FRAME_TYPE_NORMAL, + get_flags (widget), + client_width, client_height, + layout, + get_text_height (widget), + button_states, + get_mini_icon (), + get_icon ()); + ++i; + } + + end = clock (); + + g_print ("Drew %d frames for %dx%d clients in %g seconds (%g seconds per frame)\n", + ITERATIONS, client_width, client_height, + ((double)end - (double)start) / CLOCKS_PER_SEC, + ((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS); + + g_object_unref (G_OBJECT (layout)); + g_object_unref (G_OBJECT (pixmap)); + gtk_widget_destroy (widget); +} + typedef struct { GdkRectangle rect; diff --git a/src/theme.c b/src/theme.c index f7da90dca..b98c6135a 100644 --- a/src/theme.c +++ b/src/theme.c @@ -28,58 +28,81 @@ #include #include -#define GDK_COLOR_RGBA(color) \ - (0xff | \ - (((color).red / 256) << 24) | \ - (((color).green / 256) << 16) | \ - (((color).blue / 256) << 8)) +#define GDK_COLOR_RGBA(color) \ + ((guint32) (0xff | \ + (((color).red / 256) << 24) | \ + (((color).green / 256) << 16) | \ + (((color).blue / 256) << 8))) -#define GDK_COLOR_RGB(color) \ - ((((color).red / 256) << 16) | \ - (((color).green / 256) << 8) | \ - (((color).blue / 256))) +#define GDK_COLOR_RGB(color) \ + ((guint32) ((((color).red / 256) << 16) | \ + (((color).green / 256) << 8) | \ + (((color).blue / 256)))) #define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255)) #define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s))) #define INTENSITY(r, g, b) (r * 0.30 + g * 0.59 + b * 0.11) +#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255))) static GdkPixbuf * -colorize_pixbuf (GdkPixbuf *orig, GdkColor *new_color) +colorize_pixbuf (GdkPixbuf *orig, + GdkColor *new_color) { GdkPixbuf *pixbuf; double intensity; int x, y; guchar r, g, b; - guchar *src, *dest; - + const guchar *src; + guchar *dest; + int orig_rowstride; + int dest_rowstride; + int width, height; + gboolean has_alpha; + const guchar *src_pixels; + guchar *dest_pixels; + r = new_color->red / 256; g = new_color->green / 256; b = new_color->blue / 256; - + pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig), gdk_pixbuf_get_bits_per_sample (orig), gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig)); + + orig_rowstride = gdk_pixbuf_get_rowstride (orig); + dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + has_alpha = gdk_pixbuf_get_has_alpha (orig); + src_pixels = gdk_pixbuf_get_pixels (orig); + dest_pixels = gdk_pixbuf_get_pixels (pixbuf); - for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++) + for (y = 0; y < height; y++) { - src = gdk_pixbuf_get_pixels (orig) + y * gdk_pixbuf_get_rowstride (orig); - dest = gdk_pixbuf_get_pixels (pixbuf) + y * gdk_pixbuf_get_rowstride (pixbuf); + src = src_pixels + y * orig_rowstride; + dest = dest_pixels + y * dest_rowstride; - for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++) { - - intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; - - dest[0] = (guchar)(r * intensity); - dest[1] = g * intensity; - dest[2] = b * intensity; - - if (gdk_pixbuf_get_has_alpha (orig)) - dest[3] = src[3]; - - src += gdk_pixbuf_get_has_alpha (orig) ? 4 : 3; - dest += gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3; - } + for (x = 0; x < width; x++) + { + intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; + + dest[0] = CLAMP_UCHAR (r * intensity); + dest[1] = CLAMP_UCHAR (g * intensity); + dest[2] = CLAMP_UCHAR (b * intensity); + + if (has_alpha) + { + dest[3] = src[3]; + src += 4; + dest += 4; + } + else + { + src += 3; + dest += 3; + } + } } return pixbuf; @@ -2151,6 +2174,8 @@ meta_draw_op_free (MetaDrawOp *op) g_object_unref (G_OBJECT (op->data.image.pixbuf)); if (op->data.image.colorize_spec) meta_color_spec_free (op->data.image.colorize_spec); + if (op->data.image.colorize_cache_pixbuf) + g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); g_free (op->data.image.x); g_free (op->data.image.y); g_free (op->data.image.width); @@ -2345,7 +2370,6 @@ scale_and_alpha_pixbuf (GdkPixbuf *src, pixbuf = NULL; - pixbuf = src; if (gdk_pixbuf_get_width (pixbuf) == width && gdk_pixbuf_get_height (pixbuf) == height) @@ -2445,18 +2469,31 @@ draw_op_as_pixbuf (const MetaDrawOp *op, { if (op->data.image.colorize_spec) { - GdkPixbuf *tmp_pixbuf; GdkColor color; - meta_color_spec_render (op->data.image.colorize_spec, - widget, &color); - tmp_pixbuf = colorize_pixbuf (op->data.image.pixbuf, - &color); - - pixbuf = scale_and_alpha_pixbuf (tmp_pixbuf, - op->data.image.alpha, - width, height); - g_object_unref (tmp_pixbuf); + meta_color_spec_render (op->data.image.colorize_spec, + widget, &color); + + if (op->data.image.colorize_cache_pixbuf == NULL || + op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color)) + { + if (op->data.image.colorize_cache_pixbuf) + g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); + + /* const cast here */ + ((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf = + colorize_pixbuf (op->data.image.pixbuf, + &color); + ((MetaDrawOp*)op)->data.image.colorize_cache_pixel = + GDK_COLOR_RGB (color); + } + + if (op->data.image.colorize_cache_pixbuf) + { + pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf, + op->data.image.alpha, + width, height); + } } else { diff --git a/src/theme.h b/src/theme.h index db59cc83e..5e8061921 100644 --- a/src/theme.h +++ b/src/theme.h @@ -260,6 +260,8 @@ struct _MetaDrawOp char *y; char *width; char *height; + guint32 colorize_cache_pixel; + GdkPixbuf *colorize_cache_pixbuf; } image; struct {