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