Merge branch 'gallium-no-rhw-position'
[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 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 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 assert(t->base.memBlock);
1025 ofs = t->base.memBlock->ofs;
1026 t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
1027 t->bufAddr = (GLubyte *)imesa->savageScreen->texVirtual[heap] + ofs;
1028 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
1029 }
1030
1031 /* Let the world know we've used this memory recently.
1032 */
1033 driUpdateTextureLRU( &t->base );
1034 UNLOCK_HARDWARE(imesa);
1035
1036 if (t->base.dirty_images[0] || t->dirtySubImages) {
1037 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1038 fprintf(stderr, "Texture upload: |");
1039
1040 /* Heap timestamps are only reliable with Savage DRM 2.3.x or
1041 * later. Earlier versions had only 16 bit time stamps which
1042 * would wrap too frequently. */
1043 if (imesa->savageScreen->driScrnPriv->drm_version.minor >= 3) {
1044 unsigned int heap = t->base.heap->heapId;
1045 LOCK_HARDWARE(imesa);
1046 savageWaitEvent (imesa, imesa->textureHeaps[heap]->timestamp);
1047 } else {
1048 savageFlushVertices (imesa);
1049 LOCK_HARDWARE(imesa);
1050 savageFlushCmdBufLocked (imesa, GL_FALSE);
1051 WAIT_IDLE_EMPTY_LOCKED(imesa);
1052 }
1053
1054 for (i = 0 ; i < numLevels ; i++) {
1055 const GLint j = t->base.firstLevel + i; /* the texObj's level */
1056 if (t->base.dirty_images[0] & (1 << j)) {
1057 savageMarkAllTiles(t, j);
1058 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1059 fprintf (stderr, "*");
1060 } else if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) {
1061 if (t->dirtySubImages & (1 << j))
1062 fprintf (stderr, ".");
1063 else
1064 fprintf (stderr, " ");
1065 }
1066 if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j))
1067 savageUploadTexLevel( t, j );
1068 }
1069
1070 UNLOCK_HARDWARE(imesa);
1071 t->base.dirty_images[0] = 0;
1072 t->dirtySubImages = 0;
1073
1074 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
1075 fprintf(stderr, "|\n");
1076 }
1077 }
1078
1079
1080 static void
1081 savage4_set_wrap_mode( savageContextPtr imesa, unsigned unit,
1082 GLenum s_mode, GLenum t_mode )
1083 {
1084 switch( s_mode ) {
1085 case GL_REPEAT:
1086 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Wrap;
1087 break;
1088 case GL_CLAMP:
1089 case GL_CLAMP_TO_EDGE:
1090 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Clamp;
1091 break;
1092 case GL_MIRRORED_REPEAT:
1093 imesa->regs.s4.texCtrl[ unit ].ni.uMode = TAM_Mirror;
1094 break;
1095 }
1096
1097 switch( t_mode ) {
1098 case GL_REPEAT:
1099 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Wrap;
1100 break;
1101 case GL_CLAMP:
1102 case GL_CLAMP_TO_EDGE:
1103 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Clamp;
1104 break;
1105 case GL_MIRRORED_REPEAT:
1106 imesa->regs.s4.texCtrl[ unit ].ni.vMode = TAM_Mirror;
1107 break;
1108 }
1109 }
1110
1111
1112 /**
1113 * Sets the hardware bits for the specified GL texture filter modes.
1114 *
1115 * \todo
1116 * Does the Savage4 have the ability to select the magnification filter?
1117 */
1118 static void
1119 savage4_set_filter_mode( savageContextPtr imesa, unsigned unit,
1120 GLenum minFilter, GLenum magFilter )
1121 {
1122 (void) magFilter;
1123
1124 switch (minFilter) {
1125 case GL_NEAREST:
1126 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1127 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1128 break;
1129
1130 case GL_LINEAR:
1131 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1132 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_FALSE;
1133 break;
1134
1135 case GL_NEAREST_MIPMAP_NEAREST:
1136 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Point;
1137 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1138 break;
1139
1140 case GL_LINEAR_MIPMAP_NEAREST:
1141 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Bilin;
1142 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1143 break;
1144
1145 case GL_NEAREST_MIPMAP_LINEAR:
1146 case GL_LINEAR_MIPMAP_LINEAR:
1147 imesa->regs.s4.texCtrl[ unit ].ni.filterMode = TFM_Trilin;
1148 imesa->regs.s4.texCtrl[ unit ].ni.mipmapEnable = GL_TRUE;
1149 break;
1150 }
1151 }
1152
1153
1154 static void savageUpdateTex0State_s4( GLcontext *ctx )
1155 {
1156 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1157 struct gl_texture_object *tObj;
1158 struct gl_texture_image *image;
1159 savageTexObjPtr t;
1160 GLuint format;
1161
1162 /* disable */
1163 imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
1164 imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
1165 imesa->regs.s4.texCtrl[0].ui = 0x20f040;
1166 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1167 return;
1168
1169 tObj = ctx->Texture.Unit[0]._Current;
1170 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1171 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1172 /* 3D texturing enabled, or texture border - fallback */
1173 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1174 return;
1175 }
1176
1177 /* Do 2D texture setup */
1178
1179 t = tObj->DriverData;
1180 if (!t) {
1181 t = savageAllocTexObj( tObj );
1182 if (!t)
1183 return;
1184 }
1185
1186 imesa->CurrentTexObj[0] = &t->base;
1187 t->base.bound |= 1;
1188
1189 if (t->base.dirty_images[0] || t->dirtySubImages) {
1190 savageSetTexImages(imesa, tObj);
1191 savageUploadTexImages(imesa, t);
1192 }
1193
1194 driUpdateTextureLRU( &t->base );
1195
1196 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1197
1198 switch (ctx->Texture.Unit[0].EnvMode) {
1199 case GL_REPLACE:
1200 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1201 switch(format)
1202 {
1203 case GL_LUMINANCE:
1204 case GL_RGB:
1205 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1206 break;
1207
1208 case GL_LUMINANCE_ALPHA:
1209 case GL_RGBA:
1210 case GL_INTENSITY:
1211 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Copy;
1212 break;
1213
1214 case GL_ALPHA:
1215 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1216 break;
1217 }
1218 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1219 &imesa->regs.s4.texBlendCtrl[0]);
1220 break;
1221
1222 case GL_DECAL:
1223 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1224 switch (format)
1225 {
1226 case GL_RGB:
1227 case GL_LUMINANCE:
1228 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
1229 break;
1230
1231 case GL_RGBA:
1232 case GL_INTENSITY:
1233 case GL_LUMINANCE_ALPHA:
1234 imesa->regs.s4.texBlendCtrl[0].ui = TBC_DecalAlpha;
1235 break;
1236
1237 /*
1238 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1239 are undefined with GL_DECAL
1240 */
1241
1242 case GL_ALPHA:
1243 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
1244 break;
1245 }
1246 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1247 &imesa->regs.s4.texBlendCtrl[0]);
1248 break;
1249
1250 case GL_MODULATE:
1251 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1252 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1253 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1254 &imesa->regs.s4.texBlendCtrl[0]);
1255 break;
1256
1257 case GL_BLEND:
1258 imesa->regs.s4.texBlendColor.ui = imesa->texEnvColor;
1259
1260 switch (format)
1261 {
1262 case GL_ALPHA:
1263 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1264 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1265 break;
1266
1267 case GL_LUMINANCE:
1268 case GL_RGB:
1269 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Blend0;
1270 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1271 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1272 imesa->regs.s4.texDescr.ni.tex1Width =
1273 imesa->regs.s4.texDescr.ni.tex0Width;
1274 imesa->regs.s4.texDescr.ni.tex1Height =
1275 imesa->regs.s4.texDescr.ni.tex0Height;
1276 imesa->regs.s4.texDescr.ni.tex1Fmt =
1277 imesa->regs.s4.texDescr.ni.tex0Fmt;
1278
1279 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1280 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Blend1;
1281
1282 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1283 imesa->bTexEn1 = GL_TRUE;
1284 break;
1285
1286 case GL_LUMINANCE_ALPHA:
1287 case GL_RGBA:
1288 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendAlpha0;
1289 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1290 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1291 imesa->regs.s4.texDescr.ni.tex1Width =
1292 imesa->regs.s4.texDescr.ni.tex0Width;
1293 imesa->regs.s4.texDescr.ni.tex1Height =
1294 imesa->regs.s4.texDescr.ni.tex0Height;
1295 imesa->regs.s4.texDescr.ni.tex1Fmt =
1296 imesa->regs.s4.texDescr.ni.tex0Fmt;
1297
1298 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1299 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendAlpha1;
1300
1301 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1302 imesa->bTexEn1 = GL_TRUE;
1303 break;
1304
1305 case GL_INTENSITY:
1306 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendInt0;
1307 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1308 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1309 imesa->regs.s4.texDescr.ni.tex1Width =
1310 imesa->regs.s4.texDescr.ni.tex0Width;
1311 imesa->regs.s4.texDescr.ni.tex1Height =
1312 imesa->regs.s4.texDescr.ni.tex0Height;
1313 imesa->regs.s4.texDescr.ni.tex1Fmt =
1314 imesa->regs.s4.texDescr.ni.tex0Fmt;
1315
1316 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
1317 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendInt1;
1318
1319 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
1320 imesa->regs.s4.texCtrl[0].ni.alphaArg1Invert = GL_TRUE;
1321 imesa->bTexEn1 = GL_TRUE;
1322 break;
1323 }
1324 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1325 &imesa->regs.s4.texBlendCtrl[0]);
1326 break;
1327
1328 case GL_ADD:
1329 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
1330 switch (format)
1331 {
1332 case GL_ALPHA:
1333 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
1334 break;
1335
1336 case GL_LUMINANCE:
1337 case GL_RGB:
1338 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1339 break;
1340
1341 case GL_LUMINANCE_ALPHA:
1342 case GL_RGBA:
1343 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Add;
1344 break;
1345
1346 case GL_INTENSITY:
1347 imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
1348 break;
1349 }
1350 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
1351 &imesa->regs.s4.texBlendCtrl[0]);
1352 break;
1353
1354 #if GL_ARB_texture_env_combine
1355 case GL_COMBINE_ARB:
1356 __HWParseTexEnvCombine(imesa, 0, &imesa->regs.s4.texCtrl[0],
1357 &imesa->regs.s4.texBlendCtrl[0]);
1358 break;
1359 #endif
1360
1361 default:
1362 fprintf(stderr, "unknown tex env mode");
1363 exit(1);
1364 break;
1365 }
1366
1367 savage4_set_wrap_mode( imesa, 0, t->setup.sWrapMode, t->setup.tWrapMode );
1368 savage4_set_filter_mode( imesa, 0, t->setup.minFilter, t->setup.magFilter );
1369
1370 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1371 (imesa->regs.s4.texCtrl[0].ni.dBias != 0))
1372 {
1373 int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0) +
1374 SAVAGE4_LOD_OFFSET;
1375 if (bias < -256)
1376 bias = -256;
1377 else if (bias > 255)
1378 bias = 255;
1379 imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
1380 }
1381
1382 image = tObj->Image[0][tObj->BaseLevel];
1383 imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
1384 imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
1385 imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
1386 imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
1387 imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1388
1389 if (imesa->regs.s4.texDescr.ni.tex1En)
1390 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1391
1392 imesa->regs.s4.texAddr[0].ui = (uint32_t) t->setup.physAddr | 0x2;
1393 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1394 imesa->regs.s4.texAddr[0].ui |= 0x1;
1395
1396 return;
1397 }
1398 static void savageUpdateTex1State_s4( GLcontext *ctx )
1399 {
1400 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1401 struct gl_texture_object *tObj;
1402 struct gl_texture_image *image;
1403 savageTexObjPtr t;
1404 GLuint format;
1405
1406 /* disable */
1407 if(imesa->bTexEn1)
1408 {
1409 imesa->bTexEn1 = GL_FALSE;
1410 return;
1411 }
1412
1413 imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
1414 imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
1415 imesa->regs.s4.texCtrl[1].ui = 0x20f040;
1416 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
1417 if (ctx->Texture.Unit[1]._ReallyEnabled == 0)
1418 return;
1419
1420 tObj = ctx->Texture.Unit[1]._Current;
1421
1422 if ((ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1423 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1424 /* 3D texturing enabled, or texture border - fallback */
1425 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1426 return;
1427 }
1428
1429 /* Do 2D texture setup */
1430
1431 t = tObj->DriverData;
1432 if (!t) {
1433 t = savageAllocTexObj( tObj );
1434 if (!t)
1435 return;
1436 }
1437
1438 imesa->CurrentTexObj[1] = &t->base;
1439
1440 t->base.bound |= 2;
1441
1442 if (t->base.dirty_images[0] || t->dirtySubImages) {
1443 savageSetTexImages(imesa, tObj);
1444 savageUploadTexImages(imesa, t);
1445 }
1446
1447 driUpdateTextureLRU( &t->base );
1448
1449 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1450
1451 switch (ctx->Texture.Unit[1].EnvMode) {
1452 case GL_REPLACE:
1453 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1454 switch (format)
1455 {
1456 case GL_LUMINANCE:
1457 case GL_RGB:
1458 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal;
1459 break;
1460
1461 case GL_LUMINANCE_ALPHA:
1462 case GL_INTENSITY:
1463 case GL_RGBA:
1464 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Copy;
1465 break;
1466
1467 case GL_ALPHA:
1468 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1469 break;
1470 }
1471 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1472 break;
1473 case GL_MODULATE:
1474 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1475 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1476 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1477 break;
1478
1479 case GL_ADD:
1480 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1481 switch (format)
1482 {
1483 case GL_ALPHA:
1484 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1485 break;
1486
1487 case GL_LUMINANCE:
1488 case GL_RGB:
1489 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1490 break;
1491
1492 case GL_LUMINANCE_ALPHA:
1493 case GL_RGBA:
1494 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Add1;
1495 break;
1496
1497 case GL_INTENSITY:
1498 imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
1499 break;
1500 }
1501 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1502 break;
1503
1504 #if GL_ARB_texture_env_combine
1505 case GL_COMBINE_ARB:
1506 __HWParseTexEnvCombine(imesa, 1, &texCtrl, &imesa->regs.s4.texBlendCtrl);
1507 break;
1508 #endif
1509
1510 case GL_DECAL:
1511 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1512
1513 switch (format)
1514 {
1515 case GL_LUMINANCE:
1516 case GL_RGB:
1517 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal1;
1518 break;
1519 case GL_LUMINANCE_ALPHA:
1520 case GL_INTENSITY:
1521 case GL_RGBA:
1522 imesa->regs.s4.texBlendCtrl[1].ui = TBC_DecalAlpha1;
1523 break;
1524
1525 /*
1526 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1527 // are undefined with GL_DECAL
1528 */
1529 case GL_ALPHA:
1530 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1531 break;
1532 }
1533 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1534 break;
1535
1536 case GL_BLEND:
1537 if (format == GL_LUMINANCE)
1538 {
1539 /*
1540 // This is a hack for GLQuake, invert.
1541 */
1542 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_TRUE;
1543 imesa->regs.s4.texBlendCtrl[1].ui = 0;
1544 }
1545 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1546 break;
1547
1548 default:
1549 fprintf(stderr, "unknown tex 1 env mode\n");
1550 exit(1);
1551 break;
1552 }
1553
1554 savage4_set_wrap_mode( imesa, 1, t->setup.sWrapMode, t->setup.tWrapMode );
1555 savage4_set_filter_mode( imesa, 1, t->setup.minFilter, t->setup.magFilter );
1556
1557 if((ctx->Texture.Unit[1].LodBias !=0.0F) ||
1558 (imesa->regs.s4.texCtrl[1].ni.dBias != 0))
1559 {
1560 int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0) +
1561 SAVAGE4_LOD_OFFSET;
1562 if (bias < -256)
1563 bias = -256;
1564 else if (bias > 255)
1565 bias = 255;
1566 imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
1567 }
1568
1569 image = tObj->Image[0][tObj->BaseLevel];
1570 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1571 imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
1572 imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
1573 imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
1574 imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1575 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1576
1577 imesa->regs.s4.texAddr[1].ui = (uint32_t) t->setup.physAddr | 2;
1578 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1579 imesa->regs.s4.texAddr[1].ui |= 0x1;
1580 }
1581 static void savageUpdateTexState_s3d( GLcontext *ctx )
1582 {
1583 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1584 struct gl_texture_object *tObj;
1585 struct gl_texture_image *image;
1586 savageTexObjPtr t;
1587 GLuint format;
1588
1589 /* disable */
1590 imesa->regs.s3d.texCtrl.ui = 0;
1591 imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
1592 imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
1593 imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
1594 if (ctx->Texture.Unit[0]._ReallyEnabled == 0)
1595 return;
1596
1597 tObj = ctx->Texture.Unit[0]._Current;
1598 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1599 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1600 /* 3D texturing enabled, or texture border - fallback */
1601 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1602 return;
1603 }
1604
1605 /* Do 2D texture setup */
1606 t = tObj->DriverData;
1607 if (!t) {
1608 t = savageAllocTexObj( tObj );
1609 if (!t)
1610 return;
1611 }
1612
1613 imesa->CurrentTexObj[0] = &t->base;
1614 t->base.bound |= 1;
1615
1616 if (t->base.dirty_images[0] || t->dirtySubImages) {
1617 savageSetTexImages(imesa, tObj);
1618 savageUploadTexImages(imesa, t);
1619 }
1620
1621 driUpdateTextureLRU( &t->base );
1622
1623 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1624
1625 /* FIXME: copied from utah-glx, probably needs some tuning */
1626 switch (ctx->Texture.Unit[0].EnvMode) {
1627 case GL_DECAL:
1628 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECALALPHA_S3D;
1629 break;
1630 case GL_REPLACE:
1631 switch (format) {
1632 case GL_ALPHA: /* FIXME */
1633 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 1;
1634 break;
1635 case GL_LUMINANCE_ALPHA:
1636 case GL_RGBA:
1637 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = 4;
1638 break;
1639 case GL_RGB:
1640 case GL_LUMINANCE:
1641 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
1642 break;
1643 case GL_INTENSITY:
1644 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
1645 }
1646 break;
1647 case GL_BLEND: /* hardware can't do GL_BLEND */
1648 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1649 return;
1650 case GL_MODULATE:
1651 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
1652 break;
1653 default:
1654 fprintf(stderr, "unknown tex env mode\n");
1655 /*exit(1);*/
1656 break;
1657 }
1658
1659 /* The Savage3D can't handle different wrapping modes in s and t.
1660 * If they are not the same, fall back to software. */
1661 if (t->setup.sWrapMode != t->setup.tWrapMode) {
1662 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1663 return;
1664 }
1665 imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
1666 imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
1667 imesa->regs.s3d.texCtrl.ni.wrapMode =
1668 (t->setup.sWrapMode == GL_REPEAT) ? TAM_Wrap : TAM_Clamp;
1669
1670 switch (t->setup.minFilter) {
1671 case GL_NEAREST:
1672 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1673 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1674 break;
1675
1676 case GL_LINEAR:
1677 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1678 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1679 break;
1680
1681 case GL_NEAREST_MIPMAP_NEAREST:
1682 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1683 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1684 break;
1685
1686 case GL_LINEAR_MIPMAP_NEAREST:
1687 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1688 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1689 break;
1690
1691 case GL_NEAREST_MIPMAP_LINEAR:
1692 case GL_LINEAR_MIPMAP_LINEAR:
1693 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Trilin;
1694 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1695 break;
1696 }
1697
1698 /* There is no way to specify a maximum mipmap level. We may have to
1699 disable mipmapping completely. */
1700 /*
1701 if (t->max_level < t->image[0].image->WidthLog2 ||
1702 t->max_level < t->image[0].image->HeightLog2) {
1703 texCtrl.ni.mipmapEnable = GL_TRUE;
1704 if (texCtrl.ni.filterMode == TFM_Trilin)
1705 texCtrl.ni.filterMode = TFM_Bilin;
1706 texCtrl.ni.filterMode = TFM_Point;
1707 }
1708 */
1709
1710 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1711 (imesa->regs.s3d.texCtrl.ni.dBias != 0))
1712 {
1713 int bias = (int)(ctx->Texture.Unit[0].LodBias * 16.0);
1714 if (bias < -256)
1715 bias = -256;
1716 else if (bias > 255)
1717 bias = 255;
1718 imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
1719 }
1720
1721 image = tObj->Image[0][tObj->BaseLevel];
1722 imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
1723 imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
1724 imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
1725 assert (t->hwFormat <= 7);
1726 imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
1727
1728 imesa->regs.s3d.texAddr.ui = (uint32_t) t->setup.physAddr | 2;
1729 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1730 imesa->regs.s3d.texAddr.ui |= 0x1;
1731 }
1732
1733
1734 static void savageTimestampTextures( savageContextPtr imesa )
1735 {
1736 /* Timestamp current texture objects for texture heap aging.
1737 * Only useful with long-lived 32-bit event tags available
1738 * with Savage DRM 2.3.x or later. */
1739 if ((imesa->CurrentTexObj[0] || imesa->CurrentTexObj[1]) &&
1740 imesa->savageScreen->driScrnPriv->drm_version.minor >= 3) {
1741 unsigned int e;
1742 FLUSH_BATCH(imesa);
1743 e = savageEmitEvent(imesa, SAVAGE_WAIT_3D);
1744 if (imesa->CurrentTexObj[0])
1745 imesa->CurrentTexObj[0]->timestamp = e;
1746 if (imesa->CurrentTexObj[1])
1747 imesa->CurrentTexObj[1]->timestamp = e;
1748 }
1749 }
1750
1751
1752 static void savageUpdateTextureState_s4( GLcontext *ctx )
1753 {
1754 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1755
1756 /* When a texture is about to change or be disabled, timestamp the
1757 * old texture(s). We'll have to wait for this time stamp before
1758 * uploading anything to the same texture heap.
1759 */
1760 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1761 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1762 (imesa->CurrentTexObj[1] && ctx->Texture.Unit[1]._ReallyEnabled &&
1763 ctx->Texture.Unit[1]._Current->DriverData != imesa->CurrentTexObj[1]) ||
1764 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled) ||
1765 (imesa->CurrentTexObj[1] && !ctx->Texture.Unit[1]._ReallyEnabled))
1766 savageTimestampTextures(imesa);
1767
1768 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1769 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound &= ~2;
1770 imesa->CurrentTexObj[0] = 0;
1771 imesa->CurrentTexObj[1] = 0;
1772 savageUpdateTex0State_s4( ctx );
1773 savageUpdateTex1State_s4( ctx );
1774 imesa->dirty |= (SAVAGE_UPLOAD_TEX0 |
1775 SAVAGE_UPLOAD_TEX1);
1776 }
1777 static void savageUpdateTextureState_s3d( GLcontext *ctx )
1778 {
1779 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1780
1781 /* When a texture is about to change or be disabled, timestamp the
1782 * old texture(s). We'll have to wait for this time stamp before
1783 * uploading anything to the same texture heap.
1784 */
1785 if ((imesa->CurrentTexObj[0] && ctx->Texture.Unit[0]._ReallyEnabled &&
1786 ctx->Texture.Unit[0]._Current->DriverData != imesa->CurrentTexObj[0]) ||
1787 (imesa->CurrentTexObj[0] && !ctx->Texture.Unit[0]._ReallyEnabled))
1788 savageTimestampTextures(imesa);
1789
1790 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1791 imesa->CurrentTexObj[0] = 0;
1792 savageUpdateTexState_s3d( ctx );
1793 imesa->dirty |= (SAVAGE_UPLOAD_TEX0);
1794 }
1795 void savageUpdateTextureState( GLcontext *ctx)
1796 {
1797 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1798 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
1799 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_FALSE);
1800 if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1801 savageUpdateTextureState_s4 (ctx);
1802 else
1803 savageUpdateTextureState_s3d (ctx);
1804 }
1805
1806
1807
1808 /*****************************************
1809 * DRIVER functions
1810 *****************************************/
1811
1812 static void savageTexEnv( GLcontext *ctx, GLenum target,
1813 GLenum pname, const GLfloat *param )
1814 {
1815 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1816
1817 if (pname == GL_TEXTURE_ENV_MODE) {
1818
1819 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1820
1821 } else if (pname == GL_TEXTURE_ENV_COLOR) {
1822
1823 struct gl_texture_unit *texUnit =
1824 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1825 const GLfloat *fc = texUnit->EnvColor;
1826 GLuint r, g, b, a;
1827 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
1828 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
1829 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
1830 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
1831
1832 imesa->texEnvColor = ((a << 24) | (r << 16) |
1833 (g << 8) | (b << 0));
1834
1835
1836 }
1837 }
1838
1839 /* Update the heap's time stamp, so the new image is not uploaded
1840 * while the old one is still in use. If the texture that is going to
1841 * be changed is currently bound, we need to timestamp the texture
1842 * first. */
1843 static void savageTexImageChanged (savageTexObjPtr t) {
1844 if (t->base.heap) {
1845 if (t->base.bound)
1846 savageTimestampTextures(
1847 (savageContextPtr)t->base.heap->driverContext);
1848 if (t->base.timestamp > t->base.heap->timestamp)
1849 t->base.heap->timestamp = t->base.timestamp;
1850 }
1851 }
1852
1853 static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
1854 GLint internalFormat,
1855 GLint width, GLint border,
1856 GLenum format, GLenum type, const GLvoid *pixels,
1857 const struct gl_pixelstore_attrib *packing,
1858 struct gl_texture_object *texObj,
1859 struct gl_texture_image *texImage )
1860 {
1861 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1862 if (t) {
1863 savageTexImageChanged (t);
1864 } else {
1865 t = savageAllocTexObj(texObj);
1866 if (!t) {
1867 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1868 return;
1869 }
1870 }
1871 _mesa_store_teximage1d( ctx, target, level, internalFormat,
1872 width, border, format, type,
1873 pixels, packing, texObj, texImage );
1874 t->base.dirty_images[0] |= (1 << level);
1875 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1876 }
1877
1878 static void savageTexSubImage1D( GLcontext *ctx,
1879 GLenum target,
1880 GLint level,
1881 GLint xoffset,
1882 GLsizei width,
1883 GLenum format, GLenum type,
1884 const GLvoid *pixels,
1885 const struct gl_pixelstore_attrib *packing,
1886 struct gl_texture_object *texObj,
1887 struct gl_texture_image *texImage )
1888 {
1889 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1890 assert( t ); /* this _should_ be true */
1891 if (t) {
1892 savageTexImageChanged (t);
1893 savageMarkDirtyTiles(t, level, texImage->Width2, 1,
1894 xoffset, 0, width, 1);
1895 } else {
1896 t = savageAllocTexObj(texObj);
1897 if (!t) {
1898 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
1899 return;
1900 }
1901 t->base.dirty_images[0] |= (1 << level);
1902 }
1903 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
1904 format, type, pixels, packing, texObj,
1905 texImage);
1906 t->dirtySubImages |= (1 << level);
1907 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1908 }
1909
1910 static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1911 GLint internalFormat,
1912 GLint width, GLint height, GLint border,
1913 GLenum format, GLenum type, const GLvoid *pixels,
1914 const struct gl_pixelstore_attrib *packing,
1915 struct gl_texture_object *texObj,
1916 struct gl_texture_image *texImage )
1917 {
1918 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1919 if (t) {
1920 savageTexImageChanged (t);
1921 } else {
1922 t = savageAllocTexObj(texObj);
1923 if (!t) {
1924 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1925 return;
1926 }
1927 }
1928 _mesa_store_teximage2d( ctx, target, level, internalFormat,
1929 width, height, border, format, type,
1930 pixels, packing, texObj, texImage );
1931 t->base.dirty_images[0] |= (1 << level);
1932 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1933 }
1934
1935 static void savageTexSubImage2D( GLcontext *ctx,
1936 GLenum target,
1937 GLint level,
1938 GLint xoffset, GLint yoffset,
1939 GLsizei width, GLsizei height,
1940 GLenum format, GLenum type,
1941 const GLvoid *pixels,
1942 const struct gl_pixelstore_attrib *packing,
1943 struct gl_texture_object *texObj,
1944 struct gl_texture_image *texImage )
1945 {
1946 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1947 assert( t ); /* this _should_ be true */
1948 if (t) {
1949 savageTexImageChanged (t);
1950 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
1951 xoffset, yoffset, width, height);
1952 } else {
1953 t = savageAllocTexObj(texObj);
1954 if (!t) {
1955 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1956 return;
1957 }
1958 t->base.dirty_images[0] |= (1 << level);
1959 }
1960 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
1961 height, format, type, pixels, packing, texObj,
1962 texImage);
1963 t->dirtySubImages |= (1 << level);
1964 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1965 }
1966
1967 static void
1968 savageCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1969 GLint internalFormat,
1970 GLint width, GLint height, GLint border,
1971 GLsizei imageSize, const GLvoid *data,
1972 struct gl_texture_object *texObj,
1973 struct gl_texture_image *texImage )
1974 {
1975 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1976 if (t) {
1977 savageTexImageChanged (t);
1978 } else {
1979 t = savageAllocTexObj(texObj);
1980 if (!t) {
1981 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
1982 return;
1983 }
1984 }
1985 _mesa_store_compressed_teximage2d( ctx, target, level, internalFormat,
1986 width, height, border, imageSize,
1987 data, texObj, texImage );
1988 t->base.dirty_images[0] |= (1 << level);
1989 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1990 }
1991
1992 static void
1993 savageCompressedTexSubImage2D( GLcontext *ctx,
1994 GLenum target,
1995 GLint level,
1996 GLint xoffset, GLint yoffset,
1997 GLsizei width, GLsizei height,
1998 GLenum format, GLsizei imageSize,
1999 const GLvoid *data,
2000 struct gl_texture_object *texObj,
2001 struct gl_texture_image *texImage )
2002 {
2003 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
2004 assert( t ); /* this _should_ be true */
2005 if (t) {
2006 savageTexImageChanged (t);
2007 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
2008 xoffset, yoffset, width, height);
2009 } else {
2010 t = savageAllocTexObj(texObj);
2011 if (!t) {
2012 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2013 return;
2014 }
2015 t->base.dirty_images[0] |= (1 << level);
2016 }
2017 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset,
2018 width, height, format, imageSize,
2019 data, texObj, texImage);
2020 t->dirtySubImages |= (1 << level);
2021 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
2022 }
2023
2024 static void savageTexParameter( GLcontext *ctx, GLenum target,
2025 struct gl_texture_object *tObj,
2026 GLenum pname, const GLfloat *params )
2027 {
2028 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
2029 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2030
2031 if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
2032 return;
2033
2034 switch (pname) {
2035 case GL_TEXTURE_MIN_FILTER:
2036 case GL_TEXTURE_MAG_FILTER:
2037 savageSetTexFilter(t,tObj->MinFilter,tObj->MagFilter);
2038 break;
2039
2040 case GL_TEXTURE_WRAP_S:
2041 case GL_TEXTURE_WRAP_T:
2042 savageSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
2043 break;
2044
2045 case GL_TEXTURE_BORDER_COLOR:
2046 savageSetTexBorderColor(t,tObj->BorderColor.f);
2047 break;
2048
2049 default:
2050 return;
2051 }
2052
2053 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2054 }
2055
2056 static void savageBindTexture( GLcontext *ctx, GLenum target,
2057 struct gl_texture_object *tObj )
2058 {
2059 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2060
2061 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) ||
2062 (tObj->DriverData != NULL) );
2063
2064 imesa->new_state |= SAVAGE_NEW_TEXTURE;
2065 }
2066
2067 static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
2068 {
2069 driTextureObject *t = (driTextureObject *)tObj->DriverData;
2070 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
2071
2072 if (t) {
2073 if (t->bound)
2074 savageTimestampTextures(imesa);
2075
2076 driDestroyTextureObject(t);
2077 }
2078 /* Free mipmap images and the texture object itself */
2079 _mesa_delete_texture_object(ctx, tObj);
2080 }
2081
2082
2083 static struct gl_texture_object *
2084 savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
2085 {
2086 struct gl_texture_object *obj;
2087 obj = _mesa_new_texture_object(ctx, name, target);
2088 savageAllocTexObj( obj );
2089
2090 return obj;
2091 }
2092
2093 void savageDDInitTextureFuncs( struct dd_function_table *functions )
2094 {
2095 functions->TexEnv = savageTexEnv;
2096 functions->ChooseTextureFormat = savageChooseTextureFormat;
2097 functions->TexImage1D = savageTexImage1D;
2098 functions->TexSubImage1D = savageTexSubImage1D;
2099 functions->TexImage2D = savageTexImage2D;
2100 functions->TexSubImage2D = savageTexSubImage2D;
2101 functions->CompressedTexImage2D = savageCompressedTexImage2D;
2102 functions->CompressedTexSubImage2D = savageCompressedTexSubImage2D;
2103 functions->BindTexture = savageBindTexture;
2104 functions->NewTextureObject = savageNewTextureObject;
2105 functions->DeleteTexture = savageDeleteTexture;
2106 functions->IsTextureResident = driIsTextureResident;
2107 functions->TexParameter = savageTexParameter;
2108
2109 /* Texel fetching with our custom texture formats works just like
2110 * the standard argb formats. */
2111 #if 0
2112 _savage_texformat_a1114444.FetchTexel1D = _mesa_texformat_argb4444.FetchTexel1D;
2113 _savage_texformat_a1114444.FetchTexel2D = _mesa_texformat_argb4444.FetchTexel2D;
2114 _savage_texformat_a1114444.FetchTexel3D = _mesa_texformat_argb4444.FetchTexel3D;
2115 _savage_texformat_a1114444.FetchTexel1Df= _mesa_texformat_argb4444.FetchTexel1Df;
2116 _savage_texformat_a1114444.FetchTexel2Df= _mesa_texformat_argb4444.FetchTexel2Df;
2117 _savage_texformat_a1114444.FetchTexel3Df= _mesa_texformat_argb4444.FetchTexel3Df;
2118
2119 _savage_texformat_a1118888.FetchTexel1D = _mesa_texformat_argb8888.FetchTexel1D;
2120 _savage_texformat_a1118888.FetchTexel2D = _mesa_texformat_argb8888.FetchTexel2D;
2121 _savage_texformat_a1118888.FetchTexel3D = _mesa_texformat_argb8888.FetchTexel3D;
2122 _savage_texformat_a1118888.FetchTexel1Df= _mesa_texformat_argb8888.FetchTexel1Df;
2123 _savage_texformat_a1118888.FetchTexel2Df= _mesa_texformat_argb8888.FetchTexel2Df;
2124 _savage_texformat_a1118888.FetchTexel3Df= _mesa_texformat_argb8888.FetchTexel3Df;
2125 #endif
2126 }