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"
47 struct llvmpipe_tile_cache
*
48 lp_create_tile_cache( struct pipe_screen
*screen
)
50 struct llvmpipe_tile_cache
*tc
;
52 tc
= CALLOC_STRUCT( llvmpipe_tile_cache
);
63 lp_destroy_tile_cache(struct llvmpipe_tile_cache
*tc
)
65 struct pipe_screen
*screen
;
68 for (y
= 0; y
< MAX_HEIGHT
; y
+= TILE_SIZE
) {
69 for (x
= 0; x
< MAX_WIDTH
; x
+= TILE_SIZE
) {
70 struct llvmpipe_cached_tile
*tile
= &tc
->entries
[y
/TILE_SIZE
][x
/TILE_SIZE
];
73 align_free(tile
->color
);
78 screen
= tc
->transfer
->texture
->screen
;
79 screen
->tex_transfer_destroy(tc
->transfer
);
87 * Specify the surface to cache.
90 lp_tile_cache_set_surface(struct llvmpipe_tile_cache
*tc
,
91 struct pipe_surface
*ps
)
94 struct pipe_screen
*screen
= tc
->transfer
->texture
->screen
;
96 if (ps
== tc
->surface
)
99 if (tc
->transfer_map
) {
100 screen
->transfer_unmap(screen
, tc
->transfer
);
101 tc
->transfer_map
= NULL
;
104 screen
->tex_transfer_destroy(tc
->transfer
);
111 struct pipe_screen
*screen
= ps
->texture
->screen
;
114 tc
->transfer
= screen
->get_tex_transfer(screen
, ps
->texture
, ps
->face
,
115 ps
->level
, ps
->zslice
,
116 PIPE_TRANSFER_READ_WRITE
,
117 0, 0, ps
->width
, ps
->height
);
119 for (y
= 0; y
< ps
->height
; y
+= TILE_SIZE
) {
120 for (x
= 0; x
< ps
->width
; x
+= TILE_SIZE
) {
121 struct llvmpipe_cached_tile
*tile
= &tc
->entries
[y
/TILE_SIZE
][x
/TILE_SIZE
];
123 tile
->status
= LP_TILE_STATUS_UNDEFINED
;
126 tile
->color
= align_malloc( TILE_SIZE
*TILE_SIZE
*NUM_CHANNELS
, 16 );
134 * Return the transfer being cached.
136 struct pipe_surface
*
137 lp_tile_cache_get_surface(struct llvmpipe_tile_cache
*tc
)
144 lp_tile_cache_map_transfers(struct llvmpipe_tile_cache
*tc
)
146 if (tc
->transfer
&& !tc
->transfer_map
)
147 tc
->transfer_map
= tc
->screen
->transfer_map(tc
->screen
, tc
->transfer
);
152 lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache
*tc
)
154 if (tc
->transfer_map
) {
155 tc
->screen
->transfer_unmap(tc
->screen
, tc
->transfer
);
156 tc
->transfer_map
= NULL
;
162 * Set a tile to a solid color.
165 clear_tile(struct llvmpipe_cached_tile
*tile
,
166 uint8_t clear_color
[4])
168 if (clear_color
[0] == clear_color
[1] &&
169 clear_color
[1] == clear_color
[2] &&
170 clear_color
[2] == clear_color
[3]) {
171 memset(tile
->color
, clear_color
[0], TILE_SIZE
* TILE_SIZE
* 4);
175 for (y
= 0; y
< TILE_SIZE
; y
++)
176 for (x
= 0; x
< TILE_SIZE
; x
++)
177 for (chan
= 0; chan
< 4; ++chan
)
178 TILE_PIXEL(tile
->color
, x
, y
, chan
) = clear_color
[chan
];
184 * Flush the tile cache: write all dirty tiles back to the transfer.
185 * any tiles "flagged" as cleared will be "really" cleared.
188 lp_flush_tile_cache(struct llvmpipe_tile_cache
*tc
)
190 struct pipe_transfer
*pt
= tc
->transfer
;
196 /* push the tile to all positions marked as clear */
197 for (y
= 0; y
< pt
->height
; y
+= TILE_SIZE
) {
198 for (x
= 0; x
< pt
->width
; x
+= TILE_SIZE
) {
199 struct llvmpipe_cached_tile
*tile
= &tc
->entries
[y
/TILE_SIZE
][x
/TILE_SIZE
];
201 switch(tile
->status
) {
202 case LP_TILE_STATUS_UNDEFINED
:
205 case LP_TILE_STATUS_CLEAR
: {
207 * Actually clear the tiles which were flagged as being in a clear state.
210 struct pipe_screen
*screen
= pt
->texture
->screen
;
211 unsigned tw
= TILE_SIZE
;
212 unsigned th
= TILE_SIZE
;
215 if (pipe_clip_tile(x
, y
, &tw
, &th
, pt
))
218 dst
= screen
->transfer_map(screen
, pt
);
223 util_fill_rect(dst
, &pt
->block
, pt
->stride
,
227 screen
->transfer_unmap(screen
, pt
);
229 tile
->status
= LP_TILE_STATUS_UNDEFINED
;
233 case LP_TILE_STATUS_DEFINED
:
234 lp_put_tile_rgba_soa(pt
, x
, y
, tile
->color
);
235 tile
->status
= LP_TILE_STATUS_UNDEFINED
;
244 * Get a tile from the cache.
245 * \param x, y position of tile, in pixels
248 lp_get_cached_tile(struct llvmpipe_tile_cache
*tc
,
249 unsigned x
, unsigned y
)
251 struct llvmpipe_cached_tile
*tile
= &tc
->entries
[y
/TILE_SIZE
][x
/TILE_SIZE
];
252 struct pipe_transfer
*pt
= tc
->transfer
;
254 switch(tile
->status
) {
255 case LP_TILE_STATUS_CLEAR
:
256 /* don't get tile from framebuffer, just clear it */
257 clear_tile(tile
, tc
->clear_color
);
258 tile
->status
= LP_TILE_STATUS_DEFINED
;
261 case LP_TILE_STATUS_UNDEFINED
:
262 /* get new tile data from transfer */
263 lp_get_tile_rgba_soa(pt
, x
& ~(TILE_SIZE
- 1), y
& ~(TILE_SIZE
- 1), tile
->color
);
264 tile
->status
= LP_TILE_STATUS_DEFINED
;
267 case LP_TILE_STATUS_DEFINED
:
277 * When a whole surface is being cleared to a value we can avoid
278 * fetching tiles above.
279 * Save the color and set a 'clearflag' for each tile of the screen.
282 lp_tile_cache_clear(struct llvmpipe_tile_cache
*tc
, const float *rgba
,
285 struct pipe_transfer
*pt
= tc
->transfer
;
286 const unsigned w
= pt
->width
;
287 const unsigned h
= pt
->height
;
290 for(chan
= 0; chan
< 4; ++chan
)
291 tc
->clear_color
[chan
] = float_to_ubyte(rgba
[chan
]);
293 tc
->clear_val
= clearValue
;
295 /* push the tile to all positions marked as clear */
296 for (y
= 0; y
< h
; y
+= TILE_SIZE
) {
297 for (x
= 0; x
< w
; x
+= TILE_SIZE
) {
298 struct llvmpipe_cached_tile
*tile
= &tc
->entries
[y
/TILE_SIZE
][x
/TILE_SIZE
];
299 tile
->status
= LP_TILE_STATUS_CLEAR
;