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