📄 tdfx_tex.c
字号:
/* -*- mode: c; c-basic-offset: 3 -*- * * Copyright 2000 VA Linux Systems Inc., Fremont, California. * * 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 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 NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS 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. *//* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_tex.c,v 1.7 2002/11/05 17:46:10 tsi Exp $ *//* * New fixes: * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004 * * Original rewrite: * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 * * Authors: * Gareth Hughes <gareth@valinux.com> * Brian Paul <brianp@valinux.com> * */#include "enums.h"#include "image.h"#include "mipmap.h"#include "texcompress.h"#include "texformat.h"#include "teximage.h"#include "texstore.h"#include "texobj.h"#include "tdfx_context.h"#include "tdfx_tex.h"#include "tdfx_texman.h"/* no borders! can't halve 1x1! (stride > width * comp) not allowed */static void_mesa_halve2x2_teximage2d ( GLcontext *ctx, struct gl_texture_image *texImage, GLuint bytesPerPixel, GLint srcWidth, GLint srcHeight, const GLvoid *srcImage, GLvoid *dstImage ){ GLint i, j, k; GLint dstWidth = srcWidth / 2; GLint dstHeight = srcHeight / 2; GLint srcRowStride = srcWidth * bytesPerPixel; GLubyte *src = (GLubyte *)srcImage; GLubyte *dst = dstImage; GLuint dstImageOffsets = 0; GLuint bpt = 0; GLubyte *_s = NULL; GLubyte *_d = NULL; GLenum _t = 0; if (texImage->TexFormat->MesaFormat == MESA_FORMAT_RGB565) { _t = GL_UNSIGNED_SHORT_5_6_5_REV; bpt = bytesPerPixel; } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB4444) { _t = GL_UNSIGNED_SHORT_4_4_4_4_REV; bpt = bytesPerPixel; } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB1555) { _t = GL_UNSIGNED_SHORT_1_5_5_5_REV; bpt = bytesPerPixel; } if (bpt) { bytesPerPixel = 4; srcRowStride = srcWidth * bytesPerPixel; if (dstWidth == 0) { dstWidth = 1; } if (dstHeight == 0) { dstHeight = 1; } _s = src = MALLOC(srcRowStride * srcHeight); _d = dst = MALLOC(dstWidth * bytesPerPixel * dstHeight); _mesa_texstore_rgba8888(ctx, 2, GL_RGBA, &_mesa_texformat_rgba8888_rev, src, 0, 0, 0, /* dstX/Y/Zoffset */ srcRowStride, /* dstRowStride */ &dstImageOffsets, srcWidth, srcHeight, 1, texImage->_BaseFormat, _t, srcImage, &ctx->DefaultPacking); } if (srcHeight == 1) { for (i = 0; i < dstWidth; i++) { for (k = 0; k < bytesPerPixel; k++) { dst[0] = (src[0] + src[bytesPerPixel] + 1) / 2; src++; dst++; } src += bytesPerPixel; } } else if (srcWidth == 1) { for (j = 0; j < dstHeight; j++) { for (k = 0; k < bytesPerPixel; k++) { dst[0] = (src[0] + src[srcRowStride] + 1) / 2; src++; dst++; } src += srcRowStride; } } else { for (j = 0; j < dstHeight; j++) { for (i = 0; i < dstWidth; i++) { for (k = 0; k < bytesPerPixel; k++) { dst[0] = (src[0] + src[bytesPerPixel] + src[srcRowStride] + src[srcRowStride + bytesPerPixel] + 2) / 4; src++; dst++; } src += bytesPerPixel; } src += srcRowStride; } } if (bpt) { src = _s; dst = _d; texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, texImage->TexFormat, dstImage, 0, 0, 0, /* dstX/Y/Zoffset */ dstWidth * bpt, &dstImageOffsets, dstWidth, dstHeight, 1, GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking); FREE(dst); FREE(src); }}static intlogbase2(int n){ GLint i = 1; GLint log2 = 0; if (n < 0) { return -1; } while (n > i) { i *= 2; log2++; } if (i != n) { return -1; } else { return log2; }}/* * Compute various texture image parameters. * Input: w, h - source texture width and height * Output: lodlevel - Glide lod level token for the larger texture dimension * aspectratio - Glide aspect ratio token * sscale - S scale factor used during triangle setup * tscale - T scale factor used during triangle setup * wscale - OpenGL -> Glide image width scale factor * hscale - OpenGL -> Glide image height scale factor * * Sample results: * w h lodlevel aspectRatio * 128 128 GR_LOD_LOG2_128 (=7) GR_ASPECT_LOG2_1x1 (=0) * 64 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x1 (=0) * 64 32 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_2x1 (=1) * 32 64 GR_LOD_LOG2_64 (=6) GR_ASPECT_LOG2_1x2 (=-1) * 32 32 GR_LOD_LOG2_32 (=5) GR_ASPECT_LOG2_1x1 (=0) */static voidtdfxTexGetInfo(const GLcontext *ctx, int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio, float *sscale, float *tscale, int *wscale, int *hscale){ int logw, logh, ar, lod, ws, hs; float s, t; ASSERT(w >= 1); ASSERT(h >= 1); logw = logbase2(w); logh = logbase2(h); ar = logw - logh; /* aspect ratio = difference in log dimensions */ s = t = 256.0; ws = hs = 1; /* Hardware only allows a maximum aspect ratio of 8x1, so handle |ar| > 3 by scaling the image and using an 8x1 aspect ratio */ if (ar >= 0) { ASSERT(w >= h); lod = logw; if (ar <= GR_ASPECT_LOG2_8x1) { t = 256 >> ar; } else { /* have to stretch image height */ t = 32.0; hs = 1 << (ar - 3); ar = GR_ASPECT_LOG2_8x1; } } else { ASSERT(w < h); lod = logh; if (ar >= GR_ASPECT_LOG2_1x8) { s = 256 >> -ar; } else { /* have to stretch image width */ s = 32.0; ws = 1 << (-ar - 3); ar = GR_ASPECT_LOG2_1x8; } } if (lodlevel) *lodlevel = (GrLOD_t) lod; if (aspectratio) *aspectratio = (GrAspectRatio_t) ar; if (sscale) *sscale = s; if (tscale) *tscale = t; if (wscale) *wscale = ws; if (hscale) *hscale = hs;}/* * We need to call this when a texture object's minification filter * or texture image sizes change. */static void RevalidateTexture(GLcontext *ctx, struct gl_texture_object *tObj){ tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); GLint minl, maxl; if (!ti) return; minl = maxl = tObj->BaseLevel; if (tObj->Image[0][minl]) { maxl = MIN2(tObj->MaxLevel, tObj->Image[0][minl]->MaxLog2); /* compute largeLodLog2, aspect ratio and texcoord scale factors */ tdfxTexGetInfo(ctx, tObj->Image[0][minl]->Width, tObj->Image[0][minl]->Height, &ti->info.largeLodLog2, &ti->info.aspectRatioLog2, &(ti->sScale), &(ti->tScale), NULL, NULL); } if (tObj->Image[0][maxl] && (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) { /* mipmapping: need to compute smallLodLog2 */ tdfxTexGetInfo(ctx, tObj->Image[0][maxl]->Width, tObj->Image[0][maxl]->Height, &ti->info.smallLodLog2, NULL, NULL, NULL, NULL, NULL); } else { /* not mipmapping: smallLodLog2 = largeLodLog2 */ ti->info.smallLodLog2 = ti->info.largeLodLog2; maxl = minl; } ti->minLevel = minl; ti->maxLevel = maxl; ti->info.data = NULL; /* this is necessary because of fxDDCompressedTexImage2D */ if (ti->padded) { struct gl_texture_image *texImage = tObj->Image[0][minl]; tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage); if (mml->wScale != 1 || mml->hScale != 1) { ti->sScale /= mml->wScale; ti->tScale /= mml->hScale; } }}static tdfxTexInfo *fxAllocTexObjData(tdfxContextPtr fxMesa){ tdfxTexInfo *ti; if (!(ti = CALLOC(sizeof(tdfxTexInfo)))) { _mesa_problem(NULL, "tdfx driver: out of memory"); return NULL; } ti->isInTM = GL_FALSE; ti->whichTMU = TDFX_TMU_NONE; ti->tm[TDFX_TMU0] = NULL; ti->tm[TDFX_TMU1] = NULL; ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; ti->magFilt = GR_TEXTUREFILTER_BILINEAR; ti->sClamp = GR_TEXTURECLAMP_WRAP; ti->tClamp = GR_TEXTURECLAMP_WRAP; ti->mmMode = GR_MIPMAP_NEAREST; ti->LODblend = FXFALSE; return ti;}/* * Called via glBindTexture. */static voidtdfxBindTexture(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj){ tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); tdfxTexInfo *ti; if (MESA_VERBOSE & VERBOSE_DRIVER) { fprintf(stderr, "fxmesa: fxDDTexBind(%d,%p)\n", tObj->Name, tObj->DriverData); } if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D)) return; if (!tObj->DriverData) { tObj->DriverData = fxAllocTexObjData(fxMesa); } ti = TDFX_TEXTURE_DATA(tObj); ti->lastTimeUsed = fxMesa->texBindNumber++; fxMesa->new_state |= TDFX_NEW_TEXTURE;}/* * Called via glTexEnv. */static voidtdfxTexEnv(GLcontext * ctx, GLenum target, GLenum pname, const GLfloat * param){ tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { if (param) fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname, (GLint) (*param)); else fprintf(stderr, "fxmesa: texenv(%x)\n", pname); } /* XXX this is a bit of a hack to force the Glide texture * state to be updated. */ fxMesa->TexState.EnvMode[ctx->Texture.CurrentUnit] = 0; fxMesa->new_state |= TDFX_NEW_TEXTURE;}/* * Called via glTexParameter. */static voidtdfxTexParameter(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat * params){ tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); GLenum param = (GLenum) (GLint) params[0]; tdfxTexInfo *ti; if (MESA_VERBOSE & VERBOSE_DRIVER) { fprintf(stderr, "fxmesa: fxDDTexParam(%d,%p,%x,%x)\n", tObj->Name, tObj->DriverData, pname, param); } if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D)) return; if (!tObj->DriverData) tObj->DriverData = fxAllocTexObjData(fxMesa); ti = TDFX_TEXTURE_DATA(tObj); switch (pname) { case GL_TEXTURE_MIN_FILTER: switch (param) { case GL_NEAREST: ti->mmMode = GR_MIPMAP_DISABLE; ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; ti->LODblend = FXFALSE; break; case GL_LINEAR: ti->mmMode = GR_MIPMAP_DISABLE; ti->minFilt = GR_TEXTUREFILTER_BILINEAR; ti->LODblend = FXFALSE; break; case GL_NEAREST_MIPMAP_LINEAR: if (!fxMesa->Glide.HaveCombineExt) { if (fxMesa->haveTwoTMUs) { ti->mmMode = GR_MIPMAP_NEAREST; ti->LODblend = FXTRUE; } else { ti->mmMode = GR_MIPMAP_NEAREST_DITHER; ti->LODblend = FXFALSE; } ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; break; } /* XXX Voodoo3/Banshee mipmap blending seems to produce * incorrectly filtered colors for the smallest mipmap levels. * To work-around we fall-through here and use a different filter. */ case GL_NEAREST_MIPMAP_NEAREST: ti->mmMode = GR_MIPMAP_NEAREST; ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; ti->LODblend = FXFALSE; break; case GL_LINEAR_MIPMAP_LINEAR: if (!fxMesa->Glide.HaveCombineExt) { if (fxMesa->haveTwoTMUs) { ti->mmMode = GR_MIPMAP_NEAREST; ti->LODblend = FXTRUE; } else { ti->mmMode = GR_MIPMAP_NEAREST_DITHER; ti->LODblend = FXFALSE; } ti->minFilt = GR_TEXTUREFILTER_BILINEAR; break; } /* XXX Voodoo3/Banshee mipmap blending seems to produce * incorrectly filtered colors for the smallest mipmap levels. * To work-around we fall-through here and use a different filter. */ case GL_LINEAR_MIPMAP_NEAREST: ti->mmMode = GR_MIPMAP_NEAREST; ti->minFilt = GR_TEXTUREFILTER_BILINEAR; ti->LODblend = FXFALSE; break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -