2f9a1e9837b63ebc7603453f9e906f34ed8f5d23
[mesa.git] / src / mesa / pipe / softpipe / sp_texture.c
1 /**************************************************************************
2 *
3 * Copyright 2006 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 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@tungstengraphics.com>
31 */
32
33 #include "pipe/p_context.h"
34 #include "pipe/p_defines.h"
35 #include "pipe/p_util.h"
36 #include "pipe/p_winsys.h"
37
38 #include "sp_context.h"
39 #include "sp_state.h"
40 #include "sp_texture.h"
41
42
43 /* At the moment, just make softpipe use the same layout for its
44 * textures as the i945. Softpipe needs some sort of texture layout,
45 * this one was handy. May be worthwhile to simplify this code a
46 * little.
47 */
48
49 static unsigned minify( unsigned d )
50 {
51 return MAX2(1, d>>1);
52 }
53
54 static int align(int value, int alignment)
55 {
56 return (value + alignment - 1) & ~(alignment - 1);
57 }
58
59
60 static void
61 sp_miptree_set_level_info(struct softpipe_texture *spt,
62 unsigned level,
63 unsigned nr_images,
64 unsigned x, unsigned y, unsigned w, unsigned h,
65 unsigned d)
66 {
67 struct pipe_texture *pt = &spt->base;
68
69 assert(level < PIPE_MAX_TEXTURE_LEVELS);
70
71 pt->width[level] = w;
72 pt->height[level] = h;
73 pt->depth[level] = d;
74
75 spt->nr_images[level] = nr_images;
76 spt->level_offset[level] = (x + y * spt->pitch) * pt->cpp;
77
78 /*
79 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
80 level, w, h, d, x, y, spt->level_offset[level]);
81 */
82
83 /* Not sure when this would happen, but anyway:
84 */
85 if (spt->image_offset[level]) {
86 FREE( spt->image_offset[level] );
87 spt->image_offset[level] = NULL;
88 }
89
90 assert(nr_images);
91 assert(!spt->image_offset[level]);
92
93 spt->image_offset[level] = (unsigned *) MALLOC( nr_images * sizeof(unsigned) );
94 spt->image_offset[level][0] = 0;
95 }
96
97
98 static void
99 sp_miptree_set_image_offset(struct softpipe_texture *spt,
100 unsigned level, unsigned img, unsigned x, unsigned y)
101 {
102 if (img == 0 && level == 0)
103 assert(x == 0 && y == 0);
104
105 assert(img < spt->nr_images[level]);
106
107 spt->image_offset[level][img] = (x + y * spt->pitch);
108
109 /*
110 DBG("%s level %d img %d pos %d,%d image_offset %x\n",
111 __FUNCTION__, level, img, x, y, spt->image_offset[level][img]);
112 */
113 }
114
115
116 static void
117 sp_miptree_layout_2d( struct softpipe_texture *spt )
118 {
119 struct pipe_texture *pt = &spt->base;
120 int align_h = 2, align_w = 4;
121 unsigned level;
122 unsigned x = 0;
123 unsigned y = 0;
124 unsigned width = pt->width[0];
125 unsigned height = pt->height[0];
126
127 spt->pitch = pt->width[0];
128 /* XXX FIX THIS:
129 * we use alignment=64 bytes in sp_region_alloc(). If we change
130 * that, change this too.
131 */
132 if (spt->pitch < 16)
133 spt->pitch = 16;
134
135 /* May need to adjust pitch to accomodate the placement of
136 * the 2nd mipmap. This occurs when the alignment
137 * constraints of mipmap placement push the right edge of the
138 * 2nd mipmap out past the width of its parent.
139 */
140 if (pt->first_level != pt->last_level) {
141 unsigned mip1_width = align(minify(pt->width[0]), align_w)
142 + minify(minify(pt->width[0]));
143
144 if (mip1_width > pt->width[0])
145 spt->pitch = mip1_width;
146 }
147
148 /* Pitch must be a whole number of dwords, even though we
149 * express it in texels.
150 */
151 spt->pitch = align(spt->pitch * pt->cpp, 4) / pt->cpp;
152 spt->total_height = 0;
153
154 for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
155 unsigned img_height;
156
157 sp_miptree_set_level_info(spt, level, 1, x, y, width, height, 1);
158
159 if (pt->compressed)
160 img_height = MAX2(1, height/4);
161 else
162 img_height = align(height, align_h);
163
164
165 /* Because the images are packed better, the final offset
166 * might not be the maximal one:
167 */
168 spt->total_height = MAX2(spt->total_height, y + img_height);
169
170 /* Layout_below: step right after second mipmap.
171 */
172 if (level == pt->first_level + 1) {
173 x += align(width, align_w);
174 }
175 else {
176 y += img_height;
177 }
178
179 width = minify(width);
180 height = minify(height);
181 }
182 }
183
184
185 static const int initial_offsets[6][2] = {
186 {0, 0},
187 {0, 2},
188 {1, 0},
189 {1, 2},
190 {1, 1},
191 {1, 3}
192 };
193
194 static const int step_offsets[6][2] = {
195 {0, 2},
196 {0, 2},
197 {-1, 2},
198 {-1, 2},
199 {-1, 1},
200 {-1, 1}
201 };
202
203
204
205 static boolean
206 softpipe_mipmap_tree_layout(struct pipe_context *pipe, struct softpipe_texture * spt)
207 {
208 struct pipe_texture *pt = &spt->base;
209 unsigned level;
210
211 switch (pt->target) {
212 case PIPE_TEXTURE_CUBE:{
213 const unsigned dim = pt->width[0];
214 unsigned face;
215 unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
216
217 assert(lvlWidth == lvlHeight); /* cubemap images are square */
218
219 /* Depending on the size of the largest images, pitch can be
220 * determined either by the old-style packing of cubemap faces,
221 * or the final row of 4x4, 2x2 and 1x1 faces below this.
222 */
223 if (dim > 32)
224 spt->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
225 else
226 spt->pitch = 14 * 8;
227
228 spt->total_height = dim * 4 + 4;
229
230 /* Set all the levels to effectively occupy the whole rectangular region.
231 */
232 for (level = pt->first_level; level <= pt->last_level; level++) {
233 sp_miptree_set_level_info(spt, level, 6,
234 0, 0,
235 lvlWidth, lvlHeight, 1);
236 lvlWidth /= 2;
237 lvlHeight /= 2;
238 }
239
240
241 for (face = 0; face < 6; face++) {
242 unsigned x = initial_offsets[face][0] * dim;
243 unsigned y = initial_offsets[face][1] * dim;
244 unsigned d = dim;
245
246 if (dim == 4 && face >= 4) {
247 y = spt->total_height - 4;
248 x = (face - 4) * 8;
249 }
250 else if (dim < 4 && (face > 0 || pt->first_level > 0)) {
251 y = spt->total_height - 4;
252 x = face * 8;
253 }
254
255 for (level = pt->first_level; level <= pt->last_level; level++) {
256 sp_miptree_set_image_offset(spt, level, face, x, y);
257
258 d >>= 1;
259
260 switch (d) {
261 case 4:
262 switch (face) {
263 case PIPE_TEX_FACE_POS_X:
264 case PIPE_TEX_FACE_NEG_X:
265 x += step_offsets[face][0] * d;
266 y += step_offsets[face][1] * d;
267 break;
268 case PIPE_TEX_FACE_POS_Y:
269 case PIPE_TEX_FACE_NEG_Y:
270 y += 12;
271 x -= 8;
272 break;
273 case PIPE_TEX_FACE_POS_Z:
274 case PIPE_TEX_FACE_NEG_Z:
275 y = spt->total_height - 4;
276 x = (face - 4) * 8;
277 break;
278 }
279
280 case 2:
281 y = spt->total_height - 4;
282 x = 16 + face * 8;
283 break;
284
285 case 1:
286 x += 48;
287 break;
288
289 default:
290 x += step_offsets[face][0] * d;
291 y += step_offsets[face][1] * d;
292 break;
293 }
294 }
295 }
296 break;
297 }
298 case PIPE_TEXTURE_3D:{
299 unsigned width = pt->width[0];
300 unsigned height = pt->height[0];
301 unsigned depth = pt->depth[0];
302 unsigned pack_x_pitch, pack_x_nr;
303 unsigned pack_y_pitch;
304 unsigned level;
305
306 spt->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
307 spt->total_height = 0;
308
309 pack_y_pitch = MAX2(pt->height[0], 2);
310 pack_x_pitch = spt->pitch;
311 pack_x_nr = 1;
312
313 for (level = pt->first_level; level <= pt->last_level; level++) {
314 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
315 int x = 0;
316 int y = 0;
317 unsigned q, j;
318
319 sp_miptree_set_level_info(spt, level, nr_images,
320 0, spt->total_height,
321 width, height, depth);
322
323 for (q = 0; q < nr_images;) {
324 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
325 sp_miptree_set_image_offset(spt, level, q, x, y);
326 x += pack_x_pitch;
327 }
328
329 x = 0;
330 y += pack_y_pitch;
331 }
332
333
334 spt->total_height += y;
335
336 if (pack_x_pitch > 4) {
337 pack_x_pitch >>= 1;
338 pack_x_nr <<= 1;
339 assert(pack_x_pitch * pack_x_nr <= spt->pitch);
340 }
341
342 if (pack_y_pitch > 2) {
343 pack_y_pitch >>= 1;
344 }
345
346 width = minify(width);
347 height = minify(height);
348 depth = minify(depth);
349 }
350 break;
351 }
352
353 case PIPE_TEXTURE_1D:
354 case PIPE_TEXTURE_2D:
355 // case PIPE_TEXTURE_RECTANGLE:
356 sp_miptree_layout_2d(spt);
357 break;
358 default:
359 assert(0);
360 break;
361 }
362
363 /*
364 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
365 spt->pitch,
366 spt->total_height, pt->cpp, spt->pitch * spt->total_height * pt->cpp);
367 */
368
369 return TRUE;
370 }
371
372 void
373 softpipe_texture_create(struct pipe_context *pipe, struct pipe_texture **pt)
374 {
375 struct softpipe_texture *spt = REALLOC(*pt, sizeof(struct pipe_texture),
376 sizeof(struct softpipe_texture));
377
378 if (spt) {
379 memset(&spt->base + 1, 0,
380 sizeof(struct softpipe_texture) - sizeof(struct pipe_texture));
381
382 if (softpipe_mipmap_tree_layout(pipe, spt)) {
383 spt->region = pipe->winsys->region_alloc(pipe->winsys,
384 spt->pitch * (*pt)->cpp *
385 spt->total_height,
386 PIPE_SURFACE_FLAG_TEXTURE);
387 }
388
389 if (!spt->region) {
390 FREE(spt);
391 spt = NULL;
392 }
393 }
394
395 *pt = &spt->base;
396 }
397
398 void
399 softpipe_texture_release(struct pipe_context *pipe, struct pipe_texture **pt)
400 {
401 if (!*pt)
402 return;
403
404 /*
405 DBG("%s %p refcount will be %d\n",
406 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
407 */
408 if (--(*pt)->refcount <= 0) {
409 struct softpipe_texture *spt = (struct softpipe_texture *)*pt;
410 uint i;
411
412 /*
413 DBG("%s deleting %p\n", __FUNCTION__, (void *) spt);
414 */
415
416 pipe->winsys->region_release(pipe->winsys, &spt->region);
417
418 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
419 if (spt->image_offset[i])
420 free(spt->image_offset[i]);
421
422 free(spt);
423 }
424 *pt = NULL;
425 }