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