blob: 5bee051b092ba4e0cde280a3cc91061e35489bbb [file] [log] [blame]
/*
* Author: Max Lingua <sunmax@libero.it>
*/
#include <stdlib.h>
#include <stdio.h>
#include "glheader.h"
#include "mtypes.h"
#include "simple_list.h"
#include "enums.h"
#include "texstore.h"
#include "texformat.h"
#include "teximage.h"
#include "swrast/swrast.h"
#include "mm.h"
#include "s3v_context.h"
#include "s3v_tex.h"
extern void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
extern void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
/*
static GLuint s3vComputeLodBias(GLfloat bias)
{
#if TEX_DEBUG_ON
DEBUG_TEX(("*** s3vComputeLodBias ***\n"));
#endif
return bias;
}
*/
static void s3vSetTexWrapping(s3vContextPtr vmesa,
s3vTextureObjectPtr t,
GLenum wraps, GLenum wrapt)
{
GLuint t0 = t->TextureCMD;
GLuint cmd = vmesa->CMD;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vSetTexWrapping: #%i ***\n", ++times));
#endif
t0 &= ~TEX_WRAP_MASK;
cmd &= ~TEX_WRAP_MASK;
if ((wraps != GL_CLAMP) || (wrapt != GL_CLAMP)) {
DEBUG(("TEX_WRAP_ON\n"));
t0 |= TEX_WRAP_ON;
cmd |= TEX_WRAP_ON;
}
cmd |= TEX_WRAP_ON; /* FIXME: broken if off */
t->TextureCMD = t0;
vmesa->CMD = cmd;
}
static void s3vSetTexFilter(s3vContextPtr vmesa,
s3vTextureObjectPtr t,
GLenum minf, GLenum magf)
{
GLuint t0 = t->TextureCMD;
GLuint cmd = vmesa->CMD;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vSetTexFilter: #%i ***\n", ++times));
#endif
t0 &= ~TEX_FILTER_MASK;
cmd &= ~TEX_FILTER_MASK;
switch (minf) {
case GL_NEAREST:
DEBUG(("GL_NEAREST\n"));
t0 |= NEAREST;
cmd |= NEAREST;
break;
case GL_LINEAR:
DEBUG(("GL_LINEAR\n"));
t0 |= LINEAR;
cmd |= LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
DEBUG(("GL_MIPMAP_NEAREST\n"));
t0 |= MIP_NEAREST;
cmd |= MIP_NEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
DEBUG(("GL_LINEAR_MIPMAP_NEAREST\n"));
t0 |= LINEAR_MIP_NEAREST;
cmd |= LINEAR_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
DEBUG(("GL_NEAREST_MIPMAP_LINEAR\n"));
t0 |= MIP_LINEAR;
cmd |= MIP_LINEAR;
break;
case GL_LINEAR_MIPMAP_LINEAR:
DEBUG(("GL_LINEAR_MIPMAP_LINEAR\n"));
t0 |= LINEAR_MIP_LINEAR;
cmd |= LINEAR_MIP_LINEAR;
break;
default:
break;
}
/* FIXME: bilinear? */
#if 0
switch (magf) {
case GL_NEAREST:
break;
case GL_LINEAR:
break;
default:
break;
}
#endif
t->TextureCMD = t0;
DEBUG(("CMD was = 0x%x\n", vmesa->CMD));
DEBUG(("CMD is = 0x%x\n", cmd));
vmesa->CMD = cmd;
/* CMDCHANGE(); */
}
static void s3vSetTexBorderColor(s3vContextPtr vmesa,
s3vTextureObjectPtr t,
GLubyte color[4])
{
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vSetTexBorderColor: #%i ***\n", ++times));
#endif
/*FIXME: it should depend on tex col format */
/* switch(t0 ... t->TextureColorMode) */
/* case TEX_COL_ARGB1555: */
t->TextureBorderColor =
S3VIRGEPACKCOLOR555(color[0], color[1], color[2], color[3]);
DEBUG(("TextureBorderColor = 0x%x\n", t->TextureBorderColor));
vmesa->TextureBorderColor = t->TextureBorderColor;
}
static void s3vTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
s3vContextPtr vmesa = S3V_CONTEXT(ctx);
s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexParameter: #%i ***\n", ++times));
#endif
if (!t) return;
/* Can't do the update now as we don't know whether to flush
* vertices or not. Setting vmesa->new_state means that
* s3vUpdateTextureState() will be called before any triangles are
* rendered. If a statechange has occurred, it will be detected at
* that point, and buffered vertices flushed.
*/
switch (pname) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
break;
case GL_TEXTURE_BORDER_COLOR:
s3vSetTexBorderColor( vmesa, t, tObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative for Virge. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
s3vSwapOutTexObj( vmesa, t );
break;
default:
return;
}
if (t == vmesa->CurrentTexObj[0])
vmesa->dirty |= S3V_UPLOAD_TEX0;
#if 0
if (t == vmesa->CurrentTexObj[1]) {
vmesa->dirty |= S3V_UPLOAD_TEX1;
}
#endif
}
static void s3vTexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
GLuint unit = ctx->Texture.CurrentUnit;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexEnv: #%i ***\n", ++times));
#endif
/* Only one env color. Need a fallback if env colors are different
* and texture setup references env color in both units.
*/
switch (pname) {
case GL_TEXTURE_ENV_COLOR: {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
GLfloat *fc = texUnit->EnvColor;
GLuint r, g, b, a, col;
CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
col = ((a << 24) |
(r << 16) |
(g << 8) |
(b << 0));
break;
}
case GL_TEXTURE_ENV_MODE:
vmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
break;
case GL_TEXTURE_LOD_BIAS_EXT: {
/*
struct gl_texture_object *tObj =
ctx->Texture.Unit[unit]._Current;
s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
*/
break;
}
default:
break;
}
}
static void s3vTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *pack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexImage1D: #%i ***\n", ++times));
#endif
#if 1
if (t) {
#if _TEXFLUSH
DMAFLUSH();
#endif
s3vSwapOutTexObj( vmesa, t );
/*
s3vDestroyTexObj( vmesa, t );
texObj->DriverData = 0;
*/
}
#endif
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, pack, texObj, texImage );
}
static void s3vTexSubImage1D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *pack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexSubImage1D: #%i ***\n", ++times));
#endif
#if 1
if (t) {
#if _TEXFLUSH
DMAFLUSH();
#endif
s3vSwapOutTexObj( vmesa, t );
/*
s3vDestroyTexObj( vmesa, t );
texObj->DriverData = 0;
*/
}
#endif
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, pack, texObj,
texImage);
}
static void s3vTexImage2D( 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 )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexImage2D: #%i ***\n", ++times));
#endif
#if 1
if (t) {
#if _TEXFLUSH
DMAFLUSH();
#endif
s3vSwapOutTexObj( vmesa, t );
/*
s3vDestroyTexObj( vmesa, t );
texObj->DriverData = 0;
*/
}
#endif
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
}
static void s3vTexSubImage2D( 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 )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vTexSubImage2D: #%i ***\n", ++times));
#endif
#if 1
if (t) {
#if _TEXFLUSH
DMAFLUSH();
#endif
s3vSwapOutTexObj( vmesa, t );
/*
s3vDestroyTexObj( vmesa, t );
texObj->DriverData = 0;
*/
}
#endif
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
}
static void s3vBindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj )
{
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
GLuint cmd = vmesa->CMD;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vBindTexture: #%i ***\n", ++times));
#endif
if (!t) {
/*
GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
*/
t = CALLOC_STRUCT(s3v_texture_object_t);
/* Initialize non-image-dependent parts of the state:
*/
t->globj = tObj;
#if 0
if (target == GL_TEXTURE_2D) {
} else
if (target == GL_TEXTURE_1D) {
}
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
t->TextureFormat = (TF_LittleEndian |
#else
t->TextureFormat = (TF_BigEndian |
#endif
#endif
t->dirty_images = ~0;
tObj->DriverData = t;
make_empty_list( t );
#if 0
s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
s3vSetTexBorderColor( vmesa, t, tObj->BorderColor );
#endif
}
cmd = vmesa->CMD & ~MIP_MASK;
vmesa->dirty |= S3V_UPLOAD_TEX0;
vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel];
vmesa->TexStride = t->Pitch;
cmd |= MIPMAP_LEVEL(t->WidthLog2);
vmesa->CMD = cmd;
vmesa->restore_primitive = -1;
#if 0
printf("t->TextureBaseAddr[0] = 0x%x\n", t->TextureBaseAddr[0]);
printf("t->TextureBaseAddr[1] = 0x%x\n", t->TextureBaseAddr[1]);
printf("t->TextureBaseAddr[2] = 0x%x\n", t->TextureBaseAddr[2]);
#endif
}
static void s3vDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vDeleteTexture: #%i ***\n", ++times));
#endif
if (t) {
s3vContextPtr vmesa = S3V_CONTEXT( ctx );
#if _TEXFLUSH
if (vmesa) {
DMAFLUSH();
}
#endif
s3vDestroyTexObj( vmesa, t );
tObj->DriverData = 0;
}
}
static GLboolean s3vIsTextureResident( GLcontext *ctx,
struct gl_texture_object *tObj )
{
s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vIsTextureResident: #%i ***\n", ++times));
#endif
return (t && t->MemBlock);
}
static void s3vInitTextureObjects( GLcontext *ctx )
{
/* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
struct gl_texture_object *texObj;
GLuint tmp = ctx->Texture.CurrentUnit;
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vInitTextureObjects: #%i ***\n", ++times));
#endif
#if 1
ctx->Texture.CurrentUnit = 0;
texObj = ctx->Texture.Unit[0].Current1D;
s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
texObj = ctx->Texture.Unit[0].Current2D;
s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
#endif
#if 0
ctx->Texture.CurrentUnit = 1;
texObj = ctx->Texture.Unit[1].Current1D;
s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
texObj = ctx->Texture.Unit[1].Current2D;
s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
#endif
ctx->Texture.CurrentUnit = tmp;
}
void s3vInitTextureFuncs( GLcontext *ctx )
{
#if TEX_DEBUG_ON
static unsigned int times=0;
DEBUG_TEX(("*** s3vInitTextureFuncs: #%i ***\n", ++times));
#endif
ctx->Driver.TexEnv = s3vTexEnv;
ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
ctx->Driver.TexImage1D = _mesa_store_teximage1d;
ctx->Driver.TexImage2D = s3vTexImage2D;
ctx->Driver.TexImage3D = _mesa_store_teximage3d;
ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
ctx->Driver.TexSubImage2D = s3vTexSubImage2D;
ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
ctx->Driver.BindTexture = s3vBindTexture;
ctx->Driver.DeleteTexture = s3vDeleteTexture;
ctx->Driver.TexParameter = s3vTexParameter;
ctx->Driver.UpdateTexturePalette = 0;
ctx->Driver.IsTextureResident = s3vIsTextureResident;
ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
s3vInitTextureObjects( ctx );
}