[gnome-games] gnometris: solve most of the memory management issues



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]