32
32
#include "tile-swap.h"
35
static gint tile_manager_get_tile_num (TileManager *tm,
36
tile_manager_get_tile_num (TileManager *tm,
40
if ((xpixel < 0) || (xpixel >= tm->width) ||
41
(ypixel < 0) || (ypixel >= tm->height))
44
return (ypixel / TILE_HEIGHT) * tm->ntile_cols + (xpixel / TILE_WIDTH);
41
tile_manager_new (gint toplevel_width,
49
tile_manager_new (gint width,
49
g_return_val_if_fail (toplevel_width > 0, NULL);
50
g_return_val_if_fail (toplevel_height > 0, NULL);
51
g_return_val_if_fail (bpp > 0, NULL);
55
g_return_val_if_fail (width > 0 && height > 0, NULL);
56
g_return_val_if_fail (bpp > 0 && bpp <= 4, NULL);
53
58
tm = g_new0 (TileManager, 1);
55
width = toplevel_width;
56
height = toplevel_height;
64
tm->ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
65
tm->ntile_cols = (width + TILE_WIDTH - 1) / TILE_WIDTH;
67
tm->validate_proc = NULL;
70
tm->cached_tile = NULL;
64
tm->ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
65
tm->ntile_cols = (width + TILE_WIDTH - 1) / TILE_WIDTH;
121
109
tile_manager_set_validate_proc (TileManager *tm,
122
TileValidateProc proc)
110
TileValidateProc proc)
124
112
g_return_if_fail (tm != NULL);
126
114
tm->validate_proc = proc;
131
118
tile_manager_get_tile (TileManager *tm,
139
124
g_return_val_if_fail (tm != NULL, NULL);
141
tile_num = tile_manager_get_tile_num (tm, xpixel, ypixel);
145
return tile_manager_get (tm, tile_num, wantread, wantwrite);
126
return tile_manager_get (tm,
127
tile_manager_get_tile_num (tm, xpixel, ypixel),
128
wantread, wantwrite);
149
132
tile_manager_get (TileManager *tm,
178
161
bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
180
163
for (i = 0, k = 0; i < nrows; i++)
182
for (j = 0; j < ncols; j++, k++)
184
tiles[k] = g_new (Tile, 1);
185
tile_init (tiles[k], tm->bpp);
186
tile_attach (tiles[k], tm, k);
188
if (j == (ncols - 1))
189
tiles[k]->ewidth = right_tile;
191
if (i == (nrows - 1))
192
tiles[k]->eheight = bottom_tile;
165
for (j = 0; j < ncols; j++, k++)
167
Tile *new = g_new (Tile, 1);
169
tile_init (new, tm->bpp);
170
tile_attach (new, tm, k);
172
if (j == (ncols - 1))
173
new->ewidth = right_tile;
175
if (i == (nrows - 1))
176
new->eheight = bottom_tile;
178
new->size = new->ewidth * new->eheight * new->bpp;
197
185
tile_ptr = &tm->tiles[tile_num];
199
if (wantwrite && !wantread)
201
g_warning ("WRITE-ONLY TILE... UNTESTED!");
187
if (G_UNLIKELY (wantwrite && !wantread))
188
g_warning ("WRITE-ONLY TILE... UNTESTED!");
204
190
#ifdef DEBUG_TILE_MANAGER
205
if ((*tile_ptr)->share_count && (*tile_ptr)->write_count)
191
if (G_UNLIKELY ((*tile_ptr)->share_count && (*tile_ptr)->write_count))
206
192
g_printerr (">> MEEPITY %d,%d <<\n",
207
193
(*tile_ptr)->share_count, (*tile_ptr)->write_count);
212
TILE_MUTEX_LOCK (*tile_ptr);
215
if ((*tile_ptr)->share_count > 1)
217
/* Copy-on-write required */
218
Tile *newtile = g_new (Tile, 1);
221
tile_init (newtile, (*tile_ptr)->bpp);
223
newtile->ewidth = (*tile_ptr)->ewidth;
224
newtile->eheight = (*tile_ptr)->eheight;
225
newtile->valid = (*tile_ptr)->valid;
227
newsize = tile_size_inline (newtile);
228
newtile->data = g_new (guchar, newsize);
231
g_warning ("Oh boy, r/w tile is invalid... we suck. "
200
if ((*tile_ptr)->share_count > 1)
202
/* Copy-on-write required */
203
Tile *new = g_new (Tile, 1);
205
tile_init (new, (*tile_ptr)->bpp);
207
new->ewidth = (*tile_ptr)->ewidth;
208
new->eheight = (*tile_ptr)->eheight;
209
new->valid = (*tile_ptr)->valid;
211
new->size = new->ewidth * new->eheight * new->bpp;
212
new->data = g_new (guchar, new->size);
234
214
if ((*tile_ptr)->rowhint)
235
newtile->rowhint = g_memdup ((*tile_ptr)->rowhint,
215
new->rowhint = g_memdup ((*tile_ptr)->rowhint,
237
217
sizeof (TileRowHint));
239
if ((*tile_ptr)->data)
241
memcpy (newtile->data, (*tile_ptr)->data, newsize);
245
tile_lock (*tile_ptr);
246
memcpy (newtile->data, (*tile_ptr)->data, newsize);
247
tile_release (*tile_ptr, FALSE);
250
tile_detach (*tile_ptr, tm, tile_num);
251
TILE_MUTEX_LOCK (newtile);
252
tile_attach (newtile, tm, tile_num);
256
(*tile_ptr)->write_count++;
257
(*tile_ptr)->dirty = TRUE;
219
if ((*tile_ptr)->data)
221
memcpy (new->data, (*tile_ptr)->data, new->size);
225
tile_lock (*tile_ptr);
226
memcpy (new->data, (*tile_ptr)->data, new->size);
227
tile_release (*tile_ptr, FALSE);
230
tile_detach (*tile_ptr, tm, tile_num);
232
tile_attach (new, tm, tile_num);
236
(*tile_ptr)->write_count++;
237
(*tile_ptr)->dirty = TRUE;
259
239
#ifdef DEBUG_TILE_MANAGER
262
if ((*tile_ptr)->write_count)
263
g_printerr ("STINK! r/o on r/w tile (%d)\n",
242
if (G_UNLIKELY ((*tile_ptr)->write_count))
243
g_printerr ("STINK! r/o on r/w tile (%d)\n",
264
244
(*tile_ptr)->write_count);
268
TILE_MUTEX_UNLOCK (*tile_ptr);
269
248
tile_lock (*tile_ptr);
322
281
col = toplevel_tile->tlink->tile_num % tm->ntile_cols;
323
282
row = toplevel_tile->tlink->tile_num / tm->ntile_cols;
325
x = ((col * TILE_WIDTH + toplevel_tile->ewidth / 2.0) /
326
(gdouble) tm->width);
327
y = ((row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) /
328
(gdouble) tm->height);
284
x = (col * TILE_WIDTH + toplevel_tile->ewidth / 2.0) / (gdouble) tm->width;
285
y = (row * TILE_HEIGHT + toplevel_tile->eheight / 2.0) / (gdouble) tm->height;
332
291
col = x * tm->width / TILE_WIDTH;
333
292
row = y * tm->height / TILE_HEIGHT;
334
294
num = row * tm->ntile_cols + col;
335
296
tile_invalidate (&tm->tiles[num], tm, num);
341
301
tile_invalidate_tile (Tile **tile_ptr,
348
308
g_return_if_fail (tile_ptr != NULL);
349
309
g_return_if_fail (tm != NULL);
351
tile_num = tile_manager_get_tile_num (tm, xpixel, ypixel);
311
num = tile_manager_get_tile_num (tm, xpixel, ypixel);
355
tile_invalidate (tile_ptr, tm, tile_num);
315
tile_invalidate (tile_ptr, tm, num);
360
319
tile_invalidate (Tile **tile_ptr,
364
323
Tile *tile = *tile_ptr;
366
325
g_return_if_fail (tile_ptr != NULL);
367
326
g_return_if_fail (tm != NULL);
369
TILE_MUTEX_LOCK (tile);
374
if (tile->share_count > 1)
331
if (G_UNLIKELY (tile->share_count > 1))
376
333
/* This tile is shared. Replace it with a new, invalid tile. */
377
Tile *newtile = g_new (Tile, 1);
334
Tile *new = g_new (Tile, 1);
379
336
g_print ("invalidating shared tile (executing buggy code!!!)\n");
381
tile_init (newtile, tile->bpp);
382
newtile->ewidth = tile->ewidth;
383
newtile->eheight = tile->eheight;
338
tile_init (new, tile->bpp);
340
new->ewidth = tile->ewidth;
341
new->eheight = tile->eheight;
342
new->size = tile->size;
384
344
tile_detach (tile, tm, tile_num);
385
TILE_MUTEX_LOCK (newtile);
386
tile_attach (newtile, tm, tile_num);
387
tile = *tile_ptr = newtile;
346
tile_attach (new, tm, tile_num);
347
tile = *tile_ptr = new;
390
350
if (tile->listhead)
391
351
tile_cache_flush (tile);
393
353
tile->valid = FALSE;
396
357
g_free (tile->data);
397
358
tile->data = NULL;
399
361
if (tile->swap_offset != -1)
401
363
/* If the tile is on disk, then delete its
404
366
tile_swap_delete (tile);
408
TILE_MUTEX_UNLOCK (tile);
413
371
tile_manager_map_tile (TileManager *tm,
422
378
g_return_if_fail (tm != NULL);
423
379
g_return_if_fail (srctile != NULL);
425
if ((xpixel < 0) || (xpixel >= tm->width) ||
426
(ypixel < 0) || (ypixel >= tm->height))
381
num = tile_manager_get_tile_num (tm, xpixel, ypixel);
383
if (G_UNLIKELY (num < 0))
428
g_warning ("tile_manager_map_tile: tile co-ord out of range.");
385
g_warning ("%s: tile coordinates out of range.", G_GNUC_FUNCTION);
432
tile_row = ypixel / TILE_HEIGHT;
433
tile_col = xpixel / TILE_WIDTH;
434
tile_num = tile_row * tm->ntile_cols + tile_col;
436
tile_manager_map (tm, tile_num, srctile);
389
tile_manager_map (tm, num, srctile);
440
393
tile_manager_map (TileManager *tm,
474
427
bottom_tile = tm->height - ((nrows - 1) * TILE_HEIGHT);
476
429
for (i = 0, k = 0; i < nrows; i++)
478
for (j = 0; j < ncols; j++, k++)
431
for (j = 0; j < ncols; j++, k++)
433
Tile *new = g_new (Tile, 1);
480
435
#ifdef DEBUG_TILE_MANAGER
483
tiles[k] = g_new (Tile, 1);
484
tile_init (tiles[k], tm->bpp);
485
tile_attach (tiles[k], tm, k);
487
if (j == (ncols - 1))
488
tiles[k]->ewidth = right_tile;
490
if (i == (nrows - 1))
491
tiles[k]->eheight = bottom_tile;
438
tile_init (new, tm->bpp);
439
tile_attach (new, tm, k);
441
if (j == (ncols - 1))
442
new->ewidth = right_tile;
444
if (i == (nrows - 1))
445
new->eheight = bottom_tile;
447
new->size = new->ewidth * new->eheight * new->bpp;
496
454
tile_ptr = &tm->tiles[tile_num];
499
457
g_printerr (")");
503
g_warning("tile_manager_map: srctile not validated yet! please report.");
460
if (G_UNLIKELY (! srctile->valid))
461
g_warning("%s: srctile not validated yet! please report", G_GNUC_FUNCTION);
505
TILE_MUTEX_LOCK (*tile_ptr);
506
if ((*tile_ptr)->ewidth != srctile->ewidth ||
507
(*tile_ptr)->eheight != srctile->eheight ||
508
(*tile_ptr)->bpp != srctile->bpp)
463
if (G_UNLIKELY ((*tile_ptr)->ewidth != srctile->ewidth ||
464
(*tile_ptr)->eheight != srctile->eheight ||
465
(*tile_ptr)->bpp != srctile->bpp))
510
g_warning ("tile_manager_map: nonconformant map (%p -> %p)",
467
g_warning ("%s: nonconformant map (%p -> %p)",
468
G_GNUC_FUNCTION, srctile, *tile_ptr);
513
471
tile_detach (*tile_ptr, tm, tile_num);
515
473
#ifdef DEBUG_TILE_MANAGER
516
474
g_printerr (">");
519
TILE_MUTEX_LOCK (srctile);
521
477
#ifdef DEBUG_TILE_MANAGER
522
478
g_printerr (" [src:%p tm:%p tn:%d] ", srctile, tm, tile_num);
713
646
PixelDataHandle *
714
647
request_pixel_data (TileManager *tm,
722
655
PixelDataHandlePrivate *pdh;
723
656
guint tile_num_1, tile_num_2;
726
659
pdh = g_new (PixelDataHandlePrivate, 1);
728
pdh->readable = wantread;
729
pdh->writeable = wantwrite;
734
pdh->public.width = w = (x2-x1)+1;
735
pdh->public.height = h = (y2-y1)+1;
662
pdh->readable = wantread;
663
pdh->writeable = wantwrite;
668
pdh->public.width = w = (x2 - x1) + 1;
669
pdh->public.height = h = (y2 - y1) + 1;
737
671
tile_num_1 = tile_manager_get_tile_num (tm, x1, y1);
738
672
tile_num_2 = tile_manager_get_tile_num (tm, x2, y2);
798
732
for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
799
733
for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
801
t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
802
s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
803
d = buffer + stride * (y - y1) + tm->bpp * (x - x1);
804
rows = tile_eheight (t) - y % TILE_HEIGHT;
805
if (rows > (y2 - y + 1))
808
cols = tile_ewidth (t) - x % TILE_WIDTH;
809
if (cols > (x2 - x + 1))
812
srcstride = tile_ewidth (t) * tile_bpp (t);
816
memcpy (d, s, cols * tm->bpp);
821
tile_release (t, FALSE);
735
t = tile_manager_get_tile (tm, x, y, TRUE, FALSE);
736
s = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
737
d = buffer + stride * (y - y1) + tm->bpp * (x - x1);
739
rows = tile_eheight (t) - y % TILE_HEIGHT;
740
if (rows > (y2 - y + 1))
743
cols = tile_ewidth (t) - x % TILE_WIDTH;
744
if (cols > (x2 - x + 1))
747
srcstride = tile_ewidth (t) * tile_bpp (t);
751
memcpy (d, s, cols * tm->bpp);
756
tile_release (t, FALSE);
826
write_pixel_data (TileManager *tm,
761
write_pixel_data (TileManager *tm,
766
const guchar *buffer,
840
776
for (y = y1; y <= y2; y += TILE_HEIGHT - (y % TILE_HEIGHT))
841
777
for (x = x1; x <= x2; x += TILE_WIDTH - (x % TILE_WIDTH))
843
t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
844
s = buffer + stride * (y - y1) + tm->bpp * (x - x1);
845
d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
846
rows = tile_eheight (t) - y % TILE_HEIGHT;
847
if (rows > (y2 - y + 1))
850
cols = tile_ewidth (t) - x % TILE_WIDTH;
851
if (cols > (x2 - x + 1))
854
dststride = tile_ewidth (t) * tile_bpp (t);
858
memcpy (d, s, cols * tm->bpp);
863
tile_release (t, TRUE);
779
t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
780
s = buffer + stride * (y - y1) + tm->bpp * (x - x1);
781
d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
782
rows = tile_eheight (t) - y % TILE_HEIGHT;
783
if (rows > (y2 - y + 1))
786
cols = tile_ewidth (t) - x % TILE_WIDTH;
787
if (cols > (x2 - x + 1))
790
dststride = tile_ewidth (t) * tile_bpp (t);
794
memcpy (d, s, cols * tm->bpp);
799
tile_release (t, TRUE);
868
804
read_pixel_data_1 (TileManager *tm,
873
809
if (x >= 0 && y >= 0 && x < tm->width && y < tm->height)
886
822
if (tm->cached_tile)
888
guchar *data = tile_data_pointer (tm->cached_tile,
889
x % TILE_WIDTH, y % TILE_HEIGHT);
824
const guchar *src = tile_data_pointer (tm->cached_tile,
893
*(guint32*)buffer = *(guint32*)data;
898
for (i = 0; i < tm->bpp; i++)
908
write_pixel_data_1 (TileManager *tm,
844
write_pixel_data_1 (TileManager *tm,
847
const guchar *buffer)
916
t = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
917
d = tile_data_pointer (t, x % TILE_WIDTH, y % TILE_HEIGHT);
918
memcpy (d, buffer, tm->bpp);
919
tile_release (t, TRUE);
849
Tile *tile = tile_manager_get_tile (tm, x, y, TRUE, TRUE);
850
guchar *dest = tile_data_pointer (tile, x % TILE_WIDTH, y % TILE_HEIGHT);
864
tile_release (tile, TRUE);