Use endianness test function provided by mesa.
[mesa.git] / src / mesa / drivers / dri / r300 / r300_texstate.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "context.h"
39 #include "macros.h"
40 #include "texformat.h"
41 #include "enums.h"
42
43 #include "r300_context.h"
44 #include "r300_state.h"
45 #include "r300_ioctl.h"
46 #include "radeon_ioctl.h"
47 #include "r300_tex.h"
48 #include "r300_reg.h"
49
50
51 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5 \
52 || ((f) >= MESA_FORMAT_RGBA_FLOAT32 && \
53 (f) <= MESA_FORMAT_INTENSITY_FLOAT16)) \
54 && tx_table_le[f].flag )
55
56 #define _ASSIGN(entry, format) \
57 [ MESA_FORMAT_ ## entry ] = { format, 0, 1}
58
59 static const struct {
60 GLuint format, filter, flag;
61 } tx_table_be[] = {
62 /*
63 * Note that the _REV formats are the same as the non-REV formats.
64 * This is because the REV and non-REV formats are identical as a
65 * byte string, but differ when accessed as 16-bit or 32-bit words
66 * depending on the endianness of the host. Since the textures are
67 * transferred to the R300 as a byte string (i.e. without any
68 * byte-swapping), the R300 sees the REV and non-REV formats
69 * identically. -- paulus
70 */
71 _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
72 _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
73 _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
74 _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
75 _ASSIGN(RGB888, 0xffffffff),
76 _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
77 _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
78 _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
79 _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
80 _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
81 _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
82 _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
83 _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
84 _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)),
85 _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)),
86 _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)),
87 _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
88 _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
89 _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ),
90 _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE),
91 _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
92 _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
93 _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
94 _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
95 _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)),
96 _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)),
97 _ASSIGN(RGB_FLOAT32, 0xffffffff),
98 _ASSIGN(RGB_FLOAT16, 0xffffffff),
99 _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)),
100 _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)),
101 _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)),
102 _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)),
103 _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)),
104 _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)),
105 _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)),
106 _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
107 };
108
109 static const struct {
110 GLuint format, filter, flag;
111 } tx_table_le[] = {
112 _ASSIGN(RGBA8888, R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8)),
113 _ASSIGN(RGBA8888_REV, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)),
114 _ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
115 _ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
116 _ASSIGN(RGB888, 0xffffffff),
117 _ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
118 _ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
119 _ASSIGN(ARGB4444, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
120 _ASSIGN(ARGB4444_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4)),
121 _ASSIGN(ARGB1555, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
122 _ASSIGN(ARGB1555_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)),
123 _ASSIGN(AL88, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
124 _ASSIGN(AL88_REV, R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8)),
125 _ASSIGN(RGB332, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z3Y3X2)),
126 _ASSIGN(A8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)),
127 _ASSIGN(L8, R300_EASY_TX_FORMAT(X, X, X, ONE, X8)),
128 _ASSIGN(I8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
129 _ASSIGN(CI8, R300_EASY_TX_FORMAT(X, X, X, X, X8)),
130 _ASSIGN(YCBCR, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE ),
131 _ASSIGN(YCBCR_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, G8R8_G8B8)|R300_TX_FORMAT_YUV_MODE),
132 _ASSIGN(RGB_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1)),
133 _ASSIGN(RGBA_DXT1, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1)),
134 _ASSIGN(RGBA_DXT3, R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3)),
135 _ASSIGN(RGBA_DXT5, R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5)),
136 _ASSIGN(RGBA_FLOAT32, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R32G32B32A32)),
137 _ASSIGN(RGBA_FLOAT16, R300_EASY_TX_FORMAT(Z, Y, X, W, FL_R16G16B16A16)),
138 _ASSIGN(RGB_FLOAT32, 0xffffffff),
139 _ASSIGN(RGB_FLOAT16, 0xffffffff),
140 _ASSIGN(ALPHA_FLOAT32, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I32)),
141 _ASSIGN(ALPHA_FLOAT16, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, FL_I16)),
142 _ASSIGN(LUMINANCE_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I32)),
143 _ASSIGN(LUMINANCE_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, ONE, FL_I16)),
144 _ASSIGN(LUMINANCE_ALPHA_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I32A32)),
145 _ASSIGN(LUMINANCE_ALPHA_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, Y, FL_I16A16)),
146 _ASSIGN(INTENSITY_FLOAT32, R300_EASY_TX_FORMAT(X, X, X, X, FL_I32)),
147 _ASSIGN(INTENSITY_FLOAT16, R300_EASY_TX_FORMAT(X, X, X, X, FL_I16)),
148 };
149
150 #undef _ASSIGN
151
152
153 /**
154 * This function computes the number of bytes of storage needed for
155 * the given texture object (all mipmap levels, all cube faces).
156 * The \c image[face][level].x/y/width/height parameters for upload/blitting
157 * are computed here. \c filter, \c format, etc. will be set here
158 * too.
159 *
160 * \param rmesa Context pointer
161 * \param tObj GL texture object whose images are to be posted to
162 * hardware state.
163 */
164 static void r300SetTexImages(r300ContextPtr rmesa,
165 struct gl_texture_object *tObj)
166 {
167 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
168 const struct gl_texture_image *baseImage =
169 tObj->Image[0][tObj->BaseLevel];
170 GLint curOffset, blitWidth;
171 GLint i, texelBytes;
172 GLint numLevels;
173 GLint log2Width, log2Height, log2Depth;
174 const GLuint ui = 1;
175
176 /* Set the hardware texture format
177 */
178 if (VALID_FORMAT(baseImage->TexFormat->MesaFormat)) {
179 if (_mesa_little_endian()) {
180 t->format =
181 tx_table_le[baseImage->TexFormat->MesaFormat].format;
182 t->filter |=
183 tx_table_le[baseImage->TexFormat->MesaFormat].filter;
184 } else {
185 t->format =
186 tx_table_be[baseImage->TexFormat->MesaFormat].format;
187 t->filter |=
188 tx_table_be[baseImage->TexFormat->MesaFormat].filter;
189 }
190 } else {
191 _mesa_problem(NULL, "unexpected texture format in %s",
192 __FUNCTION__);
193 return;
194 }
195
196 texelBytes = baseImage->TexFormat->TexelBytes;
197
198 /* Compute which mipmap levels we really want to send to the hardware.
199 */
200 driCalculateTextureFirstLastLevel((driTextureObject *) t);
201 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
202 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
203 log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
204
205 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
206
207 assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
208
209 /* Calculate mipmap offsets and dimensions for blitting (uploading)
210 * The idea is that we lay out the mipmap levels within a block of
211 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
212 */
213 curOffset = 0;
214 blitWidth = R300_BLIT_WIDTH_BYTES;
215 t->tile_bits = 0;
216
217 /* figure out if this texture is suitable for tiling. */
218 #if 0 /* Disabled for now */
219 if (texelBytes) {
220 if (rmesa->texmicrotile && (tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
221 /* texrect might be able to use micro tiling too in theory? */
222 (baseImage->Height > 1)) {
223
224 /* allow 32 (bytes) x 1 mip (which will use two times the space
225 the non-tiled version would use) max if base texture is large enough */
226 if ((numLevels == 1) ||
227 (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
228 (baseImage->Width * texelBytes > 64)) ||
229 ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
230 t->tile_bits |= R300_TXO_MICRO_TILE;
231 }
232 }
233
234 if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
235 /* we can set macro tiling even for small textures, they will be untiled anyway */
236 t->tile_bits |= R300_TXO_MACRO_TILE;
237 }
238 }
239 #endif
240
241 for (i = 0; i < numLevels; i++) {
242 const struct gl_texture_image *texImage;
243 GLuint size;
244
245 texImage = tObj->Image[0][i + t->base.firstLevel];
246 if (!texImage)
247 break;
248
249 /* find image size in bytes */
250 if (texImage->IsCompressed) {
251 if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) {
252 // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format);
253 if ((texImage->Width + 3) < 8) /* width one block */
254 size = texImage->CompressedSize * 4;
255 else if ((texImage->Width + 3) < 16)
256 size = texImage->CompressedSize * 2;
257 else size = texImage->CompressedSize;
258 }
259 else /* DXT3/5, 16 bytes per block */
260 {
261 WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
262 // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width);
263 if ((texImage->Width + 3) < 8)
264 size = texImage->CompressedSize * 2;
265 else size = texImage->CompressedSize;
266 }
267
268 } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
269 size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
270 blitWidth = 64 / texelBytes;
271 } else if (t->tile_bits & R300_TXO_MICRO_TILE) {
272 /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
273 though the actual offset may be different (if texture is less than
274 32 bytes width) to the untiled case */
275 int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
276 size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
277 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
278 } else {
279 int w = (texImage->Width * texelBytes + 31) & ~31;
280 size = w * texImage->Height * texImage->Depth;
281 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
282 }
283 assert(size > 0);
284
285 if(0)
286 fprintf(stderr, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage->Width, texImage->Height,
287 texImage->Depth, texImage->TexFormat->TexelBytes,
288 texImage->InternalFormat);
289
290 /* Align to 32-byte offset. It is faster to do this unconditionally
291 * (no branch penalty).
292 */
293
294 curOffset = (curOffset + 0x1f) & ~0x1f;
295
296 if (texelBytes) {
297 t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
298 t->image[0][i].y = 0;
299 t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
300 t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
301 } else {
302 t->image[0][i].x = curOffset % R300_BLIT_WIDTH_BYTES;
303 t->image[0][i].y = curOffset / R300_BLIT_WIDTH_BYTES;
304 t->image[0][i].width = MIN2(size, R300_BLIT_WIDTH_BYTES);
305 t->image[0][i].height = size / t->image[0][i].width;
306 }
307 #if 0
308 /* for debugging only and only applicable to non-rectangle targets */
309 assert(size % t->image[0][i].width == 0);
310 assert(t->image[0][i].x == 0
311 || (size < R300_BLIT_WIDTH_BYTES
312 && t->image[0][i].height == 1));
313 #endif
314
315 if (0)
316 fprintf(stderr,
317 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
318 i, texImage->Width, texImage->Height,
319 t->image[0][i].x, t->image[0][i].y,
320 t->image[0][i].width, t->image[0][i].height,
321 size, curOffset);
322
323 curOffset += size;
324
325 }
326
327 /* Align the total size of texture memory block.
328 */
329 t->base.totalSize =
330 (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
331
332 /* Setup remaining cube face blits, if needed */
333 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
334 GLuint face;
335 for (face = 1; face < 6; face++) {
336 for (i = 0; i < numLevels; i++) {
337 t->image[face][i].x = t->image[0][i].x;
338 t->image[face][i].y = t->image[0][i].y;
339 t->image[face][i].width = t->image[0][i].width;
340 t->image[face][i].height =
341 t->image[0][i].height;
342 }
343 }
344 t->base.totalSize *= 6; /* total texmem needed */
345 }
346
347 /* Hardware state:
348 */
349 #if 0
350 t->format &= ~(R200_TXFORMAT_WIDTH_MASK |
351 R200_TXFORMAT_HEIGHT_MASK |
352 R200_TXFORMAT_CUBIC_MAP_ENABLE |
353 R200_TXFORMAT_F5_WIDTH_MASK |
354 R200_TXFORMAT_F5_HEIGHT_MASK);
355 t->format |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
356 (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
357 #endif
358 #if 0
359 t->format_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
360 if (tObj->Target == GL_TEXTURE_3D) {
361 t->format_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
362 t->format_x |= R200_TEXCOORD_VOLUME;
363 } else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
364 ASSERT(log2Width == log2Height);
365 t->format |= R300_TX_FORMAT_CUBIC_MAP;
366
367 t->format_x |= R200_TEXCOORD_CUBIC_ENV;
368 t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
369 (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
370 (log2Width << R200_FACE_WIDTH_2_SHIFT) |
371 (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
372 (log2Width << R200_FACE_WIDTH_3_SHIFT) |
373 (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
374 (log2Width << R200_FACE_WIDTH_4_SHIFT) |
375 (log2Height << R200_FACE_HEIGHT_4_SHIFT));
376 }
377 #endif
378 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
379 ASSERT(log2Width == log2Height);
380 t->format |= R300_TX_FORMAT_CUBIC_MAP;
381 }
382
383 t->size = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
384 |((tObj->Image[0][t->base.firstLevel]->Height - 1) << R300_TX_HEIGHTMASK_SHIFT))
385 |((numLevels - 1) << R300_TX_MAX_MIP_LEVEL_SHIFT);
386
387 /* Only need to round to nearest 32 for textures, but the blitter
388 * requires 64-byte aligned pitches, and we may/may not need the
389 * blitter. NPOT only!
390 */
391 if (baseImage->IsCompressed) {
392 t->pitch =
393 (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
394 }
395 else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
396 unsigned int align = blitWidth - 1;
397 t->pitch = ((tObj->Image[0][t->base.firstLevel]->Width *
398 texelBytes) + 63) & ~(63);
399 t->size |= R300_TX_SIZE_TXPITCH_EN;
400 t->pitch_reg = (((tObj->Image[0][t->base.firstLevel]->Width) + align) & ~align) - 1;
401 }
402 else {
403 t->pitch =
404 ((tObj->Image[0][t->base.firstLevel]->Width *
405 texelBytes) + 63) & ~(63);
406 }
407
408 t->dirty_state = TEX_ALL;
409
410 /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
411 }
412
413
414 /* ================================================================
415 * Texture unit state management
416 */
417
418 static GLboolean enable_tex_2d(GLcontext * ctx, int unit)
419 {
420 r300ContextPtr rmesa = R300_CONTEXT(ctx);
421 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
422 struct gl_texture_object *tObj = texUnit->_Current;
423 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
424
425 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
426
427 if (t->base.dirty_images[0]) {
428 R300_FIREVERTICES(rmesa);
429 r300SetTexImages(rmesa, tObj);
430 r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
431 if (!t->base.memBlock)
432 return GL_FALSE;
433 }
434
435 return GL_TRUE;
436 }
437
438 #if ENABLE_HW_3D_TEXTURE
439 static GLboolean enable_tex_3d(GLcontext * ctx, int unit)
440 {
441 r300ContextPtr rmesa = R300_CONTEXT(ctx);
442 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
443 struct gl_texture_object *tObj = texUnit->_Current;
444 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
445
446 /* Need to load the 3d images associated with this unit.
447 */
448 #if 0
449 if (t->format & R200_TXFORMAT_NON_POWER2) {
450 t->format &= ~R200_TXFORMAT_NON_POWER2;
451 t->base.dirty_images[0] = ~0;
452 }
453 #endif
454 ASSERT(tObj->Target == GL_TEXTURE_3D);
455
456 /* R100 & R200 do not support mipmaps for 3D textures.
457 */
458 if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
459 return GL_FALSE;
460 }
461
462 if (t->base.dirty_images[0]) {
463 R300_FIREVERTICES(rmesa);
464 r300SetTexImages(rmesa, tObj);
465 r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
466 if (!t->base.memBlock)
467 return GL_FALSE;
468 }
469
470 return GL_TRUE;
471 }
472 #endif
473
474 static GLboolean enable_tex_cube(GLcontext * ctx, int unit)
475 {
476 r300ContextPtr rmesa = R300_CONTEXT(ctx);
477 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
478 struct gl_texture_object *tObj = texUnit->_Current;
479 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
480 GLuint face;
481
482 /* Need to load the 2d images associated with this unit.
483 */
484 #if 0
485 if (t->format & R200_TXFORMAT_NON_POWER2) {
486 t->format &= ~R200_TXFORMAT_NON_POWER2;
487 for (face = 0; face < 6; face++)
488 t->base.dirty_images[face] = ~0;
489 }
490 #endif
491 ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
492
493 if (t->base.dirty_images[0] || t->base.dirty_images[1] ||
494 t->base.dirty_images[2] || t->base.dirty_images[3] ||
495 t->base.dirty_images[4] || t->base.dirty_images[5]) {
496 /* flush */
497 R300_FIREVERTICES(rmesa);
498 /* layout memory space, once for all faces */
499 r300SetTexImages(rmesa, tObj);
500 }
501
502 /* upload (per face) */
503 for (face = 0; face < 6; face++) {
504 if (t->base.dirty_images[face]) {
505 r300UploadTexImages(rmesa,
506 (r300TexObjPtr) tObj->DriverData,
507 face);
508 }
509 }
510
511 if (!t->base.memBlock) {
512 /* texmem alloc failed, use s/w fallback */
513 return GL_FALSE;
514 }
515
516 return GL_TRUE;
517 }
518
519 static GLboolean enable_tex_rect(GLcontext * ctx, int unit)
520 {
521 r300ContextPtr rmesa = R300_CONTEXT(ctx);
522 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
523 struct gl_texture_object *tObj = texUnit->_Current;
524 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
525
526 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
527
528 if (t->base.dirty_images[0]) {
529 R300_FIREVERTICES(rmesa);
530 r300SetTexImages(rmesa, tObj);
531 r300UploadTexImages(rmesa, (r300TexObjPtr) tObj->DriverData, 0);
532 if (!t->base.memBlock && !rmesa->prefer_gart_client_texturing)
533 return GL_FALSE;
534 }
535
536 return GL_TRUE;
537 }
538
539 static GLboolean update_tex_common(GLcontext * ctx, int unit)
540 {
541 r300ContextPtr rmesa = R300_CONTEXT(ctx);
542 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
543 struct gl_texture_object *tObj = texUnit->_Current;
544 r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData;
545
546 /* Fallback if there's a texture border */
547 if (tObj->Image[0][tObj->BaseLevel]->Border > 0)
548 return GL_FALSE;
549
550 /* Update state if this is a different texture object to last
551 * time.
552 */
553 if (rmesa->state.texture.unit[unit].texobj != t) {
554 if (rmesa->state.texture.unit[unit].texobj != NULL) {
555 /* The old texture is no longer bound to this texture unit.
556 * Mark it as such.
557 */
558
559 rmesa->state.texture.unit[unit].texobj->base.bound &=
560 ~(1UL << unit);
561 }
562
563 rmesa->state.texture.unit[unit].texobj = t;
564 t->base.bound |= (1UL << unit);
565 t->dirty_state |= 1 << unit;
566 driUpdateTextureLRU((driTextureObject *) t); /* XXX: should be locked! */
567 }
568
569 return !t->border_fallback;
570 }
571
572 static GLboolean r300UpdateTextureUnit(GLcontext * ctx, int unit)
573 {
574 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
575
576 if (texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT)) {
577 return (enable_tex_rect(ctx, unit) &&
578 update_tex_common(ctx, unit));
579 } else if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
580 return (enable_tex_2d(ctx, unit) &&
581 update_tex_common(ctx, unit));
582 }
583 #if ENABLE_HW_3D_TEXTURE
584 else if (texUnit->_ReallyEnabled & (TEXTURE_3D_BIT)) {
585 return (enable_tex_3d(ctx, unit) &&
586 update_tex_common(ctx, unit));
587 }
588 #endif
589 else if (texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT)) {
590 return (enable_tex_cube(ctx, unit) &&
591 update_tex_common(ctx, unit));
592 } else if (texUnit->_ReallyEnabled) {
593 return GL_FALSE;
594 } else {
595 return GL_TRUE;
596 }
597 }
598
599 void r300UpdateTextureState(GLcontext * ctx)
600 {
601 GLboolean ok;
602
603 ok = (r300UpdateTextureUnit(ctx, 0) &&
604 r300UpdateTextureUnit(ctx, 1) &&
605 r300UpdateTextureUnit(ctx, 2) &&
606 r300UpdateTextureUnit(ctx, 3) &&
607 r300UpdateTextureUnit(ctx, 4) &&
608 r300UpdateTextureUnit(ctx, 5) &&
609 r300UpdateTextureUnit(ctx, 6) &&
610 r300UpdateTextureUnit(ctx, 7)
611 );
612 }