#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "macros.h"
#include "texformat.h"
#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_vb.h"
#include "r128_tris.h"
#include "r128_tex.h"
static void r128SetTexImages( r128ContextPtr rmesa,
const struct gl_texture_object *tObj )
{
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
int log2Pitch, log2Height, log2Size, log2MinSize;
int totalSize;
int i;
GLint firstLevel, lastLevel;
assert(t);
assert(baseImage);
if ( R128_DEBUG & DEBUG_VERBOSE_API )
fprintf( stderr, "%s( %p )\n", __FUNCTION__, (void *)tObj );
switch (baseImage->TexFormat->MesaFormat) {
case MESA_FORMAT_ARGB8888:
t->textureFormat = R128_DATATYPE_ARGB8888;
break;
case MESA_FORMAT_ARGB4444:
t->textureFormat = R128_DATATYPE_ARGB4444;
break;
case MESA_FORMAT_RGB565:
t->textureFormat = R128_DATATYPE_RGB565;
break;
case MESA_FORMAT_RGB332:
t->textureFormat = R128_DATATYPE_RGB8;
break;
case MESA_FORMAT_CI8:
t->textureFormat = R128_DATATYPE_CI8;
break;
case MESA_FORMAT_YCBCR:
t->textureFormat = R128_DATATYPE_YVYU422;
break;
case MESA_FORMAT_YCBCR_REV:
t->textureFormat = R128_DATATYPE_VYUY422;
break;
default:
_mesa_problem(rmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
};
driCalculateTextureFirstLastLevel( (driTextureObject *) t );
firstLevel = t->base.firstLevel;
lastLevel = t->base.lastLevel;
log2Pitch = tObj->Image[firstLevel]->WidthLog2;
log2Height = tObj->Image[firstLevel]->HeightLog2;
log2Size = MAX2(log2Pitch, log2Height);
log2MinSize = log2Size;
t->base.dirty_images[0] = 0;
totalSize = 0;
for ( i = firstLevel; i <= lastLevel; i++ ) {
const struct gl_texture_image *texImage;
texImage = tObj->Image[i];
if ( !texImage || !texImage->Data ) {
lastLevel = i - 1;
break;
}
log2MinSize = texImage->MaxLog2;
t->image[i - firstLevel].offset = totalSize;
t->image[i - firstLevel].width = tObj->Image[i]->Width;
t->image[i - firstLevel].height = tObj->Image[i]->Height;
t->base.dirty_images[0] |= (1 << i);
totalSize += (tObj->Image[i]->Height *
tObj->Image[i]->Width *
tObj->Image[i]->TexFormat->TexelBytes);
totalSize = (totalSize + 31) & ~31;
}
t->base.totalSize = totalSize;
t->base.firstLevel = firstLevel;
t->base.lastLevel = lastLevel;
t->setup.tex_cntl &= ~(0xf << 16);
t->setup.tex_cntl |= t->textureFormat;
t->setup.tex_combine_cntl = 0x00000000;
t->setup.tex_size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) |
(log2Size << R128_TEX_SIZE_SHIFT) |
(log2Height << R128_TEX_HEIGHT_SHIFT) |
(log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
t->setup.tex_offset[i] = 0x00000000;
}
if (firstLevel == lastLevel)
t->setup.tex_cntl |= R128_MIP_MAP_DISABLE;
else
t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE;
}
#define COLOR_COMB_DISABLE (R128_COMB_DIS | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
R128_COLOR_FACTOR_NTEX)
#define COLOR_COMB_ADD (R128_COMB_ADD | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
R128_COMB_FCN_MSB | \
R128_COLOR_FACTOR_CONST_COLOR)
#define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
R128_ALPHA_FACTOR_NTEX_ALPHA)
#define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
R128_INP_FACTOR_A_INT_ALPHA)
#define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
R128_INP_FACTOR_A_PREV_ALPHA)
static GLboolean r128UpdateTextureEnv( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLint source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
GLuint combine;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p, %d )\n",
__FUNCTION__, (void *)ctx, unit );
}
if ( unit == 0 ) {
combine = INPUT_INTERP;
} else {
combine = INPUT_PREVIOUS;
}
switch ( texUnit->EnvMode ) {
case GL_REPLACE:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
combine |= (COLOR_COMB_DISABLE |
ALPHA_COMB_DISABLE);
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_DISABLE |
ALPHA_COMB_COPY_INPUT);
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_DISABLE);
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_MODULATE:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_MODULATE);
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_COPY_INPUT);
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_MODULATE);
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_DECAL:
switch ( format ) {
case GL_RGBA:
combine |= (COLOR_COMB_BLEND_TEX |
ALPHA_COMB_COPY_INPUT);
break;
case GL_RGB:
combine |= (COLOR_COMB_DISABLE |
ALPHA_COMB_COPY_INPUT);
break;
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_COPY_INPUT);
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_BLEND:
if ( !R128_IS_PLAIN( rmesa ) ) {
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
combine |= (COLOR_COMB_BLEND_COLOR |
ALPHA_COMB_MODULATE);
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_BLEND_COLOR |
ALPHA_COMB_COPY_INPUT);
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_MODULATE);
break;
case GL_INTENSITY:
switch ( rmesa->env_color & 0xff000000 ) {
case 0x00000000:
combine |= (COLOR_COMB_BLEND_COLOR |
ALPHA_COMB_MODULATE_NTEX);
default:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_MODULATE);
return GL_FALSE;
}
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
}
if ( rmesa->blend_flags ) {
return GL_FALSE;
}
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= (COLOR_COMB_MODULATE_NTEX |
ALPHA_COMB_MODULATE);
break;
#if 0
case 0x00ffffff:
if ( unit == 0 ) {
combine |= (COLOR_COMB_MODULATE_NTEX |
ALPHA_COMB_MODULATE);
} else {
combine |= (COLOR_COMB_ADD |
ALPHA_COMB_COPY_INPUT);
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_MODULATE);
return GL_FALSE;
}
break;
case GL_RGB:
case GL_LUMINANCE:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= (COLOR_COMB_MODULATE_NTEX |
ALPHA_COMB_COPY_INPUT);
break;
#if 0
case 0x00ffffff:
if ( unit == 0 ) {
combine |= (COLOR_COMB_MODULATE_NTEX |
ALPHA_COMB_COPY_INPUT);
} else {
combine |= (COLOR_COMB_ADD |
ALPHA_COMB_COPY_INPUT);
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_COPY_INPUT);
return GL_FALSE;
}
break;
case GL_ALPHA:
if ( unit == 0 ) {
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_MODULATE);
} else {
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_COPY_INPUT);
}
break;
case GL_INTENSITY:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= COLOR_COMB_MODULATE_NTEX;
break;
#if 0
case 0x00ffffff:
if ( unit == 0 ) {
combine |= COLOR_COMB_MODULATE_NTEX;
} else {
combine |= COLOR_COMB_ADD;
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_MODULATE);
return GL_FALSE;
}
switch ( rmesa->env_color & 0xff000000 ) {
case 0x00000000:
combine |= ALPHA_COMB_MODULATE_NTEX;
break;
#if 0
case 0xff000000:
if ( unit == 0 ) {
combine |= ALPHA_COMB_MODULATE_NTEX;
} else {
combine |= ALPHA_COMB_ADD;
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE |
ALPHA_COMB_MODULATE);
return GL_FALSE;
}
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_ADD:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
combine |= (COLOR_COMB_ADD |
ALPHA_COMB_MODULATE);
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_ADD |
ALPHA_COMB_COPY_INPUT);
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT |
ALPHA_COMB_MODULATE);
break;
case GL_INTENSITY:
combine |= (COLOR_COMB_ADD |
ALPHA_COMB_ADD);
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
default:
return GL_FALSE;
}
if ( rmesa->tex_combine[unit] != combine ) {
rmesa->tex_combine[unit] = combine;
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
}
return GL_TRUE;
}
static void disable_tex( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
FLUSH_BATCH( rmesa );
if ( rmesa->CurrentTexObj[unit] ) {
rmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
rmesa->CurrentTexObj[unit] = NULL;
}
rmesa->setup.tex_cntl_c &= ~(R128_TEXMAP_ENABLE << unit);
rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
(R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
rmesa->dirty |= R128_UPLOAD_CONTEXT;
rmesa->blend_flags &= ~R128_BLEND_MULTITEX;
}
static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
if ( t->base.dirty_images[0] ) {
r128SetTexImages( rmesa, tObj );
r128UploadTexImages( rmesa, t );
if ( !t->base.memBlock )
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean update_tex_common( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
return GL_FALSE;
}
if ( rmesa->CurrentTexObj[unit] != t ) {
if ( rmesa->CurrentTexObj[unit] != NULL ) {
rmesa->CurrentTexObj[unit]->base.bound &=
~(1UL << unit);
}
rmesa->CurrentTexObj[unit] = t;
t->base.bound |= (1UL << unit);
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
driUpdateTextureLRU( (driTextureObject *) t );
}
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
(R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
if ( unit == 0 ) {
rmesa->setup.tex_cntl_c |= R128_TEXMAP_ENABLE;
rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 0;
rmesa->setup.scale_3d_cntl &= ~R128_TEX_CACHE_SPLIT;
t->setup.tex_cntl &= ~R128_SEC_SELECT_SEC_ST;
}
else {
rmesa->setup.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE;
rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 16;
rmesa->setup.scale_3d_cntl |= R128_TEX_CACHE_SPLIT;
t->setup.tex_cntl |= R128_SEC_SELECT_SEC_ST;
if ( R128_IS_PLAIN( rmesa ) )
rmesa->blend_flags |= R128_BLEND_MULTITEX;
}
rmesa->dirty |= R128_UPLOAD_CONTEXT;
return r128UpdateTextureEnv( ctx, unit );
}
static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
return (enable_tex_2d( ctx, unit ) &&
update_tex_common( ctx, unit ));
}
else if ( texUnit->_ReallyEnabled ) {
return GL_FALSE;
}
else {
disable_tex( ctx, unit );
return GL_TRUE;
}
}
void r128UpdateTextureState( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLboolean ok;
rmesa->tmu_source[0] = 0;
rmesa->tmu_source[1] = 1;
if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
rmesa->tmu_source[0] = 1;
rmesa->tmu_source[1] = 0;
}
ok = (updateTextureUnit( ctx, 0 ) &&
updateTextureUnit( ctx, 1 ));
FALLBACK( rmesa, R128_FALLBACK_TEXTURE, !ok );
}