home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / tile.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-03  |  6.7 KB  |  373 lines

  1. #include <stdio.h>
  2.  
  3. #include "tile.h"
  4. #include "tile_pvt.h"
  5. #include "tile_cache.h"
  6. #include "tile_manager.h"
  7. #include "tile_swap.h"
  8.  
  9.  
  10. static void tile_destroy (Tile *tile);
  11.  
  12. int tile_count = 0;
  13.  
  14. void
  15. tile_sanitize_rowhints (Tile *tile)
  16. {
  17.   int height, y;
  18.  
  19.   /*  If tile has rowhints array already, do nothing.  */
  20.   if (tile->rowhint)
  21.     return;
  22.  
  23.   height = tile->eheight;
  24.   
  25.   tile->rowhint = g_new (TileRowHint, height);
  26.   
  27.   for (y=0; y<height; y++)
  28.     {
  29.       tile->rowhint[y] = TILEROWHINT_UNKNOWN;
  30.     }
  31. }
  32.  
  33. TileRowHint
  34. tile_get_rowhint (Tile *tile, int yoff)
  35. {
  36. #ifdef HINTS_SANITY
  37.   if (yoff < tile_eheight(tile) && yoff>=0)
  38.     {
  39.       return tile->rowhint[yoff];
  40.     }
  41.   else
  42.     g_error("GET_ROWHINT OUT OF RANGE");
  43.   return TILEROWHINT_OUTOFRANGE;
  44. #else
  45.   return tile->rowhint[yoff];  
  46. #endif
  47. }
  48.  
  49. void
  50. tile_set_rowhint (Tile *tile, int yoff, TileRowHint rowhint)
  51. {
  52. #ifdef HINTS_SANITY
  53.   if (yoff < tile_eheight(tile) && yoff>=0)
  54.     {
  55.       tile->rowhint[yoff] = rowhint;
  56.     }
  57.   else
  58.     g_error("SET_ROWHINT OUT OF RANGE");
  59. #else
  60.   tile->rowhint[yoff] = rowhint;
  61. #endif
  62. }
  63.  
  64. void
  65. tile_init (Tile *tile,
  66.        int   bpp)
  67. {
  68.   tile->ref_count = 0;
  69.   tile->write_count = 0;
  70.   tile->share_count = 0;
  71.   tile->dirty = FALSE;
  72.   tile->valid = FALSE;
  73.   tile->data = NULL;
  74.   tile->ewidth = TILE_WIDTH;
  75.   tile->eheight = TILE_HEIGHT;
  76.   tile->bpp = bpp;
  77.   tile->swap_num = 1;
  78.   tile->swap_offset = -1;
  79.   tile->tlink = NULL;
  80.   tile->next = tile->prev = NULL;
  81.   tile->listhead = NULL;
  82.   tile->rowhint = NULL;
  83.  
  84. #ifdef USE_PTHREADS
  85.   {
  86.     pthread_mutex_init(&tile->mutex, NULL);
  87.   }
  88.   tile_count++;
  89. #endif
  90. }
  91.  
  92. int tile_ref_count = 0;
  93. int tile_share_count = 0;
  94. int tile_active_count = 0;
  95.  
  96. #ifdef HINTS_SANITY
  97. int tile_exist_peak = 0;
  98. int tile_exist_count = 0;
  99. #endif
  100.  
  101. void
  102. tile_lock (Tile *tile)
  103. {
  104.   /* Increment the global reference count.
  105.    */
  106.   tile_ref_count += 1;
  107.  
  108.   /* Increment this tile's reference count.
  109.    */
  110.  
  111.   TILE_MUTEX_LOCK (tile);
  112.   tile->ref_count += 1;
  113.  
  114.   if (tile->ref_count == 1) 
  115.     {
  116.       if (tile->listhead) 
  117.     {
  118.       /* remove from cache, move to main store */
  119.       tile_cache_flush (tile);
  120.     }
  121.       tile_active_count ++;
  122.     }
  123.   if (tile->data == NULL)
  124.     {
  125.       /* There is no data, so the tile must be swapped out */
  126.       tile_swap_in (tile);
  127.     }
  128.  
  129.   TILE_MUTEX_UNLOCK (tile);
  130.  
  131.   /* Call 'tile_manager_validate' if the tile was invalid.
  132.    */
  133.   if (!tile->valid)
  134.     {
  135.       /* an invalid tile should never be shared, so this should work */
  136.       tile_manager_validate ((TileManager*) tile->tlink->tm, tile);
  137.     }
  138.  
  139.  
  140. }
  141.  
  142.  
  143. void
  144. tile_release (Tile *tile, int dirty)
  145. {
  146.   /* Decrement the global reference count.
  147.    */
  148.   tile_ref_count -= 1;
  149.  
  150.   TILE_MUTEX_LOCK(tile);
  151.  
  152.   /* Decrement this tile's reference count.
  153.    */
  154.   tile->ref_count -= 1;
  155.  
  156.   /* Decrement write ref count if dirtying
  157.    */
  158.   if (dirty)
  159.     {
  160.       int y;
  161.  
  162.       tile->write_count -= 1;
  163.  
  164.       if (tile->rowhint)
  165.     {
  166.       for (y = 0; y < tile->eheight; y++)
  167.         {
  168.           tile->rowhint[y] = TILEROWHINT_UNKNOWN;
  169.         }
  170.     }
  171.     }
  172.  
  173.   if (tile->ref_count == 0)
  174.     {
  175.       tile_active_count--;
  176.       if (tile->share_count == 0)
  177.     {
  178.       /* tile is truly dead */
  179.       tile_destroy (tile);
  180.       return;            /* skip terminal unlock */
  181.     }
  182.       else 
  183.     {
  184.       /* last reference was just released, so move the tile to the
  185.          tile cache */
  186.       tile_cache_insert (tile);
  187.     }
  188.     }
  189.  
  190.   TILE_MUTEX_UNLOCK (tile);
  191. }
  192.  
  193. void
  194. tile_alloc (Tile *tile)
  195. {
  196.   if (tile->data)
  197.     return;
  198.  
  199.   /* Allocate the data for the tile.
  200.    */
  201.   tile->data = g_new (guchar, tile_size (tile));
  202.  
  203. #ifdef HINTS_SANITY
  204.   tile_exist_count++;
  205.   if (tile_exist_count > tile_exist_peak)
  206.     tile_exist_peak = tile_exist_count;
  207. #endif
  208. }
  209.  
  210. static void
  211. tile_destroy (Tile *tile)
  212. {
  213.   if (tile->ref_count) 
  214.     {
  215.       g_warning ("tried to destroy a ref'd tile");
  216.       return;
  217.     }
  218.   if (tile->share_count)
  219.     {
  220.       g_warning ("tried to destroy an attached tile");
  221.       return;
  222.     }
  223.   if (tile->data) 
  224.     {
  225.       g_free (tile->data);
  226.       tile->data = NULL;
  227.     }
  228.   if (tile->rowhint) 
  229.     {
  230.       g_free (tile->rowhint);
  231.       tile->rowhint = NULL;
  232.     }
  233.   if (tile->swap_offset != -1)
  234.     {
  235.       /* If the tile is on disk, then delete its
  236.        *  presence there.
  237.        */
  238.       tile_swap_delete (tile);
  239.     }
  240.   if (tile->listhead)
  241.     tile_cache_flush (tile);
  242.   
  243.   TILE_MUTEX_UNLOCK (tile); 
  244.   g_free (tile);
  245.   tile_count --;
  246.  
  247. #ifdef HINTS_SANITY
  248.   tile_exist_count--;
  249. #endif
  250. }
  251.  
  252.  
  253. int
  254. tile_size (Tile *tile)
  255. {
  256.   int size;
  257.   /* Return the actual size of the tile data.
  258.    *  (Based on its effective width and height).
  259.    */
  260.   size = tile->ewidth * tile->eheight * tile->bpp;
  261.   return size;
  262. }
  263.  
  264.  
  265. int
  266. tile_ewidth (Tile *tile)
  267. {
  268.   return tile->ewidth;
  269. }
  270.  
  271.  
  272. int
  273. tile_eheight (Tile *tile)
  274. {
  275.   return tile->eheight;
  276. }
  277.  
  278.  
  279. int
  280. tile_bpp (Tile *tile)
  281. {
  282.   return tile->bpp;
  283. }
  284.  
  285.  
  286. int 
  287. tile_is_valid (Tile *tile)
  288. {
  289.   return tile->valid;
  290. }
  291.  
  292.  
  293. void
  294. tile_mark_valid (Tile *tile)
  295. {
  296.   TILE_MUTEX_LOCK (tile);
  297.   tile->valid = TRUE;
  298.   TILE_MUTEX_UNLOCK (tile);
  299. }
  300.  
  301.  
  302. void
  303. tile_attach (Tile *tile, void *tm, int tile_num)
  304. {
  305.   TileLink *tmp;
  306.  
  307.   if ((tile->share_count > 0) && (!tile->valid)) 
  308.     {
  309.       /* trying to share invalid tiles is problematic, not to mention silly */
  310.       tile_manager_validate ((TileManager*) tile->tlink->tm, tile);
  311.     }
  312.   tile->share_count++;
  313.   tile_share_count++;
  314. #ifdef TILE_DEBUG
  315.   g_print("tile_attach: %p -> (%p,%d) *%d\n", tile, tm, tile_num, tile->share_count);
  316. #endif
  317.  
  318.   /* link this tile into the tile's tilelink chain */
  319.   tmp = g_new (TileLink, 1);
  320.   tmp->tm = tm;
  321.   tmp->tile_num = tile_num;
  322.   tmp->next = tile->tlink;
  323.   tile->tlink = tmp;
  324. }
  325.  
  326. void
  327. tile_detach (Tile *tile, void *tm, int tile_num)
  328. {
  329.   TileLink **link;
  330.   TileLink *tmp;
  331.  
  332. #ifdef TILE_DEBUG
  333.   g_print("tile_detach: %p ~> (%p,%d) r%d *%d\n", tile, tm, tile_num,
  334.       tile->ref_count, tile->share_count);
  335. #endif
  336.  
  337.   for (link = &tile->tlink;
  338.        *link != NULL;
  339.        link = &(*link)->next)
  340.     {
  341.       if (((*link)->tm == tm) && ((*link)->tile_num == tile_num))
  342.     break;
  343.     }
  344.  
  345.   if (*link == NULL) 
  346.     {
  347.       g_warning ("Tried to detach a nonattached tile -- TILE BUG!");
  348.       return;
  349.     }
  350.  
  351.   tmp = *link;
  352.   *link = tmp->next;
  353.   g_free (tmp);
  354.  
  355.   tile_share_count--;
  356.   tile->share_count--;
  357.  
  358.   if (tile->share_count == 0 && tile->ref_count == 0)
  359.     {
  360.       tile_destroy (tile);
  361.       return;
  362.     }
  363.   TILE_MUTEX_UNLOCK (tile);
  364. }
  365.  
  366.  
  367. void *
  368. tile_data_pointer (Tile *tile, int xoff, int yoff)
  369. {
  370.   int offset = yoff * tile->ewidth + xoff;
  371.   return (void *)(tile->data + offset * tile->bpp);
  372. }
  373.