summaryrefslogtreecommitdiff
path: root/xc/lib/GL/mesa/src/drv/r128/r128_tex.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/r128/r128_tex.c')
-rw-r--r--xc/lib/GL/mesa/src/drv/r128/r128_tex.c1852
1 files changed, 1852 insertions, 0 deletions
diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tex.c b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c
new file mode 100644
index 000000000..6a82a527e
--- /dev/null
+++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c
@@ -0,0 +1,1852 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+ Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ * Gareth Hughes <gareth@precisioninsight.com>
+ *
+ */
+
+#include "r128_init.h"
+#include "r128_mesa.h"
+#include "r128_xmesa.h"
+#include "r128_context.h"
+#include "r128_lock.h"
+#include "r128_state.h"
+#include "r128_reg.h"
+#include "r128_cce.h"
+#include "r128_vb.h"
+#include "r128_tex.h"
+
+#include "mmath.h"
+#include "simple_list.h"
+
+static void r128SetTexWrap(r128TexObjPtr t, GLenum srwap, GLenum twrap);
+static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf);
+static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4]);
+
+/* Allocate and initialize hardware state associated with texture `t' */
+/* NOTE: This function is only called while holding the hardware lock */
+static r128TexObjPtr r128CreateTexObj(r128ContextPtr r128ctx,
+ struct gl_texture_object *tObj)
+{
+ r128TexObjPtr t;
+ struct gl_texture_image *image;
+ int log2Pitch, log2Height, log2Size, log2MinSize;
+ int totalSize;
+ int i;
+
+ image = tObj->Image[0];
+ if (!image) return NULL; /* ERROR!!! */
+
+ t = (r128TexObjPtr)calloc(1,sizeof(*t));
+ if (!t) return NULL; /* ERROR!!! */
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API)
+ fprintf(stderr, "r128CreateTexObj(%p)\n", tObj);
+
+ switch (image->Format) {
+ case GL_RGBA:
+ case GL_ALPHA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ if (r128ctx->r128Screen->bpp == 32) {
+ t->texelBytes = 4;
+ t->textureFormat = R128_DATATYPE_ARGB8888;
+ } else {
+ t->texelBytes = 2;
+ t->textureFormat = R128_DATATYPE_ARGB4444;
+ }
+ break;
+
+ case GL_RGB:
+ if (r128ctx->r128Screen->bpp == 32) {
+ t->texelBytes = 4;
+ t->textureFormat = R128_DATATYPE_ARGB8888;
+ } else {
+ t->texelBytes = 2;
+ t->textureFormat = R128_DATATYPE_RGB565;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ if (r128ctx->r128Screen->bpp == 32) {
+ t->texelBytes = 4;
+ t->textureFormat = R128_DATATYPE_ARGB8888;
+ } else {
+ t->texelBytes = 2;
+ /* Use this to get true greys */
+ t->textureFormat = R128_DATATYPE_ARGB1555;
+ }
+ break;
+
+ case GL_COLOR_INDEX:
+ t->texelBytes = 1;
+ t->textureFormat = R128_DATATYPE_CI8;
+ break;
+
+ default:
+ /* ERROR!!! */
+ fprintf(stderr, "r128CreateTexObj: bad image->Format\n");
+ free(t);
+ return NULL;
+ }
+
+ /* Calculate dimensions in log domain */
+ for (i = 1, log2Height = 0; i < image->Height; i *= 2) log2Height++;
+ for (i = 1, log2Pitch = 0; i < image->Width; i *= 2) log2Pitch++;
+ if (image->Width > image->Height) log2Size = log2Pitch;
+ else log2Size = log2Height;
+
+ t->dirty_images = 0;
+
+ /* Calculate mipmap offsets and dimensions */
+ totalSize = 0;
+ for (i = 0; i <= log2Size && tObj->Image[i]; i++) {
+ t->image[i].offset = totalSize;
+ t->image[i].width = tObj->Image[i]->Width;
+ t->image[i].height = tObj->Image[i]->Height;
+ t->dirty_images |= 1 << i;
+ totalSize += (tObj->Image[i]->Height *
+ tObj->Image[i]->Width *
+ t->texelBytes);
+
+ /* Offsets must be 32-byte aligned for host data blits */
+ totalSize = (totalSize + 31) & ~31;
+ }
+ log2MinSize = log2Size - i + 1;
+
+ t->totalSize = totalSize;
+ t->internFormat = image->IntFormat;
+
+ t->bound = 0;
+ t->heap = 0; /* This is set in r128UploadTexImages */
+ t->tObj = tObj;
+
+ t->memBlock = NULL;
+ t->bufAddr = NULL;
+
+ t->regs.tex_cntl = t->textureFormat;
+ t->regs.size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) |
+ (log2Size << R128_TEX_SIZE_SHIFT) |
+ (log2Height << R128_TEX_HEIGHT_SHIFT) |
+ (log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
+ t->regs.border_color = 0x00000000;
+
+ if (log2MinSize == log2Size ||
+ log2MinSize != 0)
+ t->regs.tex_cntl |= R128_MIP_MAP_DISABLE;
+
+ r128SetTexWrap(t, tObj->WrapS, tObj->WrapT);
+ r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter);
+ r128SetTexBorderColor(t, tObj->BorderColor);
+
+ tObj->DriverData = t;
+
+ make_empty_list(t);
+
+ return t;
+}
+
+/* Destroy hardware state associated with texture `t' */
+/* NOTE: This function can be called while holding the hardware lock and
+ while not holding the lock*/
+void r128DestroyTexObj(r128ContextPtr r128ctx, r128TexObjPtr t)
+{
+ if (!t) return;
+
+ if (t->memBlock) {
+ mmFreeMem(t->memBlock);
+ t->memBlock = NULL;
+ }
+
+ if (t->tObj) t->tObj->DriverData = NULL;
+ if (t->bound) r128ctx->CurrentTexObj[t->bound-1] = NULL;
+
+ remove_from_list(t);
+ free(t);
+}
+
+/* Keep track of swapped out texture objects */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128SwapOutTexObj(r128ContextPtr r128ctx, r128TexObjPtr t)
+{
+ if (t->memBlock) {
+ mmFreeMem(t->memBlock);
+ t->memBlock = NULL;
+ }
+
+ t->dirty_images = ~0;
+ move_to_tail(&r128ctx->SwappedOut, t);
+}
+
+/* Print out debugging information about texture LRU */
+void r128PrintLocalLRU(r128ContextPtr r128ctx, int heap)
+{
+ r128TexObjPtr t;
+ int sz = 1 << (r128ctx->r128Screen->log2TexGran[heap]);
+
+ foreach(t, &r128ctx->TexObjList[heap]) {
+ if (!t->tObj) {
+ fprintf(stderr, "Placeholder %d at 0x%x sz 0x%x\n",
+ t->memBlock->ofs / sz,
+ t->memBlock->ofs,
+ t->memBlock->size);
+ } else {
+ fprintf(stderr, "Texture (bound %d) at 0x%x sz 0x%x\n",
+ t->bound,
+ t->memBlock->ofs,
+ t->memBlock->size);
+ }
+ }
+}
+
+void r128PrintGlobalLRU(r128ContextPtr r128ctx, int heap)
+{
+ R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap];
+ int i, j;
+
+ for (i = 0, j = R128_NR_TEX_REGIONS ; i < R128_NR_TEX_REGIONS ; i++) {
+ fprintf(stderr, "list[%d] age %d next %d prev %d\n",
+ j, list[j].age, list[j].next, list[j].prev);
+ j = list[j].next;
+ if (j == R128_NR_TEX_REGIONS) break;
+ }
+
+ if (j != R128_NR_TEX_REGIONS) {
+ fprintf(stderr, "Loop detected in global LRU\n");
+ }
+}
+
+/* Reset the global texture LRU */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128ResetGlobalLRU(r128ContextPtr r128ctx, int heap)
+{
+ R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap];
+ int log2sz = 1 << r128ctx->r128Screen->log2TexGran[heap];
+ int i;
+
+ /*
+ * (Re)initialize the global circular LRU list. The last element in
+ * the array (R128_NR_TEX_REGIONS) is the sentinal. Keeping it at
+ * the end of the array allows it to be addressed rationally when
+ * looking up objects at a particular location in texture memory.
+ */
+
+ for (i = 0; (i+1) * log2sz <= r128ctx->r128Screen->texSize[heap]; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = R128_NR_TEX_REGIONS;
+ list[i].prev = i-1;
+ list[i].next = R128_NR_TEX_REGIONS;
+ list[R128_NR_TEX_REGIONS].prev = i;
+ list[R128_NR_TEX_REGIONS].next = 0;
+ r128ctx->r128Screen->SAREA->texAge[heap] = 0;
+}
+
+/* Update the local and glock texture LRUs */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128UpdateTexLRU(r128ContextPtr r128ctx, r128TexObjPtr t)
+{
+ int heap = t->heap;
+ R128TexRegion *list = r128ctx->r128Screen->SAREA->texList[heap];
+ int log2sz = r128ctx->r128Screen->log2TexGran[heap];
+
+ int start = t->memBlock->ofs >> log2sz;
+ int end = (t->memBlock->ofs + t->memBlock->size-1) >> log2sz;
+ int i;
+
+ r128ctx->lastTexAge[heap] = ++r128ctx->r128Screen->SAREA->texAge[heap];
+
+ /* Update our local LRU */
+ move_to_head(&r128ctx->TexObjList[heap], t);
+
+ /* Update the global LRU */
+ for (i = start ; i <= end ; i++) {
+ list[i].in_use = 1;
+ list[i].age = r128ctx->lastTexAge[heap];
+
+ /* remove_from_list(i) */
+ list[(CARD32)list[i].next].prev = list[i].prev;
+ list[(CARD32)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i) */
+ list[i].prev = R128_NR_TEX_REGIONS;
+ list[i].next = list[R128_NR_TEX_REGIONS].next;
+ list[(CARD32)list[R128_NR_TEX_REGIONS].next].prev = i;
+ list[R128_NR_TEX_REGIONS].next = i;
+ }
+}
+
+/* Update our notion of what textures have been changed since we last
+ held the lock. This pertains to both our local textures and the
+ textures belonging to other clients. Keep track of other client's
+ textures by pushing a placeholder texture onto the LRU list -- these
+ are denoted by (tObj == NULL). */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128TexturesGone(r128ContextPtr r128ctx, int heap,
+ int offset, int size, int in_use)
+{
+ r128TexObjPtr t, tmp;
+
+ foreach_s (t, tmp, &r128ctx->TexObjList[heap]) {
+ if (t->memBlock->ofs >= offset + size ||
+ t->memBlock->ofs + t->memBlock->size <= offset)
+ continue;
+
+ /* It overlaps - kick it out. Need to hold onto the currently
+ bound objects, however. */
+ if (t->bound) r128SwapOutTexObj(r128ctx, t);
+ else r128DestroyTexObj(r128ctx, t);
+ }
+
+ if (in_use) {
+ t = (r128TexObjPtr) calloc(1,sizeof(*t));
+ if (!t) return;
+
+ t->memBlock = mmAllocMem(r128ctx->texHeap[heap], size, 0, offset);
+ insert_at_head(&r128ctx->TexObjList[heap], t);
+ }
+}
+
+/* Update our client's shared texture state. If another client has
+ modified a region in which we have textures, then we need to figure
+ out which of our textures has been removed, and update our global
+ LRU. */
+void r128AgeTextures(r128ContextPtr r128ctx, int heap)
+{
+ R128SAREAPrivPtr sarea = r128ctx->r128Screen->SAREA;
+
+ if (sarea->texAge[heap] != r128ctx->lastTexAge[heap]) {
+ int log2sz = 1 << r128ctx->r128Screen->log2TexGran[heap];
+ int nr = 0;
+ int idx;
+
+ for (idx = sarea->texList[heap][R128_NR_TEX_REGIONS].prev;
+ idx != R128_NR_TEX_REGIONS && nr < R128_NR_TEX_REGIONS;
+ idx = sarea->texList[heap][idx].prev, nr++) {
+
+ /* If switching texturing schemes, then the SAREA might not
+ have been properly cleared, so we need to reset the
+ global texture LRU. */
+ if (idx * log2sz > r128ctx->r128Screen->texSize[heap]) {
+ nr = R128_NR_TEX_REGIONS;
+ break;
+ }
+
+ if (sarea->texList[heap][idx].age > r128ctx->lastTexAge[heap])
+ r128TexturesGone(r128ctx, heap, idx * log2sz, log2sz,
+ sarea->texList[heap][idx].in_use);
+ }
+
+ if (nr == R128_NR_TEX_REGIONS) {
+ r128TexturesGone(r128ctx, heap,
+ 0, r128ctx->r128Screen->texSize[heap], 0);
+ r128ResetGlobalLRU(r128ctx, heap);
+ }
+
+ r128ctx->dirty |= R128_UPDATE_TEX0IMAGES;
+ r128ctx->dirty |= R128_UPDATE_TEX1IMAGES;
+ r128ctx->lastTexAge[heap] = sarea->texAge[heap];
+ }
+}
+
+/* Convert a block of Mesa-formatted texture to an 8bpp hardware format */
+static void r128ConvertTexture8bpp(r128ContextPtr r128ctx,
+ struct gl_texture_image *image,
+ int x, int y, int width, int height,
+ int pitch)
+{
+ CARD8 *src;
+ CARD32 pix;
+ int i, j;
+
+ switch (image->Format) {
+ case GL_RGB:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3;
+ for (j = width >> 2; j; j--) {
+ pix = ((R128PACKCOLOR332( src[0], src[1], src[2]) ) |
+ (R128PACKCOLOR332( src[3], src[4], src[5]) << 8) |
+ (R128PACKCOLOR332( src[6], src[7], src[8]) << 16) |
+ (R128PACKCOLOR332( src[9], src[10], src[11]) << 24));
+ R128CCE(pix);
+ src += 12;
+ }
+ }
+ break;
+
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_INTENSITY:
+ case GL_COLOR_INDEX:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width >> 2; j; j--) {
+ pix = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+ R128CCE(pix);
+ src += 4;
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "r128ConvertTexture8bpp: unsupported format 0x%x\n",
+ image->Format);
+ }
+}
+
+/* Convert a block of Mesa-formatted texture to a 16bpp hardware format */
+static void r128ConvertTexture16bpp(r128ContextPtr r128ctx,
+ struct gl_texture_image *image,
+ int x, int y, int width, int height,
+ int pitch)
+{
+ CARD8 *src;
+ CARD32 pix;
+ int i, j;
+
+ switch (image->Format) {
+ case GL_RGB:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3;
+ for (j = width >> 1; j; j--) {
+ pix = ((R128PACKCOLOR565(src[0], src[1], src[2]) ) |
+ (R128PACKCOLOR565(src[3], src[4], src[5]) << 16));
+ R128CCE(pix);
+ src += 6;
+ }
+ }
+ break;
+
+ case GL_RGBA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4;
+ for (j = width >> 1; j; j--) {
+ pix =
+ ((R128PACKCOLOR4444(src[0], src[1], src[2], src[3]) ) |
+ (R128PACKCOLOR4444(src[4], src[5], src[6], src[7])<<16));
+ R128CCE(pix);
+ src += 8;
+ }
+ }
+ break;
+
+ case GL_ALPHA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width >> 1; j; j--) {
+ pix = ((R128PACKCOLOR4444(0xff, 0xff, 0xff, src[0]) ) |
+ (R128PACKCOLOR4444(0xff, 0xff, 0xff, src[1]) << 16));
+ R128CCE(pix);
+ src += 2;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width >> 1; j; j--) {
+ pix = ((R128PACKCOLOR1555(src[0], src[0], src[0], 0xff) ) |
+ (R128PACKCOLOR1555(src[1], src[1], src[1], 0xff)<<16));
+ R128CCE(pix);
+ src += 2;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 2;
+ for (j = width >> 1; j; j--) {
+ pix =
+ ((R128PACKCOLOR4444(src[0], src[0], src[0], src[1]) ) |
+ (R128PACKCOLOR4444(src[2], src[2], src[2], src[3])<<16));
+ R128CCE(pix);
+ src += 4;
+ }
+ }
+ break;
+
+ case GL_INTENSITY:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width >> 1; j; j--) {
+ pix =
+ ((R128PACKCOLOR4444(src[0], src[0], src[0], src[0]) ) |
+ (R128PACKCOLOR4444(src[1], src[1], src[1], src[1])<<16));
+ R128CCE(pix);
+ src += 2;
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "r128ConvertTexture16bpp: unsupported format 0x%x\n",
+ image->Format);
+ }
+}
+
+/* Convert a block of Mesa-formatted texture to a 32bpp hardware format */
+static void r128ConvertTexture32bpp(r128ContextPtr r128ctx,
+ struct gl_texture_image *image,
+ int x, int y, int width, int height,
+ int pitch)
+{
+ CARD8 *src;
+ CARD32 pix;
+ int i, j;
+
+ switch (image->Format) {
+ case GL_RGB:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 3;
+ for (j = width; j; j--) {
+ pix = R128PACKCOLOR8888(src[0], src[1], src[2], 0xff);
+ R128CCE(pix);
+ src += 3;
+ }
+ }
+ break;
+
+ case GL_RGBA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 4;
+ for (j = width; j; j--) {
+ pix = R128PACKCOLOR8888(src[0], src[1], src[2], src[3]);
+ R128CCE(pix);
+ src += 4;
+ }
+ }
+ break;
+
+ case GL_ALPHA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width; j; j--) {
+ pix = R128PACKCOLOR8888(0xff, 0xff, 0xff, src[0]);
+ R128CCE(pix);
+ src += 1;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE:
+ for (i = 0 ; i < height ; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width; j; j--) {
+ pix = R128PACKCOLOR8888(src[0], src[0], src[0], 0xff);
+ R128CCE(pix);
+ src += 1;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x) * 2;
+ for (j = width; j; j-- ) {
+ pix = R128PACKCOLOR8888(src[0], src[0], src[0], src[1]);
+ R128CCE(pix);
+ src += 2;
+ }
+ }
+ break;
+
+ case GL_INTENSITY:
+ for (i = 0; i < height; i++) {
+ src = (CARD8 *)image->Data + ((y + i) * pitch + x);
+ for (j = width; j; j--) {
+ pix = R128PACKCOLOR8888(src[0], src[0], src[0], src[0]);
+ R128CCE(pix);
+ src += 1;
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "r128ConvertTexture32bpp: unsupported format 0x%x\n",
+ image->Format);
+ }
+}
+
+/* Upload the texture image associated with texture `t' at level `level'
+ at the address relative to `start'. */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128UploadSubImage(r128ContextPtr r128ctx,
+ r128TexObjPtr t, int level,
+ int x, int y, int width, int height)
+{
+ struct gl_texture_image *image;
+ int texelsPerDword = 0;
+ int imageWidth, imageHeight;
+ int remaining, rows;
+ int format, pitch, dwords;
+ CARD32 offset;
+
+ /* Ensure we have a valid texture to upload */
+ if (level < 0 || level > R128_TEX_MAXLEVELS) return;
+ if (!(image = t->tObj->Image[level])) return;
+
+ /* FIXME: support RGB888 (i.e., 24bpp) textures? */
+ switch (t->texelBytes) {
+ case 1: texelsPerDword = 4; break;
+ case 2: texelsPerDword = 2; break;
+ case 4: texelsPerDword = 1; break;
+ }
+
+ imageWidth = image->Width;
+ imageHeight = image->Height;
+
+ format = t->textureFormat >> 16;
+
+ /* The texel upload routines have a minimum width, so force the size
+ if needed */
+ if (imageWidth < texelsPerDword) {
+ int factor;
+
+ factor = texelsPerDword / imageWidth;
+ imageWidth = texelsPerDword;
+ imageHeight /= factor;
+ if (imageHeight == 0) {
+ /* In this case, the texel converter will actually walk a
+ texel or two off the end of the image, but normal malloc
+ alignment should prevent it from ever causing a fault. */
+ imageHeight = 1;
+ }
+ }
+
+ /* We can't upload to a pitch less than 8 texels so we will need to
+ linearly upload all modified rows for textures smaller than this.
+ This makes the x/y/width/height different for the blitter and the
+ texture walker. */
+ if (imageWidth >= 8) {
+ /* The texture walker and the blitter look identical */
+ pitch = imageWidth >> 3;
+ } else {
+ int factor;
+ int y2;
+ int start, end;
+
+ start = (y * imageWidth) & ~7;
+ end = (y + height) * imageWidth;
+
+ if (end - start < 8) {
+ /* Handle the case where the total number of texels uploaded
+ is < 8 */
+ x = 0;
+ y = start / 8;
+ width = end - start;
+ height = 1;
+ } else {
+ /* Upload some number of full 8 texel blit rows */
+ factor = 8 / imageWidth;
+
+ y2 = y + height - 1;
+ y /= factor;
+ y2 /= factor;
+
+ x = 0;
+ width = 8;
+ height = y2 - y + 1;
+ }
+
+ /* Fixed pitch of 8 */
+ pitch = 1;
+ }
+
+ dwords = width * height / texelsPerDword;
+ offset = (CARD32)(t->bufAddr + t->image[level].offset);
+
+ /* Fix offset for AGP textures */
+ if (t->heap == R128_AGP_TEX_HEAP)
+ offset += R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) {
+ fprintf(stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n",
+ width, height, image->Width, image->Height, x, y);
+ fprintf(stderr, " blit ofs: 0x%08x pitch: 0x%x dwords: %d "
+ "level: %d format: %x\n",
+ (int)offset, pitch, dwords, level, format);
+ }
+
+#define R128_MAX_BLIT_DWORDS 8192
+ /* Subdivide the texture if required */
+ if (dwords < R128_MAX_BLIT_DWORDS) {
+ rows = height;
+ } else {
+ rows = (R128_MAX_BLIT_DWORDS * texelsPerDword) / (2 * width);
+ }
+
+ /* Flush the pixel cache, and mark the contents as Read Invalid */
+ R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0);
+ R128CCE(r128ctx->regs.pc_gui_ctlstat |
+ R128_PC_RI_GUI |
+ R128_PC_FLUSH_GUI);
+ R128CCE_SUBMIT_PACKETS();
+
+ /* Build the CCE host data blit header */
+ R128CCE3(R128_CCE_PACKET3_CNTL_HOSTDATA_BLT, 0);
+
+ /* DP_GUI_MASTER_CNTL */
+ R128CCE(R128_GMC_DST_PITCH_OFFSET_CNTL |
+ R128_GMC_BRUSH_NONE |
+ (format << 8) |
+ R128_GMC_SRC_DATATYPE_COLOR |
+ R128_ROP3_S |
+ R128_DP_SRC_SOURCE_HOST_DATA |
+ R128_GMC_CLR_CMP_CNTL_DIS |
+ R128_AUX_CLIP_DIS |
+ R128_GMC_WR_MSK_DIS );
+
+ /* DST_OFFSET_PITCH - fixed at the moment until we get better ring
+ control */
+ R128CCE((pitch << 21) | (offset>>5));
+
+ /* FRGD_COLOR, BKGD_COLOR */
+ R128CCE(0xffffffff);
+ R128CCE(0xffffffff);
+
+ for (remaining = height; remaining > 0; remaining -= rows, y += rows) {
+ height = (remaining >= rows) ? rows : remaining;
+ dwords = width * height / texelsPerDword;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API) {
+ fprintf(stderr, " blitting: %d,%d at %d,%d - %d dwords\n",
+ width, height, x, y, dwords);
+ }
+
+ r128ctx->CCEbuf[0] &= ~R128_CCE_PACKET_COUNT_MASK;
+ r128ctx->CCEbuf[0] |= (dwords + 6) << 16;
+
+ /* Blit coords, size */
+ R128CCE((y << 16) | x);
+ R128CCE((height << 16) | width);
+ R128CCE(dwords);
+
+ /* Actually do the texture conversion */
+ switch (t->texelBytes) {
+ case 1:
+ r128ConvertTexture8bpp(r128ctx, image,
+ x, y, width, height, width);
+ break;
+ case 2:
+ r128ConvertTexture16bpp(r128ctx, image,
+ x, y, width, height, width);
+ break;
+ case 4:
+ r128ConvertTexture32bpp(r128ctx,
+ image, x, y, width, height, width);
+ break;
+ }
+
+ /* Flush the pixel cache */
+ R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0 );
+ R128CCE(r128ctx->regs.pc_gui_ctlstat | R128_PC_FLUSH_GUI);
+
+ /* Save the partial blit header */
+ R128CCE_SUBMIT_PACKETS();
+ r128ctx->CCEcount = 5;
+ }
+
+ /* Clean up CCE ring buffer */
+ r128ctx->CCEcount = 0;
+}
+
+/* Upload the texture images associated with texture `t'. This might
+ require removing our own and/or other client's texture objects to
+ make room for these images. */
+/* NOTE: This function is only called while holding the hardware lock */
+int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t)
+{
+ int i;
+ int minLevel;
+ int maxLevel;
+ int heap;
+
+ if (!t) return 0;
+
+ /* Choose the heap appropriately */
+ heap = t->heap = R128_LOCAL_TEX_HEAP;
+ if (!r128ctx->r128Screen->IsPCI &&
+ t->totalSize > r128ctx->r128Screen->texSize[heap])
+ heap = t->heap = R128_AGP_TEX_HEAP;
+
+ /* Do we need to eject LRU texture objects? */
+ if (!t->memBlock) {
+ /* Allocate a memory block on a 4k boundary (1<<12 == 4096) */
+ t->memBlock = mmAllocMem(r128ctx->texHeap[heap], t->totalSize, 12, 0);
+
+ /* Try AGP before kicking anything out of local mem */
+ if (!t->memBlock && heap == R128_LOCAL_TEX_HEAP) {
+ t->memBlock = mmAllocMem(r128ctx->texHeap[R128_AGP_TEX_HEAP],
+ t->totalSize, 12, 0);
+
+ if (t->memBlock) heap = t->heap = R128_AGP_TEX_HEAP;
+ }
+
+ /* Kick out textures until the requested texture fits */
+ while (!t->memBlock) {
+ if (r128ctx->TexObjList[heap].prev->bound) {
+ fprintf(stderr,
+ "r128UploadTexImages: ran into bound texture\n");
+ return -1;
+ }
+ if (r128ctx->TexObjList[heap].prev ==
+ &(r128ctx->TexObjList[heap])) {
+ if (r128ctx->r128Screen->IsPCI) {
+ fprintf(stderr, "r128UploadTexImages: upload texture "
+ "failure on local texture heaps, sz=%d\n",
+ t->totalSize);
+ return -1;
+ } else if (heap == R128_LOCAL_TEX_HEAP) {
+ heap = t->heap = R128_AGP_TEX_HEAP;
+ continue;
+ } else {
+ fprintf(stderr, "r128UploadTexImages: upload texture "
+ "failure on both local and AGP texture heaps, "
+ "sz=%d\n",
+ t->totalSize);
+ return -1;
+ }
+ }
+
+ r128DestroyTexObj(r128ctx, r128ctx->TexObjList[heap].prev);
+
+ t->memBlock = mmAllocMem(r128ctx->texHeap[heap],
+ t->totalSize, 12, 0);
+ }
+
+ /* Set the base offset of the texture image */
+ t->bufAddr = (unsigned char *)r128ctx->r128Screen->texOffset[heap];
+ t->bufAddr += t->memBlock->ofs;
+
+ maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >>
+ R128_TEX_SIZE_SHIFT);
+ minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >>
+ R128_TEX_MIN_SIZE_SHIFT);
+
+ /* Update the hardware's texture image addresses */
+ switch (t->bound) {
+ case 1:
+ /* Set texture offsets */
+ if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) {
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr;
+ } else {
+ for (i = maxLevel; i >= minLevel; i--)
+ r128ctx->regs.prim_tex_offset[i] =
+ t->image[maxLevel-i].offset + (CARD32)t->bufAddr;
+ }
+ /* Fix AGP texture offsets */
+ if (heap == R128_AGP_TEX_HEAP)
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.prim_tex_offset[i] +=
+ R128_AGP_TEX_OFFSET +
+ r128ctx->r128Screen->agpTexOffset;
+ /* Force loading the new state into the hardware */
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_TEX0STATE;
+ break;
+
+ case 2:
+ /* Set texture offsets */
+ if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) {
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr;
+ } else {
+ for (i = maxLevel; i >= minLevel; i--)
+ r128ctx->regs.sec_tex_offset[i] =
+ t->image[maxLevel-i].offset + (CARD32)t->bufAddr;
+ }
+ /* Fix AGP texture offsets */
+ if (heap == R128_AGP_TEX_HEAP)
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.sec_tex_offset[i] +=
+ R128_AGP_TEX_OFFSET +
+ r128ctx->r128Screen->agpTexOffset;
+ /* Force loading the new state into the hardware */
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_TEX1STATE;
+ break;
+
+ default:
+ return -1;
+ }
+ }
+
+ /* Let the world know we've used this memory recently */
+ r128UpdateTexLRU(r128ctx, t);
+
+ /* Upload any images that are new */
+ if (t->dirty_images) {
+ int num_levels = (((t->regs.size_pitch & R128_TEX_SIZE_MASK) >>
+ R128_TEX_SIZE_SHIFT) -
+ ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >>
+ R128_TEX_MIN_SIZE_SHIFT));
+
+ for (i = 0; i <= num_levels; i++) {
+ if (t->dirty_images & (1<<i)) {
+ r128UploadSubImage(r128ctx, t, i, 0, 0,
+ t->image[i].width, t->image[i].height);
+ }
+ }
+
+ r128ctx->regs.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
+
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_ENGINESTATE;
+ }
+
+ t->dirty_images = 0;
+ return 0;
+}
+
+/* Update the hardware state for texture unit 0 */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128UpdateTex0State(r128ContextPtr r128ctx)
+{
+ GLcontext *ctx = r128ctx->glCtx;
+ r128TexObjPtr t;
+ struct gl_texture_object *tObj;
+ int i;
+ CARD32 tex_size_pitch, tex_combine_cntl;
+
+ /* Only update the hardware texture state if the texture is current,
+ complete and enabled. */
+ if (!(tObj = ctx->Texture.Unit[0].Current)) return;
+ if ((tObj != ctx->Texture.Unit[0].CurrentD[2]) &&
+ (tObj != ctx->Texture.Unit[0].CurrentD[1])) return;
+ if (!tObj->Complete) return;
+
+ /* If neither tex0 nor tex1 is enabled, then disable tex0. However,
+ if tex1 is enabled but tex0 is disabled, then we need to enable
+ tex0 and have it to copy the input (see how tex_combine_cntl is
+ setup below). */
+ if (!(ctx->Texture.Enabled & (ENABLE_TEX0 | ENABLE_TEX1))) {
+ r128ctx->regs.tex_cntl_c &= ~R128_TEXMAP_ENABLE;
+ return;
+ }
+
+ /* If this is the first time the texture has been used, then create
+ a new texture object for it. */
+ t = tObj->DriverData;
+ if (!t) t = r128CreateTexObj(r128ctx, tObj);
+ if (!t) return;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API)
+ fprintf(stderr, "r128UpdateTex0State(%p, 0x%08x)\n",
+ tObj, (int)t->dirty_images);
+
+ /* Force any texture images to be loaded into the hardware */
+ if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX0IMAGES;
+
+ /* Bind texture to texture 0 unit */
+ r128ctx->CurrentTexObj[0] = t;
+ t->bound = 1;
+
+ if (t->memBlock) r128UpdateTexLRU(r128ctx, t);
+
+ /* Set the texture environment state */
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_REPLACE:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_DIS |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_DIS |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_BLEND:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ switch (r128ctx->regs.constant_color_c &
+ R128_CONSTANT_COLOR_MASK) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ switch (r128ctx->regs.constant_color_c &
+ R128_CONSTANT_COLOR_MASK) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_INTENSITY:
+ switch (r128ctx->regs.constant_color_c &
+ R128_CONSTANT_COLOR_MASK) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_NTEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_MODULATE:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_DECAL:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ tex_combine_cntl = (R128_COMB_BLEND_TEXTURE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_RGB:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ /* Undefined behaviour - just copy the input */
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_ADD:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_ADD |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_ADD |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* If tex0 is disabled, then make sure it just copies the input */
+ if (!(ctx->Texture.Enabled & ENABLE_TEX0))
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_INT_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_INT_ALPHA);
+
+ /* Enable tex0 */
+ r128ctx->regs.tex_cntl_c |= R128_TEXMAP_ENABLE;
+
+ tex_size_pitch = r128ctx->regs.tex_size_pitch_c;
+ tex_size_pitch &= ~R128_TEX_SIZE_PITCH_MASK;
+ tex_size_pitch |= t->regs.size_pitch << R128_TEX_SIZE_PITCH_SHIFT;
+
+ /* Set the primary texture state in r128ctx->regs */
+ r128ctx->regs.prim_tex_cntl_c = t->regs.tex_cntl;
+ r128ctx->regs.prim_texture_combine_cntl_c = tex_combine_cntl;
+ r128ctx->regs.tex_size_pitch_c = tex_size_pitch;
+ r128ctx->regs.prim_texture_border_color_c = t->regs.border_color;
+
+ /* Set texture offsets */
+ if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) {
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr;
+ } else {
+ int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >>
+ R128_TEX_SIZE_SHIFT);
+ int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >>
+ R128_TEX_MIN_SIZE_SHIFT);
+ for (i = maxLevel; i >= minLevel; i--)
+ r128ctx->regs.prim_tex_offset[i] =
+ t->image[maxLevel-i].offset + (CARD32)t->bufAddr;
+ }
+ /* Fix AGP texture offsets */
+ if (t->heap == R128_AGP_TEX_HEAP)
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.prim_tex_offset[i] +=
+ R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset;
+
+ /* Force loading the new state into the hardware */
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_TEX0STATE | R128_CTX_ENGINESTATE;
+}
+
+/* Update the hardware state for texture unit 1 */
+/* NOTE: This function is only called while holding the hardware lock */
+static void r128UpdateTex1State(r128ContextPtr r128ctx)
+{
+ GLcontext *ctx = r128ctx->glCtx;
+ r128TexObjPtr t;
+ struct gl_texture_object *tObj;
+ int i;
+ CARD32 tex_size_pitch, tex_combine_cntl, tex_cntl;
+
+ /* Only update the hardware texture state if the texture is current,
+ complete and enabled. */
+ if (!(tObj = ctx->Texture.Unit[1].Current)) return;
+ if ((tObj != ctx->Texture.Unit[1].CurrentD[2]) &&
+ (tObj != ctx->Texture.Unit[1].CurrentD[1])) return;
+ if (!tObj->Complete) return;
+
+ /* If tex1 is not enabled, then disable it */
+ if (!(ctx->Texture.Enabled & ENABLE_TEX1)) {
+ r128ctx->regs.tex_cntl_c &= ~R128_SEC_TEXMAP_ENABLE;
+ return;
+ }
+
+ /* If this is the first time the texture has been used, then create
+ a new texture object for it. */
+ t = tObj->DriverData;
+ if (!t) t = r128CreateTexObj(r128ctx, tObj);
+ if (!t) return;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API)
+ fprintf(stderr, "r128UpdateTex1State(%p, 0x%08x)\n",
+ tObj, (int)t->dirty_images);
+
+ /* Force any texture images to be loaded into the hardware */
+ if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX1IMAGES;
+
+ /* Bind texture to texture 1 unit */
+ r128ctx->CurrentTexObj[1] = t;
+ t->bound = 2;
+
+ if (t->memBlock) r128UpdateTexLRU(r128ctx, t);
+
+ /* Set the texture environment state */
+ switch (ctx->Texture.Unit[1].EnvMode) {
+ case GL_REPLACE:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_DIS |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_DIS |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_BLEND:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ switch ( r128ctx->regs.constant_color_c & R128_CONSTANT_COLOR_MASK ) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ switch (r128ctx->regs.constant_color_c &
+ R128_CONSTANT_COLOR_MASK) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA );
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA );
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_INTENSITY:
+ switch (r128ctx->regs.constant_color_c &
+ R128_CONSTANT_COLOR_MASK) {
+ case R128_CONSTANT_COLOR_ZERO:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_NTEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_NTEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case R128_CONSTANT_COLOR_ONE:
+ default:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ r128ctx->Fallback |= R128_FALLBACK_TEXTURE;
+ break;
+ }
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_MODULATE:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_MODULATE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_DECAL:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ tex_combine_cntl = (R128_COMB_BLEND_TEXTURE |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_RGB:
+ tex_combine_cntl = (R128_COMB_DIS |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ /* Undefined behaviour - just copy the input */
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ case GL_ADD:
+ switch (tObj->Image[0]->Format) {
+ case GL_RGBA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ tex_combine_cntl = (R128_COMB_ADD |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_RGB:
+ case GL_LUMINANCE:
+ tex_combine_cntl = (R128_COMB_ADD |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_COPY_INP |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_ALPHA:
+ tex_combine_cntl = (R128_COMB_COPY_INP |
+ R128_COLOR_FACTOR_TEX |
+ R128_INPUT_FACTOR_PREV_COLOR |
+ R128_COMB_ALPHA_MODULATE |
+ R128_ALPHA_FACTOR_TEX_ALPHA |
+ R128_INP_FACTOR_A_PREV_ALPHA);
+ break;
+ case GL_COLOR_INDEX:
+ default:
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ /* Enable tex1 */
+ r128ctx->regs.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE;
+
+ tex_size_pitch = r128ctx->regs.tex_size_pitch_c;
+ tex_size_pitch &= ~R128_SEC_TEX_SIZE_PITCH_MASK;
+ tex_size_pitch |= t->regs.size_pitch << R128_SEC_TEX_SIZE_PITCH_SHIFT;
+
+ tex_cntl = t->regs.tex_cntl | R128_SEC_SELECT_SEC_ST;
+
+ /* Set the secondary texture state in r128ctx->regs */
+ r128ctx->regs.sec_tex_cntl_c = tex_cntl;
+ r128ctx->regs.sec_tex_combine_cntl_c = tex_combine_cntl;
+ r128ctx->regs.tex_size_pitch_c = tex_size_pitch;
+ r128ctx->regs.sec_texture_border_color_c = t->regs.border_color;
+
+ /* Set texture offsets */
+ if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) {
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr;
+ } else {
+ int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >>
+ R128_TEX_SIZE_SHIFT);
+ int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >>
+ R128_TEX_MIN_SIZE_SHIFT);
+ for (i = maxLevel; i >= minLevel; i--)
+ r128ctx->regs.sec_tex_offset[i] =
+ t->image[maxLevel-i].offset + (CARD32)t->bufAddr;
+ }
+ /* Fix AGP texture offsets */
+ if (t->heap == R128_AGP_TEX_HEAP)
+ for (i = 0; i < R128_TEX_MAXLEVELS; i++)
+ r128ctx->regs.sec_tex_offset[i] +=
+ R128_AGP_TEX_OFFSET + r128ctx->r128Screen->agpTexOffset;
+
+ /* Force loading the new state into the hardware */
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_TEX1STATE | R128_CTX_ENGINESTATE;
+}
+
+/* Update the hardware texture state */
+/* NOTE: This function is only called while holding the hardware lock */
+void r128UpdateTextureState(r128ContextPtr r128ctx)
+{
+ /* Clear the GL_BLEND texturing fallback */
+ r128ctx->Fallback &= ~R128_FALLBACK_TEXTURE;
+
+ /* Unbind any currently bound textures */
+ if (r128ctx->CurrentTexObj[0]) r128ctx->CurrentTexObj[0]->bound = 0;
+ if (r128ctx->CurrentTexObj[1]) r128ctx->CurrentTexObj[1]->bound = 0;
+ r128ctx->CurrentTexObj[0] = NULL;
+ r128ctx->CurrentTexObj[1] = NULL;
+
+ /* Update the texture unit 0/1 state */
+ r128UpdateTex0State(r128ctx);
+ r128UpdateTex1State(r128ctx);
+}
+
+/* Set the texture wrap mode */
+static void r128SetTexWrap(r128TexObjPtr t, GLenum swrap, GLenum twrap)
+{
+ t->regs.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
+
+ switch (swrap) {
+ case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_S_CLAMP; break;
+ case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_S_WRAP; break;
+ default: /* ERROR!! */ return;
+ }
+
+ switch (twrap) {
+ case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_T_CLAMP; break;
+ case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_T_WRAP; break;
+ default: /* ERROR!! */ return;
+ }
+}
+
+/* Set the texture filter mode */
+static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf)
+{
+ t->regs.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
+
+ switch (minf) {
+ case GL_NEAREST:
+ t->regs.tex_cntl |= R128_MIN_BLEND_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->regs.tex_cntl |= R128_MIN_BLEND_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ t->regs.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ t->regs.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
+ break;
+ default: /* ERROR!! */ return;
+ }
+
+ switch (magf) {
+ case GL_NEAREST:
+ t->regs.tex_cntl |= R128_MAG_BLEND_NEAREST;
+ break;
+ case GL_LINEAR:
+ t->regs.tex_cntl |= R128_MAG_BLEND_LINEAR;
+ break;
+ }
+}
+
+/* Set the texture border color */
+static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4])
+{
+ t->regs.border_color = r128PackColor(32, c[0], c[1], c[2], c[3]);
+}
+
+/* Set the texture environment state */
+static void r128DDTexEnv(GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *param)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit;
+ GLubyte c[4];
+ CARD32 col;
+
+ /* FIXME: Add texture LOD bias extension */
+
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ /* TexEnv modes are handled in UpdateTextureState */
+ R128CCE_FLUSH_VB_LOCK(r128ctx);
+ r128ctx->dirty |= R128_UPDATE_TEXSTATE;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ FLOAT_RGBA_TO_UBYTE_RGBA(texUnit->EnvColor, c);
+ col = r128PackColor(32, c[0], c[1], c[2], c[3]);
+ if (r128ctx->regs.constant_color_c != col) {
+ R128CCE_FLUSH_VB_LOCK(r128ctx);
+ r128ctx->regs.constant_color_c = col;
+
+ /* FIXME: Load into hardware now??? */
+ r128ctx->dirty |= R128_UPDATE_CONTEXT;
+ r128ctx->dirty_context |= R128_CTX_TEXENVSTATE;
+ }
+ break;
+ default:
+ return;
+ }
+}
+
+/* Upload a new texture image */
+static void r128DDTexImage(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+ r128TexObjPtr t;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API)
+ fprintf(stderr, "r128DDTexImage(%p, level %d)\n", tObj, level);
+
+ if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return;
+ if (level >= R128_TEX_MAXLEVELS) return;
+
+ t = (r128TexObjPtr)tObj->DriverData;
+ if (t) {
+ if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx);
+
+ /* Destroy the old texture, and upload a new one. The actual
+ uploading of the texture image occurs in the UploadSubImage
+ function. */
+ r128DestroyTexObj(r128ctx, t);
+ r128ctx->dirty |= R128_UPDATE_TEXSTATE;
+ }
+}
+
+/* Upload a new texture sub-image */
+static void r128DDTexSubImage(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+ r128TexObjPtr t;
+
+ if (R128_DEBUG_FLAGS & DEBUG_VERBOSE_API)
+ fprintf(stderr, "r128DDTexSubImage(%p, level %d) "
+ "size: %d,%d of %d,%d\n",
+ tObj, level, width, height, image->Width, image->Height);
+
+ if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return;
+ if (level >= R128_TEX_MAXLEVELS) return;
+
+ t = (r128TexObjPtr)tObj->DriverData;
+ if (t) {
+ if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx);
+
+ LOCK_HARDWARE(r128ctx);
+ r128UploadSubImage(r128ctx, t, level,
+ xoffset, yoffset, width, height);
+ UNLOCK_HARDWARE(r128ctx);
+
+ /* Update the context state */
+ r128ctx->regs.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
+
+ r128ctx->dirty |= (R128_UPDATE_CONTEXT |
+ R128_UPDATE_TEXSTATE);
+ r128ctx->dirty_context |= (R128_CTX_ENGINESTATE |
+ R128_CTX_TEX0STATE |
+ R128_CTX_TEX1STATE);
+ }
+}
+
+/* Set the texture parameter state */
+static void r128DDTexParameter(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+ r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
+
+ if (!t) return;
+ if ((target != GL_TEXTURE_2D) && (target != GL_TEXTURE_1D)) return;
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx);
+ r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx);
+ r128SetTexWrap(t, tObj->WrapS, tObj->WrapT);
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx);
+ r128SetTexBorderColor(t, tObj->BorderColor);
+ break;
+
+ default:
+ return;
+ }
+
+ r128ctx->dirty |= R128_UPDATE_TEXSTATE;
+}
+
+/* Bind a texture to the currently active texture unit */
+static void r128DDBindTexture(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+
+ R128CCE_FLUSH_VB_LOCK(r128ctx);
+
+ /* Unbind the old texture */
+ if (r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]) {
+ r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0;
+ r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit] = NULL;
+ }
+
+ /* The actualy binding occurs in the Tex[01]UpdateState function */
+ r128ctx->dirty |= R128_UPDATE_TEXSTATE;
+}
+
+/* Remove texture from AGP/local texture memory */
+static void r128DDDeleteTexture(GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ r128ContextPtr r128ctx = R128_CONTEXT(ctx);
+ r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
+
+ if (t) {
+ if (t->bound) {
+ R128CCE_FLUSH_VB_LOCK(r128ctx);
+
+ r128ctx->CurrentTexObj[t->bound-1] = 0;
+ r128ctx->dirty |= R128_UPDATE_TEXSTATE;
+ }
+
+ r128DestroyTexObj(r128ctx, t);
+ tObj->DriverData = NULL;
+ }
+}
+
+/* Determine if a texture is currently residing in either AGP/local
+ texture memory */
+static GLboolean r128DDIsTextureResident(GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
+
+ return t && t->memBlock;
+}
+
+/* Initialize the driver's texture functions */
+void r128DDInitTextureFuncs(GLcontext *ctx)
+{
+ ctx->Driver.TexEnv = r128DDTexEnv;
+ ctx->Driver.TexImage = r128DDTexImage;
+ ctx->Driver.TexSubImage = r128DDTexSubImage;
+ ctx->Driver.TexParameter = r128DDTexParameter;
+ ctx->Driver.BindTexture = r128DDBindTexture;
+ ctx->Driver.DeleteTexture = r128DDDeleteTexture;
+ ctx->Driver.UpdateTexturePalette = NULL;
+ ctx->Driver.ActiveTexture = NULL;
+ ctx->Driver.IsTextureResident = r128DDIsTextureResident;
+ ctx->Driver.PrioritizeTexture = NULL;
+}