Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 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 "util/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", __func__);
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", __func__);
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", __func__);
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
	       __func__, _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 _Current->Target.
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,
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)  pname %s\n",
386
		__func__, ctx, texObj,
387
	       _mesa_lookup_enum_by_nr( pname ) );
388
 
389
   switch ( pname ) {
390
   case GL_TEXTURE_MIN_FILTER:
391
   case GL_TEXTURE_MAG_FILTER:
392
   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
393
   case GL_TEXTURE_WRAP_S:
394
   case GL_TEXTURE_WRAP_T:
395
   case GL_TEXTURE_WRAP_R:
396
   case GL_TEXTURE_BORDER_COLOR:
397
   case GL_TEXTURE_BASE_LEVEL:
398
   case GL_TEXTURE_MAX_LEVEL:
399
   case GL_TEXTURE_MIN_LOD:
400
   case GL_TEXTURE_MAX_LOD:
401
      t->validated = GL_FALSE;
402
      break;
403
 
404
   default:
405
      return;
406
   }
407
}
408
 
409
 
410
static void r200DeleteTexture(struct gl_context * ctx, struct gl_texture_object *texObj)
411
{
412
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
413
   radeonTexObj* t = radeon_tex_obj(texObj);
414
 
415
   radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_NORMAL,
416
           "%s( %p (target = %s) )\n", __func__,
417
	   (void *)texObj,
418
	   _mesa_lookup_enum_by_nr(texObj->Target));
419
 
420
   if (rmesa) {
421
      int i;
422
      radeon_firevertices(&rmesa->radeon);
423
      for ( i = 0 ; i < rmesa->radeon.glCtx.Const.MaxTextureUnits ; i++ ) {
424
	 if ( t == rmesa->state.texture.unit[i].texobj ) {
425
	    rmesa->state.texture.unit[i].texobj = NULL;
426
	    rmesa->hw.tex[i].dirty = GL_FALSE;
427
	    rmesa->hw.cube[i].dirty = GL_FALSE;
428
	 }
429
      }
430
   }
431
 
432
   radeon_miptree_unreference(&t->mt);
433
 
434
   _mesa_delete_texture_object(ctx, texObj);
435
}
436
 
437
/* Need:
438
 *  - Same GEN_MODE for all active bits
439
 *  - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
440
 *  - STRQ presumably all supported (matrix means incoming R values
441
 *    can end up in STQ, this has implications for vertex support,
442
 *    presumably ok if maos is used, though?)
443
 *
444
 * Basically impossible to do this on the fly - just collect some
445
 * basic info & do the checks from ValidateState().
446
 */
447
static void r200TexGen( struct gl_context *ctx,
448
			  GLenum coord,
449
			  GLenum pname,
450
			  const GLfloat *params )
451
{
452
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
453
   GLuint unit = ctx->Texture.CurrentUnit;
454
   rmesa->recheck_texgen[unit] = GL_TRUE;
455
}
456
 
457
 
458
/**
459
 * Allocate a new texture object.
460
 * Called via ctx->Driver.NewTextureObject.
461
 * Note: this function will be called during context creation to
462
 * allocate the default texture objects.
463
 * Fixup MaxAnisotropy according to user preference.
464
 */
465
static struct gl_texture_object *r200NewTextureObject(struct gl_context * ctx,
466
						      GLuint name,
467
						      GLenum target)
468
{
469
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
470
   radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
471
 
472
 
473
   radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL,
474
           "%s(%p) target %s, new texture %p.\n",
475
	   __func__, ctx,
476
	   _mesa_lookup_enum_by_nr(target), t);
477
 
478
   _mesa_initialize_texture_object(ctx, &t->base, name, target);
479
   t->base.Sampler.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
480
 
481
   /* Initialize hardware state */
482
   r200SetTexWrap( t, t->base.Sampler.WrapS, t->base.Sampler.WrapT, t->base.Sampler.WrapR );
483
   r200SetTexMaxAnisotropy( t, t->base.Sampler.MaxAnisotropy );
484
   r200SetTexFilter(t, t->base.Sampler.MinFilter, t->base.Sampler.MagFilter);
485
   r200SetTexBorderColor(t, t->base.Sampler.BorderColor.f);
486
 
487
   return &t->base;
488
}
489
 
490
static struct gl_sampler_object *
491
r200NewSamplerObject(struct gl_context *ctx, GLuint name)
492
{
493
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
494
   struct gl_sampler_object *samp = _mesa_new_sampler_object(ctx, name);
495
   if (samp)
496
      samp->MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy;
497
   return samp;
498
}
499
 
500
 
501
 
502
void r200InitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
503
{
504
   /* Note: we only plug in the functions we implement in the driver
505
    * since _mesa_init_driver_functions() was already called.
506
    */
507
 
508
   radeon_init_common_texture_funcs(radeon, functions);
509
 
510
   functions->NewTextureObject		= r200NewTextureObject;
511
   //   functions->BindTexture		= r200BindTexture;
512
   functions->DeleteTexture		= r200DeleteTexture;
513
 
514
   functions->TexEnv			= r200TexEnv;
515
   functions->TexParameter		= r200TexParameter;
516
   functions->TexGen			= r200TexGen;
517
   functions->NewSamplerObject		= r200NewSamplerObject;
518
}