mesa: replace gl_texture_format with gl_format
[mesa.git] / src / mesa / drivers / dri / savage / savagetex.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include <stdlib.h>
27 #include <stdio.h>
28
29 #include <GL/gl.h>
30
31 #include "main/mm.h"
32 #include "savagecontext.h"
33 #include "savagetex.h"
34 #include "savagetris.h"
35 #include "savageioctl.h"
36 #include "main/simple_list.h"
37 #include "main/enums.h"
38 #include "savage_bci.h"
39
40 #include "main/macros.h"
41 #include "main/texformat.h"
42 #include "main/texstore.h"
43 #include "main/texobj.h"
44 #include "main/convolve.h"
45 #include "main/colormac.h"
46
47 #include "swrast/swrast.h"
48
49 #include "xmlpool.h"
50
51 #define TILE_INDEX_DXT1 0
52 #define TILE_INDEX_8 1
53 #define TILE_INDEX_16 2
54 #define TILE_INDEX_DXTn 3
55 #define TILE_INDEX_32 4
56
57 /* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get
58 * somewhere close to software rendering.
59 */
60 #define SAVAGE4_LOD_OFFSET 10
61
62 /* Tile info for S3TC formats counts in 4x4 blocks instead of texels.
63 * In DXT1 each block is encoded in 64 bits. In DXT3 and 5 each block is
64 * encoded in 128 bits. */
65
66 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
67 * is repeated to fill a 4x4 pixel area. The figure below shows the
68 * layout of those 4x4 pixel areas in the 8x8 subtile.
69 *
70 * 4 2
71 * x 1
72 *
73 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
74 */
75 static const savageTileInfo tileInfo_pro[5] = {
76 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
77 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
78 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
79 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
80 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
81 };
82
83 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
84 * image is repeated to fill a 4x4 pixel area. The figures below show
85 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
86 *
87 * second last subtile: 4 last subtile: 2
88 * x 1
89 */
90 static const savageTileInfo tileInfo_s3d_s4[5] = {
91 {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */
92 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
93 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
94 {16, 8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */
95 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
96 };
97
98 /** \brief Template for subtile uploads.
99 * \param h height in pixels
100 * \param w width in bytes
101 */
102 #define SUBTILE_FUNC(w,h) \
103 static INLINE GLubyte *savageUploadSubtile_##w##x##h \
104 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
105 { \
106 GLuint y; \
107 for (y = 0; y < h; ++y) { \
108 memcpy (dest, src, w); \
109 src += srcStride; \
110 dest += w; \
111 } \
112 return dest; \
113 }
114
115 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
116 SUBTILE_FUNC(4, 8)
117 SUBTILE_FUNC(8, 8)
118 SUBTILE_FUNC(16, 8)
119 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
120
121 SUBTILE_FUNC(8, 2) /* DXT1 */
122 SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 */
123
124 /** \brief Upload a complete tile from src (srcStride) to dest
125 *
126 * \param tileInfo Pointer to tiling information
127 * \param wInSub Width of source/dest image in subtiles
128 * \param hInSub Height of source/dest image in subtiles
129 * \param bpp Bytes per pixel
130 * \param src Pointer to source data
131 * \param srcStride Byte stride of rows in the source data
132 * \param dest Pointer to destination
133 *
134 * Writes linearly to the destination memory in order to exploit write
135 * combining.
136 *
137 * For a complete tile wInSub and hInSub are set to the same values as
138 * in tileInfo. If the source image is smaller than a whole tile in
139 * one or both dimensions then they are set to the values of the
140 * source image. This only works as long as the source image is bigger
141 * than 8x8 pixels.
142 */
143 static void savageUploadTile (const savageTileInfo *tileInfo,
144 GLuint wInSub, GLuint hInSub, GLuint bpp,
145 GLubyte *src, GLuint srcStride, GLubyte *dest) {
146 GLuint subStride = tileInfo->subWidth * bpp;
147 GLubyte *srcSRow = src, *srcSTile = src;
148 GLubyte *(*subtileFunc) (GLubyte *, GLubyte *, GLuint);
149 GLuint sx, sy;
150 switch (subStride) {
151 case 2: subtileFunc = savageUploadSubtile_2x8; break;
152 case 4: subtileFunc = savageUploadSubtile_4x8; break;
153 case 8: subtileFunc = tileInfo->subHeight == 8 ?
154 savageUploadSubtile_8x8 : savageUploadSubtile_8x2; break;
155 case 16: subtileFunc = tileInfo->subHeight == 8 ?
156 savageUploadSubtile_16x8 : savageUploadSubtile_16x2; break;
157 case 32: subtileFunc = savageUploadSubtile_32x8; break;
158 default: assert(0);
159 }
160 for (sy = 0; sy < hInSub; ++sy) {
161 srcSTile = srcSRow;
162 for (sx = 0; sx < wInSub; ++sx) {
163 src = srcSTile;
164 dest = subtileFunc (dest, src, srcStride);
165 srcSTile += subStride;
166 }
167 srcSRow += srcStride * tileInfo->subHeight;
168 }
169 }
170
171 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
172 *
173 * \param tileInfo Pointer to tiling information
174 * \param width Width of the image
175 * \param height Height of the image
176 * \param bpp Bytes per pixel
177 * \param src Pointer to source data
178 * \param dest Pointer to destination
179 *
180 * This function handles all the special cases that need to be taken
181 * care off. The caller may need to call this function multiple times
182 * with the destination offset in different ways since small texture
183 * images must be repeated in order to fill a whole tile (or 4x4 for
184 * the last 3 levels).
185 *
186 * FIXME: Repeating inside this function would be more efficient.
187 */
188 static void savageUploadTiny (const savageTileInfo *tileInfo,
189 GLuint pixWidth, GLuint pixHeight,
190 GLuint width, GLuint height, GLuint bpp,
191 GLubyte *src, GLubyte *dest) {
192 GLuint size = MAX2(pixWidth, pixHeight);
193
194 if (width > tileInfo->subWidth) { /* assert: height <= subtile height */
195 GLuint wInSub = width / tileInfo->subWidth;
196 GLuint srcStride = width * bpp;
197 GLuint subStride = tileInfo->subWidth * bpp;
198 GLuint subSkip = (tileInfo->subHeight - height) * subStride;
199 GLubyte *srcSTile = src;
200 GLuint sx, y;
201 for (sx = 0; sx < wInSub; ++sx) {
202 src = srcSTile;
203 for (y = 0; y < height; ++y) {
204 memcpy (dest, src, subStride);
205 src += srcStride;
206 dest += subStride;
207 }
208 dest += subSkip;
209 srcSTile += subStride;
210 }
211 } else if (size > 4) { /* a tile or less wide, except the last 3 levels */
212 GLuint srcStride = width * bpp;
213 GLuint subStride = tileInfo->subWidth * bpp;
214 /* if the subtile width is 4 we have to skip every other subtile */
215 GLuint subSkip = tileInfo->subWidth <= 4 ?
216 subStride * tileInfo->subHeight : 0;
217 GLuint skipRemainder = tileInfo->subHeight - 1;
218 GLuint y;
219 for (y = 0; y < height; ++y) {
220 memcpy (dest, src, srcStride);
221 src += srcStride;
222 dest += subStride;
223 if ((y & skipRemainder) == skipRemainder)
224 dest += subSkip;
225 }
226 } else { /* the last 3 mipmap levels */
227 GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);
228 GLuint subStride = tileInfo->subWidth * bpp;
229 GLuint y;
230 dest += offset;
231 for (y = 0; y < height; ++y) {
232 memcpy (dest, src, bpp*width);
233 src += width * bpp;
234 dest += subStride;
235 }
236 }
237 }
238
239 /** \brief Upload an image from mesa's internal copy.
240 */
241 static void savageUploadTexLevel( savageTexObjPtr t, int level )
242 {
243 const struct gl_texture_image *image = t->base.tObj->Image[0][level];
244 const savageTileInfo *tileInfo = t->tileInfo;
245 GLuint pixWidth = image->Width2, pixHeight = image->Height2;
246 GLuint bpp = t->texelBytes;
247 GLuint width, height;
248
249 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
250 * this using normal textured triangles.
251 *
252 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
253 */
254 if(image->Border != 0)
255 fprintf (stderr, "Not supported texture border %d.\n",
256 (int) image->Border);
257
258 if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
259 t->hwFormat == TFT_S3TC4Bit) {
260 width = (pixWidth+3) / 4;
261 height = (pixHeight+3) / 4;
262 } else {
263 width = pixWidth;
264 height = pixHeight;
265 }
266
267 if (pixWidth >= 8 && pixHeight >= 8) {
268 GLuint *dirtyPtr = t->image[level].dirtyTiles;
269 GLuint dirtyMask = 1;
270
271 if (width >= tileInfo->width && height >= tileInfo->height) {
272 GLuint wInTiles = width / tileInfo->width;
273 GLuint hInTiles = height / tileInfo->height;
274 GLubyte *srcTRow = image->Data, *src;
275 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
276 GLuint x, y;
277 for (y = 0; y < hInTiles; ++y) {
278 src = srcTRow;
279 for (x = 0; x < wInTiles; ++x) {
280 if (*dirtyPtr & dirtyMask) {
281 savageUploadTile (tileInfo,
282 tileInfo->wInSub, tileInfo->hInSub,
283 bpp, src, width * bpp, dest);
284 }
285 src += tileInfo->width * bpp;
286 dest += 2048; /* tile size is always 2k */
287 if (dirtyMask == 1<<31) {
288 dirtyMask = 1;
289 dirtyPtr++;
290 } else
291 dirtyMask <<= 1;
292 }
293 srcTRow += width * tileInfo->height * bpp;
294 }
295 } else if (width >= tileInfo->width) {
296 GLuint wInTiles = width / tileInfo->width;
297 GLubyte *src = image->Data;
298 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
299 GLuint tileStride = tileInfo->width * bpp * height;
300 savageContextPtr imesa = (savageContextPtr)t->base.heap->driverContext;
301 GLuint x;
302 /* Savage3D-based chips seem so use a constant tile stride
303 * of 2048 for vertically incomplete tiles, but only if
304 * the color depth is 32bpp. Nobody said this was supposed
305 * to be logical!
306 */
307 if (bpp == 4 && imesa->savageScreen->chipset < S3_SAVAGE4)
308 tileStride = 2048;
309 for (x = 0; x < wInTiles; ++x) {
310 if (*dirtyPtr & dirtyMask) {
311 savageUploadTile (tileInfo,
312 tileInfo->wInSub,
313 height / tileInfo->subHeight,
314 bpp, src, width * bpp, dest);
315 }
316 src += tileInfo->width * bpp;
317 dest += tileStride;
318 if (dirtyMask == 1<<31) {
319 dirtyMask = 1;
320 dirtyPtr++;
321 } else
322 dirtyMask <<= 1;
323 }
324 } else {
325 savageUploadTile (tileInfo, width / tileInfo->subWidth,
326 height / tileInfo->subHeight, bpp,
327 image->Data, width * bpp,
328 (GLubyte *)(t->bufAddr+t->image[level].offset));
329 }
330 } else {
331 GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
332 if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||
333 t->hwFormat == TFT_S3TC4Bit)
334 minWidth = minHeight = 1;
335 else
336 minWidth = minHeight = 4;
337 if (width > minWidth || height > minHeight) {
338 minWidth = tileInfo->subWidth;
339 minHeight = tileInfo->subHeight;
340 }
341 hRepeat = width >= minWidth ? 1 : minWidth / width;
342 vRepeat = height >= minHeight ? 1 : minHeight / height;
343 for (y = 0; y < vRepeat; ++y) {
344 GLuint offset = y * tileInfo->subWidth*height * bpp;
345 for (x = 0; x < hRepeat; ++x) {
346 savageUploadTiny (tileInfo, pixWidth, pixHeight,
347 width, height, bpp, image->Data,
348 (GLubyte *)(t->bufAddr +
349 t->image[level].offset+offset));
350 offset += width * bpp;
351 }
352 }
353 }
354 }
355
356 /** \brief Compute the destination size of a texture image
357 */
358 static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
359 /* full subtiles */
360 if (width >= 8 && height >= 8)
361 return width * height * bpp;
362 /* special case for the last three mipmap levels: the hardware computes
363 * the offset internally */
364 else if (width <= 4 && height <= 4)
365 return 0;
366 /* partially filled sub tiles waste memory
367 * on Savage3D and Savage4 with subtile width 4 every other subtile is
368 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
369 else if (width >= 8)
370 return width * 8 * bpp;
371 else if (height >= 8)
372 return 8 * height * bpp;
373 else
374 return 64 * bpp;
375 }
376
377 /** \brief Compute the destination size of a compressed texture image
378 */
379 static GLuint savageCompressedTexImageSize (GLuint width, GLuint height,
380 GLuint bpp) {
381 width = (width+3) / 4;
382 height = (height+3) / 4;
383 /* full subtiles */
384 if (width >= 2 && height >= 2)
385 return width * height * bpp;
386 /* special case for the last three mipmap levels: the hardware computes
387 * the offset internally */
388 else if (width <= 1 && height <= 1)
389 return 0;
390 /* partially filled sub tiles waste memory
391 * on Savage3D and Savage4 with subtile width 4 every other subtile is
392 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
393 else if (width >= 2)
394 return width * 2 * bpp;
395 else if (height >= 2)
396 return 2 * height * bpp;
397 else
398 return 4 * bpp;
399 }
400
401 /** \brief Compute the number of (partial) tiles of a texture image
402 */
403 static GLuint savageTexImageTiles (GLuint width, GLuint height,
404 const savageTileInfo *tileInfo)
405 {
406 return (width + tileInfo->width - 1) / tileInfo->width *
407 (height + tileInfo->height - 1) / tileInfo->height;
408 }
409
410 /** \brief Mark dirty tiles
411 *
412 * Some care must be taken because tileInfo may not be set or not
413 * up-to-date. So we check if tileInfo is initialized and if the number
414 * of tiles in the bit vector matches the number of tiles computed from
415 * the current tileInfo.
416 */
417 static void savageMarkDirtyTiles (savageTexObjPtr t, GLuint level,
418 GLuint totalWidth, GLuint totalHeight,
419 GLint xoffset, GLint yoffset,
420 GLsizei width, GLsizei height)
421 {
422 GLuint wInTiles, hInTiles;
423 GLuint x0, y0, x1, y1;
424 GLuint x, y;
425 if (!t->tileInfo)
426 return;
427 wInTiles = (totalWidth + t->tileInfo->width - 1) / t->tileInfo->width;
428 hInTiles = (totalHeight + t->tileInfo->height - 1) / t->tileInfo->height;
429 if (wInTiles * hInTiles != t->image[level].nTiles)
430 return;
431
432 x0 = xoffset / t->tileInfo->width;
433 y0 = yoffset / t->tileInfo->height;
434 x1 = (xoffset + width - 1) / t->tileInfo->width;
435 y1 = (yoffset + height - 1) / t->tileInfo->height;
436
437 for (y = y0; y <= y1; ++y) {
438 GLuint *ptr = t->image[level].dirtyTiles + (y * wInTiles + x0) / 32;
439 GLuint mask = 1 << (y * wInTiles + x0) % 32;
440 for (x = x0; x <= x1; ++x) {
441 *ptr |= mask;
442 if (mask == (1<<31)) {
443 ptr++;
444 mask = 1;
445 } else {
446 mask <<= 1;
447 }
448 }
449 }
450 }
451
452 /** \brief Mark all tiles as dirty
453 */
454 static void savageMarkAllTiles (savageTexObjPtr t, GLuint level)
455 {
456 GLuint words = (t->image[level].nTiles + 31) / 32;
457 if (words)
458 memset(t->image[level].dirtyTiles, ~0, words*sizeof(GLuint));
459 }
460
461
462 static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t)
463 {
464 tex->setup.sWrapMode = s;
465 tex->setup.tWrapMode = t;
466 }
467
468 static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
469 {
470 t->setup.minFilter = minf;
471 t->setup.magFilter = magf;
472 }
473
474
475 /* Need a fallback ?
476 */
477 static void savageSetTexBorderColor(savageTexObjPtr t, const GLfloat color[4])
478 {
479 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
480 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
481 }
482
483
484
485 static savageTexObjPtr
486 savageAllocTexObj( struct gl_texture_object *texObj )
487 {
488 savageTexObjPtr t;
489
490 t = (savageTexObjPtr) calloc(1,sizeof(*t));
491 texObj->DriverData = t;
492 if ( t != NULL ) {
493 GLuint i;
494
495 /* Initialize non-image-dependent parts of the state:
496 */
497 t->base.tObj = texObj;
498 t->base.dirty_images[0] = 0;
499 t->dirtySubImages = 0;
500 t->tileInfo = NULL;
501
502 /* Initialize dirty tiles bit vectors
503 */
504 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i)
505 t->image[i].nTiles = 0;
506
507 /* FIXME Something here to set initial values for other parts of
508 * FIXME t->setup?
509 */
510
511 make_empty_list( &t->base );
512
513 savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
514 savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
515 savageSetTexBorderColor(t,texObj->BorderColor);
516 }
517
518 return t;
519 }
520
521 /* Mesa texture formats for alpha-images on Savage3D/IX/MX
522 *
523 * Promoting texture images to ARGB888 or ARGB4444 doesn't work
524 * because we can't tell the hardware to ignore the color components
525 * and only use the alpha component. So we define our own texture
526 * formats that promote to ARGB8888 or ARGB4444 and set the color
527 * components to white. This way we get the correct result.
528 */
529
530 #if 0
531 /* Using MESA_FORMAT_RGBA8888 to store alpha-only textures should
532 * work but is space inefficient.
533 */
534
535 static GLboolean
536 _savage_texstore_a1114444(TEXSTORE_PARAMS);
537
538 static GLboolean
539 _savage_texstore_a1118888(TEXSTORE_PARAMS);
540
541 static struct gl_texture_format _savage_texformat_a1114444 = {
542 MESA_FORMAT_ARGB4444, /* MesaFormat */
543 GL_RGBA, /* BaseFormat */
544 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
545 4, /* RedBits */
546 4, /* GreenBits */
547 4, /* BlueBits */
548 4, /* AlphaBits */
549 0, /* LuminanceBits */
550 0, /* IntensityBits */
551 0, /* IndexBits */
552 0, /* DepthBits */
553 0, /* StencilBits */
554 2, /* TexelBytes */
555 _savage_texstore_a1114444, /* StoreTexImageFunc */
556 NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
557 * savageDDInitTextureFuncs */
558 };
559 static struct gl_texture_format _savage_texformat_a1118888 = {
560 MESA_FORMAT_ARGB8888, /* MesaFormat */
561 GL_RGBA, /* BaseFormat */
562 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
563 8, /* RedBits */
564 8, /* GreenBits */
565 8, /* BlueBits */
566 8, /* AlphaBits */
567 0, /* LuminanceBits */
568 0, /* IntensityBits */
569 0, /* IndexBits */
570 0, /* DepthBits */
571 0, /* StencilBits */
572 4, /* TexelBytes */
573 _savage_texstore_a1118888, /* StoreTexImageFunc */
574 NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
575 * savageDDInitTextureFuncs */
576 };
577
578
579 static GLboolean
580 _savage_texstore_a1114444(TEXSTORE_PARAMS)
581 {
582 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
583 baseInternalFormat,
584 baseInternalFormat,
585 srcWidth, srcHeight, srcDepth,
586 srcFormat, srcType, srcAddr,
587 srcPacking);
588 const GLchan *src = tempImage;
589 GLint img, row, col;
590
591 ASSERT(dstFormat == &_savage_texformat_a1114444);
592 ASSERT(baseInternalFormat == GL_ALPHA);
593
594 if (!tempImage)
595 return GL_FALSE;
596 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
597 for (img = 0; img < srcDepth; img++) {
598 GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
599 GLubyte *dstRow = (GLubyte *) dstAddr
600 + dstImageOffsets[dstZoffset + img] * texelBytes
601 + dstYoffset * dstRowStride
602 + dstXoffset * texelBytes;
603 for (row = 0; row < srcHeight; row++) {
604 GLushort *dstUI = (GLushort *) dstRow;
605 for (col = 0; col < srcWidth; col++) {
606 dstUI[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[0]),
607 255, 255, 255 );
608 src += 1;
609 }
610 dstRow += dstRowStride;
611 }
612 }
613 _mesa_free((void *) tempImage);
614
615 return GL_TRUE;
616 }
617
618
619 static GLboolean
620 _savage_texstore_a1118888(TEXSTORE_PARAMS)
621 {
622 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
623 baseInternalFormat,
624 baseInternalFormat,
625 srcWidth, srcHeight, srcDepth,
626 srcFormat, srcType, srcAddr,
627 srcPacking);
628 const GLchan *src = tempImage;
629 GLint img, row, col;
630
631 ASSERT(dstFormat == &_savage_texformat_a1118888);
632 ASSERT(baseInternalFormat == GL_ALPHA);
633
634 if (!tempImage)
635 return GL_FALSE;
636 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
637 for (img = 0; img < srcDepth; img++) {
638 GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
639 GLubyte *dstRow = (GLubyte *) dstAddr
640 + dstImageOffsets[dstZoffset + img] * texelBytes
641 + dstYoffset * dstRowStride
642 + dstXoffset * texelBytes;
643 for (row = 0; row < srcHeight; row++) {
644 GLuint *dstUI = (GLuint *) dstRow;
645 for (col = 0; col < srcWidth; col++) {
646 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[0]),
647 255, 255, 255 );
648 src += 1;
649 }
650 dstRow += dstRowStride;
651 }
652 }
653 _mesa_free((void *) tempImage);
654
655 return GL_TRUE;
656 }
657 #endif
658
659
660 /* Called by the _mesa_store_teximage[123]d() functions. */
661 static gl_format
662 savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
663 GLenum format, GLenum type )
664 {
665 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
666 const GLboolean do32bpt =
667 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
668 const GLboolean force16bpt =
669 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
670 const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
671 (void) format;
672
673 switch ( internalFormat ) {
674 case 4:
675 case GL_RGBA:
676 case GL_COMPRESSED_RGBA:
677 switch ( type ) {
678 case GL_UNSIGNED_INT_10_10_10_2:
679 case GL_UNSIGNED_INT_2_10_10_10_REV:
680 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
681 case GL_UNSIGNED_SHORT_4_4_4_4:
682 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
683 return MESA_FORMAT_ARGB4444;
684 case GL_UNSIGNED_SHORT_5_5_5_1:
685 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
686 return MESA_FORMAT_ARGB1555;
687 default:
688 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
689 }
690
691 case 3:
692 case GL_RGB:
693 case GL_COMPRESSED_RGB:
694 switch ( type ) {
695 case GL_UNSIGNED_SHORT_4_4_4_4:
696 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
697 return MESA_FORMAT_ARGB4444;
698 case GL_UNSIGNED_SHORT_5_5_5_1:
699 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
700 return MESA_FORMAT_ARGB1555;
701 case GL_UNSIGNED_SHORT_5_6_5:
702 case GL_UNSIGNED_SHORT_5_6_5_REV:
703 return MESA_FORMAT_RGB565;
704 default:
705 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
706 }
707
708 case GL_RGBA8:
709 case GL_RGBA12:
710 case GL_RGBA16:
711 return !force16bpt ?
712 MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
713
714 case GL_RGB10_A2:
715 return !force16bpt ?
716 MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
717
718 case GL_RGBA4:
719 case GL_RGBA2:
720 return MESA_FORMAT_ARGB4444;
721
722 case GL_RGB5_A1:
723 return MESA_FORMAT_ARGB1555;
724
725 case GL_RGB8:
726 case GL_RGB10:
727 case GL_RGB12:
728 case GL_RGB16:
729 return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
730
731 case GL_RGB5:
732 case GL_RGB4:
733 case GL_R3_G3_B2:
734 return MESA_FORMAT_RGB565;
735
736 case GL_ALPHA:
737 case GL_COMPRESSED_ALPHA:
738 #if 0
739 return isSavage4 ? MESA_FORMAT_a8 : (
740 do32bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
741 #else
742 if (isSavage4)
743 return MESA_FORMAT_A8;
744 else if (do32bpt)
745 return MESA_FORMAT_ARGB8888;
746 else
747 return MESA_FORMAT_ARGB4444;
748 #endif
749 case GL_ALPHA4:
750 #if 0
751 return isSavage4 ? MESA_FORMAT_a8 : &_savage_texformat_a1114444;
752 #else
753 if (isSavage4)
754 return MESA_FORMAT_A8;
755 else
756 return MESA_FORMAT_ARGB4444;
757 #endif
758 case GL_ALPHA8:
759 case GL_ALPHA12:
760 case GL_ALPHA16:
761 #if 0
762 return isSavage4 ? MESA_FORMAT_a8 : (
763 !force16bpt ? &_savage_texformat_a1118888 : &_savage_texformat_a1114444);
764 #else
765 if (isSavage4)
766 return MESA_FORMAT_A8;
767 else if (force16bpt)
768 return MESA_FORMAT_ARGB4444;
769 else
770 return MESA_FORMAT_ARGB8888;
771 #endif
772 case 1:
773 case GL_LUMINANCE:
774 case GL_COMPRESSED_LUMINANCE:
775 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
776 return isSavage4 ? MESA_FORMAT_L8 : (
777 do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555);
778 case GL_LUMINANCE4:
779 return isSavage4 ? MESA_FORMAT_L8 : MESA_FORMAT_ARGB1555;
780 case GL_LUMINANCE8:
781 case GL_LUMINANCE12:
782 case GL_LUMINANCE16:
783 return isSavage4 ? MESA_FORMAT_L8 : (
784 !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555);
785
786 case 2:
787 case GL_LUMINANCE_ALPHA:
788 case GL_COMPRESSED_LUMINANCE_ALPHA:
789 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
790 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
791 case GL_LUMINANCE4_ALPHA4:
792 case GL_LUMINANCE6_ALPHA2:
793 return MESA_FORMAT_ARGB4444;
794 case GL_LUMINANCE8_ALPHA8:
795 case GL_LUMINANCE12_ALPHA4:
796 case GL_LUMINANCE12_ALPHA12:
797 case GL_LUMINANCE16_ALPHA16:
798 return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
799 #if 0
800 /* TFT_I8 produces garbage on ProSavageDDR and subsequent texture
801 * disable keeps rendering garbage. Disabled for now. */
802 case GL_INTENSITY:
803 case GL_COMPRESSED_INTENSITY:
804 return isSavage4 ? MESA_FORMAT_i8 : (
805 do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444);
806 case GL_INTENSITY4:
807 return isSavage4 ? MESA_FORMAT_i8 : MESA_FORMAT_ARGB4444;
808 case GL_INTENSITY8:
809 case GL_INTENSITY12:
810 case GL_INTENSITY16:
811 return isSavage4 ? MESA_FORMAT_i8 : (
812 !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444);
813 #else
814 case GL_INTENSITY:
815 case GL_COMPRESSED_INTENSITY:
816 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
817 case GL_INTENSITY4:
818 return MESA_FORMAT_ARGB4444;
819 case GL_INTENSITY8:
820 case GL_INTENSITY12:
821 case GL_INTENSITY16:
822 return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
823 #endif
824
825 case GL_RGB_S3TC:
826 case GL_RGB4_S3TC:
827 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
828 return MESA_FORMAT_RGB_DXT1;
829 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
830 return MESA_FORMAT_RGBA_DXT1;
831
832 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
833 return MESA_FORMAT_RGBA_DXT3;
834
835 case GL_RGBA_S3TC:
836 case GL_RGBA4_S3TC:
837 if (!isSavage4)
838 /* Not the best choice but Savage3D/MX/IX don't support DXT3 or DXT5. */
839 return MESA_FORMAT_RGBA_DXT1;
840 /* fall through */
841 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
842 return MESA_FORMAT_RGBA_DXT5;
843
844 /*
845 case GL_COLOR_INDEX:
846 case GL_COLOR_INDEX1_EXT:
847 case GL_COLOR_INDEX2_EXT:
848 case GL_COLOR_INDEX4_EXT:
849 case GL_COLOR_INDEX8_EXT:
850 case GL_COLOR_INDEX12_EXT:
851 case GL_COLOR_INDEX16_EXT:
852 return &_mesa_texformat_ci8;
853 */
854 default:
855 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
856 return MESA_FORMAT_NONE;
857 }
858 }
859
860 static void savageSetTexImages( savageContextPtr imesa,
861 const struct gl_texture_object *tObj )
862 {
863 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
864 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
865 GLuint offset, i, textureFormat, tileIndex, size;
866 GLint firstLevel, lastLevel;
867
868 assert(t);
869 assert(image);
870
871 switch (image->TexFormat) {
872 case MESA_FORMAT_ARGB8888:
873 textureFormat = TFT_ARGB8888;
874 t->texelBytes = tileIndex = 4;
875 break;
876 case MESA_FORMAT_ARGB1555:
877 textureFormat = TFT_ARGB1555;
878 t->texelBytes = tileIndex = 2;
879 break;
880 case MESA_FORMAT_ARGB4444:
881 textureFormat = TFT_ARGB4444;
882 t->texelBytes = tileIndex = 2;
883 break;
884 case MESA_FORMAT_RGB565:
885 textureFormat = TFT_RGB565;
886 t->texelBytes = tileIndex = 2;
887 break;
888 case MESA_FORMAT_L8:
889 textureFormat = TFT_L8;
890 t->texelBytes = tileIndex = 1;
891 break;
892 case MESA_FORMAT_I8:
893 textureFormat = TFT_I8;
894 t->texelBytes = tileIndex = 1;
895 break;
896 case MESA_FORMAT_A8:
897 textureFormat = TFT_A8;
898 t->texelBytes = tileIndex = 1;
899 break;
900 case MESA_FORMAT_RGB_DXT1:
901 textureFormat = TFT_S3TC4Bit;
902 tileIndex = TILE_INDEX_DXT1;
903 t->texelBytes = 8;
904 break;
905 case MESA_FORMAT_RGBA_DXT1:
906 textureFormat = TFT_S3TC4Bit;
907 tileIndex = TILE_INDEX_DXT1;
908 t->texelBytes = 8;
909 break;
910 case MESA_FORMAT_RGBA_DXT3:
911 textureFormat = TFT_S3TC4A4Bit;
912 tileIndex = TILE_INDEX_DXTn;
913 t->texelBytes = 16;
914 break;
915 case MESA_FORMAT_RGBA_DXT5:
916 textureFormat = TFT_S3TC4CA4Bit;
917 tileIndex = TILE_INDEX_DXTn;
918 t->texelBytes = 16;
919 break;
920 default:
921 _mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
922 return;
923 }
924 t->hwFormat = textureFormat;
925
926 /* Select tiling format depending on the chipset and texture format */
927 if (imesa->savageScreen->chipset <= S3_SAVAGE4)
928 t->tileInfo = &tileInfo_s3d_s4[tileIndex];
929 else
930 t->tileInfo = &tileInfo_pro[tileIndex];
931
932 /* Compute which mipmap levels we really want to send to the hardware.
933 */
934 driCalculateTextureFirstLastLevel( &t->base );
935 firstLevel = t->base.firstLevel;
936 lastLevel = t->base.lastLevel;
937
938 /* Figure out the size now (and count the levels). Upload won't be
939 * done until later. If the number of tiles changes, it means that
940 * this function is called for the first time on this tex object or
941 * the image or the destination color format changed. So all tiles
942 * are marked as dirty.
943 */
944 offset = 0;
945 size = 1;
946 for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) {
947 GLuint nTiles;
948 nTiles = savageTexImageTiles (image->Width2, image->Height2, t->tileInfo);
949 if (t->image[i].nTiles != nTiles) {
950 GLuint words = (nTiles + 31) / 32;
951 if (t->image[i].nTiles != 0) {
952 free(t->image[i].dirtyTiles);
953 }
954 t->image[i].dirtyTiles = malloc(words*sizeof(GLuint));
955 memset(t->image[i].dirtyTiles, ~0, words*sizeof(GLuint));
956 }
957 t->image[i].nTiles = nTiles;
958
959 t->image[i].offset = offset;
960
961 image = tObj->Image[0][i];
962 if (t->texelBytes >= 8)
963 size = savageCompressedTexImageSize (image->Width2, image->Height2,
964 t->texelBytes);
965 else
966 size = savageTexImageSize (image->Width2, image->Height2,
967 t->texelBytes);
968 offset += size;
969 }
970
971 t->base.lastLevel = i-1;
972 t->base.totalSize = offset;
973 /* the last three mipmap levels don't add to the offset. They are packed
974 * into 64 pixels. */
975 if (size == 0)
976 t->base.totalSize += (t->texelBytes >= 8 ? 4 : 64) * t->texelBytes;
977 /* 2k-aligned (really needed?) */
978 t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
979 }
980
981 void savageDestroyTexObj(savageContextPtr imesa, savageTexObjPtr t)
982 {
983 GLuint i;
984
985 /* Free dirty tiles bit vectors */
986 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) {
987 if (t->image[i].nTiles)
988 free (t->image[i].dirtyTiles);
989 }
990
991 /* See if it was the driver's current object.
992 */
993 if ( imesa != NULL )
994 {
995 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ )
996 {
997 if ( &t->base == imesa->CurrentTexObj[ i ] ) {
998 assert( t->base.bound & (1 << i) );
999 imesa->CurrentTexObj[ i ] = NULL;
1000 }
1001 }
1002 }
1003 }
1004
1005 /* Upload a texture's images to one of the texture heaps. May have to
1006 * eject our own and/or other client's texture objects to make room
1007 * for the upload.
1008 */
1009 static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t )
1010 {
1011 const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
1012 GLuint i;
1013
1014 assert(t);
1015
1016 LOCK_HARDWARE(imesa);
1017
1018 /* Do we need to eject LRU texture objects?
1019 */
1020 if (!t->base.memBlock) {
1021 GLint heap;
1022 GLuint ofs;
1023
1024 heap = driAllocateTexture(imesa->textureHeaps, imesa->lastTexHeap,
1025 (driTextureObject *)t);
1026 if (heap == -1) {
1027 UNLOCK_HARDWARE(imesa);
1028 return;
1029 }
1030
1031 ofs = t->base.memBlock->ofs;
1032 t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
1033 t->bufAddr = (GLubyte *)imesa->savageScreen->texVirtual[heap] + ofs;
1034 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
1035 }
1036
1037 /* Let the world know we've used this memory recently.
1038 */
1039 driUpdateTextureLRU( &t->base );
1040 UNLOCK_HARDWARE(imesa);
1041
1042 if (t->base.dirty_images[0] || t->dirtySubImages) {
1043 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1044 fprintf(stderr, "Texture upload: |");
1045
1046 /* Heap timestamps are only reliable with Savage DRM 2.3.x or
1047 * later. Earlier versions had only 16 bit time stamps which
1048 * would wrap too frequently. */
1049 if (imesa->savageScreen->driScrnPriv->drm_version.minor >= 3) {
1050 unsigned int heap = t->base.heap->heapId;
1051 LOCK_HARDWARE(imesa);
1052 savageWaitEvent (imesa, imesa->textureHeaps[heap]->timestamp);
1053 } else {
1054 savageFlushVertices (imesa);
1055 LOCK_HARDWARE(imesa);
1056 savageFlushCmdBufLocked (imesa, GL_FALSE);
1057 WAIT_IDLE_EMPTY_LOCKED(imesa);
1058 }
1059
1060 for (i = 0 ; i < numLevels ; i++) {
1061 const GLint j = t->base.firstLevel + i; /* the texObj's level */
1062 if (t->base.dirty_images[0] & (1 << j)) {
1063 savageMarkAllTiles(t, j);
1064 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1065 fprintf (stderr, "*");
1066 } else if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) {
1067 if (t->dirtySubImages & (1 << j))
1068 fprintf (stderr, ".");
1069 else
1070 fprintf (stderr, " ");
1071 }
1072 if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j))
1073 savageUploadTexLevel( t, j );
1074 }
1075
1076 UNLOCK_HARDWARE(imesa);
1077 t->base.dirty_images[0] = 0;
1078 t->dirtySubImages = 0;
1079
1080 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1081 fprintf(stderr, "|\n");
1082 }
1083 }
1084
1085
1086 static void
1087 savage4_set_wrap_mode( savageContextPtr imesa, unsigned unit,
1088 GLenum s_mode, GLenum t_mode )
1089 {
1090 switch( s_mode ) {
1091 case GL_REPEAT:
1092 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Wrap;
1093 break;
1094 case GL_CLAMP:
1095 case GL_CLAMP_TO_EDGE:
1096 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Clamp;
1097 break;
1098 case GL_MIRRORED_REPEAT:
1099 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Mirror;
1100 break;
1101 }
1102
1103 switch( t_mode ) {
1104 case GL_REPEAT:
1105 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Wrap;
1106 break;
1107 case GL_CLAMP:
1108 case GL_CLAMP_TO_EDGE:
1109 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Clamp;
1110 break;
1111 case GL_MIRRORED_REPEAT:
1112 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Mirror;
1113 break;
1114 }
1115 }
1116
1117
1118 /**
1119 * Sets the hardware bits for the specified GL texture filter modes.
1120 *
1121 * \todo
1122 * Does the Savage4 have the ability to select the magnification filter?
1123 */
1124 static void
1125 savage4_set_filter_mode( savageContextPtr imesa, unsigned unit,
1126 GLenum minFilter, GLenum magFilter )
1127 {
1128 (void) magFilter;
1129
1130 switch (minFilter) {
1131 case GL_NEAREST:
1132 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1133 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1134 break;
1135
1136 case GL_LINEAR:
1137 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1138 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1139 break;
1140
1141 case GL_NEAREST_MIPMAP_NEAREST:
1142 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1143 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1144 break;
1145
1146 case GL_LINEAR_MIPMAP_NEAREST:
1147 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1148 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1149 break;
1150
1151 case GL_NEAREST_MIPMAP_LINEAR:
1152 case GL_LINEAR_MIPMAP_LINEAR:
1153 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Trilin;
1154 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1155 break;
1156 }
1157 }
1158
1159
1160 static void savageUpdateTex0State_s4( GLcontext *ctx )
1161 {
1162 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1163 struct gl_texture_object *tObj;
1164 struct gl_texture_image *image;
1165 savageTexObjPtr t;
1166 GLuint format;
1167
1168 /* disable */
1169 imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
1170 imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
1171 imesa->regs.s4.texCtrl[0].ui = 0x20f040;
1172 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1173 return;
1174
1175 tObj = ctx->Texture.Unit[0]._Current;
1176 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1177 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1178 /* 3D texturing enabled, or texture border - fallback */
1179 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1180 return;
1181 }
1182
1183 /* Do 2D texture setup */
1184
1185 t = tObj->DriverData;
1186 if (!t) {
1187 t = savageAllocTexObj( tObj );
1188 if (!t)
1189 return;
1190 }
1191
1192 imesa->CurrentTexObj[0] = &t->base;
1193 t->base.bound |= 1;
1194
1195 if (t->base.dirty_images[0] || t->dirtySubImages) {
1196 savageSetTexImages(imesa, tObj);
1197 savageUploadTexImages(imesa, t);
1198 }
1199
1200 driUpdateTextureLRU( &t->base );
1201
1202 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1203
1204 switch (ctx->Texture.Unit[0].EnvMode) {
1205 case GL_REPLACE:
1206 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1207 switch(format)
1208 {
1209 case GL_LUMINANCE:
1210 case GL_RGB:
1211 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1212 break;
1213
1214 case GL_LUMINANCE_ALPHA:
1215 case GL_RGBA:
1216 case GL_INTENSITY:
1217 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Copy;
1218 break;
1219
1220 case GL_ALPHA:
1221 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1222 break;
1223 }
1224 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1225 &imesa->regs.s4.texBlendCtrl[0]);
1226 break;
1227
1228 case GL_DECAL:
1229 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1230 switch (format)
1231 {
1232 case GL_RGB:
1233 case GL_LUMINANCE:
1234 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1235 break;
1236
1237 case GL_RGBA:
1238 case GL_INTENSITY:
1239 case GL_LUMINANCE_ALPHA:
1240 imesa->regs.s4.texBlendCtrl[0].ui = TBC_DecalAlpha;
1241 break;
1242
1243 /*
1244 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1245 are undefined with GL_DECAL
1246 */
1247
1248 case GL_ALPHA:
1249 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1250 break;
1251 }
1252 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1253 &imesa->regs.s4.texBlendCtrl[0]);
1254 break;
1255
1256 case GL_MODULATE:
1257 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1258 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1259 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1260 &imesa->regs.s4.texBlendCtrl[0]);
1261 break;
1262
1263 case GL_BLEND:
1264 imesa->regs.s4.texBlendColor.ui = imesa->texEnvColor;
1265
1266 switch (format)
1267 {
1268 case GL_ALPHA:
1269 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1270 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1271 break;
1272
1273 case GL_LUMINANCE:
1274 case GL_RGB:
1275 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Blend0;
1276 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1277 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1278 imesa->regs.s4.texDescr.ni.tex1Width =
1279 imesa->regs.s4.texDescr.ni.tex0Width;
1280 imesa->regs.s4.texDescr.ni.tex1Height =
1281 imesa->regs.s4.texDescr.ni.tex0Height;
1282 imesa->regs.s4.texDescr.ni.tex1Fmt =
1283 imesa->regs.s4.texDescr.ni.tex0Fmt;
1284
1285 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1286 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Blend1;
1287
1288 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1289 imesa->bTexEn1 = GL_TRUE;
1290 break;
1291
1292 case GL_LUMINANCE_ALPHA:
1293 case GL_RGBA:
1294 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendAlpha0;
1295 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1296 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1297 imesa->regs.s4.texDescr.ni.tex1Width =
1298 imesa->regs.s4.texDescr.ni.tex0Width;
1299 imesa->regs.s4.texDescr.ni.tex1Height =
1300 imesa->regs.s4.texDescr.ni.tex0Height;
1301 imesa->regs.s4.texDescr.ni.tex1Fmt =
1302 imesa->regs.s4.texDescr.ni.tex0Fmt;
1303
1304 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1305 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendAlpha1;
1306
1307 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1308 imesa->bTexEn1 = GL_TRUE;
1309 break;
1310
1311 case GL_INTENSITY:
1312 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendInt0;
1313 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1314 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1315 imesa->regs.s4.texDescr.ni.tex1Width =
1316 imesa->regs.s4.texDescr.ni.tex0Width;
1317 imesa->regs.s4.texDescr.ni.tex1Height =
1318 imesa->regs.s4.texDescr.ni.tex0Height;
1319 imesa->regs.s4.texDescr.ni.tex1Fmt =
1320 imesa->regs.s4.texDescr.ni.tex0Fmt;
1321
1322 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1323 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendInt1;
1324
1325 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1326 imesa->regs.s4.texCtrl[0].ni.alphaArg1Invert = GL_TRUE;
1327 imesa->bTexEn1 = GL_TRUE;
1328 break;
1329 }
1330 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1331 &imesa->regs.s4.texBlendCtrl[0]);
1332 break;
1333
1334 case GL_ADD:
1335 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1336 switch (format)
1337 {
1338 case GL_ALPHA:
1339 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1340 break;
1341
1342 case GL_LUMINANCE:
1343 case GL_RGB:
1344 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1345 break;
1346
1347 case GL_LUMINANCE_ALPHA:
1348 case GL_RGBA:
1349 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1350 break;
1351
1352 case GL_INTENSITY:
1353 imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
1354 break;
1355 }
1356 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1357 &imesa->regs.s4.texBlendCtrl[0]);
1358 break;
1359
1360 #if GL_ARB_texture_env_combine
1361 case GL_COMBINE_ARB:
1362 __HWParseTexEnvCombine(imesa, 0, &imesa->regs.s4.texCtrl[0],
1363 &imesa->regs.s4.texBlendCtrl[0]);
1364 break;
1365 #endif
1366
1367 default:
1368 fprintf(stderr, "unknown tex env mode");
1369 exit(1);
1370 break;
1371 }
1372
1373 savage4_set_wrap_mode( imesa, 0, t->setup.sWrapMode, t->setup.tWrapMode );
1374 savage4_set_filter_mode( imesa, 0, t->setup.minFilter, t->setup.magFilter );
1375
1376 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1377 (imesa->regs.s4.texCtrl[0].ni.dBias != 0))
1378 {
1379 int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0) +
1380 SAVAGE4_LOD_OFFSET;
1381 if (bias < -256)
1382 bias = -256;
1383 else if (bias > 255)
1384 bias = 255;
1385 imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
1386 }
1387
1388 image = tObj->Image[0][tObj->BaseLevel];
1389 imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
1390 imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
1391 imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
1392 imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
1393 imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1394
1395 if (imesa->regs.s4.texDescr.ni.tex1En)
1396 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1397
1398 imesa->regs.s4.texAddr[0].ui = (uint32_t) t->setup.physAddr | 0x2;
1399 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1400 imesa->regs.s4.texAddr[0].ui |= 0x1;
1401
1402 return;
1403 }
1404 static void savageUpdateTex1State_s4( GLcontext *ctx )
1405 {
1406 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1407 struct gl_texture_object *tObj;
1408 struct gl_texture_image *image;
1409 savageTexObjPtr t;
1410 GLuint format;
1411
1412 /* disable */
1413 if(imesa->bTexEn1)
1414 {
1415 imesa->bTexEn1 = GL_FALSE;
1416 return;
1417 }
1418
1419 imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
1420 imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
1421 imesa->regs.s4.texCtrl[1].ui = 0x20f040;
1422 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
1423 if (ctx->Texture.Unit[1]._ReallyEnabled == 0)
1424 return;
1425
1426 tObj = ctx->Texture.Unit[1]._Current;
1427
1428 if ((ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1429 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1430 /* 3D texturing enabled, or texture border - fallback */
1431 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1432 return;
1433 }
1434
1435 /* Do 2D texture setup */
1436
1437 t = tObj->DriverData;
1438 if (!t) {
1439 t = savageAllocTexObj( tObj );
1440 if (!t)
1441 return;
1442 }
1443
1444 imesa->CurrentTexObj[1] = &t->base;
1445
1446 t->base.bound |= 2;
1447
1448 if (t->base.dirty_images[0] || t->dirtySubImages) {
1449 savageSetTexImages(imesa, tObj);
1450 savageUploadTexImages(imesa, t);
1451 }
1452
1453 driUpdateTextureLRU( &t->base );
1454
1455 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1456
1457 switch (ctx->Texture.Unit[1].EnvMode) {
1458 case GL_REPLACE:
1459 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1460 switch (format)
1461 {
1462 case GL_LUMINANCE:
1463 case GL_RGB:
1464 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal;
1465 break;
1466
1467 case GL_LUMINANCE_ALPHA:
1468 case GL_INTENSITY:
1469 case GL_RGBA:
1470 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Copy;
1471 break;
1472
1473 case GL_ALPHA:
1474 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1475 break;
1476 }
1477 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1478 break;
1479 case GL_MODULATE:
1480 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1481 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1482 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1483 break;
1484
1485 case GL_ADD:
1486 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1487 switch (format)
1488 {
1489 case GL_ALPHA:
1490 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1491 break;
1492
1493 case GL_LUMINANCE:
1494 case GL_RGB:
1495 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1496 break;
1497
1498 case GL_LUMINANCE_ALPHA:
1499 case GL_RGBA:
1500 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1501 break;
1502
1503 case GL_INTENSITY:
1504 imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
1505 break;
1506 }
1507 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1508 break;
1509
1510 #if GL_ARB_texture_env_combine
1511 case GL_COMBINE_ARB:
1512 __HWParseTexEnvCombine(imesa, 1, &texCtrl, &imesa->regs.s4.texBlendCtrl);
1513 break;
1514 #endif
1515
1516 case GL_DECAL:
1517 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1518
1519 switch (format)
1520 {
1521 case GL_LUMINANCE:
1522 case GL_RGB:
1523 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal1;
1524 break;
1525 case GL_LUMINANCE_ALPHA:
1526 case GL_INTENSITY:
1527 case GL_RGBA:
1528 imesa->regs.s4.texBlendCtrl[1].ui = TBC_DecalAlpha1;
1529 break;
1530
1531 /*
1532 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1533 // are undefined with GL_DECAL
1534 */
1535 case GL_ALPHA:
1536 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1537 break;
1538 }
1539 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1540 break;
1541
1542 case GL_BLEND:
1543 if (format == GL_LUMINANCE)
1544 {
1545 /*
1546 // This is a hack for GLQuake, invert.
1547 */
1548 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_TRUE;
1549 imesa->regs.s4.texBlendCtrl[1].ui = 0;
1550 }
1551 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1552 break;
1553
1554 default:
1555 fprintf(stderr, "unknown tex 1 env mode\n");
1556 exit(1);
1557 break;
1558 }
1559
1560 savage4_set_wrap_mode( imesa, 1, t->setup.sWrapMode, t->setup.tWrapMode );
1561 savage4_set_filter_mode( imesa, 1, t->setup.minFilter, t->setup.magFilter );
1562
1563 if((ctx->Texture.Unit[1].LodBias !=0.0F) ||
1564 (imesa->regs.s4.texCtrl[1].ni.dBias != 0))
1565 {
1566 int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0) +
1567 SAVAGE4_LOD_OFFSET;
1568 if (bias < -256)
1569 bias = -256;
1570 else if (bias > 255)
1571 bias = 255;
1572 imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
1573 }
1574
1575 image = tObj->Image[0][tObj->BaseLevel];
1576 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1577 imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
1578 imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
1579 imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
1580 imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1581 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1582
1583 imesa->regs.s4.texAddr[1].ui = (uint32_t) t->setup.physAddr | 2;
1584 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1585 imesa->regs.s4.texAddr[1].ui |= 0x1;
1586 }
1587 static void savageUpdateTexState_s3d( GLcontext *ctx )
1588 {
1589 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1590 struct gl_texture_object *tObj;
1591 struct gl_texture_image *image;
1592 savageTexObjPtr t;
1593 GLuint format;
1594
1595 /* disable */
1596 imesa->regs.s3d.texCtrl.ui = 0;
1597 imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
1598 imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
1599 imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
1600 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1601 return;
1602
1603 tObj = ctx->Texture.Unit[0]._Current;
1604 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1605 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1606 /* 3D texturing enabled, or texture border - fallback */
1607 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1608 return;
1609 }
1610
1611 /* Do 2D texture setup */
1612 t = tObj->DriverData;
1613 if (!t) {
1614 t = savageAllocTexObj( tObj );
1615 if (!t)
1616 return;
1617 }
1618
1619 imesa->CurrentTexObj[0] = &t->base;
1620 t->base.bound |= 1;
1621
1622 if (t->base.dirty_images[0] || t->dirtySubImages) {
1623 savageSetTexImages(imesa, tObj);
1624 savageUploadTexImages(imesa, t);
1625 }
1626
1627 driUpdateTextureLRU( &t->base );
1628
1629 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1630
1631 /* FIXME: copied from utah-glx, probably needs some tuning */
1632 switch (ctx->Texture.Unit[0].EnvMode) {
1633 case GL_DECAL:
1634 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECALALPHA_S3D;
1635 break;
1636 case GL_REPLACE:
1637 switch (format) {
1638 case GL_ALPHA: /* FIXME */
1639 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 1;
1640 break;
1641 case GL_LUMINANCE_ALPHA:
1642 case GL_RGBA:
1643 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 4;
1644 break;
1645 case GL_RGB:
1646 case GL_LUMINANCE:
1647 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
1648 break;
1649 case GL_INTENSITY:
1650 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
1651 }
1652 break;
1653 case GL_BLEND: /* hardware can't do GL_BLEND */
1654 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1655 return;
1656 case GL_MODULATE:
1657 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
1658 break;
1659 default:
1660 fprintf(stderr, "unknown tex env mode\n");
1661 /*exit(1);*/
1662 break;
1663 }
1664
1665 /* The Savage3D can't handle different wrapping modes in s and t.
1666 * If they are not the same, fall back to software. */
1667 if (t->setup.sWrapMode != t->setup.tWrapMode) {
1668 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1669 return;
1670 }
1671 imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
1672 imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
1673 imesa->regs.s3d.texCtrl.ni.wrapMode =
1674 (t->setup.sWrapMode == GL_REPEAT) ? TAM_Wrap : TAM_Clamp;
1675
1676 switch (t->setup.minFilter) {
1677 case GL_NEAREST:
1678 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1679 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1680 break;
1681
1682 case GL_LINEAR:
1683 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1684 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1685 break;
1686
1687 case GL_NEAREST_MIPMAP_NEAREST:
1688 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1689 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1690 break;
1691
1692 case GL_LINEAR_MIPMAP_NEAREST:
1693 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1694 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1695 break;
1696
1697 case GL_NEAREST_MIPMAP_LINEAR:
1698 case GL_LINEAR_MIPMAP_LINEAR:
1699 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Trilin;
1700 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1701 break;
1702 }
1703
1704 /* There is no way to specify a maximum mipmap level. We may have to
1705 disable mipmapping completely. */
1706 /*
1707 if (t->max_level < t->image[0].image->WidthLog2 ||
1708 t->max_level < t->image[0].image->HeightLog2) {
1709 texCtrl.ni.mipmapEnable = GL_TRUE;
1710 if (texCtrl.ni.filterMode == TFM_Trilin)
1711 texCtrl.ni.filterMode = TFM_Bilin;
1712 texCtrl.ni.filterMode = TFM_Point;
1713 }
1714 */
1715
1716 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1717 (imesa->regs.s3d.texCtrl.ni.dBias != 0))
1718 {
1719 int bias = (int)(ctx->Texture.Unit[0].LodBias * 16.0);
1720 if (bias < -256)
1721 bias = -256;
1722 else if (bias > 255)
1723 bias = 255;
1724 imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
1725 }
1726
1727 image = tObj->Image[0][tObj->BaseLevel];
1728 imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
1729 imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
1730 imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
1731 assert (t->hwFormat <= 7);
1732 imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
1733
1734 imesa->regs.s3d.texAddr.ui = (uint32_t) t->setup.physAddr | 2;
1735 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1736 imesa->regs.s3d.texAddr.ui |= 0x1;
1737 }
1738
1739
1740 static void savageTimestampTextures( savageContextPtr imesa )
1741 {
1742 /* Timestamp current texture objects for texture heap aging.
1743 * Only useful with long-lived 32-bit event tags available
1744 * with Savage DRM 2.3.x or later. */
1745 if ((imesa->CurrentTexObj[0] || imesa->CurrentTexObj[1]) &&
1746 imesa->savageScreen->driScrnPriv->drm_version.minor >= 3) {
1747 unsigned int e;
1748 FLUSH_BATCH(imesa);
1749 e = savageEmitEvent(imesa, SAVAGE_WAIT_3D);
1750 if (imesa->CurrentTexObj[0])
1751 imesa->CurrentTexObj[0]->timestamp = e;
1752 if (imesa->CurrentTexObj[1])
1753 imesa->CurrentTexObj[1]->timestamp = e;
1754 }
1755 }
1756
1757
1758 static void savageUpdateTextureState_s4( GLcontext *ctx )
1759 {
1760 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1761
1762 /* When a texture is about to change or be disabled, timestamp the
1763 * old texture(s). We'll have to wait for this time stamp before
1764 * uploading anything to the same texture heap.
1765 */
1766 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1767 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1768 (imesa->CurrentTexObj[1] && ctx->Texture.Unit[1]._ReallyEnabled &&
1769 ctx->Texture.Unit[1]._Current->DriverData != imesa->CurrentTexObj[1]) ||
1770 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled) ||
1771 (imesa->CurrentTexObj[1] && !ctx->Texture.Unit[1]._ReallyEnabled))
1772 savageTimestampTextures(imesa);
1773
1774 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1775 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound &= ~2;
1776 imesa->CurrentTexObj[0] = 0;
1777 imesa->CurrentTexObj[1] = 0;
1778 savageUpdateTex0State_s4( ctx );
1779 savageUpdateTex1State_s4( ctx );
1780 imesa->dirty |= (SAVAGE_UPLOAD_TEX0 |
1781 SAVAGE_UPLOAD_TEX1);
1782 }
1783 static void savageUpdateTextureState_s3d( GLcontext *ctx )
1784 {
1785 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1786
1787 /* When a texture is about to change or be disabled, timestamp the
1788 * old texture(s). We'll have to wait for this time stamp before
1789 * uploading anything to the same texture heap.
1790 */
1791 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1792 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1793 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled))
1794 savageTimestampTextures(imesa);
1795
1796 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1797 imesa->CurrentTexObj[0] = 0;
1798 savageUpdateTexState_s3d( ctx );
1799 imesa->dirty |= (SAVAGE_UPLOAD_TEX0);
1800 }
1801 void savageUpdateTextureState( GLcontext *ctx)
1802 {
1803 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1804 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
1805 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_FALSE);
1806 if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1807 savageUpdateTextureState_s4 (ctx);
1808 else
1809 savageUpdateTextureState_s3d (ctx);
1810 }
1811
1812
1813
1814 /*****************************************
1815 * DRIVER functions
1816 *****************************************/
1817
1818 static void savageTexEnv( GLcontext *ctx, GLenum target,
1819 GLenum pname, const GLfloat *param )
1820 {
1821 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1822
1823 if (pname == GL_TEXTURE_ENV_MODE) {
1824
1825 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1826
1827 } else if (pname == GL_TEXTURE_ENV_COLOR) {
1828
1829 struct gl_texture_unit *texUnit =
1830 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1831 const GLfloat *fc = texUnit->EnvColor;
1832 GLuint r, g, b, a;
1833 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
1834 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
1835 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
1836 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
1837
1838 imesa->texEnvColor = ((a << 24) | (r << 16) |
1839 (g << 8) | (b << 0));
1840
1841
1842 }
1843 }
1844
1845 /* Update the heap's time stamp, so the new image is not uploaded
1846 * while the old one is still in use. If the texture that is going to
1847 * be changed is currently bound, we need to timestamp the texture
1848 * first. */
1849 static void savageTexImageChanged (savageTexObjPtr t) {
1850 if (t->base.heap) {
1851 if (t->base.bound)
1852 savageTimestampTextures(
1853 (savageContextPtr)t->base.heap->driverContext);
1854 if (t->base.timestamp > t->base.heap->timestamp)
1855 t->base.heap->timestamp = t->base.timestamp;
1856 }
1857 }
1858
1859 static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
1860 GLint internalFormat,
1861 GLint width, GLint border,
1862 GLenum format, GLenum type, const GLvoid *pixels,
1863 const struct gl_pixelstore_attrib *packing,
1864 struct gl_texture_object *texObj,
1865 struct gl_texture_image *texImage )
1866 {
1867 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1868 if (t) {
1869 savageTexImageChanged (t);
1870 } else {
1871 t = savageAllocTexObj(texObj);
1872 if (!t) {
1873 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1874 return;
1875 }
1876 }
1877 _mesa_store_teximage1d( ctx, target, level, internalFormat,
1878 width, border, format, type,
1879 pixels, packing, texObj, texImage );
1880 t->base.dirty_images[0] |= (1 << level);
1881 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1882 }
1883
1884 static void savageTexSubImage1D( GLcontext *ctx,
1885 GLenum target,
1886 GLint level,
1887 GLint xoffset,
1888 GLsizei width,
1889 GLenum format, GLenum type,
1890 const GLvoid *pixels,
1891 const struct gl_pixelstore_attrib *packing,
1892 struct gl_texture_object *texObj,
1893 struct gl_texture_image *texImage )
1894 {
1895 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1896 assert( t ); /* this _should_ be true */
1897 if (t) {
1898 savageTexImageChanged (t);
1899 savageMarkDirtyTiles(t, level, texImage->Width2, 1,
1900 xoffset, 0, width, 1);
1901 } else {
1902 t = savageAllocTexObj(texObj);
1903 if (!t) {
1904 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
1905 return;
1906 }
1907 t->base.dirty_images[0] |= (1 << level);
1908 }
1909 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
1910 format, type, pixels, packing, texObj,
1911 texImage);
1912 t->dirtySubImages |= (1 << level);
1913 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1914 }
1915
1916 static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1917 GLint internalFormat,
1918 GLint width, GLint height, GLint border,
1919 GLenum format, GLenum type, const GLvoid *pixels,
1920 const struct gl_pixelstore_attrib *packing,
1921 struct gl_texture_object *texObj,
1922 struct gl_texture_image *texImage )
1923 {
1924 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1925 if (t) {
1926 savageTexImageChanged (t);
1927 } else {
1928 t = savageAllocTexObj(texObj);
1929 if (!t) {
1930 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1931 return;
1932 }
1933 }
1934 _mesa_store_teximage2d( ctx, target, level, internalFormat,
1935 width, height, border, format, type,
1936 pixels, packing, texObj, texImage );
1937 t->base.dirty_images[0] |= (1 << level);
1938 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1939 }
1940
1941 static void savageTexSubImage2D( GLcontext *ctx,
1942 GLenum target,
1943 GLint level,
1944 GLint xoffset, GLint yoffset,
1945 GLsizei width, GLsizei height,
1946 GLenum format, GLenum type,
1947 const GLvoid *pixels,
1948 const struct gl_pixelstore_attrib *packing,
1949 struct gl_texture_object *texObj,
1950 struct gl_texture_image *texImage )
1951 {
1952 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1953 assert( t ); /* this _should_ be true */
1954 if (t) {
1955 savageTexImageChanged (t);
1956 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
1957 xoffset, yoffset, width, height);
1958 } else {
1959 t = savageAllocTexObj(texObj);
1960 if (!t) {
1961 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1962 return;
1963 }
1964 t->base.dirty_images[0] |= (1 << level);
1965 }
1966 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
1967 height, format, type, pixels, packing, texObj,
1968 texImage);
1969 t->dirtySubImages |= (1 << level);
1970 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1971 }
1972
1973 static void
1974 savageCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1975 GLint internalFormat,
1976 GLint width, GLint height, GLint border,
1977 GLsizei imageSize, const GLvoid *data,
1978 struct gl_texture_object *texObj,
1979 struct gl_texture_image *texImage )
1980 {
1981 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1982 if (t) {
1983 savageTexImageChanged (t);
1984 } else {
1985 t = savageAllocTexObj(texObj);
1986 if (!t) {
1987 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1988 return;
1989 }
1990 }
1991 _mesa_store_compressed_teximage2d( ctx, target, level, internalFormat,
1992 width, height, border, imageSize,
1993 data, texObj, texImage );
1994 t->base.dirty_images[0] |= (1 << level);
1995 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1996 }
1997
1998 static void
1999 savageCompressedTexSubImage2D( GLcontext *ctx,
2000 GLenum target,
2001 GLint level,
2002 GLint xoffset, GLint yoffset,
2003 GLsizei width, GLsizei height,
2004 GLenum format, GLsizei imageSize,
2005 const GLvoid *data,
2006 struct gl_texture_object *texObj,
2007 struct gl_texture_image *texImage )
2008 {
2009 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
2010 assert( t ); /* this _should_ be true */
2011 if (t) {
2012 savageTexImageChanged (t);
2013 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
2014 xoffset, yoffset, width, height);
2015 } else {
2016 t = savageAllocTexObj(texObj);
2017 if (!t) {
2018 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2019 return;
2020 }
2021 t->base.dirty_images[0] |= (1 << level);
2022 }
2023 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset,
2024 width, height, format, imageSize,
2025 data, texObj, texImage);
2026 t->dirtySubImages |= (1 << level);
2027 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
2028 }
2029
2030 static void savageTexParameter( GLcontext *ctx, GLenum target,
2031 struct gl_texture_object *tObj,
2032 GLenum pname, const GLfloat *params )
2033 {
2034 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
2035 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2036
2037 if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
2038 return;
2039
2040 switch (pname) {
2041 case GL_TEXTURE_MIN_FILTER:
2042 case GL_TEXTURE_MAG_FILTER:
2043 savageSetTexFilter(t,tObj->MinFilter,tObj->MagFilter);
2044 break;
2045
2046 case GL_TEXTURE_WRAP_S:
2047 case GL_TEXTURE_WRAP_T:
2048 savageSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
2049 break;
2050
2051 case GL_TEXTURE_BORDER_COLOR:
2052 savageSetTexBorderColor(t,tObj->BorderColor);
2053 break;
2054
2055 default:
2056 return;
2057 }
2058
2059 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2060 }
2061
2062 static void savageBindTexture( GLcontext *ctx, GLenum target,
2063 struct gl_texture_object *tObj )
2064 {
2065 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2066
2067 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) ||
2068 (tObj->DriverData != NULL) );
2069
2070 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2071 }
2072
2073 static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
2074 {
2075 driTextureObject *t = (driTextureObject *)tObj->DriverData;
2076 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2077
2078 if (t) {
2079 if (t->bound)
2080 savageTimestampTextures(imesa);
2081
2082 driDestroyTextureObject(t);
2083 }
2084 /* Free mipmap images and the texture object itself */
2085 _mesa_delete_texture_object(ctx, tObj);
2086 }
2087
2088
2089 static struct gl_texture_object *
2090 savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
2091 {
2092 struct gl_texture_object *obj;
2093 obj = _mesa_new_texture_object(ctx, name, target);
2094 savageAllocTexObj( obj );
2095
2096 return obj;
2097 }
2098
2099 void savageDDInitTextureFuncs( struct dd_function_table *functions )
2100 {
2101 functions->TexEnv = savageTexEnv;
2102 functions->ChooseTextureFormat = savageChooseTextureFormat;
2103 functions->TexImage1D = savageTexImage1D;
2104 functions->TexSubImage1D = savageTexSubImage1D;
2105 functions->TexImage2D = savageTexImage2D;
2106 functions->TexSubImage2D = savageTexSubImage2D;
2107 functions->CompressedTexImage2D = savageCompressedTexImage2D;
2108 functions->CompressedTexSubImage2D = savageCompressedTexSubImage2D;
2109 functions->BindTexture = savageBindTexture;
2110 functions->NewTextureObject = savageNewTextureObject;
2111 functions->DeleteTexture = savageDeleteTexture;
2112 functions->IsTextureResident = driIsTextureResident;
2113 functions->TexParameter = savageTexParameter;
2114
2115 /* Texel fetching with our custom texture formats works just like
2116 * the standard argb formats. */
2117 #if 0
2118 _savage_texformat_a1114444.FetchTexel1D = _mesa_texformat_argb4444.FetchTexel1D;
2119 _savage_texformat_a1114444.FetchTexel2D = _mesa_texformat_argb4444.FetchTexel2D;
2120 _savage_texformat_a1114444.FetchTexel3D = _mesa_texformat_argb4444.FetchTexel3D;
2121 _savage_texformat_a1114444.FetchTexel1Df= _mesa_texformat_argb4444.FetchTexel1Df;
2122 _savage_texformat_a1114444.FetchTexel2Df= _mesa_texformat_argb4444.FetchTexel2Df;
2123 _savage_texformat_a1114444.FetchTexel3Df= _mesa_texformat_argb4444.FetchTexel3Df;
2124
2125 _savage_texformat_a1118888.FetchTexel1D = _mesa_texformat_argb8888.FetchTexel1D;
2126 _savage_texformat_a1118888.FetchTexel2D = _mesa_texformat_argb8888.FetchTexel2D;
2127 _savage_texformat_a1118888.FetchTexel3D = _mesa_texformat_argb8888.FetchTexel3D;
2128 _savage_texformat_a1118888.FetchTexel1Df= _mesa_texformat_argb8888.FetchTexel1Df;
2129 _savage_texformat_a1118888.FetchTexel2Df= _mesa_texformat_argb8888.FetchTexel2Df;
2130 _savage_texformat_a1118888.FetchTexel3Df= _mesa_texformat_argb8888.FetchTexel3Df;
2131 #endif
2132 }