Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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