Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lp_tile_cache.c 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**************************************************************************
  2. *
  3. * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial portions
  16. * of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. **************************************************************************/
  27. /**
  28. * Texture tile caching.
  29. *
  30. * Author:
  31. * Brian Paul
  32. */
  33. #include "pipe/p_inlines.h"
  34. #include "util/u_memory.h"
  35. #include "util/u_math.h"
  36. #include "util/u_tile.h"
  37. #include "util/u_rect.h"
  38. #include "lp_context.h"
  39. #include "lp_tile_soa.h"
  40. #include "lp_tile_cache.h"
  41. #define MAX_WIDTH 4096
  42. #define MAX_HEIGHT 4096
  43. enum llvmpipe_tile_status
  44. {
  45. LP_TILE_STATUS_UNDEFINED = 0,
  46. LP_TILE_STATUS_CLEAR = 1,
  47. LP_TILE_STATUS_DEFINED = 2
  48. };
  49. struct llvmpipe_cached_tile
  50. {
  51. enum llvmpipe_tile_status status;
  52. /** color in SOA format */
  53. uint8_t *color;
  54. };
  55. struct llvmpipe_tile_cache
  56. {
  57. struct pipe_screen *screen;
  58. struct pipe_surface *surface; /**< the surface we're caching */
  59. struct pipe_transfer *transfer;
  60. void *transfer_map;
  61. struct llvmpipe_cached_tile entries[MAX_WIDTH/TILE_SIZE][MAX_HEIGHT/TILE_SIZE];
  62. uint8_t clear_color[4]; /**< for color bufs */
  63. uint clear_val; /**< for z+stencil, or packed color clear value */
  64. struct llvmpipe_cached_tile *last_tile; /**< most recently retrieved tile */
  65. };
  66. struct llvmpipe_tile_cache *
  67. lp_create_tile_cache( struct pipe_screen *screen )
  68. {
  69. struct llvmpipe_tile_cache *tc;
  70. int maxLevels, maxTexSize;
  71. /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
  72. maxLevels = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  73. maxTexSize = 1 << (maxLevels - 1);
  74. assert(MAX_WIDTH >= maxTexSize);
  75. tc = CALLOC_STRUCT( llvmpipe_tile_cache );
  76. if(!tc)
  77. return NULL;
  78. tc->screen = screen;
  79. return tc;
  80. }
  81. void
  82. lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc)
  83. {
  84. struct pipe_screen *screen;
  85. unsigned x, y;
  86. for (y = 0; y < MAX_HEIGHT; y += TILE_SIZE) {
  87. for (x = 0; x < MAX_WIDTH; x += TILE_SIZE) {
  88. struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
  89. if(tile->color)
  90. align_free(tile->color);
  91. }
  92. }
  93. if (tc->transfer) {
  94. screen = tc->transfer->texture->screen;
  95. screen->tex_transfer_destroy(tc->transfer);
  96. }
  97. FREE( tc );
  98. }
  99. /**
  100. * Specify the surface to cache.
  101. */
  102. void
  103. lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc,
  104. struct pipe_surface *ps)
  105. {
  106. if (tc->transfer) {
  107. struct pipe_screen *screen = tc->transfer->texture->screen;
  108. if (ps == tc->surface)
  109. return;
  110. if (tc->transfer_map) {
  111. screen->transfer_unmap(screen, tc->transfer);
  112. tc->transfer_map = NULL;
  113. }
  114. screen->tex_transfer_destroy(tc->transfer);
  115. tc->transfer = NULL;
  116. }
  117. tc->surface = ps;
  118. if (ps) {
  119. struct pipe_screen *screen = ps->texture->screen;
  120. unsigned x, y;
  121. tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
  122. ps->level, ps->zslice,
  123. PIPE_TRANSFER_READ_WRITE,
  124. 0, 0, ps->width, ps->height);
  125. for (y = 0; y < ps->height; y += TILE_SIZE) {
  126. for (x = 0; x < ps->width; x += TILE_SIZE) {
  127. struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
  128. tile->status = LP_TILE_STATUS_UNDEFINED;
  129. if(!tile->color)
  130. tile->color = align_malloc( TILE_SIZE*TILE_SIZE*NUM_CHANNELS, 16 );
  131. }
  132. }
  133. }
  134. }
  135. /**
  136. * Return the transfer being cached.
  137. */
  138. struct pipe_surface *
  139. lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc)
  140. {
  141. return tc->surface;
  142. }
  143. void
  144. lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc)
  145. {
  146. if (tc->transfer && !tc->transfer_map)
  147. tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
  148. }
  149. void
  150. lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc)
  151. {
  152. if (tc->transfer_map) {
  153. tc->screen->transfer_unmap(tc->screen, tc->transfer);
  154. tc->transfer_map = NULL;
  155. }
  156. }
  157. /**
  158. * Set a tile to a solid color.
  159. */
  160. static void
  161. clear_tile(struct llvmpipe_cached_tile *tile,
  162. uint8_t clear_color[4])
  163. {
  164. if (clear_color[0] == clear_color[1] &&
  165. clear_color[1] == clear_color[2] &&
  166. clear_color[2] == clear_color[3]) {
  167. memset(tile->color, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
  168. }
  169. else {
  170. uint x, y, chan;
  171. for (y = 0; y < TILE_SIZE; y++)
  172. for (x = 0; x < TILE_SIZE; x++)
  173. for (chan = 0; chan < 4; ++chan)
  174. TILE_PIXEL(tile->color, x, y, chan) = clear_color[chan];
  175. }
  176. }
  177. /**
  178. * Flush the tile cache: write all dirty tiles back to the transfer.
  179. * any tiles "flagged" as cleared will be "really" cleared.
  180. */
  181. void
  182. lp_flush_tile_cache(struct llvmpipe_tile_cache *tc)
  183. {
  184. struct pipe_transfer *pt = tc->transfer;
  185. unsigned x, y;
  186. if(!pt)
  187. return;
  188. assert(tc->transfer_map);
  189. /* push the tile to all positions marked as clear */
  190. for (y = 0; y < pt->height; y += TILE_SIZE) {
  191. for (x = 0; x < pt->width; x += TILE_SIZE) {
  192. struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
  193. if(tile->status != LP_TILE_STATUS_UNDEFINED) {
  194. unsigned w = TILE_SIZE;
  195. unsigned h = TILE_SIZE;
  196. if (!pipe_clip_tile(x, y, &w, &h, pt)) {
  197. switch(tile->status) {
  198. case LP_TILE_STATUS_CLEAR:
  199. /* Actually clear the tiles which were flagged as being in a
  200. * clear state. */
  201. util_fill_rect(tc->transfer_map, pt->texture->format, pt->stride,
  202. x, y, w, h,
  203. tc->clear_val);
  204. break;
  205. case LP_TILE_STATUS_DEFINED:
  206. lp_tile_write_4ub(pt->texture->format,
  207. tile->color,
  208. tc->transfer_map, pt->stride,
  209. x, y, w, h);
  210. break;
  211. default:
  212. assert(0);
  213. break;
  214. }
  215. }
  216. tile->status = LP_TILE_STATUS_UNDEFINED;
  217. }
  218. }
  219. }
  220. }
  221. /**
  222. * Get a tile from the cache.
  223. * \param x, y position of tile, in pixels
  224. */
  225. void *
  226. lp_get_cached_tile(struct llvmpipe_tile_cache *tc,
  227. unsigned x, unsigned y )
  228. {
  229. struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
  230. struct pipe_transfer *pt = tc->transfer;
  231. assert(tc->surface);
  232. assert(tc->transfer);
  233. if(!tc->transfer_map)
  234. lp_tile_cache_map_transfers(tc);
  235. assert(tc->transfer_map);
  236. switch(tile->status) {
  237. case LP_TILE_STATUS_CLEAR:
  238. /* don't get tile from framebuffer, just clear it */
  239. clear_tile(tile, tc->clear_color);
  240. tile->status = LP_TILE_STATUS_DEFINED;
  241. break;
  242. case LP_TILE_STATUS_UNDEFINED: {
  243. unsigned w = TILE_SIZE;
  244. unsigned h = TILE_SIZE;
  245. x &= ~(TILE_SIZE - 1);
  246. y &= ~(TILE_SIZE - 1);
  247. if (!pipe_clip_tile(x, y, &w, &h, tc->transfer))
  248. lp_tile_read_4ub(pt->texture->format,
  249. tile->color,
  250. tc->transfer_map, tc->transfer->stride,
  251. x, y, w, h);
  252. tile->status = LP_TILE_STATUS_DEFINED;
  253. break;
  254. }
  255. case LP_TILE_STATUS_DEFINED:
  256. /* nothing to do */
  257. break;
  258. }
  259. return tile->color;
  260. }
  261. /**
  262. * When a whole surface is being cleared to a value we can avoid
  263. * fetching tiles above.
  264. * Save the color and set a 'clearflag' for each tile of the screen.
  265. */
  266. void
  267. lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba,
  268. uint clearValue)
  269. {
  270. struct pipe_transfer *pt = tc->transfer;
  271. const unsigned w = pt->width;
  272. const unsigned h = pt->height;
  273. unsigned x, y, chan;
  274. for(chan = 0; chan < 4; ++chan)
  275. tc->clear_color[chan] = float_to_ubyte(rgba[chan]);
  276. tc->clear_val = clearValue;
  277. /* push the tile to all positions marked as clear */
  278. for (y = 0; y < h; y += TILE_SIZE) {
  279. for (x = 0; x < w; x += TILE_SIZE) {
  280. struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE];
  281. tile->status = LP_TILE_STATUS_CLEAR;
  282. }
  283. }
  284. }