2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
32 #include "savagecontext.h"
33 #include "savagetex.h"
34 #include "savagetris.h"
35 #include "savageioctl.h"
36 #include "simple_list.h"
38 #include "savage_bci.h"
41 #include "texformat.h"
45 #include "swrast/swrast.h"
49 /* Size 1, 2 and 4 images are packed into the last subtile. Each image
50 * is repeated to fill a 4x4 pixel area. The figure below shows the
51 * layout of those 4x4 pixel areas in the 8x8 subtile.
56 * Yuck! 8-bit texture formats use 4x8 subtiles. See below.
58 static const savageTileInfo tileInfo_pro[5] = {
59 {64, 64, 8, 8, 8, 8, {0x12, 0x02}}, /* 4-bit */
60 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
61 {64, 16, 8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */
62 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
63 {32, 16, 4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */
66 /* Size 1, 2 and 4 images are packed into the last two subtiles. Each
67 * image is repeated to fill a 4x4 pixel area. The figures below show
68 * the layout of those 4x4 pixel areas in the two 4x8 subtiles.
70 * second last subtile: 4 last subtile: 2
73 static const savageTileInfo tileInfo_s3d_s4[5] = {
74 {64, 64, 16, 8, 4, 8, {0x18, 0x10}}, /* 4-bit */
75 {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */
76 {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */
77 { 0, 0, 0, 0, 0, 0, {0x00, 0x00}}, /* 24-bit */
78 {32, 16, 8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */
81 /** \brief Template for subtile uploads.
82 * \param h height in pixels
83 * \param w width in bytes
85 #define SUBTILE_FUNC(w,h) \
86 static __inline GLubyte *savageUploadSubtile_##w##x##h \
87 (GLubyte *dest, GLubyte *src, GLuint srcStride) \
90 for (y = 0; y < h; ++y) { \
91 memcpy (dest, src, w); \
98 SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */
102 SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */
104 /** \brief Table of subtile upload functions
106 * Indexed by the binary logarithm of the width in bytes.
108 static GLubyte *(*savageSubtileTab[]) (GLubyte *, GLubyte *, GLuint) = {
110 savageUploadSubtile_2x8,
111 savageUploadSubtile_4x8,
112 savageUploadSubtile_8x8,
113 savageUploadSubtile_16x8,
114 savageUploadSubtile_32x8
117 /** \brief Upload a complete tile from src (srcStride) to dest
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
127 * Writes linearly to the destination memory in order to exploit write
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
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 savageSubtileTab[(tileInfo->subWidth == 4 ? 2 : 3) +
143 ((bpp == 1) ? 0 : (bpp == 2) ? 1 : 2)];
145 for (sy = 0; sy < hInSub; ++sy) {
147 for (sx = 0; sx < wInSub; ++sx) {
149 dest = subtileFunc (dest, src, srcStride);
150 srcSTile += subStride;
152 srcSRow += srcStride * tileInfo->subHeight;
156 /** \brief Upload a image that is smaller than 8 pixels in either dimension.
158 * \param tileInfo Pointer to tiling information
159 * \param width Width of the image
160 * \param height Height of the image
161 * \param bpp Bytes per pixel
162 * \param src Pointer to source data
163 * \param dest Pointer to destination
165 * This function handles all the special cases that need to be taken
166 * care off. The caller may need to call this function multiple times
167 * with the destination offset in different ways since small texture
168 * images must be repeated in order to fill a whole tile (or 4x4 for
169 * the last 3 levels).
171 * FIXME: Repeating inside this function would be more efficient.
173 static void savageUploadTiny (const savageTileInfo *tileInfo,
174 GLuint width, GLuint height, GLuint bpp,
175 GLubyte *src, GLubyte *dest) {
176 GLuint size = MAX2(width, height);
178 if (width > tileInfo->subWidth) { /* assert: height <= subtile height */
179 GLuint wInSub = width / tileInfo->subWidth;
180 GLuint srcStride = width * bpp;
181 GLuint subStride = tileInfo->subWidth * bpp;
182 GLuint subSkip = (tileInfo->subHeight - height) * subStride;
183 GLubyte *srcSTile = src;
185 for (sx = 0; sx < wInSub; ++sx) {
187 for (y = 0; y < height; ++y) {
188 memcpy (dest, src, subStride);
193 srcSTile += subStride;
195 } else if (size > 4) { /* a tile or less wide, except the last 3 levels */
196 GLuint srcStride = width * bpp;
197 GLuint subStride = tileInfo->subWidth * bpp;
198 /* if the subtile width is 4 we have to skip every other subtile */
199 GLuint subSkip = tileInfo->subWidth == 4 ?
200 subStride * tileInfo->subHeight : 0;
202 for (y = 0; y < height; ++y) {
203 memcpy (dest, src, srcStride);
209 } else { /* the last 3 mipmap levels */
210 GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);
211 GLuint subStride = tileInfo->subWidth * bpp;
214 for (y = 0; y < height; ++y) {
215 memcpy (dest, src, bpp*width);
222 /** \brief Upload an image from mesa's internal copy.
224 static void savageUploadTexLevel( savageTexObjPtr t, int level )
226 const struct gl_texture_image *image = t->base.tObj->Image[0][level];
227 const savageTileInfo *tileInfo = t->tileInfo;
228 GLuint width = image->Width2, height = image->Height2;
229 GLuint bpp = t->texelBytes;
231 /* FIXME: Need triangle (rather than pixel) fallbacks to simulate
232 * this using normal textured triangles.
234 * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.
236 if(image->Border != 0)
237 fprintf (stderr, "Not supported texture border %d.\n",
238 (int) image->Border);
240 if (width >= 8 && height >= tileInfo->subHeight) {
241 GLuint *dirtyPtr = t->image[level].dirtyTiles;
242 GLuint dirtyMask = 1;
244 if (width >= tileInfo->width && height >= tileInfo->height) {
245 GLuint wInTiles = width / tileInfo->width;
246 GLuint hInTiles = height / tileInfo->height;
247 GLubyte *srcTRow = image->Data, *src;
248 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
250 for (y = 0; y < hInTiles; ++y) {
252 for (x = 0; x < wInTiles; ++x) {
253 if (*dirtyPtr & dirtyMask) {
254 savageUploadTile (tileInfo,
255 tileInfo->wInSub, tileInfo->hInSub,
256 bpp, src, width * bpp, dest);
258 src += tileInfo->width * bpp;
259 dest += 2048; /* tile size is always 2k */
260 if (dirtyMask == 1<<31) {
266 srcTRow += width * tileInfo->height * bpp;
268 } else if (width >= tileInfo->width) {
269 GLuint wInTiles = width / tileInfo->width;
270 GLubyte *src = image->Data;
271 GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
272 GLuint tileStride = tileInfo->width * bpp * height;
273 savageContextPtr imesa = (savageContextPtr)t->base.heap->driverContext;
275 /* Savage3D-based chips seem so use a constant tile stride
276 * of 2048 for vertically incomplete tiles, but only if
277 * the color depth is 32bpp. Nobody said this was supposed
280 if (bpp == 4 && imesa->savageScreen->chipset < S3_SAVAGE4)
282 for (x = 0; x < wInTiles; ++x) {
283 if (*dirtyPtr & dirtyMask) {
284 savageUploadTile (tileInfo,
286 height / tileInfo->subHeight,
287 bpp, src, width * bpp, dest);
289 src += tileInfo->width * bpp;
291 if (dirtyMask == 1<<31) {
298 savageUploadTile (tileInfo, width / tileInfo->subWidth,
299 height / tileInfo->subHeight, bpp,
300 image->Data, width * bpp,
301 (GLubyte *)(t->bufAddr+t->image[level].offset));
304 GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
305 if (width > 4 || height > 4) {
306 minWidth = tileInfo->subWidth;
307 minHeight = tileInfo->subHeight;
312 hRepeat = width >= minWidth ? 1 : minWidth / width;
313 vRepeat = height >= minHeight ? 1 : minHeight / height;
314 for (y = 0; y < vRepeat; ++y) {
315 GLuint offset = y * tileInfo->subWidth*height * bpp;
316 for (x = 0; x < hRepeat; ++x) {
317 savageUploadTiny (tileInfo, width, height, bpp, image->Data,
318 (GLubyte *)(t->bufAddr +
319 t->image[level].offset+offset));
320 offset += width * bpp;
326 /** \brief Compute the destination size of a texture image
328 static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
330 if (width >= 8 && height >= 8)
331 return width * height * bpp;
332 /* special case for the last three mipmap levels: the hardware computes
333 * the offset internally */
334 else if (width <= 4 && height <= 4)
336 /* partially filled sub tiles waste memory
337 * on Savage3D and Savage4 with subtile width 4 every other subtile is
338 * skipped if width < 8 so we can assume a uniform subtile width of 8 */
340 return width * 8 * bpp;
341 else if (height >= 8)
342 return 8 * height * bpp;
347 /** \brief Compute the number of (partial) tiles of a texture image
349 static GLuint savageTexImageTiles (GLuint width, GLuint height,
350 const savageTileInfo *tileInfo)
352 return (width + tileInfo->width - 1) / tileInfo->width *
353 (height + tileInfo->height - 1) / tileInfo->height;
356 /** \brief Mark dirty tiles
358 * Some care must be taken because tileInfo may not be set or not
359 * up-to-date. So we check if tileInfo is initialized and if the number
360 * of tiles in the bit vector matches the number of tiles computed from
361 * the current tileInfo.
363 static void savageMarkDirtyTiles (savageTexObjPtr t, GLuint level,
364 GLuint totalWidth, GLuint totalHeight,
365 GLint xoffset, GLint yoffset,
366 GLsizei width, GLsizei height)
368 GLuint wInTiles, hInTiles;
369 GLuint x0, y0, x1, y1;
373 wInTiles = (totalWidth + t->tileInfo->width - 1) / t->tileInfo->width;
374 hInTiles = (totalHeight + t->tileInfo->height - 1) / t->tileInfo->height;
375 if (wInTiles * hInTiles != t->image[level].nTiles)
378 x0 = xoffset / t->tileInfo->width;
379 y0 = yoffset / t->tileInfo->height;
380 x1 = (xoffset + width - 1) / t->tileInfo->width;
381 y1 = (yoffset + height - 1) / t->tileInfo->height;
383 for (y = y0; y <= y1; ++y) {
384 GLuint *ptr = t->image[level].dirtyTiles + (y * wInTiles + x0) / 32;
385 GLuint mask = 1 << (y * wInTiles + x0) % 32;
386 for (x = x0; x <= x1; ++x) {
388 if (mask == (1<<31)) {
398 /** \brief Mark all tiles as dirty
400 static void savageMarkAllTiles (savageTexObjPtr t, GLuint level)
402 GLuint words = (t->image[level].nTiles + 31) / 32;
404 memset(t->image[level].dirtyTiles, ~0, words*sizeof(GLuint));
408 static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t)
410 tex->setup.sWrapMode = s;
411 tex->setup.tWrapMode = t;
414 static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
416 t->setup.minFilter = minf;
417 t->setup.magFilter = magf;
423 static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
425 /* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
426 /*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
431 static savageTexObjPtr
432 savageAllocTexObj( struct gl_texture_object *texObj )
436 t = (savageTexObjPtr) calloc(1,sizeof(*t));
437 texObj->DriverData = t;
441 /* Initialize non-image-dependent parts of the state:
443 t->base.tObj = texObj;
444 t->base.dirty_images[0] = 0;
445 t->dirtySubImages = 0;
448 /* Initialize dirty tiles bit vectors
450 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i)
451 t->image[i].nTiles = 0;
453 /* FIXME Something here to set initial values for other parts of
457 make_empty_list( &t->base );
459 savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
460 savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
461 savageSetTexBorderColor(t,texObj->_BorderChan);
467 /* Called by the _mesa_store_teximage[123]d() functions. */
468 static const struct gl_texture_format *
469 savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
470 GLenum format, GLenum type )
472 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
473 const GLboolean do32bpt =
474 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
475 const GLboolean force16bpt =
476 ( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
477 const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
480 switch ( internalFormat ) {
483 case GL_COMPRESSED_RGBA:
485 case GL_UNSIGNED_INT_10_10_10_2:
486 case GL_UNSIGNED_INT_2_10_10_10_REV:
487 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
488 case GL_UNSIGNED_SHORT_4_4_4_4:
489 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
490 return &_mesa_texformat_argb4444;
491 case GL_UNSIGNED_SHORT_5_5_5_1:
492 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
493 return &_mesa_texformat_argb1555;
495 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
500 case GL_COMPRESSED_RGB:
502 case GL_UNSIGNED_SHORT_4_4_4_4:
503 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
504 return &_mesa_texformat_argb4444;
505 case GL_UNSIGNED_SHORT_5_5_5_1:
506 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
507 return &_mesa_texformat_argb1555;
508 case GL_UNSIGNED_SHORT_5_6_5:
509 case GL_UNSIGNED_SHORT_5_6_5_REV:
510 return &_mesa_texformat_rgb565;
512 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
519 &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
523 &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
527 return &_mesa_texformat_argb4444;
530 return &_mesa_texformat_argb1555;
536 return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
541 return &_mesa_texformat_rgb565;
544 case GL_COMPRESSED_ALPHA:
545 return isSavage4 ? &_mesa_texformat_a8 : (
546 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
548 return isSavage4 ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444;
552 return isSavage4 ? &_mesa_texformat_a8 : (
553 !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
557 case GL_COMPRESSED_LUMINANCE:
558 /* no alpha, but use argb1555 in 16bit case to get pure grey values */
559 return isSavage4 ? &_mesa_texformat_l8 : (
560 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
562 return isSavage4 ? &_mesa_texformat_l8 : &_mesa_texformat_argb1555;
566 return isSavage4 ? &_mesa_texformat_l8 : (
567 !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555);
570 case GL_LUMINANCE_ALPHA:
571 case GL_COMPRESSED_LUMINANCE_ALPHA:
572 /* Savage4 has a al44 texture format. But it's not supported by Mesa. */
573 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
574 case GL_LUMINANCE4_ALPHA4:
575 case GL_LUMINANCE6_ALPHA2:
576 return &_mesa_texformat_argb4444;
577 case GL_LUMINANCE8_ALPHA8:
578 case GL_LUMINANCE12_ALPHA4:
579 case GL_LUMINANCE12_ALPHA12:
580 case GL_LUMINANCE16_ALPHA16:
581 return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
584 case GL_COMPRESSED_INTENSITY:
585 return isSavage4 ? &_mesa_texformat_i8 : (
586 do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
588 return isSavage4 ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
592 return isSavage4 ? &_mesa_texformat_i8 : (
593 !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444);
596 case GL_COLOR_INDEX1_EXT:
597 case GL_COLOR_INDEX2_EXT:
598 case GL_COLOR_INDEX4_EXT:
599 case GL_COLOR_INDEX8_EXT:
600 case GL_COLOR_INDEX12_EXT:
601 case GL_COLOR_INDEX16_EXT:
602 return &_mesa_texformat_ci8;
605 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
610 static void savageSetTexImages( savageContextPtr imesa,
611 const struct gl_texture_object *tObj )
613 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
614 struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
615 GLuint offset, i, textureFormat, size;
616 GLint firstLevel, lastLevel;
621 switch (image->TexFormat->MesaFormat) {
622 case MESA_FORMAT_ARGB8888:
623 textureFormat = TFT_ARGB8888;
626 case MESA_FORMAT_ARGB1555:
627 textureFormat = TFT_ARGB1555;
630 case MESA_FORMAT_ARGB4444:
631 textureFormat = TFT_ARGB4444;
634 case MESA_FORMAT_RGB565:
635 textureFormat = TFT_RGB565;
639 textureFormat = TFT_L8;
643 textureFormat = TFT_I8;
647 textureFormat = TFT_A8;
651 _mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
654 t->hwFormat = textureFormat;
656 /* Select tiling format depending on the chipset and bytes per texel */
657 if (imesa->savageScreen->chipset <= S3_SAVAGE4)
658 t->tileInfo = &tileInfo_s3d_s4[t->texelBytes];
660 t->tileInfo = &tileInfo_pro[t->texelBytes];
662 /* Compute which mipmap levels we really want to send to the hardware.
664 driCalculateTextureFirstLastLevel( &t->base );
665 firstLevel = t->base.firstLevel;
666 lastLevel = t->base.lastLevel;
668 /* Figure out the size now (and count the levels). Upload won't be
669 * done until later. If the number of tiles changes, it means that
670 * this function is called for the first time on this tex object or
671 * the image or the destination color format changed. So all tiles
672 * are marked as dirty.
676 for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) {
678 nTiles = savageTexImageTiles (image->Width2, image->Height2, t->tileInfo);
679 if (t->image[i].nTiles != nTiles) {
680 GLuint words = (nTiles + 31) / 32;
681 if (t->image[i].nTiles != 0) {
682 free(t->image[i].dirtyTiles);
684 t->image[i].dirtyTiles = malloc(words*sizeof(GLuint));
685 memset(t->image[i].dirtyTiles, ~0, words*sizeof(GLuint));
687 t->image[i].nTiles = nTiles;
689 t->image[i].offset = offset;
691 image = tObj->Image[0][i];
692 size = savageTexImageSize (image->Width2, image->Height2,
697 t->base.lastLevel = i-1;
698 t->base.totalSize = offset;
699 /* the last three mipmap levels don't add to the offset. They are packed
702 t->base.totalSize += 64 * t->texelBytes;
703 /* 2k-aligned (really needed?) */
704 t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
707 void savageDestroyTexObj(savageContextPtr imesa, savageTexObjPtr t)
711 /* Free dirty tiles bit vectors */
712 for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) {
713 if (t->image[i].nTiles)
714 free (t->image[i].dirtyTiles);
717 /* See if it was the driver's current object.
721 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ )
723 if ( &t->base == imesa->CurrentTexObj[ i ] ) {
724 assert( t->base.bound & (1 << i) );
725 imesa->CurrentTexObj[ i ] = NULL;
731 /* Upload a texture's images to one of the texture heaps. May have to
732 * eject our own and/or other client's texture objects to make room
735 static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t )
737 const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
742 LOCK_HARDWARE(imesa);
744 /* Do we need to eject LRU texture objects?
746 if (!t->base.memBlock) {
750 heap = driAllocateTexture(imesa->textureHeaps, imesa->lastTexHeap,
751 (driTextureObject *)t);
753 UNLOCK_HARDWARE(imesa);
757 ofs = t->base.memBlock->ofs;
758 t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
759 t->bufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
760 imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
763 /* Let the world know we've used this memory recently.
765 driUpdateTextureLRU( &t->base );
766 UNLOCK_HARDWARE(imesa);
768 if (t->base.dirty_images[0] || t->dirtySubImages) {
769 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
770 fprintf(stderr, "Texture upload: |");
772 savageFlushVertices (imesa);
773 LOCK_HARDWARE(imesa);
774 savageFlushCmdBufLocked (imesa, GL_FALSE);
775 WAIT_IDLE_EMPTY_LOCKED(imesa);
777 for (i = 0 ; i < numLevels ; i++) {
778 const GLint j = t->base.firstLevel + i; /* the texObj's level */
779 if (t->base.dirty_images[0] & (1 << j)) {
780 savageMarkAllTiles(t, j);
781 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
782 fprintf (stderr, "*");
783 } else if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) {
784 if (t->dirtySubImages & (1 << j))
785 fprintf (stderr, ".");
787 fprintf (stderr, " ");
789 if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j))
790 savageUploadTexLevel( t, j );
793 UNLOCK_HARDWARE(imesa);
794 t->base.dirty_images[0] = 0;
795 t->dirtySubImages = 0;
797 if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX)
798 fprintf(stderr, "|\n");
805 static void savageUpdateTex0State_s4( GLcontext *ctx )
807 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
808 struct gl_texture_object *tObj;
809 struct gl_texture_image *image;
814 if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
815 imesa->regs.s4.texDescr.ni.tex0En = GL_FALSE;
816 imesa->regs.s4.texBlendCtrl[0].ui = TBC_NoTexMap;
817 imesa->regs.s4.texCtrl[0].ui = 0x20f040;
821 tObj = ctx->Texture.Unit[0]._Current;
822 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
823 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
824 /* 3D texturing enabled, or texture border - fallback */
825 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
829 /* Do 2D texture setup */
831 t = tObj->DriverData;
833 t = savageAllocTexObj( tObj );
838 imesa->CurrentTexObj[0] = &t->base;
841 if (t->base.dirty_images[0] || t->dirtySubImages) {
842 savageSetTexImages(imesa, tObj);
843 savageUploadTexImages(imesa, t);
846 driUpdateTextureLRU( &t->base );
848 format = tObj->Image[0][tObj->BaseLevel]->Format;
850 switch (ctx->Texture.Unit[0].EnvMode) {
852 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
857 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
860 case GL_LUMINANCE_ALPHA:
863 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Copy;
867 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
870 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
871 &imesa->regs.s4.texBlendCtrl[0]);
875 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
880 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Decal;
885 case GL_LUMINANCE_ALPHA:
886 imesa->regs.s4.texBlendCtrl[0].ui = TBC_DecalAlpha;
890 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
891 are undefined with GL_DECAL
895 imesa->regs.s4.texBlendCtrl[0].ui = TBC_CopyAlpha;
898 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
899 &imesa->regs.s4.texBlendCtrl[0]);
903 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
904 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
905 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
906 &imesa->regs.s4.texBlendCtrl[0]);
914 imesa->regs.s4.texBlendCtrl[0].ui = TBC_ModulAlpha;
915 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
920 imesa->regs.s4.texBlendCtrl[0].ui = TBC_Blend0;
921 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
922 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
923 imesa->regs.s4.texDescr.ni.tex1Width =
924 imesa->regs.s4.texDescr.ni.tex0Width;
925 imesa->regs.s4.texDescr.ni.tex1Height =
926 imesa->regs.s4.texDescr.ni.tex0Height;
927 imesa->regs.s4.texDescr.ni.tex1Fmt =
928 imesa->regs.s4.texDescr.ni.tex0Fmt;
930 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
931 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Blend1;
933 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
934 imesa->bTexEn1 = GL_TRUE;
937 case GL_LUMINANCE_ALPHA:
939 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendAlpha0;
940 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
941 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
942 imesa->regs.s4.texDescr.ni.tex1Width =
943 imesa->regs.s4.texDescr.ni.tex0Width;
944 imesa->regs.s4.texDescr.ni.tex1Height =
945 imesa->regs.s4.texDescr.ni.tex0Height;
946 imesa->regs.s4.texDescr.ni.tex1Fmt =
947 imesa->regs.s4.texDescr.ni.tex0Fmt;
949 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
950 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendAlpha1;
952 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
953 imesa->bTexEn1 = GL_TRUE;
957 imesa->regs.s4.texBlendCtrl[0].ui = TBC_BlendInt0;
958 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
959 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
960 imesa->regs.s4.texDescr.ni.tex1Width =
961 imesa->regs.s4.texDescr.ni.tex0Width;
962 imesa->regs.s4.texDescr.ni.tex1Height =
963 imesa->regs.s4.texDescr.ni.tex0Height;
964 imesa->regs.s4.texDescr.ni.tex1Fmt =
965 imesa->regs.s4.texDescr.ni.tex0Fmt;
967 imesa->regs.s4.texAddr[1].ui = imesa->regs.s4.texAddr[0].ui;
968 imesa->regs.s4.texBlendCtrl[1].ui = TBC_BlendInt1;
970 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_TRUE;
971 imesa->regs.s4.texCtrl[0].ni.alphaArg1Invert = GL_TRUE;
972 imesa->bTexEn1 = GL_TRUE;
975 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
976 &imesa->regs.s4.texBlendCtrl[0]);
983 imesa->regs.s4.texCtrl[0].ni.clrArg1Invert = GL_FALSE;
984 imesa->regs.s4.texBlendCtrl[0].ui = TBC_AddAlpha;
985 __HWEnvCombineSingleUnitScale(imesa, 0, 0,
986 &imesa->regs.s4.texBlendCtrl[0]);
989 #if GL_ARB_texture_env_combine
991 __HWParseTexEnvCombine(imesa, 0, &imesa->regs.s4.texCtrl[0],
992 &imesa->regs.s4.texBlendCtrl[0]);
997 fprintf(stderr, "unknown tex env mode");
1002 imesa->regs.s4.texCtrl[0].ni.uMode =
1003 t->setup.sWrapMode == GL_REPEAT ? 0 : 1;
1004 imesa->regs.s4.texCtrl[0].ni.vMode =
1005 t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
1007 switch (t->setup.minFilter)
1010 imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Point;
1011 imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
1015 imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Bilin;
1016 imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_FALSE;
1019 case GL_NEAREST_MIPMAP_NEAREST:
1020 imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Point;
1021 imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
1024 case GL_LINEAR_MIPMAP_NEAREST:
1025 imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Bilin;
1026 imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
1029 case GL_NEAREST_MIPMAP_LINEAR:
1030 case GL_LINEAR_MIPMAP_LINEAR:
1031 imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Trilin;
1032 imesa->regs.s4.texCtrl[0].ni.mipmapEnable = GL_TRUE;
1036 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1037 (imesa->regs.s4.texCtrl[0].ni.dBias != 0))
1039 int bias = (int)(ctx->Texture.Unit[0].LodBias * 32.0);
1042 else if (bias > 255)
1044 imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
1047 image = tObj->Image[0][tObj->BaseLevel];
1048 imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
1049 imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
1050 imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
1051 imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
1052 imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1054 if (imesa->regs.s4.texDescr.ni.tex1En)
1055 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1057 imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->setup.physAddr | 0x2;
1058 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1059 imesa->regs.s4.texAddr[0].ui |= 0x1;
1063 static void savageUpdateTex1State_s4( GLcontext *ctx )
1065 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1066 struct gl_texture_object *tObj;
1067 struct gl_texture_image *image;
1074 imesa->bTexEn1 = GL_FALSE;
1078 if (ctx->Texture.Unit[1]._ReallyEnabled == 0) {
1079 imesa->regs.s4.texDescr.ni.tex1En = GL_FALSE;
1080 imesa->regs.s4.texBlendCtrl[1].ui = TBC_NoTexMap1;
1081 imesa->regs.s4.texCtrl[1].ui = 0x20f040;
1082 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_FALSE;
1086 tObj = ctx->Texture.Unit[1]._Current;
1088 if ((ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1089 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1090 /* 3D texturing enabled, or texture border - fallback */
1091 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1095 /* Do 2D texture setup */
1097 t = tObj->DriverData;
1099 t = savageAllocTexObj( tObj );
1104 imesa->CurrentTexObj[1] = &t->base;
1108 if (t->base.dirty_images[0] || t->dirtySubImages) {
1109 savageSetTexImages(imesa, tObj);
1110 savageUploadTexImages(imesa, t);
1113 driUpdateTextureLRU( &t->base );
1115 format = tObj->Image[0][tObj->BaseLevel]->Format;
1117 switch (ctx->Texture.Unit[1].EnvMode) {
1119 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1124 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal;
1127 case GL_LUMINANCE_ALPHA:
1130 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Copy;
1134 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1137 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1140 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1141 imesa->regs.s4.texBlendCtrl[1].ui = TBC_ModulAlpha1;
1142 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1145 /*#if GL_EXT_texture_env_add*/
1147 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1148 imesa->regs.s4.texBlendCtrl[1].ui = TBC_AddAlpha1;
1149 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1153 #if GL_ARB_texture_env_combine
1154 case GL_COMBINE_ARB:
1155 __HWParseTexEnvCombine(imesa, 1, &texCtrl, &imesa->regs.s4.texBlendCtrl);
1160 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_FALSE;
1166 imesa->regs.s4.texBlendCtrl[1].ui = TBC_Decal1;
1168 case GL_LUMINANCE_ALPHA:
1171 imesa->regs.s4.texBlendCtrl[1].ui = TBC_DecalAlpha1;
1175 // GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_INTENSITY
1176 // are undefined with GL_DECAL
1179 imesa->regs.s4.texBlendCtrl[1].ui = TBC_CopyAlpha1;
1182 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1186 if (format == GL_LUMINANCE)
1189 // This is a hack for GLQuake, invert.
1191 imesa->regs.s4.texCtrl[1].ni.clrArg1Invert = GL_TRUE;
1192 imesa->regs.s4.texBlendCtrl[1].ui = 0;
1194 __HWEnvCombineSingleUnitScale(imesa, 0, 1, &imesa->regs.s4.texBlendCtrl);
1198 fprintf(stderr, "unkown tex 1 env mode\n");
1203 imesa->regs.s4.texCtrl[1].ni.uMode =
1204 t->setup.sWrapMode == GL_REPEAT ? 0 : 1;
1205 imesa->regs.s4.texCtrl[1].ni.vMode =
1206 t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
1208 switch (t->setup.minFilter)
1211 imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Point;
1212 imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
1216 imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Bilin;
1217 imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_FALSE;
1220 case GL_NEAREST_MIPMAP_NEAREST:
1221 imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Point;
1222 imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
1225 case GL_LINEAR_MIPMAP_NEAREST:
1226 imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Bilin;
1227 imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
1230 case GL_NEAREST_MIPMAP_LINEAR:
1231 case GL_LINEAR_MIPMAP_LINEAR:
1232 imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Trilin;
1233 imesa->regs.s4.texCtrl[1].ni.mipmapEnable = GL_TRUE;
1237 if((ctx->Texture.Unit[1].LodBias !=0.0F) ||
1238 (imesa->regs.s4.texCtrl[1].ni.dBias != 0))
1240 int bias = (int)(ctx->Texture.Unit[1].LodBias * 32.0);
1243 else if (bias > 255)
1245 imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
1248 image = tObj->Image[0][tObj->BaseLevel];
1249 imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
1250 imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
1251 imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
1252 imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
1253 imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
1254 imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
1256 imesa->regs.s4.texAddr[1].ui = (u_int32_t) t->setup.physAddr | 2;
1257 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1258 imesa->regs.s4.texAddr[1].ui |= 0x1;
1260 static void savageUpdateTexState_s3d( GLcontext *ctx )
1262 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1263 struct gl_texture_object *tObj;
1264 struct gl_texture_image *image;
1269 if (ctx->Texture.Unit[0]._ReallyEnabled == 0) {
1270 imesa->regs.s3d.texCtrl.ui = 0;
1271 imesa->regs.s3d.texCtrl.ni.texEn = GL_FALSE;
1272 imesa->regs.s3d.texCtrl.ni.dBias = 0x08;
1273 imesa->regs.s3d.texCtrl.ni.texXprEn = GL_TRUE;
1277 tObj = ctx->Texture.Unit[0]._Current;
1278 if ((ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
1279 || tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1280 /* 3D texturing enabled, or texture border - fallback */
1281 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_TRUE);
1285 /* Do 2D texture setup */
1286 t = tObj->DriverData;
1288 t = savageAllocTexObj( tObj );
1293 imesa->CurrentTexObj[0] = &t->base;
1296 if (t->base.dirty_images[0] || t->dirtySubImages) {
1297 savageSetTexImages(imesa, tObj);
1298 savageUploadTexImages(imesa, t);
1301 driUpdateTextureLRU( &t->base );
1303 format = tObj->Image[0][tObj->BaseLevel]->Format;
1305 /* FIXME: copied from utah-glx, probably needs some tuning */
1306 switch (ctx->Texture.Unit[0].EnvMode) {
1308 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_DECAL_S3D;
1311 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_COPY_S3D;
1313 case GL_BLEND: /* FIXIT */
1315 imesa->regs.s3d.drawCtrl.ni.texBlendCtrl = SAVAGETBC_MODULATEALPHA_S3D;
1318 fprintf(stderr, "unkown tex env mode\n");
1323 imesa->regs.s3d.drawCtrl.ni.flushPdDestWrites = GL_TRUE;
1324 imesa->regs.s3d.drawCtrl.ni.flushPdZbufWrites = GL_TRUE;
1326 /* FIXME: this is how the utah-driver works. I doubt it's the ultimate
1328 imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
1329 imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
1330 if (t->setup.sWrapMode == GL_CLAMP)
1331 imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Clamp;
1333 imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Wrap;
1335 switch (t->setup.minFilter) {
1337 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1338 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1342 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1343 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
1346 case GL_NEAREST_MIPMAP_NEAREST:
1347 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
1348 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1351 case GL_LINEAR_MIPMAP_NEAREST:
1352 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Bilin;
1353 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1356 case GL_NEAREST_MIPMAP_LINEAR:
1357 case GL_LINEAR_MIPMAP_LINEAR:
1358 imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Trilin;
1359 imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_FALSE;
1363 /* There is no way to specify a maximum mipmap level. We may have to
1364 disable mipmapping completely. */
1366 if (t->max_level < t->image[0].image->WidthLog2 ||
1367 t->max_level < t->image[0].image->HeightLog2) {
1368 texCtrl.ni.mipmapEnable = GL_TRUE;
1369 if (texCtrl.ni.filterMode == TFM_Trilin)
1370 texCtrl.ni.filterMode = TFM_Bilin;
1371 texCtrl.ni.filterMode = TFM_Point;
1375 if((ctx->Texture.Unit[0].LodBias !=0.0F) ||
1376 (imesa->regs.s3d.texCtrl.ni.dBias != 0))
1378 int bias = (int)(ctx->Texture.Unit[0].LodBias * 16.0);
1381 else if (bias > 255)
1383 imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
1386 image = tObj->Image[0][tObj->BaseLevel];
1387 imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
1388 imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
1389 imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
1390 assert (t->hwFormat <= 7);
1391 imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
1393 imesa->regs.s3d.texAddr.ui = (u_int32_t) t->setup.physAddr | 2;
1394 if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
1395 imesa->regs.s3d.texAddr.ui |= 0x1;
1400 static void savageUpdateTextureState_s4( GLcontext *ctx )
1402 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1403 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1404 if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->bound &= ~2;
1405 imesa->CurrentTexObj[0] = 0;
1406 imesa->CurrentTexObj[1] = 0;
1407 savageUpdateTex0State_s4( ctx );
1408 savageUpdateTex1State_s4( ctx );
1409 imesa->dirty |= (SAVAGE_UPLOAD_TEX0 |
1410 SAVAGE_UPLOAD_TEX1);
1412 static void savageUpdateTextureState_s3d( GLcontext *ctx )
1414 savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1415 if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->bound &= ~1;
1416 imesa->CurrentTexObj[0] = 0;
1417 savageUpdateTexState_s3d( ctx );
1418 imesa->dirty |= (SAVAGE_UPLOAD_TEX0);
1420 void savageUpdateTextureState( GLcontext *ctx)
1422 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1423 FALLBACK (ctx, SAVAGE_FALLBACK_TEXTURE, GL_FALSE);
1424 FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_FALSE);
1425 if (imesa->savageScreen->chipset >= S3_SAVAGE4)
1426 savageUpdateTextureState_s4 (ctx);
1428 savageUpdateTextureState_s3d (ctx);
1433 /*****************************************
1435 *****************************************/
1437 static void savageTexEnv( GLcontext *ctx, GLenum target,
1438 GLenum pname, const GLfloat *param )
1440 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1442 if (pname == GL_TEXTURE_ENV_MODE) {
1444 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1446 } else if (pname == GL_TEXTURE_ENV_COLOR) {
1448 struct gl_texture_unit *texUnit =
1449 &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1450 const GLfloat *fc = texUnit->EnvColor;
1451 GLuint r, g, b, a, col;
1452 CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
1453 CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
1454 CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
1455 CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
1466 static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
1467 GLint internalFormat,
1468 GLint width, GLint border,
1469 GLenum format, GLenum type, const GLvoid *pixels,
1470 const struct gl_pixelstore_attrib *packing,
1471 struct gl_texture_object *texObj,
1472 struct gl_texture_image *texImage )
1474 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1476 /* Do nothing. Marking the image as dirty below is sufficient. */
1478 t = savageAllocTexObj(texObj);
1480 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1484 _mesa_store_teximage1d( ctx, target, level, internalFormat,
1485 width, border, format, type,
1486 pixels, packing, texObj, texImage );
1487 t->base.dirty_images[0] |= (1 << level);
1488 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1491 static void savageTexSubImage1D( GLcontext *ctx,
1496 GLenum format, GLenum type,
1497 const GLvoid *pixels,
1498 const struct gl_pixelstore_attrib *packing,
1499 struct gl_texture_object *texObj,
1500 struct gl_texture_image *texImage )
1502 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1503 assert( t ); /* this _should_ be true */
1505 savageMarkDirtyTiles(t, level, texImage->Width2, 1,
1506 xoffset, 0, width, 1);
1508 t = savageAllocTexObj(texObj);
1510 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
1513 t->base.dirty_images[0] |= (1 << level);
1515 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
1516 format, type, pixels, packing, texObj,
1518 t->dirtySubImages |= (1 << level);
1519 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1522 static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
1523 GLint internalFormat,
1524 GLint width, GLint height, GLint border,
1525 GLenum format, GLenum type, const GLvoid *pixels,
1526 const struct gl_pixelstore_attrib *packing,
1527 struct gl_texture_object *texObj,
1528 struct gl_texture_image *texImage )
1530 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1532 /* Do nothing. Marking the image as dirty below is sufficient. */
1534 t = savageAllocTexObj(texObj);
1536 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1540 _mesa_store_teximage2d( ctx, target, level, internalFormat,
1541 width, height, border, format, type,
1542 pixels, packing, texObj, texImage );
1543 t->base.dirty_images[0] |= (1 << level);
1544 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1547 static void savageTexSubImage2D( GLcontext *ctx,
1550 GLint xoffset, GLint yoffset,
1551 GLsizei width, GLsizei height,
1552 GLenum format, GLenum type,
1553 const GLvoid *pixels,
1554 const struct gl_pixelstore_attrib *packing,
1555 struct gl_texture_object *texObj,
1556 struct gl_texture_image *texImage )
1558 savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
1559 assert( t ); /* this _should_ be true */
1561 savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2,
1562 xoffset, yoffset, width, height);
1564 t = savageAllocTexObj(texObj);
1566 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
1569 t->base.dirty_images[0] |= (1 << level);
1571 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
1572 height, format, type, pixels, packing, texObj,
1574 t->dirtySubImages |= (1 << level);
1575 SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
1578 static void savageTexParameter( GLcontext *ctx, GLenum target,
1579 struct gl_texture_object *tObj,
1580 GLenum pname, const GLfloat *params )
1582 savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
1583 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1585 if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
1589 case GL_TEXTURE_MIN_FILTER:
1590 case GL_TEXTURE_MAG_FILTER:
1591 savageSetTexFilter(t,tObj->MinFilter,tObj->MagFilter);
1594 case GL_TEXTURE_WRAP_S:
1595 case GL_TEXTURE_WRAP_T:
1596 savageSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
1599 case GL_TEXTURE_BORDER_COLOR:
1600 savageSetTexBorderColor(t,tObj->_BorderChan);
1607 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1610 static void savageBindTexture( GLcontext *ctx, GLenum target,
1611 struct gl_texture_object *tObj )
1613 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1615 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) ||
1616 (tObj->DriverData != NULL) );
1618 imesa->new_state |= SAVAGE_NEW_TEXTURE;
1621 static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
1623 driTextureObject *t = (driTextureObject *)tObj->DriverData;
1624 savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
1631 driDestroyTextureObject(t);
1633 /* Free mipmap images and the texture object itself */
1634 _mesa_delete_texture_object(ctx, tObj);
1638 static struct gl_texture_object *
1639 savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1641 struct gl_texture_object *obj;
1642 obj = _mesa_new_texture_object(ctx, name, target);
1643 savageAllocTexObj( obj );
1648 void savageDDInitTextureFuncs( struct dd_function_table *functions )
1650 functions->TexEnv = savageTexEnv;
1651 functions->ChooseTextureFormat = savageChooseTextureFormat;
1652 functions->TexImage1D = savageTexImage1D;
1653 functions->TexSubImage1D = savageTexSubImage1D;
1654 functions->TexImage2D = savageTexImage2D;
1655 functions->TexSubImage2D = savageTexSubImage2D;
1656 functions->BindTexture = savageBindTexture;
1657 functions->NewTextureObject = savageNewTextureObject;
1658 functions->DeleteTexture = savageDeleteTexture;
1659 functions->IsTextureResident = driIsTextureResident;
1660 functions->TexParameter = savageTexParameter;