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