#include "image.h"
#include "texutil.h"
#include "texformat.h"
#include "teximage.h"
#include "texstore.h"
#include "tdfx_context.h"
#include "tdfx_tex.h"
#include "tdfx_texman.h"
static int
logbase2(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;
}
}
static void
tdfxTexGetInfo(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;
if (ar >= 0) {
ASSERT(width >= height);
lod = logw;
s = 256.0;
ws = 1;
if (ar <= GR_ASPECT_LOG2_8x1) {
t = 256 >> ar;
hs = 1;
}
else {
t = 32.0;
hs = 1 << (ar - 3);
}
}
else {
ASSERT(width < height);
lod = logh;
t = 256.0;
hs = 1;
if (ar >= GR_ASPECT_LOG2_1x8) {
s = 256 >> -ar;
ws = 1;
}
else {
s = 32.0;
ws = 1 << (-ar - 3);
}
}
if (ar < GR_ASPECT_LOG2_1x8)
ar = GR_ASPECT_LOG2_1x8;
else if (ar > GR_ASPECT_LOG2_8x1)
ar = GR_ASPECT_LOG2_8x1;
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;
}
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[minl]) {
maxl = MIN2(tObj->MaxLevel, tObj->Image[minl]->MaxLog2);
tdfxTexGetInfo(ctx, tObj->Image[minl]->Width, tObj->Image[minl]->Height,
&ti->info.largeLodLog2,
&ti->info.aspectRatioLog2,
&(ti->sScale), &(ti->tScale), NULL, NULL);
}
if (tObj->Image[maxl] && (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR)) {
tdfxTexGetInfo(ctx, tObj->Image[maxl]->Width,
tObj->Image[maxl]->Height,
&ti->info.smallLodLog2, NULL,
NULL, NULL, NULL, NULL);
}
else {
ti->info.smallLodLog2 = ti->info.largeLodLog2;
maxl = minl;
}
ti->minLevel = minl;
ti->maxLevel = maxl;
ti->info.data = NULL;
}
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;
}
void
tdfxDDBindTexture(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_2D)
return;
if (!tObj->DriverData) {
tObj->DriverData = fxAllocTexObjData(fxMesa);
}
ti = TDFX_TEXTURE_DATA(tObj);
ti->lastTimeUsed = fxMesa->texBindNumber++;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
void
tdfxDDTexEnv(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);
}
fxMesa->TexState.EnvMode[ctx->Texture.CurrentUnit] = 0;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
void
tdfxDDTexParameter(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_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 (TDFX_IS_NAPALM(fxMesa)) {
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;
}
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 (TDFX_IS_NAPALM(fxMesa)) {
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;
}
case GL_LINEAR_MIPMAP_NEAREST:
ti->mmMode = GR_MIPMAP_NEAREST;
ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
ti->LODblend = FXFALSE;
break;
default:
break;
}
RevalidateTexture(ctx, tObj);
fxMesa->new_state |= TDFX_NEW_TEXTURE;
break;
case GL_TEXTURE_MAG_FILTER:
switch (param) {
case GL_NEAREST:
ti->magFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
break;
case GL_LINEAR:
ti->magFilt = GR_TEXTUREFILTER_BILINEAR;
break;
default:
break;
}
fxMesa->new_state |= TDFX_NEW_TEXTURE;
break;
case GL_TEXTURE_WRAP_S:
switch (param) {
case GL_CLAMP:
ti->sClamp = GR_TEXTURECLAMP_CLAMP;
break;
case GL_REPEAT:
ti->sClamp = GR_TEXTURECLAMP_WRAP;
break;
default:
break;
}
fxMesa->new_state |= TDFX_NEW_TEXTURE;
break;
case GL_TEXTURE_WRAP_T:
switch (param) {
case GL_CLAMP:
ti->tClamp = GR_TEXTURECLAMP_CLAMP;
break;
case GL_REPEAT:
ti->tClamp = GR_TEXTURECLAMP_WRAP;
break;
default:
break;
}
fxMesa->new_state |= TDFX_NEW_TEXTURE;
break;
case GL_TEXTURE_BORDER_COLOR:
break;
case GL_TEXTURE_MIN_LOD:
break;
case GL_TEXTURE_MAX_LOD:
break;
case GL_TEXTURE_BASE_LEVEL:
RevalidateTexture(ctx, tObj);
break;
case GL_TEXTURE_MAX_LEVEL:
RevalidateTexture(ctx, tObj);
break;
default:
break;
}
}
void
tdfxDDDeleteTexture(GLcontext * ctx, struct gl_texture_object *tObj)
{
if (ctx && ctx->DriverCtx) {
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTMFreeTexture(fxMesa, tObj);
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
}
GLboolean
tdfxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
{
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
return (GLboolean) (ti && ti->isInTM);
}
static void
convertPalette(FxU32 data[256], const struct gl_color_table *table)
{
const GLubyte *tableUB = (const GLubyte *) table->Table;
GLint width = table->Size;
FxU32 r, g, b, a;
GLint i;
ASSERT(table->TableType == GL_UNSIGNED_BYTE);
switch (table->Format) {
case GL_INTENSITY:
for (i = 0; i < width; i++) {
r = tableUB[i];
g = tableUB[i];
b = tableUB[i];
a = tableUB[i];
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
case GL_LUMINANCE:
for (i = 0; i < width; i++) {
r = tableUB[i];
g = tableUB[i];
b = tableUB[i];
a = 255;
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
case GL_ALPHA:
for (i = 0; i < width; i++) {
r = g = b = 255;
a = tableUB[i];
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
case GL_LUMINANCE_ALPHA:
for (i = 0; i < width; i++) {
r = g = b = tableUB[i * 2 + 0];
a = tableUB[i * 2 + 1];
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
case GL_RGB:
for (i = 0; i < width; i++) {
r = tableUB[i * 3 + 0];
g = tableUB[i * 3 + 1];
b = tableUB[i * 3 + 2];
a = 255;
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
case GL_RGBA:
for (i = 0; i < width; i++) {
r = tableUB[i * 4 + 0];
g = tableUB[i * 4 + 1];
b = tableUB[i * 4 + 2];
a = tableUB[i * 4 + 3];
data[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
break;
}
}
void
tdfxDDTexturePalette(GLcontext * ctx, struct gl_texture_object *tObj)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
if (tObj) {
tdfxTexInfo *ti;
if (!tObj->Palette.Table)
return;
if (!tObj->DriverData)
tObj->DriverData = fxAllocTexObjData(fxMesa);
ti = TDFX_TEXTURE_DATA(tObj);
convertPalette(ti->palette.data, &tObj->Palette);
}
else {
convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
}
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
#if 000
static FxBool TexusFatalError = FXFALSE;
static FxBool TexusError = FXFALSE;
#define TX_DITHER_NONE 0x00000000
static void
fxTexusError(const char *string, FxBool fatal)
{
_mesa_problem(NULL, string);
TexusError = FXTRUE;
TexusFatalError = fatal;
}
#endif
const struct gl_texture_format *
tdfxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum srcFormat, GLenum srcType )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa);
switch (internalFormat) {
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
return &_mesa_texformat_i8;
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
return &_mesa_texformat_rgb565;
case 3:
case GL_RGB:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return (allow32bpt) ? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565;
break;
case GL_RGBA2:
case GL_RGBA4:
return &_mesa_texformat_argb4444;
case 4:
case GL_RGBA:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return allow32bpt ? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_COLOR_INDEX:
case GL_COLOR_INDEX1_EXT:
case GL_COLOR_INDEX2_EXT:
case GL_COLOR_INDEX4_EXT:
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX12_EXT:
case GL_COLOR_INDEX16_EXT:
return &_mesa_texformat_ci8;
default:
_mesa_problem(ctx, "unexpected format in tdfxDDChooseTextureFormat");
return NULL;
}
}
static GrTextureFormat_t
fxGlideFormat(GLint mesaFormat)
{
switch (mesaFormat) {
case MESA_FORMAT_I8:
return GR_TEXFMT_ALPHA_8;
case MESA_FORMAT_A8:
return GR_TEXFMT_ALPHA_8;
case MESA_FORMAT_L8:
return GR_TEXFMT_INTENSITY_8;
case MESA_FORMAT_CI8:
return GR_TEXFMT_P_8;
case MESA_FORMAT_AL88:
return GR_TEXFMT_ALPHA_INTENSITY_88;
case MESA_FORMAT_RGB565:
return GR_TEXFMT_RGB_565;
case MESA_FORMAT_ARGB4444:
return GR_TEXFMT_ARGB_4444;
case MESA_FORMAT_ARGB1555:
return GR_TEXFMT_ARGB_1555;
case MESA_FORMAT_ARGB8888:
return GR_TEXFMT_ARGB_8888;
default:
_mesa_problem(NULL, "Unexpected format in fxGlideFormat");
return 0;
}
}
static void
fetch_intensity8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLubyte *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = *texel;
rgba[GCOMP] = *texel;
rgba[BCOMP] = *texel;
rgba[ACOMP] = *texel;
}
static void
fetch_luminance8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLubyte *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = *texel;
rgba[GCOMP] = *texel;
rgba[BCOMP] = *texel;
rgba[ACOMP] = 255;
}
static void
fetch_alpha8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLubyte *texel;
i = i * mml->wScale;
j = j * mml->hScale;
i = i * mml->width / texImage->Width;
j = j * mml->height / texImage->Height;
texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = 255;
rgba[GCOMP] = 255;
rgba[BCOMP] = 255;
rgba[ACOMP] = *texel;
}
static void
fetch_index8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
(void) mml;
}
static void
fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLubyte *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
rgba[RCOMP] = texel[0];
rgba[GCOMP] = texel[0];
rgba[BCOMP] = texel[0];
rgba[ACOMP] = texel[1];
}
static void
fetch_r5g6b5(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLushort *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLushort *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63;
rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31;
rgba[ACOMP] = 255;
}
static void
fetch_r4g4b4a4(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLushort *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLushort *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15;
rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15;
rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15;
rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15;
}
static void
fetch_r5g5b5a1(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLushort *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLushort *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31;
rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31;
rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31;
rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255;
}
static void
fetch_a8r8g8b8(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLvoid * texelOut)
{
GLchan *rgba = (GLchan *) texelOut;
const tdfxMipMapLevel *mml = TDFX_TEXIMAGE_DATA(texImage);
const GLuint *texel;
i = i * mml->wScale;
j = j * mml->hScale;
texel = ((GLuint *) texImage->Data) + j * mml->width + i;
rgba[RCOMP] = (((*texel) >> 16) & 0xff);
rgba[GCOMP] = (((*texel) >> 8) & 0xff);
rgba[BCOMP] = (((*texel) ) & 0xff);
rgba[ACOMP] = (((*texel) >> 24) & 0xff);
}
static FetchTexelFunc
fxFetchFunction(GLint mesaFormat)
{
switch (mesaFormat) {
case MESA_FORMAT_I8:
return fetch_intensity8;
case MESA_FORMAT_A8:
return fetch_alpha8;
case MESA_FORMAT_L8:
return fetch_luminance8;
case MESA_FORMAT_CI8:
return fetch_index8;
case MESA_FORMAT_AL88:
return fetch_luminance8_alpha8;
case MESA_FORMAT_RGB565:
return fetch_r5g6b5;
case MESA_FORMAT_ARGB4444:
return fetch_r4g4b4a4;
case MESA_FORMAT_ARGB1555:
return fetch_r5g5b5a1;
case MESA_FORMAT_ARGB8888:
return fetch_a8r8g8b8;
default:
_mesa_problem(NULL, "Unexpected format in fxFetchFunction");
printf("%d\n", mesaFormat);
return NULL;
}
}
void
tdfxDDTexImage2D(GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat, GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
GLint texelBytes;
ti = TDFX_TEXTURE_DATA(texObj);
if (!ti) {
texObj->DriverData = fxAllocTexObjData(fxMesa);
if (!texObj->DriverData) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
ti = TDFX_TEXTURE_DATA(texObj);
}
mml = TDFX_TEXIMAGE_DATA(texImage);
if (!mml) {
texImage->DriverData = CALLOC(sizeof(tdfxMipMapLevel));
if (!texImage->DriverData) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
mml = TDFX_TEXIMAGE_DATA(texImage);
}
tdfxTexGetInfo(ctx,
texImage->Width, texImage->Height,
NULL,
NULL,
NULL, NULL,
&mml->wScale, &mml->hScale);
mml->width = width * mml->wScale;
mml->height = height * mml->hScale;
assert(ctx->Driver.ChooseTextureFormat);
texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
internalFormat, format, type);
assert(texImage->TexFormat);
mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
ti->info.format = mml->glideFormat;
texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat);
texelBytes = texImage->TexFormat->TexelBytes;
if (mml->width != width || mml->height != height) {
GLvoid *tempImage;
tempImage = MALLOC(width * height * texelBytes);
if (!tempImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
_mesa_transfer_teximage(ctx, 2, texImage->Format,
texImage->TexFormat,
tempImage,
width, height, 1, 0, 0, 0,
width * texelBytes,
0,
format, type, pixels, packing);
assert(!texImage->Data);
texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
FREE(tempImage);
return;
}
_mesa_rescale_teximage2d(texelBytes,
mml->width * texelBytes,
width, height,
mml->width, mml->height,
tempImage , texImage->Data );
FREE(tempImage);
}
else {
assert(!texImage->Data);
texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
_mesa_transfer_teximage(ctx, 2, texImage->Format,
texImage->TexFormat, texImage->Data,
width, height, 1, 0, 0, 0,
texImage->Width * texelBytes,
0,
format, type, pixels, packing);
}
RevalidateTexture(ctx, texObj);
ti->reloadImages = GL_TRUE;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
void
tdfxDDTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
GLint texelBytes;
if (!texObj->DriverData) {
_mesa_problem(ctx, "problem in fxDDTexSubImage2D");
return;
}
ti = TDFX_TEXTURE_DATA(texObj);
assert(ti);
mml = TDFX_TEXIMAGE_DATA(texImage);
assert(mml);
assert(texImage->Data);
assert(texImage->Format);
texelBytes = texImage->TexFormat->TexelBytes;
if (mml->wScale != 1 || mml->hScale != 1) {
const GLint newWidth = width * mml->wScale;
const GLint newHeight = height * mml->hScale;
GLvoid *scaledImage, *tempImage;
GLubyte *destAddr;
tempImage = MALLOC(width * height * texelBytes);
if (!tempImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
return;
}
_mesa_transfer_teximage(ctx, 2, texImage->Format,
texImage->TexFormat,
(GLubyte *) tempImage,
width, height, 1,
0, 0, 0,
width * texelBytes,
0,
format, type, pixels, packing);
scaledImage = MALLOC(newWidth * newHeight * texelBytes);
if (!scaledImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
FREE(tempImage);
return;
}
destAddr = (GLubyte *) texImage->Data
+ (yoffset * mml->hScale * mml->width
+ xoffset * mml->wScale) * texelBytes;
_mesa_rescale_teximage2d(texelBytes,
mml->width * texelBytes,
width, height,
newWidth, newHeight,
tempImage, destAddr);
FREE(tempImage);
FREE(scaledImage);
}
else {
_mesa_transfer_teximage(ctx, 2, texImage->Format,
texImage->TexFormat,
(GLubyte *) texImage->Data,
width, height, 1,
xoffset, yoffset, 0,
mml->width * texelBytes,
0,
format, type, pixels, packing);
}
ti->reloadImages = GL_TRUE;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
}
#if 0000
GLboolean
tdfxDDCompressedTexImage2D( GLcontext *ctx, GLenum target,
GLint level, GLsizei imageSize,
const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLboolean *retainInternalCopy)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
const GLboolean allow32bpt = TDFX_IS_NAPALM(fxMesa);
GrTextureFormat_t gldformat;
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
GLint dstWidth, dstHeight, wScale, hScale, texelSize;
MesaIntTexFormat intFormat;
GLboolean isCompressedFormat;
GLsizei texSize;
if (target != GL_TEXTURE_2D || texImage->Border > 0)
return GL_FALSE;
if (!texObj->DriverData)
texObj->DriverData = fxAllocTexObjData(fxMesa);
ti = TDFX_TEXTURE_DATA(texObj);
mml = &ti->mipmapLevel[level];
isCompressedFormat = tdfxDDIsCompressedGlideFormatMacro(texImage->IntFormat);
if (!isCompressedFormat) {
_mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(format)");
return GL_FALSE;
}
tdfxTexGetFormat(texImage->IntFormat, allow32bpt,
&gldformat, &intFormat, &texelSize);
tdfxTexGetInfo(ctx,
texImage->Width, texImage->Height,
NULL,
NULL,
NULL, NULL,
&wScale, &hScale);
dstWidth = texImage->Width * wScale;
dstHeight = texImage->Height * hScale;
_mesa_set_teximage_component_sizes(intFormat, texImage);
texSize = tdfxDDCompressedImageSize(ctx,
texImage->IntFormat,
2,
texImage->Width,
texImage->Height,
1);
if (texSize != imageSize) {
_mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2D(texSize)");
return GL_FALSE;
}
if (!mml->data || mml->glideFormat != gldformat ||
mml->width != dstWidth || mml->height != dstHeight ||
texSize != mml->dataSize) {
if (mml->data) {
FREE(mml->data);
}
mml->data = MALLOC(texSize);
if (!mml->data) {
return GL_FALSE;
}
mml->texelSize = texelSize;
mml->glideFormat = gldformat;
mml->width = dstWidth;
mml->height = dstHeight;
tdfxTMMoveOutTM(fxMesa, texObj);
}
MEMCPY(mml->data, data, imageSize);
RevalidateTexture(ctx, texObj);
ti->reloadImages = GL_TRUE;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
*retainInternalCopy = GL_FALSE;
return GL_TRUE;
}
GLboolean
tdfxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
GLint level, GLint xoffset,
GLint yoffset, GLsizei width,
GLint height, GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
if ((xoffset != 0) && (yoffset != 0)
&& (width != texImage->Width)
&& (height != texImage->Height)) {
return GL_FALSE;
}
ti = TDFX_TEXTURE_DATA(texObj);
mml = &ti->mipmapLevel[level];
if (imageSize != mml->dataSize) {
return GL_FALSE;
}
MEMCPY(data, mml->data, imageSize);
ti->reloadImages = GL_TRUE;
fxMesa->new_state |= TDFX_NEW_TEXTURE;
return GL_TRUE;
}
#endif
#if 0
static void
PrintTexture(int w, int h, int c, const GLubyte * data)
{
int i, j;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (c == 2)
printf("%02x %02x ", data[0], data[1]);
else if (c == 3)
printf("%02x %02x %02x ", data[0], data[1], data[2]);
data += c;
}
printf("\n");
}
}
#endif
GLboolean
tdfxDDTestProxyTexImage(GLcontext *ctx, GLenum target,
GLint level, GLint internalFormat,
GLenum format, GLenum type,
GLint width, GLint height,
GLint depth, GLint border)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
switch (target) {
case GL_PROXY_TEXTURE_1D:
return GL_TRUE;
case GL_PROXY_TEXTURE_2D:
{
struct gl_texture_object *tObj;
tdfxTexInfo *ti;
int memNeeded;
tObj = ctx->Texture.Proxy2D;
if (!tObj->DriverData)
tObj->DriverData = fxAllocTexObjData(fxMesa);
ti = TDFX_TEXTURE_DATA(tObj);
tObj->Image[level]->Width = width;
tObj->Image[level]->Height = height;
tObj->Image[level]->Border = border;
#if 0
tObj->Image[level]->IntFormat = internalFormat;
#endif
if (level == 0) {
tObj->MinFilter = tObj->MagFilter = GL_NEAREST;
}
else {
tObj->MinFilter = GL_LINEAR_MIPMAP_LINEAR;
tObj->MagFilter = GL_NEAREST;
}
RevalidateTexture(ctx, tObj);
if (ti->LODblend && !shared->umaTexMemory) {
memNeeded = fxMesa->Glide.grTexTextureMemRequired(
GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
}
else {
memNeeded = fxMesa->Glide.grTexTextureMemRequired(
GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
}
if (memNeeded > shared->totalTexMem[0])
return GL_FALSE;
else
return GL_TRUE;
}
case GL_PROXY_TEXTURE_3D:
return GL_TRUE;
default:
return GL_TRUE;
}
}
#if 000
void
tdfxDDGetCompressedTexImage( GLcontext *ctx, GLenum target,
GLint lod, void *image,
const struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
if (target != GL_TEXTURE_2D)
return;
if (!texObj->DriverData)
return;
ti = TDFX_TEXTURE_DATA(texObj);
mml = &ti->mipmapLevel[lod];
if (mml->data) {
MEMCPY(image, mml->data, mml->dataSize);
}
}
#endif
GLint
tdfxDDSpecificCompressedTexFormat(GLcontext *ctx,
GLint internalFormat,
GLint numDimensions)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
if (numDimensions != 2) {
return internalFormat;
}
if (!fxMesa->Glide.txImgQuantize || !fxMesa->Glide.txImgDequantizeFXT1) {
return internalFormat;
}
switch (internalFormat) {
case GL_COMPRESSED_RGB_ARB:
return GL_COMPRESSED_RGB_FXT1_3DFX;
case GL_COMPRESSED_RGBA_ARB:
return GL_COMPRESSED_RGBA_FXT1_3DFX;
}
return internalFormat;
}
GLint
tdfxDDBaseCompressedTexFormat(GLcontext *ctx,
GLint internalFormat)
{
switch (internalFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
return GL_RGB;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return GL_RGBA;
}
return -1;
}
GLboolean
tdfxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat)
{
return tdfxDDIsCompressedFormatMacro(internalFormat);
}
GLsizei
tdfxDDCompressedImageSize(GLcontext *ctx,
GLenum intFormat,
GLuint numDimensions,
GLuint width,
GLuint height,
GLuint depth)
{
if (numDimensions != 2) {
return 0;
}
switch (intFormat) {
case GL_COMPRESSED_RGB_FXT1_3DFX:
case GL_COMPRESSED_RGBA_FXT1_3DFX:
width = (width + 0x7) &~ 0x7;
height = (height + 0x3) &~ 0x3;
return width * height;
}
return 0;
}