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