• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3 
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28 
29 /*
30  * Authors:
31  *   Keith Whitwell <keith@tungstengraphics.com>
32  */
33 
34 #include "main/glheader.h"
35 #include "main/imports.h"
36 #include "main/colormac.h"
37 #include "main/context.h"
38 #include "main/enums.h"
39 #include "main/image.h"
40 #include "main/mfeatures.h"
41 #include "main/simple_list.h"
42 #include "main/teximage.h"
43 #include "main/texobj.h"
44 #include "main/samplerobj.h"
45 
46 #include "radeon_mipmap_tree.h"
47 #include "r200_context.h"
48 #include "r200_ioctl.h"
49 #include "r200_tex.h"
50 
51 #include "xmlpool.h"
52 
53 
54 
55 /**
56  * Set the texture wrap modes.
57  *
58  * \param t Texture object whose wrap modes are to be set
59  * \param swrap Wrap mode for the \a s texture coordinate
60  * \param twrap Wrap mode for the \a t texture coordinate
61  */
62 
r200SetTexWrap(radeonTexObjPtr t,GLenum swrap,GLenum twrap,GLenum rwrap)63 static void r200SetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
64 {
65    GLboolean  is_clamp = GL_FALSE;
66    GLboolean  is_clamp_to_border = GL_FALSE;
67    struct gl_texture_object *tObj = &t->base;
68 
69    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
70 		"%s(tex %p) sw %s, tw %s, rw %s\n",
71 		__func__, t,
72 		_mesa_lookup_enum_by_nr(swrap),
73 		_mesa_lookup_enum_by_nr(twrap),
74 		_mesa_lookup_enum_by_nr(rwrap));
75 
76    t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
77 
78    switch ( swrap ) {
79    case GL_REPEAT:
80       t->pp_txfilter |= R200_CLAMP_S_WRAP;
81       break;
82    case GL_CLAMP:
83       t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
84       is_clamp = GL_TRUE;
85       break;
86    case GL_CLAMP_TO_EDGE:
87       t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
88       break;
89    case GL_CLAMP_TO_BORDER:
90       t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
91       is_clamp_to_border = GL_TRUE;
92       break;
93    case GL_MIRRORED_REPEAT:
94       t->pp_txfilter |= R200_CLAMP_S_MIRROR;
95       break;
96    case GL_MIRROR_CLAMP_EXT:
97       t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
98       is_clamp = GL_TRUE;
99       break;
100    case GL_MIRROR_CLAMP_TO_EDGE_EXT:
101       t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
102       break;
103    case GL_MIRROR_CLAMP_TO_BORDER_EXT:
104       t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
105       is_clamp_to_border = GL_TRUE;
106       break;
107    default:
108       _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
109    }
110 
111    if (tObj->Target != GL_TEXTURE_1D) {
112       switch ( twrap ) {
113       case GL_REPEAT:
114          t->pp_txfilter |= R200_CLAMP_T_WRAP;
115          break;
116       case GL_CLAMP:
117          t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
118          is_clamp = GL_TRUE;
119          break;
120       case GL_CLAMP_TO_EDGE:
121          t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
122          break;
123       case GL_CLAMP_TO_BORDER:
124          t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
125          is_clamp_to_border = GL_TRUE;
126          break;
127       case GL_MIRRORED_REPEAT:
128          t->pp_txfilter |= R200_CLAMP_T_MIRROR;
129          break;
130       case GL_MIRROR_CLAMP_EXT:
131          t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
132          is_clamp = GL_TRUE;
133          break;
134       case GL_MIRROR_CLAMP_TO_EDGE_EXT:
135          t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
136          break;
137       case GL_MIRROR_CLAMP_TO_BORDER_EXT:
138          t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
139          is_clamp_to_border = GL_TRUE;
140          break;
141       default:
142          _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
143       }
144    }
145 
146    t->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
147 
148    switch ( rwrap ) {
149    case GL_REPEAT:
150       t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
151       break;
152    case GL_CLAMP:
153       t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
154       is_clamp = GL_TRUE;
155       break;
156    case GL_CLAMP_TO_EDGE:
157       t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
158       break;
159    case GL_CLAMP_TO_BORDER:
160       t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
161       is_clamp_to_border = GL_TRUE;
162       break;
163    case GL_MIRRORED_REPEAT:
164       t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
165       break;
166    case GL_MIRROR_CLAMP_EXT:
167       t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
168       is_clamp = GL_TRUE;
169       break;
170    case GL_MIRROR_CLAMP_TO_EDGE_EXT:
171       t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
172       break;
173    case GL_MIRROR_CLAMP_TO_BORDER_EXT:
174       t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
175       is_clamp_to_border = GL_TRUE;
176       break;
177    default:
178       _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__);
179    }
180 
181    if ( is_clamp_to_border ) {
182       t->pp_txfilter |= R200_BORDER_MODE_D3D;
183    }
184 
185    t->border_fallback = (is_clamp && is_clamp_to_border);
186 }
187 
r200SetTexMaxAnisotropy(radeonTexObjPtr t,GLfloat max)188 static void r200SetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
189 {
190    t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
191    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
192 	"%s(tex %p) max %f.\n",
193 	__func__, t, max);
194 
195    if ( max <= 1.0 ) {
196       t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
197    } else if ( max <= 2.0 ) {
198       t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
199    } else if ( max <= 4.0 ) {
200       t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
201    } else if ( max <= 8.0 ) {
202       t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
203    } else {
204       t->pp_txfilter |= R200_MAX_ANISO_16_TO_1;
205    }
206 }
207 
208 /**
209  * Set the texture magnification and minification modes.
210  *
211  * \param t Texture whose filter modes are to be set
212  * \param minf Texture minification mode
213  * \param magf Texture magnification mode
214  */
215 
r200SetTexFilter(radeonTexObjPtr t,GLenum minf,GLenum magf)216 static void r200SetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
217 {
218    GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
219 
220    /* Force revalidation to account for switches from/to mipmapping. */
221    t->validated = GL_FALSE;
222 
223    t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
224    t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
225 
226    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
227 	"%s(tex %p) minf %s, maxf %s, anisotropy %d.\n",
228 	__func__, t,
229 	_mesa_lookup_enum_by_nr(minf),
230 	_mesa_lookup_enum_by_nr(magf),
231 	anisotropy);
232 
233    if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
234       switch ( minf ) {
235       case GL_NEAREST:
236 	 t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
237 	 break;
238       case GL_LINEAR:
239 	 t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
240 	 break;
241       case GL_NEAREST_MIPMAP_NEAREST:
242 	 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
243 	 break;
244       case GL_NEAREST_MIPMAP_LINEAR:
245 	 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
246 	 break;
247       case GL_LINEAR_MIPMAP_NEAREST:
248 	 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
249 	 break;
250       case GL_LINEAR_MIPMAP_LINEAR:
251 	 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
252 	 break;
253       }
254    } else {
255       switch ( minf ) {
256       case GL_NEAREST:
257 	 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
258 	 break;
259       case GL_LINEAR:
260 	 t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
261 	 break;
262       case GL_NEAREST_MIPMAP_NEAREST:
263       case GL_LINEAR_MIPMAP_NEAREST:
264 	 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
265 	 break;
266       case GL_NEAREST_MIPMAP_LINEAR:
267       case GL_LINEAR_MIPMAP_LINEAR:
268 	 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
269 	 break;
270       }
271    }
272 
273    /* Note we don't have 3D mipmaps so only use the mag filter setting
274     * to set the 3D texture filter mode.
275     */
276    switch ( magf ) {
277    case GL_NEAREST:
278       t->pp_txfilter |= R200_MAG_FILTER_NEAREST;
279       t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
280       break;
281    case GL_LINEAR:
282       t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
283       t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
284       break;
285    }
286 }
287 
r200SetTexBorderColor(radeonTexObjPtr t,const GLfloat color[4])288 static void r200SetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] )
289 {
290    GLubyte c[4];
291    CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
292    CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
293    CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
294    CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
295    t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
296 }
297 
r200TexEnv(struct gl_context * ctx,GLenum target,GLenum pname,const GLfloat * param)298 static void r200TexEnv( struct gl_context *ctx, GLenum target,
299 			  GLenum pname, const GLfloat *param )
300 {
301    r200ContextPtr rmesa = R200_CONTEXT(ctx);
302    GLuint unit = ctx->Texture.CurrentUnit;
303    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
304 
305    radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_VERBOSE, "%s( %s )\n",
306 	       __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
307 
308    /* This is incorrect: Need to maintain this data for each of
309     * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
310     * between them according to _ReallyEnabled.
311     */
312    switch ( pname ) {
313    case GL_TEXTURE_ENV_COLOR: {
314       GLubyte c[4];
315       GLuint envColor;
316       _mesa_unclamped_float_rgba_to_ubyte(c, texUnit->EnvColor);
317       envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
318       if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
319 	 R200_STATECHANGE( rmesa, tf );
320 	 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
321       }
322       break;
323    }
324 
325    case GL_TEXTURE_LOD_BIAS_EXT: {
326       GLfloat bias, min;
327       GLuint b;
328       const int fixed_one = R200_LOD_BIAS_FIXED_ONE;
329 
330       /* The R200's LOD bias is a signed 2's complement value with a
331        * range of -16.0 <= bias < 16.0.
332        *
333        * NOTE: Add a small bias to the bias for conform mipsel.c test.
334        */
335       bias = *param;
336       min = driQueryOptionb (&rmesa->radeon.optionCache, "no_neg_lod_bias") ?
337 	  0.0 : -16.0;
338       bias = CLAMP( bias, min, 16.0 );
339       b = ((int)(bias * fixed_one)
340 		+ R200_LOD_BIAS_CORRECTION) & R200_LOD_BIAS_MASK;
341 
342       if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
343 	 R200_STATECHANGE( rmesa, tex[unit] );
344 	 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
345 	 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
346       }
347       break;
348    }
349    case GL_COORD_REPLACE_ARB:
350       if (ctx->Point.PointSprite) {
351 	 R200_STATECHANGE( rmesa, spr );
352 	 if ((GLenum)param[0]) {
353 	    rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit;
354 	 } else {
355 	    rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit);
356 	 }
357       }
358       break;
359    default:
360       return;
361    }
362 }
363 
r200TexUpdateParameters(struct gl_context * ctx,GLuint unit)364 void r200TexUpdateParameters(struct gl_context *ctx, GLuint unit)
365 {
366    struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
367    radeonTexObj* t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
368 
369    r200SetTexMaxAnisotropy(t , samp->MaxAnisotropy);
370    r200SetTexFilter(t, samp->MinFilter, samp->MagFilter);
371    r200SetTexWrap(t, samp->WrapS, samp->WrapT, samp->WrapR);
372    r200SetTexBorderColor(t, samp->BorderColor.f);
373 }
374 
375 /**
376  * Changes variables and flags for a state update, which will happen at the
377  * next UpdateTextureState
378  */
r200TexParameter(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,GLenum pname,const GLfloat * params)379 static void r200TexParameter( struct gl_context *ctx, GLenum target,
380 				struct gl_texture_object *texObj,
381 				GLenum pname, const GLfloat *params )
382 {
383    radeonTexObj* t = radeon_tex_obj(texObj);
384 
385    radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_VERBOSE,
386 		"%s(%p, tex %p)  target %s, pname %s\n",
387 		__FUNCTION__, ctx, texObj,
388 		_mesa_lookup_enum_by_nr( target ),
389 	       _mesa_lookup_enum_by_nr( pname ) );
390 
391    switch ( pname ) {
392    case GL_TEXTURE_MIN_FILTER:
393    case GL_TEXTURE_MAG_FILTER:
394    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
395    case GL_TEXTURE_WRAP_S:
396    case GL_TEXTURE_WRAP_T:
397    case GL_TEXTURE_WRAP_R:
398    case GL_TEXTURE_BORDER_COLOR:
399    case GL_TEXTURE_BASE_LEVEL:
400    case GL_TEXTURE_MAX_LEVEL:
401    case GL_TEXTURE_MIN_LOD:
402    case GL_TEXTURE_MAX_LOD:
403       t->validated = GL_FALSE;
404       break;
405 
406    default:
407       return;
408    }
409 }
410 
411 
r200DeleteTexture(struct gl_context * ctx,struct gl_texture_object * texObj)412 static void r200DeleteTexture(struct gl_context * ctx, struct gl_texture_object *texObj)
413 {
414    r200ContextPtr rmesa = R200_CONTEXT(ctx);
415    radeonTexObj* t = radeon_tex_obj(texObj);
416 
417    radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_NORMAL,
418            "%s( %p (target = %s) )\n", __FUNCTION__,
419 	   (void *)texObj,
420 	   _mesa_lookup_enum_by_nr(texObj->Target));
421 
422    if (rmesa) {
423       int i;
424       radeon_firevertices(&rmesa->radeon);
425       for ( i = 0 ; i < rmesa->radeon.glCtx->Const.MaxTextureUnits ; i++ ) {
426 	 if ( t == rmesa->state.texture.unit[i].texobj ) {
427 	    rmesa->state.texture.unit[i].texobj = NULL;
428 	    rmesa->hw.tex[i].dirty = GL_FALSE;
429 	    rmesa->hw.cube[i].dirty = GL_FALSE;
430 	 }
431       }
432    }
433 
434    radeon_miptree_unreference(&t->mt);
435 
436    _mesa_delete_texture_object(ctx, texObj);
437 }
438 
439 /* Need:
440  *  - Same GEN_MODE for all active bits
441  *  - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
442  *  - STRQ presumably all supported (matrix means incoming R values
443  *    can end up in STQ, this has implications for vertex support,
444  *    presumably ok if maos is used, though?)
445  *
446  * Basically impossible to do this on the fly - just collect some
447  * basic info & do the checks from ValidateState().
448  */
r200TexGen(struct gl_context * ctx,GLenum coord,GLenum pname,const GLfloat * params)449 static void r200TexGen( struct gl_context *ctx,
450 			  GLenum coord,
451 			  GLenum pname,
452 			  const GLfloat *params )
453 {
454    r200ContextPtr rmesa = R200_CONTEXT(ctx);
455    GLuint unit = ctx->Texture.CurrentUnit;
456    rmesa->recheck_texgen[unit] = GL_TRUE;
457 }
458 
459 
460 /**
461  * Allocate a new texture object.
462  * Called via ctx->Driver.NewTextureObject.
463  * Note: this function will be called during context creation to
464  * allocate the default texture objects.
465  * Fixup MaxAnisotropy according to user preference.
466  */
r200NewTextureObject(struct gl_context * ctx,GLuint name,GLenum target)467 static struct gl_texture_object *r200NewTextureObject(struct gl_context * ctx,
468 						      GLuint name,
469 						      GLenum target)
470 {
471    r200ContextPtr rmesa = R200_CONTEXT(ctx);
472    radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
473 
474 
475    radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
476            "%s(%p) target %s, new texture %p.\n",
477 	   __FUNCTION__, ctx,
478 	   _mesa_lookup_enum_by_nr(target), t);
479 
480    _mesa_initialize_texture_object(&t->base, name, target);
481    t->base.Sampler.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
482 
483    /* Initialize hardware state */
484    r200SetTexWrap( t, t->base.Sampler.WrapS, t->base.Sampler.WrapT, t->base.Sampler.WrapR );
485    r200SetTexMaxAnisotropy( t, t->base.Sampler.MaxAnisotropy );
486    r200SetTexFilter(t, t->base.Sampler.MinFilter, t->base.Sampler.MagFilter);
487    r200SetTexBorderColor(t, t->base.Sampler.BorderColor.f);
488 
489    return &t->base;
490 }
491 
492 static struct gl_sampler_object *
r200NewSamplerObject(struct gl_context * ctx,GLuint name)493 r200NewSamplerObject(struct gl_context *ctx, GLuint name)
494 {
495    r200ContextPtr rmesa = R200_CONTEXT(ctx);
496    struct gl_sampler_object *samp = _mesa_new_sampler_object(ctx, name);
497    if (samp)
498       samp->MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
499    return samp;
500 }
501 
502 
503 
r200InitTextureFuncs(radeonContextPtr radeon,struct dd_function_table * functions)504 void r200InitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
505 {
506    /* Note: we only plug in the functions we implement in the driver
507     * since _mesa_init_driver_functions() was already called.
508     */
509 
510    radeon_init_common_texture_funcs(radeon, functions);
511 
512    functions->NewTextureObject		= r200NewTextureObject;
513    //   functions->BindTexture		= r200BindTexture;
514    functions->DeleteTexture		= r200DeleteTexture;
515 
516    functions->TexEnv			= r200TexEnv;
517    functions->TexParameter		= r200TexParameter;
518    functions->TexGen			= r200TexGen;
519    functions->NewSamplerObject		= r200NewSamplerObject;
520 }
521