diff options
author | Benjamin Otte <otte@gnome.org> | 2006-05-29 13:44:13 +0000 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2006-05-29 13:44:13 +0000 |
commit | b1fe36389ac5f1fc4b114cb657a24ef13fa5cc05 (patch) | |
tree | 17cf07d1001757ac09a6aef946a4ed5327541553 | |
parent | 12b4174f8ef17153c7092ed7ef7ceb70b49a8e79 (diff) |
* libgame/game-graphic.c: (game_graphic_copy),
(game_graphic_do_create_cache), (game_graphic_class_init),
(game_graphic_draw_area_no_cache), (game_graphic_draw_area),
(game_graphic_get_cache), (game_cairo_pattern_matches):
* libgame/game-graphic.h:
update caching mechanism to use a vfunc
clean up the API used for caching
* libgame/game-colored.c: (game_colored_draw):
update function name
* libgame/game-board.c: (game_board_class_init), (game_board_init):
* libgame/game-viewport.c: (game_viewport_class_init),
(game_viewport_init):
* games/pacman/pacman-graphic.c: (pacman_graphic_draw),
(pacman_graphic_create_cache), (pacman_graphic_set_property),
(pacman_graphic_class_init):
use new method of saying "no cache for me"
* libgame/game-animation.c: (game_animation_add_image),
(game_animation_dispose), (game_animation_create_cache),
(game_animation_class_init):
implement caching
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | games/pacman/pacman-graphic.c | 14 | ||||
-rw-r--r-- | libgame/game-animation.c | 28 | ||||
-rw-r--r-- | libgame/game-board.c | 4 | ||||
-rw-r--r-- | libgame/game-colored.c | 2 | ||||
-rw-r--r-- | libgame/game-graphic.c | 164 | ||||
-rw-r--r-- | libgame/game-graphic.h | 11 | ||||
-rw-r--r-- | libgame/game-viewport.c | 4 |
8 files changed, 174 insertions, 76 deletions
@@ -1,3 +1,26 @@ +2006-05-29 Benjamin Otte <in7y118@public.uni-hamburg.de> + + * libgame/game-graphic.c: (game_graphic_copy), + (game_graphic_do_create_cache), (game_graphic_class_init), + (game_graphic_draw_area_no_cache), (game_graphic_draw_area), + (game_graphic_get_cache), (game_cairo_pattern_matches): + * libgame/game-graphic.h: + update caching mechanism to use a vfunc + clean up the API used for caching + * libgame/game-colored.c: (game_colored_draw): + update function name + * libgame/game-board.c: (game_board_class_init), (game_board_init): + * libgame/game-viewport.c: (game_viewport_class_init), + (game_viewport_init): + * games/pacman/pacman-graphic.c: (pacman_graphic_draw), + (pacman_graphic_create_cache), (pacman_graphic_set_property), + (pacman_graphic_class_init): + use new method of saying "no cache for me" + * libgame/game-animation.c: (game_animation_add_image), + (game_animation_dispose), (game_animation_create_cache), + (game_animation_class_init): + implement caching + 2006-05-28 Benjamin Otte <in7y118@public.uni-hamburg.de> * libgame/game-geom-basics.c: (game_point_distance): diff --git a/games/pacman/pacman-graphic.c b/games/pacman/pacman-graphic.c index 6c97c62..d5221a1 100644 --- a/games/pacman/pacman-graphic.c +++ b/games/pacman/pacman-graphic.c @@ -69,12 +69,19 @@ pacman_graphic_draw (GameGraphic *graphic, cairo_t *cr, const GameRectangle *are cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); cairo_set_line_width (cr, 0.02); cairo_stroke (cr); -#if 1 /* eye */ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); cairo_arc (cr, eye_x, eye_y, 0.05, 0.0, 2 * GAME_PI); cairo_fill (cr); -#endif +} + +static cairo_pattern_t * +pacman_graphic_create_cache (GameGraphic *graphic, cairo_t *cr) +{ + if (PACMAN_GRAPHIC (graphic)->animate) + return NULL; + + return GAME_GRAPHIC_CLASS (parent_class)->create_cache (graphic, cr); } static void @@ -114,8 +121,6 @@ pacman_graphic_set_property (GObject *object, guint param_id, break; case PROP_ANIMATE: graphic->animate = g_value_get_boolean (value); - GAME_GRAPHIC (graphic)->cache_policy = graphic->animate ? - GAME_GRAPHIC_CACHE_NEVER : GAME_GRAPHIC_CACHE_ALWAYS; break; case PROP_COLOR: graphic->color = *((GameColor *) g_value_get_boxed (value)); @@ -165,6 +170,7 @@ pacman_graphic_class_init (gpointer g_class, gpointer class_data) gameobject_class->tick_func = pacman_graphic_tick; graphic_class->draw = pacman_graphic_draw; + graphic_class->create_cache = pacman_graphic_create_cache; } static void diff --git a/libgame/game-animation.c b/libgame/game-animation.c index f8b4379..d3198e7 100644 --- a/libgame/game-animation.c +++ b/libgame/game-animation.c @@ -32,6 +32,7 @@ enum { typedef struct { cairo_surface_t * surface; + cairo_pattern_t * cache; guint duration; } GameAnimationFrame; static GameGraphicClass *parent_class = NULL; @@ -84,7 +85,7 @@ game_animation_start (GameAnimation *anim) static void game_animation_add_image (GameAnimation *anim, cairo_surface_t *surface, guint duration) { - GameAnimationFrame frame = { surface, duration }; + GameAnimationFrame frame = { surface, NULL, duration }; g_array_append_val (anim->frames, frame); if (anim->frames->len == 1) @@ -119,6 +120,8 @@ game_animation_dispose (GObject *object) for (i = 0; i < anim->frames->len; i++) { frame = &g_array_index(anim->frames, GameAnimationFrame, i); cairo_surface_destroy (frame->surface); + if (frame->cache) + cairo_pattern_destroy (frame->cache); } g_array_free (anim->frames, TRUE); anim->frames = NULL; @@ -166,11 +169,32 @@ game_animation_tick (GameObject *object) game_animation_update_image (anim, frame->surface); } +static cairo_pattern_t * +game_animation_create_cache (GameGraphic *graphic, cairo_t *cr) +{ + GameAnimationFrame *frame; + GameAnimation *anim = GAME_ANIMATION (graphic); + + frame = &g_array_index(anim->frames, GameAnimationFrame, anim->current); + + if (frame->cache) { + if (game_cairo_pattern_matches (cr, frame->cache)) { + cairo_pattern_reference (frame->cache); + return frame->cache; + } + cairo_pattern_destroy (frame->cache); + //frame->cache = NULL; + } + frame->cache = GAME_GRAPHIC_CLASS (parent_class)->create_cache (graphic, cr); + return frame->cache; +} + static void game_animation_class_init (gpointer g_class, gpointer class_data) { GObjectClass *object_class = G_OBJECT_CLASS (g_class); GameObjectClass *gameobject_class = GAME_OBJECT_CLASS (g_class); + GameGraphicClass *graphic_class = GAME_GRAPHIC_CLASS (g_class); parent_class = g_type_class_peek_parent (g_class); @@ -185,6 +209,8 @@ game_animation_class_init (gpointer g_class, gpointer class_data) gameobject_class->copy = game_animation_copy; gameobject_class->tick_func = game_animation_tick; + + graphic_class->create_cache = game_animation_create_cache; } static void diff --git a/libgame/game-board.c b/libgame/game-board.c index b74d2ee..08bfc9b 100644 --- a/libgame/game-board.c +++ b/libgame/game-board.c @@ -255,16 +255,14 @@ game_board_class_init (gpointer g_class, gpointer class_data) gameobject_class->game_set = game_board_game_set; graphic_class->draw = game_board_draw; + graphic_class->create_cache = NULL; } static void game_board_init (GTypeInstance *instance, gpointer g_class) { - GameGraphic *graphic = GAME_GRAPHIC (instance); GameBoard *board = GAME_BOARD (instance); - graphic->cache_policy = GAME_GRAPHIC_CACHE_NEVER; - board->sprite_type = GAME_TYPE_SPRITE; } diff --git a/libgame/game-colored.c b/libgame/game-colored.c index 975a7ab..db706d5 100644 --- a/libgame/game-colored.c +++ b/libgame/game-colored.c @@ -133,7 +133,7 @@ game_colored_draw (GameGraphic *graphic, cairo_t *cr, const GameRectangle *area) game_graphic_draw_area (colored->base, cr, area); game_color_as_cairo_source (cr, &colored->color); if (colored->mask) { - cairo_pattern_t *mask = game_graphic_create_cache (colored->mask, cr); + cairo_pattern_t *mask = game_graphic_get_cache (colored->mask, cr); if (mask) { cairo_mask (cr, mask); } else { diff --git a/libgame/game-graphic.c b/libgame/game-graphic.c index 101c367..7363eae 100644 --- a/libgame/game-graphic.c +++ b/libgame/game-graphic.c @@ -115,7 +115,6 @@ game_graphic_copy (GameObject *odest, GameObject *osrc) GameGraphic *src = GAME_GRAPHIC (osrc); dest->rect = src->rect; - dest->cache_policy = src->cache_policy; dest->cache = src->cache; if (dest->cache) cairo_pattern_reference (dest->cache); @@ -123,11 +122,69 @@ game_graphic_copy (GameObject *odest, GameObject *osrc) return GAME_OBJECT_CLASS (parent_class)->copy (odest, osrc); } +static cairo_pattern_t * +game_graphic_do_create_cache (GameGraphic *graphic, cairo_t *cr) +{ + cairo_matrix_t matrix; + cairo_t *crc; + cairo_surface_t *cache; + cairo_pattern_t *pattern; + double width, height; + + g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), NULL); + g_return_val_if_fail (cr != NULL, NULL); + + cairo_get_matrix (cr, &matrix); + if (!GAME_DOUBLE_EQUAL (matrix.xy, 0.0) || + !GAME_DOUBLE_EQUAL (matrix.xy, 0.0)) + return NULL; + + width = graphic->rect.x2 - graphic->rect.x1; + height = graphic->rect.y2 - graphic->rect.y1; +#if 1 + cache = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR_ALPHA, ceil (matrix.xx * width), + ceil (matrix.yy * height)); +#else + cache = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + ceil (matrix.xx * width), ceil (matrix.yy * height)); +#endif + if (cairo_surface_status (cache) != CAIRO_STATUS_SUCCESS) { + cairo_surface_destroy (cache); + return NULL; + } + crc = cairo_create (cache); + /* clear surface */ + cairo_save (crc); + cairo_set_operator (crc, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba (crc, 0.0, 0.0, 0.0, 0.0); + cairo_paint (crc); + cairo_restore (crc); + + cairo_scale (crc, matrix.xx, matrix.yy); + cairo_translate (crc, - graphic->rect.x1, - graphic->rect.y1); + if (!game_graphic_draw_area_no_cache (graphic, crc, &graphic->rect)) { + cairo_surface_destroy (cache); + cairo_destroy (crc); + return NULL; + } + + pattern = cairo_pattern_create_for_surface (cache); + cairo_get_matrix (crc, &matrix); + cairo_pattern_set_matrix (pattern, &matrix); + + cairo_surface_destroy (cache); + cairo_destroy (crc); + + return pattern; +} + static void game_graphic_class_init (gpointer g_class, gpointer class_data) { GObjectClass *object_class = G_OBJECT_CLASS (g_class); GameObjectClass *gameobject_class = GAME_OBJECT_CLASS (g_class); + GameGraphicClass *graphic_class = GAME_GRAPHIC_CLASS (g_class); parent_class = g_type_class_peek_parent (g_class); @@ -159,6 +216,8 @@ game_graphic_class_init (gpointer g_class, gpointer class_data) gameobject_class->copy = game_graphic_copy; gameobject_class->to_string = game_graphic_to_string; + + graphic_class->create_cache = game_graphic_do_create_cache; } static void @@ -222,8 +281,8 @@ game_graphic_invalidate_cache (GameGraphic *graphic) } } -static gboolean -game_graphic_do_draw_area (GameGraphic *graphic, cairo_t *cr, +gboolean +game_graphic_draw_area_no_cache (GameGraphic *graphic, cairo_t *cr, const GameRectangle *rect) { GameGraphicClass *klass; @@ -256,8 +315,8 @@ gboolean game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const GameRectangle *rect) { - cairo_matrix_t matrix; GameRectangle inval; + cairo_pattern_t *cache; g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), FALSE); g_return_val_if_fail (cr != NULL, FALSE); @@ -266,24 +325,15 @@ game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const if (!game_rectangle_intersect (&inval, &graphic->rect, rect)) return TRUE; - if (graphic->cache_policy == GAME_GRAPHIC_CACHE_NEVER) - return game_graphic_do_draw_area (graphic, cr, rect); - cairo_get_matrix (cr, &matrix); - if (!GAME_DOUBLE_EQUAL (matrix.xy, 0.0) || - !GAME_DOUBLE_EQUAL (matrix.yx, 0.0)) - return game_graphic_do_draw_area (graphic, cr, rect); - if (graphic->cache != NULL) { - cairo_matrix_t pmatrix; - cairo_pattern_get_matrix (graphic->cache, &pmatrix); - if (!GAME_DOUBLE_EQUAL (matrix.xx, pmatrix.xx) || - !GAME_DOUBLE_EQUAL (matrix.yy, pmatrix.yy)) - game_graphic_invalidate_cache (graphic); - } - if (graphic->cache == NULL) { - graphic->cache = game_graphic_create_cache (graphic, cr); - if (graphic->cache == NULL) - return game_graphic_do_draw_area (graphic, cr, rect); + cache = game_graphic_get_cache (graphic, cr); + if (graphic->cache != cache) { + game_graphic_invalidate_cache (graphic); + graphic->cache = cache; + if (cache) + cairo_pattern_reference (cache); } + if (graphic->cache == NULL) + return game_graphic_draw_area_no_cache (graphic, cr, rect); cairo_save (cr); cairo_set_source (cr, graphic->cache); cairo_paint (cr); @@ -292,54 +342,44 @@ game_graphic_draw_area (GameGraphic *graphic, cairo_t *cr, const } cairo_pattern_t * -game_graphic_create_cache (GameGraphic *graphic, cairo_t *cr) +game_graphic_get_cache (GameGraphic *graphic, cairo_t *cr) { - cairo_matrix_t matrix; - cairo_t *crc; - cairo_surface_t *cache; - cairo_pattern_t *pattern; - double width, height; + GameGraphicClass *klass; + cairo_pattern_t *cache; g_return_val_if_fail (GAME_IS_GRAPHIC (graphic), NULL); g_return_val_if_fail (cr != NULL, NULL); - - cairo_get_matrix (cr, &matrix); - width = graphic->rect.x2 - graphic->rect.x1; - height = graphic->rect.y2 - graphic->rect.y1; -#if 1 - cache = cairo_surface_create_similar (cairo_get_target (cr), - CAIRO_CONTENT_COLOR_ALPHA, ceil (matrix.xx * width), - ceil (matrix.yy * height)); -#else - cache = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - ceil (matrix.xx * width), ceil (matrix.yy * height)); -#endif - if (cairo_surface_status (cache) != CAIRO_STATUS_SUCCESS) { - cairo_surface_destroy (cache); - return NULL; - } - crc = cairo_create (cache); - /* clear surface */ - cairo_save (crc); - cairo_set_operator (crc, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba (crc, 0.0, 0.0, 0.0, 0.0); - cairo_paint (crc); - cairo_restore (crc); - cairo_scale (crc, matrix.xx, matrix.yy); - cairo_translate (crc, - graphic->rect.x1, - graphic->rect.y1); - if (!game_graphic_do_draw_area (graphic, crc, &graphic->rect)) { - cairo_surface_destroy (cache); - cairo_destroy (crc); - return NULL; + if (graphic->cache != NULL && + game_cairo_pattern_matches (cr, graphic->cache)) { + cairo_pattern_reference (graphic->cache); + return graphic->cache; } + klass = GAME_GRAPHIC_GET_CLASS (graphic); + if (klass->create_cache) + cache = klass->create_cache (graphic, cr); + else + cache = NULL; - pattern = cairo_pattern_create_for_surface (cache); - cairo_get_matrix (crc, &matrix); - cairo_pattern_set_matrix (pattern, &matrix); + return cache; +} - cairo_surface_destroy (cache); - cairo_destroy (crc); +gboolean +game_cairo_pattern_matches (cairo_t *cr, cairo_pattern_t *pattern) +{ + cairo_matrix_t cmatrix, pmatrix, result; + + g_return_val_if_fail (cr != NULL, FALSE); + g_return_val_if_fail (pattern != NULL, FALSE); - return pattern; + cairo_get_matrix (cr, &cmatrix); + cairo_pattern_get_matrix (pattern, &pmatrix); + cairo_matrix_invert (&pmatrix); + cairo_matrix_multiply (&result, &cmatrix, &pmatrix); + /* FIXME: need to somehow check surface types? */ + return GAME_DOUBLE_EQUAL (result.xx, 1.0) && + GAME_DOUBLE_EQUAL (result.yy, 1.0) && + GAME_DOUBLE_EQUAL (result.xy, 0.0) && + GAME_DOUBLE_EQUAL (result.yx, 0.0); } + diff --git a/libgame/game-graphic.h b/libgame/game-graphic.h index 6298642..9aead8a 100644 --- a/libgame/game-graphic.h +++ b/libgame/game-graphic.h @@ -44,7 +44,6 @@ struct _GameGraphic { /*< protected >*/ GameRectangle rect; - GameGraphicCachePolicy cache_policy; /*< private >*/ cairo_pattern_t * cache; @@ -57,6 +56,8 @@ struct _GameGraphicClass { void (* draw) (GameGraphic * graphic, cairo_t * cr, const GameRectangle * rect); + cairo_pattern_t * (* create_cache) (GameGraphic * graphic, + cairo_t * cr); /* signals */ void (* invalidate) (GameGraphic * graphic, const GameRectangle * rect); @@ -74,9 +75,15 @@ gboolean game_graphic_draw (GameGraphic * graphic, gboolean game_graphic_draw_area (GameGraphic * graphic, cairo_t * cr, const GameRectangle * rectangle); +gboolean game_graphic_draw_area_no_cache (GameGraphic * graphic, + cairo_t * cr, + const GameRectangle * rect); -cairo_pattern_t *game_graphic_create_cache (GameGraphic * graphic, +cairo_pattern_t *game_graphic_get_cache (GameGraphic * graphic, cairo_t * cr); +/* FIXME: find a header/file for this */ +gboolean game_cairo_pattern_matches (cairo_t * cr, + cairo_pattern_t * pattern); G_END_DECLS diff --git a/libgame/game-viewport.c b/libgame/game-viewport.c index f447f6d..251f2cf 100644 --- a/libgame/game-viewport.c +++ b/libgame/game-viewport.c @@ -171,14 +171,12 @@ game_viewport_class_init (gpointer g_class, gpointer class_data) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); graphic_class->draw = game_viewport_draw; + graphic_class->create_cache = NULL; } static void game_viewport_init (GTypeInstance *instance, gpointer g_class) { - GameGraphic *graphic = GAME_GRAPHIC (instance); - - graphic->cache_policy = GAME_GRAPHIC_CACHE_NEVER; } GType |