[gnome-games] gnometris: solve most of the memory management issues
- From: Jason Clinton <jclinton src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-games] gnometris: solve most of the memory management issues
- Date: Thu, 27 Aug 2009 04:01:26 +0000 (UTC)
commit c7c45c29bbffa554c598a18c3e104ee11cedadf4
Author: Jason D. Clinton <me jasonclinton com>
Date: Wed Aug 26 22:59:41 2009 -0500
gnometris: solve most of the memory management issues
gnometris/blockops.cpp | 140 +++++++++++++++++++++++--------------------
gnometris/blocks-cache.cpp | 28 ++++++---
gnometris/blocks.cpp | 37 +++++++-----
gnometris/blocks.h | 5 +-
gnometris/preview.cpp | 9 +--
gnometris/preview.h | 2 +-
gnometris/renderer.cpp | 6 +-
gnometris/renderer.h | 4 +-
8 files changed, 128 insertions(+), 103 deletions(-)
---
diff --git a/gnometris/blockops.cpp b/gnometris/blockops.cpp
index a5d24b1..703517d 100644
--- a/gnometris/blockops.cpp
+++ b/gnometris/blockops.cpp
@@ -110,12 +110,14 @@ BlockOps::BlockOps() :
(BlockOps::move_end), this);
move_alpha = clutter_alpha_new_full (move_time,
CLUTTER_EASE_IN_QUAD);
+ g_object_ref (move_alpha);
fall_time = clutter_timeline_new (FALL_TIMING);
g_signal_connect (fall_time, "completed", G_CALLBACK
(BlockOps::fall_end), this);
fall_alpha = clutter_alpha_new_full (fall_time,
CLUTTER_EASE_IN_QUAD);
+ g_object_ref (fall_alpha);
explode_time = clutter_timeline_new (720);
g_signal_connect (explode_time, "completed", G_CALLBACK
@@ -140,10 +142,6 @@ BlockOps::BlockOps() :
{
field[i] = new Block[LINES];
backfield[i] = new Block[LINES];
- for (int j = 0; j < LINES; ++j)
- {
- field[i][j].bindAnimations (this);
- }
}
}
@@ -300,18 +298,23 @@ BlockOps::dropBlock()
void
BlockOps::fallingToLaying()
{
- for (int x = 0; x < COLUMNS; ++x)
- for (int y = 0; y < LINES; ++y)
- if (field[x][y].what == FALLING)
- {
- field[x][y].what = LAYING;
- if (!animate)
- continue;
- clutter_actor_set_position (field[x][y].actor,
- field[x][y].x,
- field[x][y].y);
- clutter_behaviour_remove_all (field[x][y].move_behaviour);
+ for (int x = 0; x < COLUMNS; ++x) {
+ for (int y = 0; y < LINES; ++y) {
+ Block *cell = &field[x][y];
+ if (cell->what == FALLING) {
+ cell->what = LAYING;
+ //if (!animate)
+ // continue;
+ clutter_actor_set_position (cell->actor,
+ cell->x, cell->y);
+ if (cell->move_behaviour) {
+ clutter_behaviour_remove_all (cell->move_behaviour);
+ g_object_unref (cell->move_behaviour);
+ cell->move_behaviour = NULL;
+ }
}
+ }
+ }
}
void
@@ -319,23 +322,27 @@ BlockOps::eliminateLine(int l)
{
for (int x = 0; x < COLUMNS; ++x)
{
- if (field[x][l].actor) {
+ Block *cell = &field[x][l];
+ if (cell->actor) {
int cur_x, cur_y = 0;
- g_object_get (G_OBJECT (field[x][l].actor), "x", &cur_x, "y", &cur_y, NULL);
- clutter_actor_raise_top (field[x][l].actor);
+ g_object_get (G_OBJECT (cell->actor), "x", &cur_x, "y", &cur_y, NULL);
+ clutter_actor_raise_top (cell->actor);
ClutterPath *path_line = clutter_path_new ();
clutter_path_add_move_to (path_line, cur_x, cur_y);
clutter_path_add_line_to (path_line,
cur_x + g_random_int_range (-60 - cell_width / 4, 60),
cur_y + g_random_int_range (-60 - cell_height / 4, 60));
- clutter_behaviour_remove_all (field[x][l].explode_move_behaviour);
- clutter_behaviour_path_set_path (CLUTTER_BEHAVIOUR_PATH(field[x][l].explode_move_behaviour),
- path_line);
- clutter_behaviour_apply (field[x][l].explode_move_behaviour, field[x][l].actor);
- clutter_behaviour_apply (explode_fade_behaviour, field[x][l].actor);
- clutter_behaviour_apply (explode_scale_behaviour, field[x][l].actor);
- destroy_actors = g_list_prepend (destroy_actors, field[x][l].actor);
- field[x][l].actor = NULL;
+ if (cell->explode_move_behaviour) {
+ clutter_behaviour_remove_all (cell->explode_move_behaviour);
+ g_object_unref (cell->explode_move_behaviour);
+ }
+ cell->explode_move_behaviour = clutter_behaviour_path_new (explode_alpha,
+ path_line);
+ clutter_behaviour_apply (cell->explode_move_behaviour, cell->actor);
+ clutter_behaviour_apply (explode_fade_behaviour, cell->actor);
+ clutter_behaviour_apply (explode_scale_behaviour, cell->actor);
+ destroy_actors = g_list_prepend (destroy_actors, cell->actor);
+ cell->actor = NULL;
}
}
}
@@ -549,23 +556,20 @@ BlockOps::emptyField(int filled_lines, int fill_prob)
for (int x = 0; x < COLUMNS; ++x)
{
- field[x][y].what = EMPTY;
- if (field[x][y].actor) {
- clutter_actor_destroy (CLUTTER_ACTOR(field[x][y].actor));
- field[x][y].actor = NULL;
- }
+ Block *cell = &field[x][y];
+ cell->what = EMPTY;
+ cell->emptyCell ();
if ((y>=(LINES - filled_lines)) && (x != blank) &&
((g_random_int_range(0, 10)) < fill_prob)) {
guint tmpColor = g_random_int_range(0, NCOLOURS);
- field[x][y].what = LAYING;
- field[x][y].color = tmpColor;
- field[x][y].createActor (playingField,
- blocks_cache_get_block_texture_by_id (cache,
- tmpColor),
- cell_width,
- cell_height);
- clutter_actor_set_position (CLUTTER_ACTOR(field[x][y].actor),
+ cell->what = LAYING;
+ cell->color = tmpColor;
+ cell->createActor (playingField,
+ blocks_cache_get_block_texture_by_id (cache, tmpColor),
+ cell_width, cell_height);
+ g_object_set (G_OBJECT(cell->actor), "sync-size", true, NULL);
+ clutter_actor_set_position (CLUTTER_ACTOR(cell->actor),
x*(cell_width), y*(cell_height));
}
}
@@ -587,19 +591,16 @@ BlockOps::putBlockInField (SlotType fill)
int i = posx - 2 + x;
int j = y + posy;
- field[i][j].what = fill;
- field[i][j].color = color;
+ Block *cell = &field[i][j];
+ cell->what = fill;
if (fill == FALLING) {
- field[i][j].createActor (playingField,
- blocks_cache_get_block_texture_by_id (cache,
- color),
- cell_width,
- cell_height);
+ cell->color = color;
+ cell->createActor (playingField,
+ blocks_cache_get_block_texture_by_id (cache, color),
+ cell_width, cell_height);
} else {
- if (field[i][j].actor) {
- clutter_actor_destroy (field[i][j].actor);
- field[i][j].actor = NULL;
- }
+ cell->color = color;
+ cell->emptyCell ();
}
}
}
@@ -616,12 +617,16 @@ BlockOps::moveBlockInField (gint x_trans, gint y_trans)
if (blockTable[blocknr][rot][x][y]) {
int i = posx - 2 + x;
int j = y + posy;
-
- blocks_actor[x][y] = field[i-x_trans][j-y_trans].actor;
- field[i-x_trans][j-y_trans].what = EMPTY;
- field[i-x_trans][j-y_trans].actor = NULL;
- if (animate)
- clutter_behaviour_remove_all (field[i-x_trans][j-y_trans].move_behaviour);
+ Block *source_cell = &field[i-x_trans][j-y_trans];
+
+ blocks_actor[x][y] = source_cell->actor;
+ source_cell->what = EMPTY;
+ source_cell->actor = NULL;
+ if (animate && source_cell->move_behaviour) {
+ clutter_behaviour_remove_all (source_cell->move_behaviour);
+ g_object_unref (source_cell->move_behaviour);
+ source_cell->move_behaviour = NULL;
+ }
}
}
}
@@ -630,19 +635,24 @@ BlockOps::moveBlockInField (gint x_trans, gint y_trans)
if (blockTable[blocknr][rot][x][y]) {
gint i = posx - 2 + x;
gint j = y + posy;
+ Block *cell = &field[i][j];
- field[i][j].what = FALLING;
- field[i][j].color = color;
- field[i][j].actor = blocks_actor[x][y];
- if (field[i][j].actor && animate) {
+ cell->what = FALLING;
+ cell->color = color;
+ cell->actor = blocks_actor[x][y];
+ if (cell->actor && animate) {
gint cur_x, cur_y = 0;
- g_object_get (G_OBJECT (field[i][j].actor), "x", &cur_x, "y", &cur_y, NULL);
+ g_object_get (G_OBJECT (cell->actor), "x", &cur_x, "y", &cur_y, NULL);
ClutterPath *path_line = clutter_path_new ();
clutter_path_add_move_to (path_line, cur_x, cur_y);
- clutter_path_add_line_to (path_line, field[i][j].x, field[i][j].y);
- clutter_behaviour_remove_all (field[i][j].move_behaviour);
- clutter_behaviour_path_set_path (CLUTTER_BEHAVIOUR_PATH(field[i][j].move_behaviour), path_line);
- clutter_behaviour_apply (field[i][j].move_behaviour, field[i][j].actor);
+ clutter_path_add_line_to (path_line, cell->x, cell->y);
+ if (cell->move_behaviour) {
+ clutter_behaviour_remove_all (cell->move_behaviour);
+ g_object_unref (cell->move_behaviour);
+ }
+ cell->move_behaviour = clutter_behaviour_path_new (CLUTTER_ALPHA(move_alpha),
+ CLUTTER_PATH(path_line));
+ clutter_behaviour_apply (cell->move_behaviour, cell->actor);
}
}
}
diff --git a/gnometris/blocks-cache.cpp b/gnometris/blocks-cache.cpp
index 5d37a86..7d0903a 100644
--- a/gnometris/blocks-cache.cpp
+++ b/gnometris/blocks-cache.cpp
@@ -63,6 +63,12 @@ enum
#define LOG_CACHE_MISS(obj)
#endif /* GNOME_ENABLE_DEBUG */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
+#else
+#define CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
+#endif
+
static void blocks_cache_dispose (GObject *object);
static void blocks_cache_finalize (GObject *object);
@@ -287,13 +293,16 @@ blocks_cache_get_block_texture_by_id (BlocksCache *cache,
}
if (handle == COGL_INVALID_HANDLE) {
- cairo_surface_t *imgbuf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- 64, 64); /*FIXME for pixel-level precision*/
+ guint rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, 32);
+ guchar *cr_surface_data = static_cast<guchar*>(g_malloc0 (32 * rowstride));
+ cairo_surface_t *cr_surface = cairo_image_surface_create_for_data (cr_surface_data,
+ CAIRO_FORMAT_ARGB32,
+ 32, 32, rowstride); /*FIXME for pixel-level precision*/
LOG_CACHE_MISS (cache);
Renderer *renderer = rendererFactory (priv->theme);
- cairo_t *cr = cairo_create (imgbuf);
+ cairo_t *cr = cairo_create (cr_surface);
if (!cr) {
priv->colours[colour] = FAILED_HANDLE;
@@ -303,14 +312,15 @@ blocks_cache_get_block_texture_by_id (BlocksCache *cache,
renderer->drawCell (cr, colour);
cairo_destroy (cr);
- handle = cogl_texture_new_from_data (64,
- 64,
+ handle = cogl_texture_new_from_data (32,
+ 32,
COGL_TEXTURE_NONE,
- COGL_PIXEL_FORMAT_RGBA_8888,
+ CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT,
COGL_PIXEL_FORMAT_ANY,
- 2048,
- cairo_image_surface_get_data (imgbuf));
- cairo_surface_destroy (imgbuf);
+ rowstride,
+ cr_surface_data);
+ cairo_surface_destroy (cr_surface);
+ g_free (cr_surface_data);
if (handle == COGL_INVALID_HANDLE) {
priv->colours[colour] = FAILED_HANDLE;
diff --git a/gnometris/blocks.cpp b/gnometris/blocks.cpp
index f2afd23..3a8a2c0 100644
--- a/gnometris/blocks.cpp
+++ b/gnometris/blocks.cpp
@@ -45,29 +45,34 @@ Block::~Block ()
}
void
-Block::createActor (ClutterActor *chamber, CoglHandle texture_source, gint pxwidth, gint pxheight)
+Block::emptyCell ()
{
- if (actor)
+ if (actor) {
clutter_actor_destroy (CLUTTER_ACTOR(actor));
+ actor = NULL;
+ }
+ if (move_behaviour) {
+ g_object_unref (move_behaviour);
+ move_behaviour = NULL;
+ }
+ if (fall_behaviour) {
+ g_object_unref (fall_behaviour);
+ fall_behaviour = NULL;
+ }
+ if (explode_move_behaviour) {
+ g_object_unref (explode_move_behaviour);
+ explode_move_behaviour = NULL;
+ }
+}
+
+void
+Block::createActor (ClutterActor *chamber, CoglHandle texture_source, gint pxwidth, gint pxheight)
+{
actor = clutter_texture_new ();
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE(actor),
texture_source);
clutter_group_add (CLUTTER_GROUP (chamber), actor);
clutter_actor_set_position (CLUTTER_ACTOR(actor), x, y);
- clutter_actor_show (CLUTTER_ACTOR(actor));
-}
-
-void
-Block::bindAnimations (BlockOps *f)
-{
- move_behaviour = clutter_behaviour_path_new_with_knots (f->move_alpha,
- NULL, 0);
-
- fall_behaviour = clutter_behaviour_path_new_with_knots (f->fall_alpha,
- NULL, 0);
-
- explode_move_behaviour = clutter_behaviour_path_new_with_knots (f->explode_alpha,
- NULL, 0);
}
Block&
diff --git a/gnometris/blocks.h b/gnometris/blocks.h
index 7b84dab..0f9890a 100644
--- a/gnometris/blocks.h
+++ b/gnometris/blocks.h
@@ -40,6 +40,8 @@ public:
Block ();
~Block ();
+ void emptyCell ();
+
Block& moveFrom (Block &b, BlockOps *f);
SlotType what;
@@ -52,8 +54,7 @@ public:
void createActor (ClutterActor *chamber, CoglHandle texture_source, gint pxwidth, gint pxheight);
void bindAnimations (BlockOps *f);
- /* Every block will have a unique position
- * These can be continuously cleared and repopulated with new paths */
+ /* Every block will have a unique position*/
ClutterBehaviour *move_behaviour;
ClutterBehaviour *fall_behaviour;
ClutterBehaviour *explode_move_behaviour;
diff --git a/gnometris/preview.cpp b/gnometris/preview.cpp
index 1d96f34..83660c2 100644
--- a/gnometris/preview.cpp
+++ b/gnometris/preview.cpp
@@ -87,7 +87,7 @@ Preview::enable(bool en)
}
void
-Preview::setTheme (gint id)
+Preview::setTheme (guint id)
{
themeID = id;
@@ -112,6 +112,7 @@ Preview::previewBlock(gint bnr, gint bcol)
for (y = 1; y < PREVIEW_HEIGHT - 1; y++) {
if ((blocknr != -1) &&
blockTable[blocknr][0][x-1][y-1]) {
+ blocks[x][y].emptyCell ();
blocks[x][y].what = LAYING;
blocks[x][y].createActor (piece,
blocks_cache_get_block_texture_by_id (cache, color),
@@ -121,10 +122,8 @@ Preview::previewBlock(gint bnr, gint bcol)
x*PREVIEW_SIZE*4, y*PREVIEW_SIZE*4);
} else {
blocks[x][y].what = EMPTY;
- if (blocks[x][y].actor) {
- clutter_actor_destroy (CLUTTER_ACTOR(blocks[x][y].actor));
- blocks[x][y].actor = NULL;
- }
+ if (blocks[x][y].actor)
+ blocks[x][y].emptyCell ();
}
}
}
diff --git a/gnometris/preview.h b/gnometris/preview.h
index 8a66c6c..9572a4e 100644
--- a/gnometris/preview.h
+++ b/gnometris/preview.h
@@ -37,7 +37,7 @@ public:
}
void enable (bool enable);
- void setTheme (gint id);
+ void setTheme (guint id);
void previewBlock (int bnr, int bcolor);
private:
diff --git a/gnometris/renderer.cpp b/gnometris/renderer.cpp
index 3fe63ea..e438747 100644
--- a/gnometris/renderer.cpp
+++ b/gnometris/renderer.cpp
@@ -33,9 +33,9 @@ const ThemeTableEntry ThemeTable[] = {{N_("Plain"), "plain"},
{NULL, NULL}};
-gint themeNameToNumber (const gchar *id)
+guint themeNameToNumber (const gchar *id)
{
- int i;
+ guint i;
const ThemeTableEntry *t;
if (id == NULL)
@@ -53,7 +53,7 @@ gint themeNameToNumber (const gchar *id)
return 0;
}
-Renderer * rendererFactory (gint id)
+Renderer * rendererFactory (guint id)
{
Renderer *r;
switch (id) {
diff --git a/gnometris/renderer.h b/gnometris/renderer.h
index 8341d40..70dddd9 100644
--- a/gnometris/renderer.h
+++ b/gnometris/renderer.h
@@ -35,14 +35,14 @@ struct ThemeTableEntry {
};
extern const ThemeTableEntry ThemeTable[];
-gint themeNameToNumber (const gchar *id);
+guint themeNameToNumber (const gchar *id);
class Renderer {
public:
virtual void drawCell (cairo_t *cr, guint color);
};
-Renderer *rendererFactory (gint id);
+Renderer *rendererFactory (guint id);
class TangoBlock:public Renderer {
public:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]