Merge remote branch 'origin/master' into lp-binning
[mesa.git] / src / gallium / drivers / softpipe / sp_tex_tile_cache.c
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 /**
29 * Texture tile caching.
30 *
31 * Author:
32 * Brian Paul
33 */
34
35 #include "pipe/p_inlines.h"
36 #include "util/u_memory.h"
37 #include "util/u_tile.h"
38 #include "util/u_math.h"
39 #include "sp_context.h"
40 #include "sp_surface.h"
41 #include "sp_texture.h"
42 #include "sp_tex_tile_cache.h"
43
44
45
46 struct softpipe_tex_tile_cache *
47 sp_create_tex_tile_cache( struct pipe_screen *screen )
48 {
49 struct softpipe_tex_tile_cache *tc;
50 uint pos;
51
52 tc = CALLOC_STRUCT( softpipe_tex_tile_cache );
53 if (tc) {
54 tc->screen = screen;
55 for (pos = 0; pos < NUM_ENTRIES; pos++) {
56 tc->entries[pos].addr.bits.invalid = 1;
57 }
58 tc->last_tile = &tc->entries[0]; /* any tile */
59 }
60 return tc;
61 }
62
63
64 void
65 sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
66 {
67 struct pipe_screen *screen;
68 uint pos;
69
70 for (pos = 0; pos < NUM_ENTRIES; pos++) {
71 /*assert(tc->entries[pos].x < 0);*/
72 }
73 if (tc->transfer) {
74 screen = tc->transfer->texture->screen;
75 screen->tex_transfer_destroy(tc->transfer);
76 }
77 if (tc->tex_trans) {
78 screen = tc->tex_trans->texture->screen;
79 screen->tex_transfer_destroy(tc->tex_trans);
80 }
81
82 FREE( tc );
83 }
84
85
86
87
88 void
89 sp_tex_tile_cache_map_transfers(struct softpipe_tex_tile_cache *tc)
90 {
91 if (tc->tex_trans && !tc->tex_trans_map)
92 tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
93 }
94
95
96 void
97 sp_tex_tile_cache_unmap_transfers(struct softpipe_tex_tile_cache *tc)
98 {
99 if (tc->tex_trans_map) {
100 tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
101 tc->tex_trans_map = NULL;
102 }
103 }
104
105 /**
106 * Invalidate all cached tiles for the cached texture.
107 * Should be called when the texture is modified.
108 */
109 void
110 sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc)
111 {
112 unsigned i;
113
114 assert(tc);
115 assert(tc->texture);
116
117 for (i = 0; i < NUM_ENTRIES; i++) {
118 tc->entries[i].addr.bits.invalid = 1;
119 }
120 }
121
122 /**
123 * Specify the texture to cache.
124 */
125 void
126 sp_tex_tile_cache_set_texture(struct softpipe_tex_tile_cache *tc,
127 struct pipe_texture *texture)
128 {
129 uint i;
130
131 assert(!tc->transfer);
132
133 if (tc->texture != texture) {
134 pipe_texture_reference(&tc->texture, texture);
135
136 if (tc->tex_trans) {
137 struct pipe_screen *screen = tc->tex_trans->texture->screen;
138
139 if (tc->tex_trans_map) {
140 screen->transfer_unmap(screen, tc->tex_trans);
141 tc->tex_trans_map = NULL;
142 }
143
144 screen->tex_transfer_destroy(tc->tex_trans);
145 tc->tex_trans = NULL;
146 }
147
148 /* mark as entries as invalid/empty */
149 /* XXX we should try to avoid this when the teximage hasn't changed */
150 for (i = 0; i < NUM_ENTRIES; i++) {
151 tc->entries[i].addr.bits.invalid = 1;
152 }
153
154 tc->tex_face = -1; /* any invalid value here */
155 }
156 }
157
158
159
160
161 /**
162 * Flush the tile cache: write all dirty tiles back to the transfer.
163 * any tiles "flagged" as cleared will be "really" cleared.
164 */
165 void
166 sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
167 {
168 int pos;
169
170 if (tc->texture) {
171 /* caching a texture, mark all entries as empty */
172 for (pos = 0; pos < NUM_ENTRIES; pos++) {
173 tc->entries[pos].addr.bits.invalid = 1;
174 }
175 tc->tex_face = -1;
176 }
177
178 }
179
180
181 /**
182 * Given the texture face, level, zslice, x and y values, compute
183 * the cache entry position/index where we'd hope to find the
184 * cached texture tile.
185 * This is basically a direct-map cache.
186 * XXX There's probably lots of ways in which we can improve this.
187 */
188 static INLINE uint
189 tex_cache_pos( union tex_tile_address addr )
190 {
191 uint entry = (addr.bits.x +
192 addr.bits.y * 9 +
193 addr.bits.z * 3 +
194 addr.bits.face +
195 addr.bits.level * 7);
196
197 return entry % NUM_ENTRIES;
198 }
199
200 /**
201 * Similar to sp_get_cached_tile() but for textures.
202 * Tiles are read-only and indexed with more params.
203 */
204 const struct softpipe_tex_cached_tile *
205 sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
206 union tex_tile_address addr )
207 {
208 struct pipe_screen *screen = tc->screen;
209 struct softpipe_tex_cached_tile *tile;
210
211 tile = tc->entries + tex_cache_pos( addr );
212
213 if (addr.value != tile->addr.value) {
214
215 /* cache miss. Most misses are because we've invaldiated the
216 * texture cache previously -- most commonly on binding a new
217 * texture. Currently we effectively flush the cache on texture
218 * bind.
219 */
220 #if 0
221 _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n"
222 " tile %u: x=%d y=%d z=%d face=%d level=%d\n",
223 pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
224 pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
225 #endif
226
227 /* check if we need to get a new transfer */
228 if (!tc->tex_trans ||
229 tc->tex_face != addr.bits.face ||
230 tc->tex_level != addr.bits.level ||
231 tc->tex_z != addr.bits.z) {
232 /* get new transfer (view into texture) */
233
234 if (tc->tex_trans) {
235 if (tc->tex_trans_map) {
236 tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
237 tc->tex_trans_map = NULL;
238 }
239
240 screen->tex_transfer_destroy(tc->tex_trans);
241 tc->tex_trans = NULL;
242 }
243
244 tc->tex_trans =
245 screen->get_tex_transfer(screen, tc->texture,
246 addr.bits.face,
247 addr.bits.level,
248 addr.bits.z,
249 PIPE_TRANSFER_READ, 0, 0,
250 u_minify(tc->texture->width0, addr.bits.level),
251 u_minify(tc->texture->height0, addr.bits.level));
252
253 tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
254
255 tc->tex_face = addr.bits.face;
256 tc->tex_level = addr.bits.level;
257 tc->tex_z = addr.bits.z;
258 }
259
260 /* get tile from the transfer (view into texture) */
261 pipe_get_tile_rgba(tc->tex_trans,
262 addr.bits.x * TILE_SIZE,
263 addr.bits.y * TILE_SIZE,
264 TILE_SIZE, TILE_SIZE,
265 (float *) tile->data.color);
266 tile->addr = addr;
267 }
268
269 tc->last_tile = tile;
270 return tile;
271 }
272
273
274