Commit 9ccef4a6 authored by scott's avatar scott

Tile overhaul. Mostly minor changes, except for tile*.*, which are

barely recognizable.
parent 1f1c9e16
Thu Jul 9 21:23:46 1998 Scott Goehring <scott@poverty.bloomington.in.us>
* tile.c tile_manager.c tile_cache.c tile.h tile_manager.h
tile_manager_pvt.h tile_pvt.h:
completely redid tile management.
* blend.c boundary.c by_color_select.c channel.c color_picker.c
drawable_cmds.c frac.c fuzzy_select.c gimpimage.c image_render.c
ink.c layer.c paint_core.c paint_funcs.c pixel_region.c
plug_in.c preferences_dialog.c procedural_db.c transform_core.c
undo.c xcf.c:
changed to reflect new tile management protocols. (Also killed
a few compilation warnings.)
Thu Jul 9 22:04:04 EDT 1998 Michael K. Johnson <johnsonm@redhat.com>
* app/clone.c: clone_motion: silently ignore cloning if the
......
......@@ -1353,7 +1353,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
return;
}
tile = tile_manager_get (tm, tile_info->tile_num, 0);
tile = tile_manager_get (tm, tile_info->tile_num, 0, TRUE, TRUE);
if (!tile)
{
g_message ("plug-in requested invalid tile (killing)\n");
......@@ -1361,14 +1361,12 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
return;
}
tile_ref2 (tile, TRUE);
if (tile_data.use_shm)
memcpy (tile->data, shm_addr, tile_size (tile));
else
memcpy (tile->data, tile_info->data, tile_size (tile));
tile_unref (tile, TRUE);
tile_release (tile, TRUE);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
......@@ -1392,7 +1390,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
return;
}
tile = tile_manager_get (tm, tile_req->tile_num, 0);
tile = tile_manager_get (tm, tile_req->tile_num, 0, TRUE, FALSE);
if (!tile)
{
g_message ("plug-in requested invalid tile (killing)\n");
......@@ -1408,8 +1406,6 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
tile_data.height = tile->eheight;
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_ref2 (tile, FALSE);
if (tile_data.use_shm)
memcpy (shm_addr, tile->data, tile_size (tile));
else
......@@ -1422,7 +1418,7 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
return;
}
tile_unref (tile, FALSE);
tile_release (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
{
......
......@@ -124,9 +124,8 @@ find_empty_segs (PixelRegion *maskPR,
if ((x / TILE_WIDTH) != tilex)
{
if (tile)
tile_unref (tile, FALSE);
tile = tile_manager_get_tile (maskPR->tiles, x, scanline, 0);
tile_ref2 (tile, FALSE);
tile_release (tile, FALSE);
tile = tile_manager_get_tile (maskPR->tiles, x, scanline, 0, TRUE, FALSE);
data = tile->data + tile->bpp *
((scanline % TILE_HEIGHT) * tile->ewidth + (x % TILE_WIDTH)) + (tile->bpp - 1);
tilex = x / TILE_WIDTH;
......@@ -153,7 +152,7 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = G_MAXINT;
if (tile)
tile_unref (tile, FALSE);
tile_release (tile, FALSE);
}
......
......@@ -124,8 +124,7 @@ pixel_region_get_row (PR, x, y, w, data, subsample)
while (x < end)
{
tile = tile_manager_get_tile (PR->tiles, x, y, 0);
tile_ref2 (tile, FALSE);
tile = tile_manager_get_tile (PR->tiles, x, y, 0, TRUE, FALSE);
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
boundary = x + (tile->ewidth - (x % TILE_WIDTH));
inc = subsample * tile->bpp;
......@@ -137,7 +136,7 @@ pixel_region_get_row (PR, x, y, w, data, subsample)
tile_data += inc;
}
tile_unref (tile, FALSE);
tile_release (tile, FALSE);
}
}
......@@ -159,8 +158,7 @@ pixel_region_set_row (PR, x, y, w, data)
while (x < end)
{
tile = tile_manager_get_tile (PR->tiles, x, y, 0);
tile_ref2 (tile, TRUE);
tile = tile_manager_get_tile (PR->tiles, x, y, 0, TRUE, TRUE);
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
boundary = x + (tile->ewidth - (x % TILE_WIDTH));
......@@ -170,7 +168,7 @@ pixel_region_set_row (PR, x, y, w, data)
*tile_data++ = *data++;
}
tile_unref (tile, TRUE);
tile_release (tile, TRUE);
}
}
......@@ -194,8 +192,7 @@ pixel_region_get_col (PR, x, y, h, data, subsample)
while (y < end)
{
tile = tile_manager_get_tile (PR->tiles, x, y, 0);
tile_ref2 (tile, FALSE);
tile = tile_manager_get_tile (PR->tiles, x, y, 0, TRUE, FALSE);
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
boundary = y + (tile->eheight - (y % TILE_HEIGHT));
inc = subsample * tile->bpp * tile->ewidth;
......@@ -207,7 +204,7 @@ pixel_region_get_col (PR, x, y, h, data, subsample)
tile_data += inc;
}
tile_unref (tile, FALSE);
tile_release (tile, FALSE);
}
}
......@@ -230,8 +227,7 @@ pixel_region_set_col (PR, x, y, h, data)
while (y < end)
{
tile = tile_manager_get_tile (PR->tiles, x, y, 0);
tile_ref2 (tile, TRUE);
tile = tile_manager_get_tile (PR->tiles, x, y, 0, TRUE, TRUE);
tile_data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
boundary = y + (tile->eheight - (y % TILE_HEIGHT));
inc = tile->bpp * tile->ewidth;
......@@ -243,7 +239,7 @@ pixel_region_set_col (PR, x, y, h, data)
tile_data += inc;
}
tile_unref (tile, TRUE);
tile_release (tile, TRUE);
}
}
......@@ -329,8 +325,8 @@ pixel_regions_process (PRI_ptr)
/* Unref the last referenced tile if the underlying region is a tile manager */
if (PRH->PR->tiles)
{
Tile *tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0);
tile_unref (tile, PRH->PR->dirty);
Tile *tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0, FALSE, FALSE);
tile_release (tile, PRH->PR->dirty);
}
PRH->PR->x += PRI->portion_width;
......@@ -376,8 +372,8 @@ pixel_regions_process_stop (PRI_ptr)
/* Unref the last referenced tile if the underlying region is a tile manager */
if (PRH->PR->tiles)
{
Tile *tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0);
tile_unref (tile, PRH->PR->dirty);
Tile *tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0, FALSE, FALSE);
tile_release (tile, PRH->PR->dirty);
}
}
......@@ -550,8 +546,7 @@ pixel_region_configure (PRH, PRI)
Tile *tile;
int offx, offy;
tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0);
tile_ref2 (tile, PRH->PR->dirty);
tile = tile_manager_get_tile (PRH->PR->tiles, PRH->PR->x, PRH->PR->y, 0, TRUE, PRH->PR->dirty);
offx = PRH->PR->x % TILE_WIDTH;
offy = PRH->PR->y % TILE_HEIGHT;
......
......@@ -46,8 +46,12 @@ static pthread_t preswap_thread;
static pthread_mutex_t dirty_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t dirty_signal = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t tile_mutex = PTHREAD_MUTEX_INITIALIZER;
#define CACHE_LOCK pthread_mutex_lock(&tile_mutex)
#define CACHE_UNLOCK pthread_mutex_unlock(&tile_mutex)
#else
static gint idle_swapper = 0;
#define CACHE_LOCK /*nothing*/
#define CACHE_UNLOCK /*nothing*/
#endif
......@@ -60,9 +64,7 @@ tile_cache_insert (Tile *tile)
if (initialize)
tile_cache_init ();
#if USE_PTHREADS
pthread_mutex_lock(&tile_mutex);
#endif
CACHE_LOCK;
if (tile->data == NULL) goto out;
/* First check and see if the tile is already
......@@ -100,6 +102,7 @@ tile_cache_insert (Tile *tile)
* if there is room in the cache. If not then we'll have
* to make room first. Note: it might be the case that the
* cache is smaller than the size of a tile in which case
* it won't be possible to put it in the cache.
*/
while ((cur_cache_size + max_tile_size) > max_cache_size)
......@@ -111,24 +114,6 @@ tile_cache_insert (Tile *tile)
* is referencing.
*/
cur_cache_size += tile_size (tile);
/* Reference the tile so that it won't be swapped out
* to disk. Swap the tile in if necessary.
* "tile_ref" cannot be used here since it calls this
* function.
*/
tile->ref_count += 1;
{
extern int tile_ref_count;
tile_ref_count += 1;
}
if (tile->ref_count == 1)
{
tile_swap_in (tile);
/* the tile must be clean */
tile->dirty = FALSE;
}
}
/* Put the tile at the end of the proper list */
......@@ -151,9 +136,7 @@ tile_cache_insert (Tile *tile)
#endif
}
out:
#ifdef USE_PTHREADS
pthread_mutex_unlock(&tile_mutex);
#endif
CACHE_UNLOCK;
}
......@@ -163,15 +146,9 @@ tile_cache_flush (Tile *tile)
if (initialize)
tile_cache_init ();
#ifdef USE_PTHREADS
pthread_mutex_lock(&tile_mutex);
#endif
CACHE_LOCK;
tile_cache_flush_internal (tile);
#ifdef USE_PTHREADS
pthread_mutex_unlock(&tile_mutex);
#endif
CACHE_UNLOCK;
}
static void
......@@ -203,34 +180,6 @@ tile_cache_flush_internal (Tile *tile)
list->first = tile->next;
tile->listhead = NULL;
/* Unreference the tile.
*/
{
extern int tile_ref_count;
tile_ref_count -= 1;
}
/* Decrement the reference count.
*/
tile->ref_count -= 1;
/* If this was the last reference to the tile, then
* swap it out to disk.
*/
if (tile->ref_count == 0)
{
/* Only need to swap out in two cases:
* 1) The tile is dirty
* 2) The tile has never been swapped
*/
if (tile->dirty || tile->swap_offset == -1)
tile_swap_out (tile);
/* Otherwise, just throw out the data--the same stuff is in swap
*/
g_free (tile->data);
tile->data = NULL;
}
}
}
......@@ -241,17 +190,12 @@ tile_cache_set_size (unsigned long cache_size)
tile_cache_init ();
max_cache_size = cache_size;
#if USE_PTHREADS
pthread_mutex_lock(&tile_mutex);
#endif
CACHE_LOCK;
while (cache_size >= max_cache_size)
{
if (!tile_cache_zorch_next ()) break;
}
#if USE_PTHREADS
pthread_mutex_unlock(&tile_mutex);
#endif
CACHE_UNLOCK;
}
......@@ -286,15 +230,11 @@ tile_cache_zorch_next ()
else if (dirty_list.first) tile = dirty_list.first;
else return FALSE;
#ifdef USE_PTHREADS
pthread_mutex_unlock(&tile_mutex);
pthread_mutex_lock(&(tile->mutex));
pthread_mutex_lock(&tile_mutex);
#endif
CACHE_UNLOCK;
TILE_MUTEX_LOCK (tile);
CACHE_LOCK;
tile_cache_flush_internal (tile);
#ifdef USE_PTHREADS
pthread_mutex_unlock(&(tile->mutex));
#endif
TILE_MUTEX_UNLOCK (tile);
return TRUE;
}
......@@ -315,10 +255,10 @@ tile_idle_thread (void *data)
pthread_cond_wait(&dirty_signal,&dirty_mutex);
pthread_mutex_unlock(&dirty_mutex);
}
if ((tile = dirty_list.first) &&
(pthread_mutex_lock(&(tile->mutex)) == 0))
if ((tile = dirty_list.first))
{
pthread_mutex_lock(&tile_mutex);
TILE_MUTEX_LOCK (tile);
CACHE_LOCK;
list = tile->listhead;
......@@ -342,9 +282,10 @@ tile_idle_thread (void *data)
else clean_list.first = tile;
clean_list.last = tile;
pthread_mutex_unlock(&tile_mutex);
CACHE_UNLOCK;
tile_swap_out(tile);
pthread_mutex_unlock(&(tile->mutex));
TILE_MUTEX_UNLOCK (tile);
}
}
}
......@@ -377,3 +318,4 @@ tile_idle_preswap (gpointer data)
return TRUE;
}
#endif
......@@ -29,7 +29,7 @@ struct _TileLevel
int ntile_rows; /* the number of tiles in each row */
int ntile_cols; /* the number of tiles in each columns */
Tile *tiles; /* the tiles for this level */
Tile **tiles; /* the tiles for this level */
};
struct _TileManager
......
......@@ -23,7 +23,9 @@
#include "tile_manager_pvt.h"
#include "tile_pvt.h" /* ick. */
static void tile_manager_destroy_level (TileLevel *level);
static void tile_manager_destroy_level (TileManager *tm,
TileLevel *level);
static void tile_invalidate (Tile **tile_ptr, TileManager *tm, int tile_num);
TileManager*
......@@ -71,7 +73,7 @@ tile_manager_destroy (TileManager *tm)
int i;
for (i = 0; i < tm->nlevels; i++)
tile_manager_destroy_level (&tm->levels[i]);
tile_manager_destroy_level (tm, &tm->levels[i]);
g_free (tm->levels);
g_free (tm);
......@@ -138,7 +140,7 @@ tile_manager_set_nlevels (TileManager *tm,
levels[i] = tm->levels[i];
for (; i < tm->nlevels; i++)
tile_manager_destroy_level (&tm->levels[i]);
tile_manager_destroy_level (tm, &tm->levels[i]);
}
g_free (tm->levels);
......@@ -158,7 +160,9 @@ Tile*
tile_manager_get_tile (TileManager *tm,
int xpixel,
int ypixel,
int level)
int level,
int wantread,
int wantwrite)
{
TileLevel *tile_level;
int tile_row;
......@@ -177,16 +181,19 @@ tile_manager_get_tile (TileManager *tm,
tile_col = xpixel / TILE_WIDTH;
tile_num = tile_row * tile_level->ntile_cols + tile_col;
return tile_manager_get (tm, tile_num, level);
return tile_manager_get (tm, tile_num, level, wantread, wantwrite);
}
Tile*
tile_manager_get (TileManager *tm,
int tile_num,
int level)
int level,
int wantread,
int wantwrite)
{
TileLevel *tile_level;
Tile *tiles;
Tile **tiles;
Tile **tile_ptr;
int ntiles;
int nrows, ncols;
int right_tile;
......@@ -204,7 +211,7 @@ tile_manager_get (TileManager *tm,
if (!tile_level->tiles)
{
tile_level->tiles = g_new (Tile, ntiles);
tile_level->tiles = g_new (Tile*, ntiles);
tiles = tile_level->tiles;
nrows = tile_level->ntile_rows;
......@@ -217,20 +224,53 @@ tile_manager_get (TileManager *tm,
{
for (j = 0; j < ncols; j++, k++)
{
tile_init (&tiles[k], tile_level->bpp);
tiles[k].tile_num = k;
tiles[k].tm = tm;
tiles[k] = g_new (Tile, 1);
tile_init (tiles[k], tile_level->bpp);
tile_attach (tiles[k], tm, k);
if (j == (ncols - 1))
tiles[k].ewidth = right_tile;
tiles[k]->ewidth = right_tile;
if (i == (nrows - 1))
tiles[k].eheight = bottom_tile;
tiles[k]->eheight = bottom_tile;
}
}
}
return &tile_level->tiles[tile_num];
tile_ptr = &tile_level->tiles[tile_num];
if (wantread)
{
TILE_MUTEX_LOCK (*tile_ptr);
if (wantwrite)
{
if ((*tile_ptr)->share_count > 1)
{
/* Copy-on-write required */
Tile *newtile = g_new (Tile, 1);
tile_init (newtile, (*tile_ptr)->bpp);
newtile->ewidth = (*tile_ptr)->ewidth;
newtile->eheight = (*tile_ptr)->eheight;
newtile->valid = (*tile_ptr)->valid;
if ((*tile_ptr)->data != NULL)
{
newtile->data = g_new (guchar, tile_size (newtile));
memcpy (newtile->data, (*tile_ptr)->data, tile_size (newtile));
}
tile_detach (*tile_ptr, tm, tile_num);
TILE_MUTEX_LOCK (newtile);
tile_attach (newtile, tm, tile_num);
*tile_ptr = newtile;
}
(*tile_ptr)->write_count++;
(*tile_ptr)->dirty = 1;
}
TILE_MUTEX_UNLOCK (*tile_ptr);
tile_lock (*tile_ptr);
}
return *tile_ptr;
}
void
......@@ -253,8 +293,8 @@ tile_manager_invalidate_tiles (TileManager *tm,
int num;
int i;
col = toplevel_tile->tile_num % tm->levels[0].ntile_cols;
row = toplevel_tile->tile_num / tm->levels[0].ntile_cols;
col = toplevel_tile->tlink->tile_num % tm->levels[0].ntile_cols;
row = toplevel_tile->tlink->tile_num / tm->levels[0].ntile_cols;
x = (col * TILE_WIDTH + toplevel_tile->ewidth / 2.0) / (double) tm->levels[0].width;
y = (row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) / (double) tm->levels[0].height;
......@@ -267,7 +307,7 @@ tile_manager_invalidate_tiles (TileManager *tm,
col = x * level->width / TILE_WIDTH;
row = y * level->height / TILE_HEIGHT;
num = row * level->ntile_cols + col;
tile_invalidate (&level->tiles[num]);
tile_invalidate (&level->tiles[num], tm, num);
}
}
}
......@@ -284,7 +324,7 @@ tile_manager_invalidate_sublevels (TileManager *tm)
{
ntiles = tm->levels[i].ntile_rows * tm->levels[i].ntile_cols;
for (j = 0; j < ntiles; j++)
tile_invalidate (&tm->levels[i].tiles[j]);
tile_invalidate (&tm->levels[i].tiles[j], tm, j);
}
}
}
......@@ -309,8 +349,8 @@ tile_manager_update_tile (TileManager *tm,
if ((level < 1) || (level >= tm->nlevels))
return;
col = toplevel_tile->tile_num % tm->levels[0].ntile_cols;
row = toplevel_tile->tile_num / tm->levels[0].ntile_cols;
col = toplevel_tile->tlink->tile_num % tm->levels[0].ntile_cols;
row = toplevel_tile->tlink->tile_num / tm->levels[0].ntile_cols;
x = (col * TILE_WIDTH + toplevel_tile->ewidth / 2.0) / (double) tm->levels[0].width;
y = (row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) / (double) tm->levels[0].height;
......@@ -338,10 +378,9 @@ tile_manager_update_tile (TileManager *tm,
row = (y * tile_level->height) / TILE_HEIGHT;
num = row * tile_level->ntile_cols + col;
tile = tile_manager_get (tm, num, level);
tile = tile_manager_get (tm, num, level, TRUE, TRUE);
tile_ref2 (tile, TRUE);
tile_ref2 (toplevel_tile, FALSE);
tile_lock (toplevel_tile);
tilew += tilex;
tileh += tiley;
......@@ -366,13 +405,13 @@ tile_manager_update_tile (TileManager *tm,
}
}
tile_unref (tile, TRUE);
tile_unref (toplevel_tile, FALSE);
tile_release (tile, TRUE);
tile_release (toplevel_tile, FALSE);
}
static void
tile_manager_destroy_level (TileLevel *level)
tile_manager_destroy_level (TileManager *tm, TileLevel *level)
{
int ntiles;
int i;
......@@ -382,8 +421,146 @@ tile_manager_destroy_level (TileLevel *level)
ntiles = level->ntile_rows * level->ntile_cols;
for (i = 0; i < ntiles; i++)
tile_invalidate (&level->tiles[i]);
{
TILE_MUTEX_LOCK (level->tiles[i]);
tile_detach (level->tiles[i], tm, i);
}
g_free (level->tiles);
}
}
static void
tile_invalidate (Tile **tile_ptr, TileManager *tm, int tile_num)
{
Tile *tile = *tile_ptr;
TILE_MUTEX_LOCK (tile);
if (!tile->valid)
goto leave;
if (tile->share_count > 1)
{
/* This tile is shared. Replace it with a new, invalid tile. */
Tile *newtile = g_new (Tile, 1);
tile_init (newtile, tile->bpp);
newtile->ewidth = tile->ewidth;
newtile->eheight = tile->eheight;
tile_detach (tile, tm, tile_num);
TILE_MUTEX_LOCK (newtile);
tile_attach (newtile, tm, tile_num);
tile = *tile_ptr = newtile;
}
if (tile->listhead)
tile_cache_flush (tile);
tile->valid = FALSE;
if (tile->data)
{
g_free (tile->data);
tile->data = NULL;
}
if (tile->swap_offset != -1)
{
/* If the tile is on disk, then delete its
* presence there.
*/
tile_swap_delete (tile);
}
leave:
TILE_MUTEX_UNLOCK (tile);
}
void
tile_manager_map_tile (TileManager *tm,
int xpixel,
int ypixel,
int level,
Tile *srctile)
{
TileLevel *tile_level;
int tile_row;
int tile_col;
int tile_num;
if ((level < 0) || (level >= tm->nlevels))
return;
tile_level = &tm->levels[level];
if ((xpixel < 0) || (xpixel >= tile_level->width) ||
(ypixel < 0) || (ypixel >= tile_level->height))
return;
tile_row = ypixel / TILE_HEIGHT;
tile_col = xpixel / TILE_WIDTH;
tile_num = tile_row * tile_level->ntile_cols + tile_col;
tile_manager_map (tm, tile_num, level, srctile);
}
void
tile_manager_map (TileManager *tm,
int tile_num,
int level,
Tile *srctile)
{
TileLevel *tile_level;
Tile **tiles;
Tile **tile_ptr;
int ntiles;
int nrows, ncols;
int right_tile;
int bottom_tile;
int i, j, k;
if ((level < 0) || (level >= tm->nlevels))
return;
tile_level = &tm->levels[level];
ntiles = tile_level->ntile_rows * tile_level->ntile_cols;
if ((tile_num < 0) || (tile_num >= ntiles))
return;
if (!tile_level->tiles)
{
tile_level->tiles = g_new (Tile*, ntiles);
tiles = tile_level->tiles;
nrows = tile_level->ntile_rows;
ncols = tile_level->ntile_cols;