074d2dabb432f412185f57ee86919793b9e35b4c
1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 * Texture tile caching.
35 #include "pipe/p_inlines.h"
36 #include "util/u_memory.h"
37 #include "util/u_math.h"
38 #include "util/u_tile.h"
39 #include "util/u_rect.h"
40 #include "lp_context.h"
41 #include "lp_surface.h"
42 #include "lp_texture.h"
43 #include "lp_tile_soa.h"
44 #include "lp_tile_cache.h"
49 * Return the position in the cache for the tile that contains win pos (x,y).
50 * We currently use a direct mapped cache so this is like a hack key.
51 * At some point we should investige something more sophisticated, like
52 * a LRU replacement policy.
54 #define CACHE_POS(x, y) \
55 (((x) + (y) * 5) % NUM_ENTRIES)
60 * Is the tile at (x,y) in cleared state?
63 is_clear_flag_set(const uint
*bitvec
, union tile_address addr
)
66 pos
= addr
.bits
.y
* (MAX_WIDTH
/ TILE_SIZE
) + addr
.bits
.x
;
67 assert(pos
/ 32 < (MAX_WIDTH
/ TILE_SIZE
) * (MAX_HEIGHT
/ TILE_SIZE
) / 32);
68 bit
= bitvec
[pos
/ 32] & (1 << (pos
& 31));
74 * Mark the tile at (x,y) as not cleared.
77 clear_clear_flag(uint
*bitvec
, union tile_address addr
)
80 pos
= addr
.bits
.y
* (MAX_WIDTH
/ TILE_SIZE
) + addr
.bits
.x
;
81 assert(pos
/ 32 < (MAX_WIDTH
/ TILE_SIZE
) * (MAX_HEIGHT
/ TILE_SIZE
) / 32);
82 bitvec
[pos
/ 32] &= ~(1 << (pos
& 31));
86 struct llvmpipe_tile_cache
*
87 lp_create_tile_cache( struct pipe_screen
*screen
)
89 struct llvmpipe_tile_cache
*tc
;
92 tc
= align_malloc( sizeof(struct llvmpipe_tile_cache
), 16 );
94 memset(tc
, 0, sizeof *tc
);
96 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
97 tc
->entries
[pos
].addr
.bits
.invalid
= 1;
99 tc
->last_tile
= &tc
->entries
[0]; /* any tile */
106 lp_destroy_tile_cache(struct llvmpipe_tile_cache
*tc
)
108 struct pipe_screen
*screen
;
111 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
112 /*assert(tc->entries[pos].x < 0);*/
115 screen
= tc
->transfer
->texture
->screen
;
116 screen
->tex_transfer_destroy(tc
->transfer
);
119 screen
= tc
->tex_trans
->texture
->screen
;
120 screen
->tex_transfer_destroy(tc
->tex_trans
);
128 * Specify the surface to cache.
131 lp_tile_cache_set_surface(struct llvmpipe_tile_cache
*tc
,
132 struct pipe_surface
*ps
)
134 assert(!tc
->texture
);
137 struct pipe_screen
*screen
= tc
->transfer
->texture
->screen
;
139 if (ps
== tc
->surface
)
142 if (tc
->transfer_map
) {
143 screen
->transfer_unmap(screen
, tc
->transfer
);
144 tc
->transfer_map
= NULL
;
147 screen
->tex_transfer_destroy(tc
->transfer
);
154 struct pipe_screen
*screen
= ps
->texture
->screen
;
156 tc
->transfer
= screen
->get_tex_transfer(screen
, ps
->texture
, ps
->face
,
157 ps
->level
, ps
->zslice
,
158 PIPE_TRANSFER_READ_WRITE
,
159 0, 0, ps
->width
, ps
->height
);
165 * Return the transfer being cached.
167 struct pipe_surface
*
168 lp_tile_cache_get_surface(struct llvmpipe_tile_cache
*tc
)
175 lp_tile_cache_map_transfers(struct llvmpipe_tile_cache
*tc
)
177 if (tc
->transfer
&& !tc
->transfer_map
)
178 tc
->transfer_map
= tc
->screen
->transfer_map(tc
->screen
, tc
->transfer
);
180 if (tc
->tex_trans
&& !tc
->tex_trans_map
)
181 tc
->tex_trans_map
= tc
->screen
->transfer_map(tc
->screen
, tc
->tex_trans
);
186 lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache
*tc
)
188 if (tc
->transfer_map
) {
189 tc
->screen
->transfer_unmap(tc
->screen
, tc
->transfer
);
190 tc
->transfer_map
= NULL
;
193 if (tc
->tex_trans_map
) {
194 tc
->screen
->transfer_unmap(tc
->screen
, tc
->tex_trans
);
195 tc
->tex_trans_map
= NULL
;
201 * Set a tile to a solid color.
204 clear_tile(struct llvmpipe_cached_tile
*tile
,
205 uint8_t clear_color
[4])
207 if (clear_color
[0] == clear_color
[1] &&
208 clear_color
[1] == clear_color
[2] &&
209 clear_color
[2] == clear_color
[3]) {
210 memset(tile
->color
, clear_color
[0], TILE_SIZE
* TILE_SIZE
* 4);
214 for (y
= 0; y
< TILE_SIZE
; y
++)
215 for (x
= 0; x
< TILE_SIZE
; x
++)
216 for (chan
= 0; chan
< 4; ++chan
)
217 TILE_PIXEL(tile
->color
, x
, y
, chan
) = clear_color
[chan
];
223 * Actually clear the tiles which were flagged as being in a clear state.
226 lp_tile_cache_flush_clear(struct llvmpipe_tile_cache
*tc
)
228 struct pipe_transfer
*pt
= tc
->transfer
;
229 struct pipe_screen
*screen
= pt
->texture
->screen
;
230 const uint w
= tc
->transfer
->width
;
231 const uint h
= tc
->transfer
->height
;
235 /* push the tile to all positions marked as clear */
236 for (y
= 0; y
< h
; y
+= TILE_SIZE
) {
237 for (x
= 0; x
< w
; x
+= TILE_SIZE
) {
238 union tile_address addr
= tile_address(x
, y
, 0, 0, 0);
240 if (is_clear_flag_set(tc
->clear_flags
, addr
)) {
241 unsigned tw
= TILE_SIZE
;
242 unsigned th
= TILE_SIZE
;
245 if (pipe_clip_tile(x
, y
, &tw
, &th
, pt
))
248 dst
= screen
->transfer_map(screen
, pt
);
253 pipe_fill_rect(dst
, &pt
->block
, pt
->stride
,
258 clear_clear_flag(tc
->clear_flags
, addr
);
265 debug_printf("num cleared: %u\n", numCleared
);
271 * Flush the tile cache: write all dirty tiles back to the transfer.
272 * any tiles "flagged" as cleared will be "really" cleared.
275 lp_flush_tile_cache(struct llvmpipe_tile_cache
*tc
)
277 struct pipe_transfer
*pt
= tc
->transfer
;
281 /* caching a drawing transfer */
282 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
283 struct llvmpipe_cached_tile
*tile
= tc
->entries
+ pos
;
284 if (!tile
->addr
.bits
.invalid
) {
285 lp_put_tile_rgba_soa(pt
,
286 tile
->addr
.bits
.x
* TILE_SIZE
,
287 tile
->addr
.bits
.y
* TILE_SIZE
,
289 tile
->addr
.bits
.invalid
= 1; /* mark as empty */
294 #if TILE_CLEAR_OPTIMIZATION
295 lp_tile_cache_flush_clear(tc
);
298 else if (tc
->texture
) {
299 /* caching a texture, mark all entries as empty */
300 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
301 tc
->entries
[pos
].addr
.bits
.invalid
= 1;
307 debug_printf("flushed tiles in use: %d\n", inuse
);
313 * Get a tile from the cache.
314 * \param x, y position of tile, in pixels
317 lp_find_cached_tile(struct llvmpipe_tile_cache
*tc
,
318 union tile_address addr
)
320 struct pipe_transfer
*pt
= tc
->transfer
;
322 /* cache pos/entry: */
323 const int pos
= CACHE_POS(addr
.bits
.x
,
325 struct llvmpipe_cached_tile
*tile
= tc
->entries
+ pos
;
327 if (addr
.value
!= tile
->addr
.value
) {
329 if (tile
->addr
.bits
.invalid
== 0) {
330 /* put dirty tile back in framebuffer */
331 lp_put_tile_rgba_soa(pt
,
332 tile
->addr
.bits
.x
* TILE_SIZE
,
333 tile
->addr
.bits
.y
* TILE_SIZE
,
339 if (is_clear_flag_set(tc
->clear_flags
, addr
)) {
340 /* don't get tile from framebuffer, just clear it */
341 clear_tile(tile
, tc
->clear_color
);
342 clear_clear_flag(tc
->clear_flags
, addr
);
345 /* get new tile data from transfer */
346 lp_get_tile_rgba_soa(pt
,
347 tile
->addr
.bits
.x
* TILE_SIZE
,
348 tile
->addr
.bits
.y
* TILE_SIZE
,
353 tc
->last_tile
= tile
;
360 * Given the texture face, level, zslice, x and y values, compute
361 * the cache entry position/index where we'd hope to find the
362 * cached texture tile.
363 * This is basically a direct-map cache.
364 * XXX There's probably lots of ways in which we can improve this.
367 tex_cache_pos( union tile_address addr
)
369 uint entry
= (addr
.bits
.x
+
373 addr
.bits
.level
* 7);
375 return entry
% NUM_ENTRIES
;
380 * When a whole surface is being cleared to a value we can avoid
381 * fetching tiles above.
382 * Save the color and set a 'clearflag' for each tile of the screen.
385 lp_tile_cache_clear(struct llvmpipe_tile_cache
*tc
, const float *rgba
,
391 for(chan
= 0; chan
< 4; ++chan
)
392 tc
->clear_color
[chan
] = float_to_ubyte(rgba
[chan
]);
394 tc
->clear_val
= clearValue
;
396 #if TILE_CLEAR_OPTIMIZATION
397 /* set flags to indicate all the tiles are cleared */
398 memset(tc
->clear_flags
, 255, sizeof(tc
->clear_flags
));
400 /* disable the optimization */
401 memset(tc
->clear_flags
, 0, sizeof(tc
->clear_flags
));
404 for (pos
= 0; pos
< NUM_ENTRIES
; pos
++) {
405 struct llvmpipe_cached_tile
*tile
= tc
->entries
+ pos
;
406 tile
->addr
.bits
.invalid
= 1;