/* * Copyright 2000-2001 VA Linux Systems, Inc. * 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 * VA LINUX SYSTEMS AND/OR ITS 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: * Keith Whitwell */ /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */ #include #include #include #include "mm.h" #include "mgacontext.h" #include "mgatex.h" #include "mgaregs.h" #include "mgatris.h" #include "mgaioctl.h" #include "enums.h" #include "simple_list.h" /*#include "mem.h"*/ #include "macros.h" #include "texformat.h" #include "texstore.h" #include "teximage.h" #include "swrast/swrast.h" #define TEX_0 1 #define TEX_1 2 /* * mgaDestroyTexObj * Free all memory associated with a texture and NULL any pointers * to it. */ void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t ) { if ( !t ) return; /* free the texture memory */ if (t->MemBlock) { mmFreeMem( t->MemBlock ); t->MemBlock = 0; if (mmesa && t->age > mmesa->dirtyAge) mmesa->dirtyAge = t->age; } /* free mesa's link */ if (t->tObj) t->tObj->DriverData = NULL; /* see if it was the driver's current object */ if (mmesa) { if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0; if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0; } remove_from_list(t); free( t ); } /* * mgaSetTexWrappings */ static void mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum sWrap, GLenum tWrap ) { GLuint val = 0; if (sWrap != GL_REPEAT) val |= TMC_clampu_enable; if (tWrap != GL_REPEAT) val |= TMC_clampv_enable; t->setup.texctl &= ~(TMC_clampu_enable|TMC_clampv_enable); t->setup.texctl |= val; } /* * mgaSetTexFilter */ static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf) { GLuint val = 0; switch (minf) { case GL_NEAREST: val = TF_minfilter_nrst; break; case GL_LINEAR: val = TF_minfilter_bilin; break; case GL_NEAREST_MIPMAP_NEAREST: val = TF_minfilter_mm1s; break; case GL_LINEAR_MIPMAP_NEAREST: val = TF_minfilter_mm4s; break; case GL_NEAREST_MIPMAP_LINEAR: val = TF_minfilter_mm2s; break; case GL_LINEAR_MIPMAP_LINEAR: val = TF_minfilter_mm8s; break; default: val = TF_minfilter_nrst; break; } switch (magf) { case GL_NEAREST: val |= TF_magfilter_nrst; break; case GL_LINEAR: val |= TF_magfilter_bilin; break; default: val |= TF_magfilter_nrst; break; } /* See OpenGL 1.2 specification */ if (magf == GL_LINEAR && (minf == GL_NEAREST_MIPMAP_NEAREST || minf == GL_NEAREST_MIPMAP_LINEAR)) { val |= (0x20 << TF_fthres_SHIFT); /* c = 0.5 */ } else { val |= (0x10 << TF_fthres_SHIFT); /* c = 0 */ } t->setup.texfilter &= (TF_minfilter_MASK | TF_magfilter_MASK | TF_fthres_MASK); t->setup.texfilter |= val; } /* * mgaSetTexBorderColor */ static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4]) { t->setup.texbordercol = MGAPACKCOLOR8888(color[0],color[1], color[2],color[3]); } static GLint mgaChooseTexFormat( mgaContextPtr mmesa, struct gl_texture_image *texImage, GLenum format, GLenum type ) { const GLboolean do32bpt = mmesa->default32BitTextures; const struct gl_texture_format *texFormat; GLint ret; if ( 0 ) fprintf( stderr, "internal=%s format=%s type=%s\n", texImage->IntFormat == 3 ? "GL_RGB (3)" : texImage->IntFormat == 4 ? "GL_RGBA (4)" : _mesa_lookup_enum_by_nr( texImage->IntFormat ), _mesa_lookup_enum_by_nr( format ), _mesa_lookup_enum_by_nr( type ) ); #define SET_FORMAT( r, gl ) \ do { \ ret = (r); \ texFormat = &(gl); \ } while (0) #define SET_FORMAT_32BPT( r32, gl32, r16, gl16 ) \ do { \ if ( do32bpt ) { \ ret = (r32); \ texFormat = &(gl32); \ } else { \ ret = (r16); \ texFormat = &(gl16); \ } \ } while (0) switch ( texImage->IntFormat ) { /* GH: Bias towards GL_RGB, GL_RGBA texture formats. This has * got to be better than sticking them way down the end of this * huge list. */ case 4: case GL_RGBA: case GL_COMPRESSED_RGBA: if ( format == GL_BGRA ) { if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { SET_FORMAT( TMC_tformat_tw32, _mesa_texformat_argb8888 ); break; } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 ); break; } } SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; case 3: case GL_RGB: case GL_COMPRESSED_RGB: if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 ); break; } SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, TMC_tformat_tw16, _mesa_texformat_rgb565 ); break; /* GH: Okay, keep checking as normal. Still test for GL_RGB, * GL_RGBA formats first. */ case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; case GL_RGBA4: case GL_RGBA2: SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; case GL_RGB5_A1: SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 ); break; case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888, TMC_tformat_tw16, _mesa_texformat_rgb565 ); break; case GL_RGB5: case GL_RGB4: case GL_R3_G3_B2: SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 ); break; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: case GL_COMPRESSED_ALPHA: /* FIXME: This will report incorrect component sizes... */ SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: /* FIXME: This will report incorrect component sizes... */ SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 ); break; 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: case GL_COMPRESSED_LUMINANCE_ALPHA: /* FIXME: This will report incorrect component sizes... */ SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: case GL_COMPRESSED_INTENSITY: /* FIXME: This will report incorrect component sizes... */ SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 ); break; 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: SET_FORMAT( TMC_tformat_tw8, _mesa_texformat_ci8 ); break; default: fprintf( stderr, "bad texture format in mgaChooseTexFormat() %d", texImage->IntFormat ); return -1; } texImage->TexFormat = texFormat; return ret; } /* * mgaCreateTexObj * Allocate space for and load the mesa images into the texture memory block. * This will happen before drawing with a new texture, or drawing with a * texture after it was swapped out or teximaged again. */ static void mgaCreateTexObj(mgaContextPtr mmesa, struct gl_texture_object *tObj) { const GLint baseLevel = tObj->BaseLevel; struct gl_texture_image *image = tObj->Image[baseLevel]; mgaTextureObjectPtr t; int i, ofs; int LastLevel; int s, s2; int tformat; if (!image) return; tObj->DriverData = t = calloc( 1, sizeof( *t ) ); if (!t) { fprintf(stderr, "mgaCreateTexObj: Failed to malloc mgaTextureObject\n" ); return; } /* FIXME: Use the real DD interface... */ tformat = mgaChooseTexFormat( mmesa, image, image->Format, GL_UNSIGNED_BYTE ); t->texelBytes = image->TexFormat->TexelBytes; /* We are going to upload all levels that are present, even if * later levels wouldn't be used by the current filtering mode. This * allows the filtering mode to change without forcing another upload * of the images. */ LastLevel = MGA_TEX_MAXLEVELS-1; ofs = 0; for ( i = 0 ; i <= LastLevel ; i++ ) { if ( !tObj->Image[i] ) { LastLevel = i - 1; break; } t->offsets[i] = ofs; t->dirty_images |= (1<Image[i]->Width, 8 ) * MAX2( tObj->Image[i]->Height, 8 ) * t->texelBytes) + 31) & ~31; } t->totalSize = ofs; t->lastLevel = LastLevel; t->tObj = tObj; t->ctx = mmesa; t->age = 0; t->bound = 0; t->MemBlock = 0; insert_at_tail(&(mmesa->SwappedOut), t); /* setup hardware register values */ t->setup.texctl = TMC_takey_1 | TMC_tamask_0 | tformat; if (image->WidthLog2 >= 3) t->setup.texctl |= ((image->WidthLog2 - 3) << TMC_tpitch_SHIFT); else t->setup.texctl |= (TMC_tpitchlin_enable | (image->Width << TMC_tpitchext_SHIFT)); t->setup.texctl2 = TMC_ckstransdis_enable; if ( mmesa->glCtx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ) t->setup.texctl2 |= TMC_specen_enable; t->setup.texfilter = (TF_minfilter_nrst | TF_magfilter_nrst | TF_filteralpha_enable | (0x10 << TF_fthres_SHIFT) | (LastLevel << TF_mapnb_SHIFT)); /* warp texture registers */ ofs = MGA_IS_G200(mmesa) ? 28 : 11; s = image->Width; s2 = image->WidthLog2; t->setup.texwidth = (MGA_FIELD(TW_twmask, s - 1) | MGA_FIELD(TW_rfw, (10 - s2 - 8) & 63 ) | MGA_FIELD(TW_tw, (s2 + ofs ) | 0x40 )); s = image->Height; s2 = image->HeightLog2; t->setup.texheight = (MGA_FIELD(TH_thmask, s - 1) | MGA_FIELD(TH_rfh, (10 - s2 - 8) & 63 ) | MGA_FIELD(TH_th, (s2 + ofs ) | 0x40 )); /* set all the register values for filtering, border, etc */ mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT ); mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); mgaSetTexBorderColor( t, tObj->_BorderChan ); } static void mgaUpdateTextureEnvG200( GLcontext *ctx ) { struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current; mgaTextureObjectPtr t; if (!tObj || !tObj->DriverData) return; t = (mgaTextureObjectPtr)tObj->DriverData; t->setup.texctl2 &= ~TMC_decalblend_enable; switch (ctx->Texture.Unit[0].EnvMode) { case GL_REPLACE: t->setup.texctl &= ~TMC_tmodulate_enable; break; case GL_MODULATE: t->setup.texctl |= TMC_tmodulate_enable; break; case GL_DECAL: t->setup.texctl &= ~TMC_tmodulate_enable; t->setup.texctl2 |= TMC_decalblend_enable; break; case GL_BLEND: FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); break; default: break; } } static void mgaUpdateTextureEnvG400( GLcontext *ctx, int unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); GLuint source = mmesa->tmu_source[unit]; struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current; GLenum format; if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) return; format = tObj->Image[tObj->BaseLevel]->Format; switch (ctx->Texture.Unit[source].EnvMode) { case GL_REPLACE: if (format == GL_RGB || format == GL_LUMINANCE) { *reg = (TD0_color_sel_arg1 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2 ); } else if (format == GL_ALPHA) { *reg = (TD0_color_sel_arg2 | TD0_color_arg2_diffuse | TD0_alpha_sel_arg1 ); } else { *reg = (TD0_color_sel_arg1 | TD0_alpha_sel_arg1 ); } break; case GL_MODULATE: if (unit == 0) { *reg = ( TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul); } else { *reg = ( TD0_color_arg2_prevstage | TD0_color_alpha_prevstage | TD0_color_sel_mul | TD0_alpha_arg2_prevstage | TD0_alpha_sel_mul); } break; case GL_DECAL: if (format == GL_RGB) { if (unit == 0) { *reg = (TD0_color_sel_arg1 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2 ); } else { *reg = (TD0_color_sel_arg1 | TD0_alpha_arg2_prevstage | TD0_alpha_sel_arg2 ); } } else if ( format == GL_RGBA ) { #if 0 if (unit == 0) { /* this doesn't work */ *reg = (TD0_color_arg2_diffuse | TD0_color_alpha_currtex | TD0_color_alpha2inv_enable | TD0_color_arg2mul_alpha2 | TD0_color_arg1mul_alpha1 | TD0_color_blend_enable | TD0_color_arg1add_mulout | TD0_color_arg2add_mulout | TD0_color_add_add | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2 ); } else { *reg = (TD0_color_arg2_prevstage | TD0_color_alpha_currtex | TD0_color_alpha2inv_enable | TD0_color_arg2mul_alpha2 | TD0_color_arg1mul_alpha1 | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | TD0_alpha_sel_arg2 ); } #else /* s/w fallback, pretty sure we can't do in h/w */ FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK ) fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n", unit ); #endif } else { if (unit == 0) { *reg = ( TD0_color_arg2_diffuse | TD0_color_sel_arg2 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2); } else { *reg = ( TD0_color_arg2_prevstage | TD0_color_sel_arg2 | TD0_alpha_arg2_prevstage | TD0_alpha_sel_arg2); } } break; case GL_ADD: if (unit == 0) { if (format == GL_INTENSITY) *reg = ( TD0_color_arg2_diffuse | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_diffuse | TD0_alpha_add_enable | TD0_alpha_sel_add); else if (format == GL_ALPHA) *reg = ( TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul); else *reg = ( TD0_color_arg2_diffuse | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul); } else { if (format == GL_INTENSITY) { *reg = ( TD0_color_arg2_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | TD0_alpha_add_enable | TD0_alpha_sel_add); } else if (format == GL_ALPHA) { *reg = ( TD0_color_arg2_prevstage | TD0_color_sel_mul | TD0_alpha_arg2_prevstage | TD0_alpha_sel_mul); } else { *reg = ( TD0_color_arg2_prevstage | TD0_color_alpha_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | TD0_alpha_sel_mul); } } break; case GL_BLEND: if (format == GL_ALPHA) { *reg = ( TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul); } else { FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK ) fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n", mmesa->envcolor ); /* Do singletexture GL_BLEND with 'all ones' env-color * by using both texture units. Multitexture gl_blend * is a fallback. */ if (unit == 0) { /* Part 1: R1 = Rf ( 1 - Rt ) * A1 = Af At */ *reg = ( TD0_color_arg2_diffuse | TD0_color_arg1_inv_enable | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg1); } else { /* Part 2: R2 = R1 + Rt * A2 = A1 */ *reg = ( TD0_color_arg2_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | TD0_alpha_sel_arg2); } } break; default: break; } } static void mgaUpdateTextureObject( GLcontext *ctx, int hw_unit ) { mgaTextureObjectPtr t; struct gl_texture_object *tObj; GLuint enabled; mgaContextPtr mmesa = MGA_CONTEXT( ctx ); GLuint gl_unit = mmesa->tmu_source[hw_unit]; enabled = ctx->Texture.Unit[gl_unit]._ReallyEnabled; tObj = ctx->Texture.Unit[gl_unit]._Current; if (enabled != TEXTURE_2D_BIT) { if (enabled) FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); return; } if (tObj->Image[tObj->BaseLevel]->Border > 0) { FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK ) fprintf( stderr, "FALLBACK: texture border\n" ); return; } if ( !tObj->DriverData ) { mgaCreateTexObj( mmesa, tObj ); if ( !tObj->DriverData ) { FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); return; } } t = (mgaTextureObjectPtr)tObj->DriverData; if (t->dirty_images) mmesa->dirty |= (MGA_UPLOAD_TEX0IMAGE << hw_unit); mmesa->CurrentTexObj[hw_unit] = t; t->bound |= hw_unit+1; /* if (t->MemBlock) */ /* mgaUpdateTexLRU( mmesa, t ); */ t->setup.texctl2 &= ~TMC_dualtex_enable; if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) && (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) t->setup.texctl2 |= TMC_dualtex_enable; t->setup.texctl2 &= ~TMC_specen_enable; if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) t->setup.texctl2 |= TMC_specen_enable; } /* The G400 is now programmed quite differently wrt texture environment. */ void mgaUpdateTextureState( GLcontext *ctx ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_FALSE ); if (mmesa->CurrentTexObj[0]) { mmesa->CurrentTexObj[0]->bound = 0; mmesa->CurrentTexObj[0] = 0; } if (mmesa->CurrentTexObj[1]) { mmesa->CurrentTexObj[1]->bound = 0; mmesa->CurrentTexObj[1] = 0; } if (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT) { mmesa->tmu_source[0] = 1; } else { mmesa->tmu_source[0] = 0; } if (MGA_IS_G400(mmesa)) { mgaUpdateTextureObject( ctx, 0 ); mgaUpdateTextureEnvG400( ctx, 0 ); mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) && (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) { mgaUpdateTextureObject( ctx, 1 ); mgaUpdateTextureEnvG400( ctx, 1 ); mmesa->dirty |= MGA_UPLOAD_TEX1; } } else { mgaUpdateTextureObject( ctx, 0 ); mgaUpdateTextureEnvG200( ctx ); } mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0; mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= (ctx->Texture.Unit[0]._ReallyEnabled ? DC_opcod_texture_trap : DC_opcod_trap); } static void mgaDDTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); if (pname == GL_TEXTURE_ENV_MODE) { /* force the texture state to be updated */ FLUSH_BATCH( MGA_CONTEXT(ctx) ); MGA_CONTEXT(ctx)->new_state |= (MGA_NEW_TEXTURE | MGA_NEW_ALPHA); } else if (pname == GL_TEXTURE_ENV_COLOR) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; GLfloat *fc = texUnit->EnvColor; GLubyte c[4]; GLuint col; COPY_4V(c, fc); col = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] ); mmesa->envcolor = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]); if (mmesa->setup.fcol != col) { FLUSH_BATCH(mmesa); mmesa->setup.fcol = col; mmesa->dirty |= MGA_UPLOAD_CONTEXT; mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR; /* Actually just require all four components to be * equal. This permits a single-pass GL_BLEND. * * More complex multitexture/multipass fallbacks * for blend can be done later. */ if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff) mmesa->blend_flags |= MGA_BLEND_ENV_COLOR; } } } static void mgaTexImage2D( 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 ) { mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData; if (t) { mgaDestroyTexObj( MGA_CONTEXT(ctx), t ); texObj->DriverData = 0; } _mesa_store_teximage2d( ctx, target, level, internalFormat, width, height, border, format, type, pixels, packing, texObj, texImage ); } static void mgaTexSubImage2D( 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 ) { mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData; if (t) { mgaDestroyTexObj( MGA_CONTEXT(ctx), t ); texObj->DriverData = 0; } _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, height, format, type, pixels, packing, texObj, texImage); } /* * mgaTexParameter * This just changes variables and flags for a state update, which * will happen at the next mgaUpdateTextureState */ static void mgaDDTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaTextureObjectPtr t; t = (mgaTextureObjectPtr) tObj->DriverData; /* if we don't have a hardware texture, it will be automatically created with current state before it is used, so we don't have to do anything now */ if ( !t || !t->bound || target != GL_TEXTURE_2D ) { return; } switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: FLUSH_BATCH(mmesa); mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: FLUSH_BATCH(mmesa); mgaSetTexWrapping(t,tObj->WrapS,tObj->WrapT); break; case GL_TEXTURE_BORDER_COLOR: FLUSH_BATCH(mmesa); mgaSetTexBorderColor(t,tObj->_BorderChan); break; default: return; } mmesa->new_state |= MGA_NEW_TEXTURE; } static void mgaDDBindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); int unit = ctx->Texture.CurrentUnit; FLUSH_BATCH(mmesa); if (mmesa->CurrentTexObj[unit]) { mmesa->CurrentTexObj[unit]->bound &= ~(unit+1); mmesa->CurrentTexObj[unit] = 0; } /* force the texture state to be updated */ MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE; } static void mgaDDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); mgaTextureObjectPtr t = (mgaTextureObjectPtr)tObj->DriverData; if ( t ) { if (mmesa) { if (t->bound) { FLUSH_BATCH(mmesa); if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0; if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0; } mmesa->new_state |= MGA_NEW_TEXTURE; } mgaDestroyTexObj( mmesa, t ); } } static GLboolean mgaDDIsTextureResident( GLcontext *ctx, struct gl_texture_object *t ) { mgaTextureObjectPtr mt = (mgaTextureObjectPtr)t->DriverData; return mt && mt->MemBlock; } void mgaDDInitTextureFuncs( GLcontext *ctx ) { ctx->Driver.TexEnv = mgaDDTexEnv; ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; ctx->Driver.TexImage1D = _mesa_store_teximage1d; ctx->Driver.TexImage2D = mgaTexImage2D; ctx->Driver.TexImage3D = _mesa_store_teximage3d; ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; ctx->Driver.TexSubImage2D = mgaTexSubImage2D; 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.TestProxyTexImage = _mesa_test_proxy_teximage; ctx->Driver.BindTexture = mgaDDBindTexture; ctx->Driver.DeleteTexture = mgaDDDeleteTexture; ctx->Driver.TexParameter = mgaDDTexParameter; ctx->Driver.UpdateTexturePalette = 0; ctx->Driver.IsTextureResident = mgaDDIsTextureResident; }