GimpTileBackendTileManager: make it work

remove dead code, simplify existing code and make full width tiles be 0-copy.
This commit is contained in:
Øyvind Kolås 2012-03-13 03:17:33 +00:00
parent 49a1fb5b9c
commit 5362448044
1 changed files with 62 additions and 221 deletions

View File

@ -39,31 +39,13 @@
struct _GimpTileBackendTileManagerPrivate struct _GimpTileBackendTileManagerPrivate
{ {
GHashTable *entries;
TileManager *tile_manager; TileManager *tile_manager;
}; };
typedef struct _RamEntry RamEntry;
struct _RamEntry
{
gint x;
gint y;
gint z;
guchar *offset;
};
static void gimp_tile_backend_tile_manager_finalize (GObject *object); static void gimp_tile_backend_tile_manager_finalize (GObject *object);
static void gimp_tile_backend_tile_manager_set_property (GObject *object, static void gimp_tile_backend_tile_manager_dispose (GObject *object);
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_tile_backend_tile_manager_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gpointer gimp_tile_backend_tile_manager_command (GeglTileSource *tile_store, static gpointer gimp_tile_backend_tile_manager_command (GeglTileSource *tile_store,
GeglTileCommand command, GeglTileCommand command,
gint x, gint x,
@ -71,21 +53,11 @@ static gpointer gimp_tile_backend_tile_manager_command (GeglTileSource *ti
gint z, gint z,
gpointer data); gpointer data);
static void dbg_alloc (int size); static void gimp_tile_write (GimpTileBackendTileManager *ram,
static void dbg_dealloc (int size);
static RamEntry * lookup_entry (GimpTileBackendTileManager *self,
gint x, gint x,
gint y, gint y,
gint z); gint z,
static guint hash_func (gconstpointer key);
static gboolean equal_func (gconstpointer a,
gconstpointer b);
static void ram_entry_write (GimpTileBackendTileManager *ram,
RamEntry *entry,
guchar *source); guchar *source);
static RamEntry * ram_entry_new (GimpTileBackendTileManager *ram);
static void ram_entry_destroy (RamEntry *entry,
GimpTileBackendTileManager *ram);
G_DEFINE_TYPE (GimpTileBackendTileManager, gimp_tile_backend_tile_manager, G_DEFINE_TYPE (GimpTileBackendTileManager, gimp_tile_backend_tile_manager,
@ -100,8 +72,7 @@ gimp_tile_backend_tile_manager_class_init (GimpTileBackendTileManagerClass *klas
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gimp_tile_backend_tile_manager_finalize; object_class->finalize = gimp_tile_backend_tile_manager_finalize;
object_class->get_property = gimp_tile_backend_tile_manager_get_property; object_class->dispose = gimp_tile_backend_tile_manager_dispose;
object_class->set_property = gimp_tile_backend_tile_manager_set_property;
g_type_class_add_private (klass, sizeof (GimpTileBackendTileManagerPrivate)); g_type_class_add_private (klass, sizeof (GimpTileBackendTileManagerPrivate));
} }
@ -115,46 +86,32 @@ gimp_tile_backend_tile_manager_init (GimpTileBackendTileManager *backend)
GIMP_TYPE_TILE_BACKEND_TILE_MANAGER, GIMP_TYPE_TILE_BACKEND_TILE_MANAGER,
GimpTileBackendTileManagerPrivate); GimpTileBackendTileManagerPrivate);
source->command = gimp_tile_backend_tile_manager_command; source->command = gimp_tile_backend_tile_manager_command;
}
backend->priv->entries = g_hash_table_new (hash_func, equal_func); static void
gimp_tile_backend_tile_manager_dispose (GObject *object)
{
GimpTileBackendTileManager *backend = GIMP_TILE_BACKEND_TILE_MANAGER (object);
g_warning ("gimp tile backend is dying!!!!!! %p\n", backend);
if (backend->priv->tile_manager)
{
tile_manager_unref (backend->priv->tile_manager);
backend->priv->tile_manager = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
} }
static void static void
gimp_tile_backend_tile_manager_finalize (GObject *object) gimp_tile_backend_tile_manager_finalize (GObject *object)
{ {
GimpTileBackendTileManager *backend = GIMP_TILE_BACKEND_TILE_MANAGER (object); GimpTileBackendTileManager *backend = GIMP_TILE_BACKEND_TILE_MANAGER (object);
g_warning ("gimp tile backend is dying!!!!!! %p\n", backend);
g_hash_table_unref (backend->priv->entries);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void static void tile_done (Tile *tile, void *data)
gimp_tile_backend_tile_manager_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{ {
switch (property_id) tile_release (data, FALSE);
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_tile_backend_tile_manager_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
} }
static gpointer static gpointer
@ -184,14 +141,24 @@ gimp_tile_backend_tile_manager_command (GeglTileSource *tile_store,
gimp_tile = tile_manager_get_at (backend_tm->priv->tile_manager, gimp_tile = tile_manager_get_at (backend_tm->priv->tile_manager,
x, y, TRUE, FALSE); x, y, TRUE, FALSE);
if (!gimp_tile)
return NULL;
g_return_val_if_fail (gimp_tile != NULL, NULL); g_return_val_if_fail (gimp_tile != NULL, NULL);
tile_size = gegl_tile_backend_get_tile_size (backend); tile_size = gegl_tile_backend_get_tile_size (backend);
tile_stride = TILE_WIDTH * tile_bpp (gimp_tile); tile_stride = TILE_WIDTH * tile_bpp (gimp_tile);
gimp_tile_stride = tile_ewidth (gimp_tile) * tile_bpp (gimp_tile); gimp_tile_stride = tile_ewidth (gimp_tile) * tile_bpp (gimp_tile);
/* XXX: Point to Tile data directly instead of using memcpy */ if (tile_stride == gimp_tile_stride)
{
/* use the GimpTile directly as GEGL tile */
tile = gegl_tile_new_bare ();
gegl_tile_set_data_full (tile, tile_data_pointer (gimp_tile, 0, 0),
tile_size, tile_done, gimp_tile);
}
else
{
/* create a copy of the tile */
tile = gegl_tile_new (tile_size); tile = gegl_tile_new (tile_size);
for (row = 0; row < tile_eheight (gimp_tile); row++) for (row = 0; row < tile_eheight (gimp_tile); row++)
{ {
@ -199,6 +166,8 @@ gimp_tile_backend_tile_manager_command (GeglTileSource *tile_store,
tile_data_pointer (gimp_tile, 0, row), tile_data_pointer (gimp_tile, 0, row),
gimp_tile_stride); gimp_tile_stride);
} }
tile_release (gimp_tile, FALSE);
}
return tile; return tile;
} }
@ -206,169 +175,49 @@ gimp_tile_backend_tile_manager_command (GeglTileSource *tile_store,
case GEGL_TILE_SET: case GEGL_TILE_SET:
{ {
GeglTile *tile = data; GeglTile *tile = data;
RamEntry *entry = lookup_entry (backend_tm, x, y, z); gimp_tile_write (backend_tm, x, y, z, gegl_tile_get_data (tile));
if (! entry)
{
entry = ram_entry_new (backend_tm);
entry->x = x;
entry->y = y;
entry->z = z;
g_hash_table_insert (backend_tm->priv->entries, entry, entry);
}
ram_entry_write (backend_tm, entry, gegl_tile_get_data (tile));
gegl_tile_mark_as_stored (tile); gegl_tile_mark_as_stored (tile);
return NULL; return NULL;
} }
case GEGL_TILE_IDLE: case GEGL_TILE_IDLE:
return NULL;
case GEGL_TILE_VOID: case GEGL_TILE_VOID:
{
RamEntry *entry = lookup_entry (backend_tm, x, y, z);
if (entry)
ram_entry_destroy (entry, backend_tm);
return NULL;
}
case GEGL_TILE_EXIST: case GEGL_TILE_EXIST:
{ return NULL;
RamEntry *entry = lookup_entry (backend_tm, x, y, z);
return GINT_TO_POINTER (entry != NULL);
}
default: default:
g_assert (command < GEGL_TILE_LAST_COMMAND && command >= 0); g_assert (command < GEGL_TILE_LAST_COMMAND && command >= 0);
} }
return NULL; return NULL;
} }
static gint allocs = 0;
static gint ram_size = 0;
static gint peak_allocs = 0;
static gint peak_tile_manager_size = 0;
static void static void
dbg_alloc (gint size) gimp_tile_write (GimpTileBackendTileManager *backend_tm,
{
allocs++;
ram_size += size;
if (allocs > peak_allocs)
peak_allocs = allocs;
if (ram_size > peak_tile_manager_size)
peak_tile_manager_size = ram_size;
}
static void
dbg_dealloc (gint size)
{
allocs--;
ram_size -= size;
}
static RamEntry *
lookup_entry (GimpTileBackendTileManager *self,
gint x, gint x,
gint y, gint y,
gint z) gint z,
{
RamEntry key;
key.x = x;
key.y = y;
key.z = z;
key.offset = 0;
return g_hash_table_lookup (self->priv->entries, &key);
}
static guint
hash_func (gconstpointer key)
{
const RamEntry *e = key;
guint hash;
gint srcA = e->x;
gint srcB = e->y;
gint srcC = e->z;
gint i;
/* interleave the 10 least significant bits of all coordinates,
* this gives us Z-order / morton order of the space and should
* work well as a hash
*/
hash = 0;
#define ADD_BIT(bit) do { hash |= (((bit) != 0) ? 1 : 0); hash <<= 1; \
} \
while (0)
for (i = 9; i >= 0; i--)
{
ADD_BIT (srcA & (1 << i));
ADD_BIT (srcB & (1 << i));
ADD_BIT (srcC & (1 << i));
}
#undef ADD_BIT
return hash;
}
static gboolean
equal_func (gconstpointer a,
gconstpointer b)
{
const RamEntry *ea = a;
const RamEntry *eb = b;
if (ea->x == eb->x &&
ea->y == eb->y &&
ea->z == eb->z)
return TRUE;
return FALSE;
}
static void
ram_entry_write (GimpTileBackendTileManager *ram,
RamEntry *entry,
guchar *source) guchar *source)
{ {
g_printerr ("WRITE %i %i %i\n", entry->x, entry->y, entry->z); Tile *gimp_tile;
//memcpy (entry->offset, source, tile_size); gint tile_stride;
} gint gimp_tile_stride;
int row;
static RamEntry * gimp_tile = tile_manager_get_at (backend_tm->priv->tile_manager,
ram_entry_new (GimpTileBackendTileManager *ram) x, y, TRUE, TRUE);
{
gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (ram));
RamEntry *self = g_slice_new (RamEntry);
self->offset = g_malloc (tile_size); if (!gimp_tile)
dbg_alloc (tile_size); return;
return self; tile_stride = TILE_WIDTH * tile_bpp (gimp_tile);
} gimp_tile_stride = tile_ewidth (gimp_tile) * tile_bpp (gimp_tile);
static void for (row = 0; row < tile_eheight (gimp_tile); row++)
ram_entry_destroy (RamEntry *entry, {
GimpTileBackendTileManager *ram) memcpy (tile_data_pointer (gimp_tile, 0, row),
{ source + row * tile_stride,
gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (ram)); gimp_tile_stride);
g_free (entry->offset); }
g_hash_table_remove (ram->priv->entries, entry); tile_release (gimp_tile, FALSE);
dbg_dealloc (tile_size);
g_slice_free (RamEntry, entry);
} }
GeglTileBackend * GeglTileBackend *
@ -392,11 +241,3 @@ gimp_tile_backend_tile_manager_new (TileManager *tm)
return ret; return ret;
} }
void
gimp_tile_backend_tile_manager_stats (void)
{
g_warning ("leaked: %i chunks (%f mb) peak: %i (%i bytes %fmb))",
allocs, ram_size / 1024 / 1024.0, peak_allocs,
peak_tile_manager_size, peak_tile_manager_size / 1024 / 1024.0);
}