Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 VMware, Inc.
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 VMWARE 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 "util/u_inlines.h"
36
#include "util/u_memory.h"
37
#include "util/u_tile.h"
38
#include "util/u_format.h"
39
#include "util/u_math.h"
40
#include "sp_context.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_context *pipe )
48
{
49
   struct softpipe_tex_tile_cache *tc;
50
   uint pos;
51
 
52
   /* make sure max texture size works */
53
   assert((TEX_TILE_SIZE << TEX_ADDR_BITS) >= (1 << (SP_MAX_TEXTURE_2D_LEVELS-1)));
54
 
55
   tc = CALLOC_STRUCT( softpipe_tex_tile_cache );
56
   if (tc) {
57
      tc->pipe = pipe;
58
      for (pos = 0; pos < Elements(tc->entries); pos++) {
59
         tc->entries[pos].addr.bits.invalid = 1;
60
      }
61
      tc->last_tile = &tc->entries[0]; /* any tile */
62
   }
63
   return tc;
64
}
65
 
66
 
67
void
68
sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
69
{
70
   if (tc) {
71
      uint pos;
72
 
73
      for (pos = 0; pos < Elements(tc->entries); pos++) {
74
         /*assert(tc->entries[pos].x < 0);*/
75
      }
76
      if (tc->transfer) {
77
         tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
78
      }
79
      if (tc->tex_trans) {
80
         tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
81
      }
82
 
83
      FREE( tc );
84
   }
85
}
86
 
87
 
88
/**
89
 * Invalidate all cached tiles for the cached texture.
90
 * Should be called when the texture is modified.
91
 */
92
void
93
sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc)
94
{
95
   unsigned i;
96
 
97
   assert(tc);
98
   assert(tc->texture);
99
 
100
   for (i = 0; i < Elements(tc->entries); i++) {
101
      tc->entries[i].addr.bits.invalid = 1;
102
   }
103
}
104
 
105
static boolean
106
sp_tex_tile_is_compat_view(struct softpipe_tex_tile_cache *tc,
107
                           struct pipe_sampler_view *view)
108
{
109
   if (!view)
110
      return FALSE;
111
   return (tc->texture == view->texture &&
112
           tc->format == view->format &&
113
           tc->swizzle_r == view->swizzle_r &&
114
           tc->swizzle_g == view->swizzle_g &&
115
           tc->swizzle_b == view->swizzle_b &&
116
           tc->swizzle_a == view->swizzle_a);
117
}
118
 
119
/**
120
 * Specify the sampler view to cache.
121
 */
122
void
123
sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc,
124
                                   struct pipe_sampler_view *view)
125
{
126
   struct pipe_resource *texture = view ? view->texture : NULL;
127
   uint i;
128
 
129
   assert(!tc->transfer);
130
 
131
   if (!sp_tex_tile_is_compat_view(tc, view)) {
132
      pipe_resource_reference(&tc->texture, texture);
133
 
134
      if (tc->tex_trans_map) {
135
         tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
136
         tc->tex_trans = NULL;
137
         tc->tex_trans_map = NULL;
138
      }
139
 
140
      if (view) {
141
         tc->swizzle_r = view->swizzle_r;
142
         tc->swizzle_g = view->swizzle_g;
143
         tc->swizzle_b = view->swizzle_b;
144
         tc->swizzle_a = view->swizzle_a;
145
         tc->format = view->format;
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 < Elements(tc->entries); i++) {
151
         tc->entries[i].addr.bits.invalid = 1;
152
      }
153
 
154
      tc->tex_z = -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 < Elements(tc->entries); pos++) {
173
         tc->entries[pos].addr.bits.invalid = 1;
174
      }
175
      tc->tex_z = -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 +
194
                 addr.bits.level * 7);
195
 
196
   return entry % NUM_TEX_TILE_ENTRIES;
197
}
198
 
199
/**
200
 * Similar to sp_get_cached_tile() but for textures.
201
 * Tiles are read-only and indexed with more params.
202
 */
203
const struct softpipe_tex_cached_tile *
204
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
205
                        union tex_tile_address addr )
206
{
207
   struct softpipe_tex_cached_tile *tile;
208
   boolean zs = util_format_is_depth_or_stencil(tc->format);
209
 
210
   tile = tc->entries + tex_cache_pos( addr );
211
 
212
   if (addr.value != tile->addr.value) {
213
 
214
      /* cache miss.  Most misses are because we've invalidated the
215
       * texture cache previously -- most commonly on binding a new
216
       * texture.  Currently we effectively flush the cache on texture
217
       * bind.
218
       */
219
#if 0
220
      _debug_printf("miss at %u:  x=%d y=%d z=%d face=%d level=%d\n"
221
                    "   tile %u:  x=%d y=%d z=%d face=%d level=%d\n",
222
                    pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
223
                    pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
224
#endif
225
 
226
      /* check if we need to get a new transfer */
227
      if (!tc->tex_trans ||
228
          tc->tex_level != addr.bits.level ||
229
          tc->tex_z != addr.bits.z) {
230
         /* get new transfer (view into texture) */
231
         unsigned width, height, layer;
232
 
233
         if (tc->tex_trans_map) {
234
            tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
235
            tc->tex_trans = NULL;
236
            tc->tex_trans_map = NULL;
237
         }
238
 
239
         width = u_minify(tc->texture->width0, addr.bits.level);
240
         if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) {
241
            height = tc->texture->array_size;
242
            layer = 0;
243
         }
244
         else {
245
            height = u_minify(tc->texture->height0, addr.bits.level);
246
            layer = addr.bits.z;
247
         }
248
 
249
         tc->tex_trans_map =
250
            pipe_transfer_map(tc->pipe, tc->texture,
251
                              addr.bits.level,
252
                              layer,
253
                              PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
254
                              0, 0, width, height, &tc->tex_trans);
255
 
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), explicitly passing
261
       * the image format.
262
       */
263
      if (!zs && util_format_is_pure_uint(tc->format)) {
264
         pipe_get_tile_ui_format(tc->tex_trans, tc->tex_trans_map,
265
                                 addr.bits.x * TEX_TILE_SIZE,
266
                                 addr.bits.y * TEX_TILE_SIZE,
267
                                 TEX_TILE_SIZE,
268
                                 TEX_TILE_SIZE,
269
                                 tc->format,
270
                                 (unsigned *) tile->data.colorui);
271
      } else if (!zs && util_format_is_pure_sint(tc->format)) {
272
         pipe_get_tile_i_format(tc->tex_trans, tc->tex_trans_map,
273
                                addr.bits.x * TEX_TILE_SIZE,
274
                                addr.bits.y * TEX_TILE_SIZE,
275
                                TEX_TILE_SIZE,
276
                                TEX_TILE_SIZE,
277
                                tc->format,
278
                                (int *) tile->data.colori);
279
      } else {
280
         pipe_get_tile_rgba_format(tc->tex_trans, tc->tex_trans_map,
281
                                   addr.bits.x * TEX_TILE_SIZE,
282
                                   addr.bits.y * TEX_TILE_SIZE,
283
                                   TEX_TILE_SIZE,
284
                                   TEX_TILE_SIZE,
285
                                   tc->format,
286
                                   (float *) tile->data.color);
287
      }
288
      tile->addr = addr;
289
   }
290
 
291
   tc->last_tile = tile;
292
   return tile;
293
}