Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.5
4
 *
5
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6
 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the "Software"),
10
 * to deal in the Software without restriction, including without limitation
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * Software is furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included
16
 * in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
/**
27
 * \file texenv.c
28
 *
29
 * glTexEnv-related functions
30
 */
31
 
32
 
33
#include "main/glheader.h"
34
#include "main/context.h"
35
#include "main/enums.h"
36
#include "main/macros.h"
37
#include "main/texenv.h"
38
#include "main/texstate.h"
39
 
40
 
41
#define TE_ERROR(errCode, msg, value)				\
42
   _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
43
 
44
 
45
/** Set texture env mode */
46
static void
47
set_env_mode(struct gl_context *ctx,
48
             struct gl_texture_unit *texUnit,
49
             GLenum mode)
50
{
51
   GLboolean legal;
52
 
53
   if (texUnit->EnvMode == mode)
54
      return;
55
 
56
   switch (mode) {
57
   case GL_MODULATE:
58
   case GL_BLEND:
59
   case GL_DECAL:
60
   case GL_REPLACE:
61
      legal = GL_TRUE;
62
      break;
63
   case GL_REPLACE_EXT:
64
      mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
65
      legal = GL_TRUE;
66
      break;
67
   case GL_ADD:
68
      legal = ctx->Extensions.EXT_texture_env_add;
69
      break;
70
   case GL_COMBINE:
71
      legal = (ctx->Extensions.EXT_texture_env_combine ||
72
               ctx->Extensions.ARB_texture_env_combine);
73
      break;
74
   case GL_COMBINE4_NV:
75
      legal = ctx->Extensions.NV_texture_env_combine4;
76
      break;
77
   default:
78
      legal = GL_FALSE;
79
   }
80
 
81
   if (legal) {
82
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
83
      texUnit->EnvMode = mode;
84
   }
85
   else {
86
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
87
   }
88
}
89
 
90
 
91
static void
92
set_env_color(struct gl_context *ctx,
93
              struct gl_texture_unit *texUnit,
94
              const GLfloat *color)
95
{
96
   GLfloat tmp[4];
97
   tmp[0] = CLAMP(color[0], 0.0F, 1.0F);
98
   tmp[1] = CLAMP(color[1], 0.0F, 1.0F);
99
   tmp[2] = CLAMP(color[2], 0.0F, 1.0F);
100
   tmp[3] = CLAMP(color[3], 0.0F, 1.0F);
101
   if (TEST_EQ_4V(tmp, texUnit->EnvColor))
102
      return;
103
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
104
   COPY_4FV(texUnit->EnvColor, tmp);
105
}
106
 
107
 
108
/** Set an RGB or A combiner mode/function */
109
static void
110
set_combiner_mode(struct gl_context *ctx,
111
                  struct gl_texture_unit *texUnit,
112
                  GLenum pname, GLenum mode)
113
{
114
   GLboolean legal;
115
 
116
   if (!ctx->Extensions.EXT_texture_env_combine &&
117
       !ctx->Extensions.ARB_texture_env_combine) {
118
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
119
      return;
120
   }
121
 
122
   switch (mode) {
123
   case GL_REPLACE:
124
   case GL_MODULATE:
125
   case GL_ADD:
126
   case GL_ADD_SIGNED:
127
   case GL_INTERPOLATE:
128
      legal = GL_TRUE;
129
      break;
130
   case GL_SUBTRACT:
131
      legal = ctx->Extensions.ARB_texture_env_combine;
132
      break;
133
   case GL_DOT3_RGB_EXT:
134
   case GL_DOT3_RGBA_EXT:
135
      legal = (ctx->Extensions.EXT_texture_env_dot3 &&
136
               pname == GL_COMBINE_RGB);
137
      break;
138
   case GL_DOT3_RGB:
139
   case GL_DOT3_RGBA:
140
      legal = (ctx->Extensions.ARB_texture_env_dot3 &&
141
               pname == GL_COMBINE_RGB);
142
      break;
143
   case GL_MODULATE_ADD_ATI:
144
   case GL_MODULATE_SIGNED_ADD_ATI:
145
   case GL_MODULATE_SUBTRACT_ATI:
146
      legal = ctx->Extensions.ATI_texture_env_combine3;
147
      break;
148
   case GL_BUMP_ENVMAP_ATI:
149
      legal = (ctx->Extensions.ATI_envmap_bumpmap &&
150
               pname == GL_COMBINE_RGB);
151
      break;
152
   default:
153
      legal = GL_FALSE;
154
   }
155
 
156
   if (!legal) {
157
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
158
      return;
159
   }
160
 
161
   switch (pname) {
162
   case GL_COMBINE_RGB:
163
      if (texUnit->Combine.ModeRGB == mode)
164
         return;
165
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
166
      texUnit->Combine.ModeRGB = mode;
167
      break;
168
 
169
   case GL_COMBINE_ALPHA:
170
      if (texUnit->Combine.ModeA == mode)
171
         return;
172
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
173
      texUnit->Combine.ModeA = mode;
174
      break;
175
   default:
176
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
177
   }
178
}
179
 
180
 
181
 
182
/** Set an RGB or A combiner source term */
183
static void
184
set_combiner_source(struct gl_context *ctx,
185
                    struct gl_texture_unit *texUnit,
186
                    GLenum pname, GLenum param)
187
{
188
   GLuint term;
189
   GLboolean alpha, legal;
190
 
191
   if (!ctx->Extensions.EXT_texture_env_combine &&
192
       !ctx->Extensions.ARB_texture_env_combine) {
193
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
194
      return;
195
   }
196
 
197
   /*
198
    * Translate pname to (term, alpha).
199
    *
200
    * The enums were given sequential values for a reason.
201
    */
202
   switch (pname) {
203
   case GL_SOURCE0_RGB:
204
   case GL_SOURCE1_RGB:
205
   case GL_SOURCE2_RGB:
206
   case GL_SOURCE3_RGB_NV:
207
      term = pname - GL_SOURCE0_RGB;
208
      alpha = GL_FALSE;
209
      break;
210
   case GL_SOURCE0_ALPHA:
211
   case GL_SOURCE1_ALPHA:
212
   case GL_SOURCE2_ALPHA:
213
   case GL_SOURCE3_ALPHA_NV:
214
      term = pname - GL_SOURCE0_ALPHA;
215
      alpha = GL_TRUE;
216
      break;
217
   default:
218
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
219
      return;
220
   }
221
 
222
   if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) {
223
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
224
      return;
225
   }
226
 
227
   assert(term < MAX_COMBINER_TERMS);
228
 
229
   /*
230
    * Error-check param (the source term)
231
    */
232
   switch (param) {
233
   case GL_TEXTURE:
234
   case GL_CONSTANT:
235
   case GL_PRIMARY_COLOR:
236
   case GL_PREVIOUS:
237
      legal = GL_TRUE;
238
      break;
239
   case GL_TEXTURE0:
240
   case GL_TEXTURE1:
241
   case GL_TEXTURE2:
242
   case GL_TEXTURE3:
243
   case GL_TEXTURE4:
244
   case GL_TEXTURE5:
245
   case GL_TEXTURE6:
246
   case GL_TEXTURE7:
247
      legal = (ctx->Extensions.ARB_texture_env_crossbar &&
248
               param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
249
      break;
250
   case GL_ZERO:
251
      legal = (ctx->Extensions.ATI_texture_env_combine3 ||
252
               ctx->Extensions.NV_texture_env_combine4);
253
      break;
254
   case GL_ONE:
255
      legal = ctx->Extensions.ATI_texture_env_combine3;
256
      break;
257
   default:
258
      legal = GL_FALSE;
259
   }
260
 
261
   if (!legal) {
262
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
263
      return;
264
   }
265
 
266
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
267
 
268
   if (alpha)
269
      texUnit->Combine.SourceA[term] = param;
270
   else
271
      texUnit->Combine.SourceRGB[term] = param;
272
}
273
 
274
 
275
/** Set an RGB or A combiner operand term */
276
static void
277
set_combiner_operand(struct gl_context *ctx,
278
                     struct gl_texture_unit *texUnit,
279
                     GLenum pname, GLenum param)
280
{
281
   GLuint term;
282
   GLboolean alpha, legal;
283
 
284
   if (!ctx->Extensions.EXT_texture_env_combine &&
285
       !ctx->Extensions.ARB_texture_env_combine) {
286
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
287
      return;
288
   }
289
 
290
   /* The enums were given sequential values for a reason.
291
    */
292
   switch (pname) {
293
   case GL_OPERAND0_RGB:
294
   case GL_OPERAND1_RGB:
295
   case GL_OPERAND2_RGB:
296
   case GL_OPERAND3_RGB_NV:
297
      term = pname - GL_OPERAND0_RGB;
298
      alpha = GL_FALSE;
299
      break;
300
   case GL_OPERAND0_ALPHA:
301
   case GL_OPERAND1_ALPHA:
302
   case GL_OPERAND2_ALPHA:
303
   case GL_OPERAND3_ALPHA_NV:
304
      term = pname - GL_OPERAND0_ALPHA;
305
      alpha = GL_TRUE;
306
      break;
307
   default:
308
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
309
      return;
310
   }
311
 
312
   if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) {
313
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
314
      return;
315
   }
316
 
317
   assert(term < MAX_COMBINER_TERMS);
318
 
319
   /*
320
    * Error-check param (the source operand)
321
    */
322
   switch (param) {
323
   case GL_SRC_COLOR:
324
   case GL_ONE_MINUS_SRC_COLOR:
325
      /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT
326
       * version.  In the ARB and NV versions they can be used for any RGB
327
       * operand.
328
       */
329
      legal = !alpha
330
	 && ((term < 2) || ctx->Extensions.ARB_texture_env_combine
331
	     || ctx->Extensions.NV_texture_env_combine4);
332
      break;
333
   case GL_ONE_MINUS_SRC_ALPHA:
334
      /* GL_ONE_MINUS_SRC_ALPHA can only be used with
335
       * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version.  In the ARB and NV
336
       * versions it can be used for any operand.
337
       */
338
      legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine
339
	 || ctx->Extensions.NV_texture_env_combine4;
340
      break;
341
   case GL_SRC_ALPHA:
342
      legal = GL_TRUE;
343
      break;
344
   default:
345
      legal = GL_FALSE;
346
   }
347
 
348
   if (!legal) {
349
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
350
      return;
351
   }
352
 
353
   FLUSH_VERTICES(ctx, _NEW_TEXTURE);
354
 
355
   if (alpha)
356
      texUnit->Combine.OperandA[term] = param;
357
   else
358
      texUnit->Combine.OperandRGB[term] = param;
359
}
360
 
361
 
362
static void
363
set_combiner_scale(struct gl_context *ctx,
364
                   struct gl_texture_unit *texUnit,
365
                   GLenum pname, GLfloat scale)
366
{
367
   GLuint shift;
368
 
369
   if (!ctx->Extensions.EXT_texture_env_combine &&
370
       !ctx->Extensions.ARB_texture_env_combine) {
371
      _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
372
      return;
373
   }
374
 
375
   if (scale == 1.0F) {
376
      shift = 0;
377
   }
378
   else if (scale == 2.0F) {
379
      shift = 1;
380
   }
381
   else if (scale == 4.0F) {
382
      shift = 2;
383
   }
384
   else {
385
      _mesa_error( ctx, GL_INVALID_VALUE,
386
                   "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
387
      return;
388
   }
389
 
390
   switch (pname) {
391
   case GL_RGB_SCALE:
392
      if (texUnit->Combine.ScaleShiftRGB == shift)
393
         return;
394
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
395
      texUnit->Combine.ScaleShiftRGB = shift;
396
      break;
397
   case GL_ALPHA_SCALE:
398
      if (texUnit->Combine.ScaleShiftA == shift)
399
         return;
400
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
401
      texUnit->Combine.ScaleShiftA = shift;
402
      break;
403
   default:
404
      TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
405
   }
406
}
407
 
408
 
409
 
410
void GLAPIENTRY
411
_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
412
{
413
   GLuint maxUnit;
414
   GET_CURRENT_CONTEXT(ctx);
415
   struct gl_texture_unit *texUnit;
416
   ASSERT_OUTSIDE_BEGIN_END(ctx);
417
 
418
   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
419
      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
420
   if (ctx->Texture.CurrentUnit >= maxUnit) {
421
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
422
      return;
423
   }
424
 
425
   texUnit = _mesa_get_current_tex_unit(ctx);
426
 
427
   if (target == GL_TEXTURE_ENV) {
428
      switch (pname) {
429
      case GL_TEXTURE_ENV_MODE:
430
         set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]);
431
         break;
432
      case GL_TEXTURE_ENV_COLOR:
433
         set_env_color(ctx, texUnit, param);
434
         break;
435
      case GL_COMBINE_RGB:
436
      case GL_COMBINE_ALPHA:
437
         set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
438
	 break;
439
      case GL_SOURCE0_RGB:
440
      case GL_SOURCE1_RGB:
441
      case GL_SOURCE2_RGB:
442
      case GL_SOURCE3_RGB_NV:
443
      case GL_SOURCE0_ALPHA:
444
      case GL_SOURCE1_ALPHA:
445
      case GL_SOURCE2_ALPHA:
446
      case GL_SOURCE3_ALPHA_NV:
447
         set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
448
	 break;
449
      case GL_OPERAND0_RGB:
450
      case GL_OPERAND1_RGB:
451
      case GL_OPERAND2_RGB:
452
      case GL_OPERAND3_RGB_NV:
453
      case GL_OPERAND0_ALPHA:
454
      case GL_OPERAND1_ALPHA:
455
      case GL_OPERAND2_ALPHA:
456
      case GL_OPERAND3_ALPHA_NV:
457
         set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
458
	 break;
459
      case GL_RGB_SCALE:
460
      case GL_ALPHA_SCALE:
461
         set_combiner_scale(ctx, texUnit, pname, param[0]);
462
	 break;
463
      case GL_BUMP_TARGET_ATI:
464
         if (!ctx->Extensions.ATI_envmap_bumpmap) {
465
	    _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
466
	    return;
467
	 }
468
	 if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
469
	 ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
470
	    /* spec doesn't say this but it seems logical */
471
	    _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
472
	    return;
473
	 }
474
	 if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
475
	    _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
476
	    return;
477
	 }
478
	 else {
479
	    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
480
	    texUnit->BumpTarget = (GLenum) (GLint) param[0];
481
	 }
482
	 break;
483
      default:
484
	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
485
	 return;
486
      }
487
   }
488
   else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
489
      /* GL_EXT_texture_lod_bias */
490
      if (!ctx->Extensions.EXT_texture_lod_bias) {
491
	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
492
	 return;
493
      }
494
      if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
495
	 if (texUnit->LodBias == param[0])
496
	    return;
497
	 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
498
         texUnit->LodBias = param[0];
499
      }
500
      else {
501
         TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
502
	 return;
503
      }
504
   }
505
   else if (target == GL_POINT_SPRITE_NV) {
506
      /* GL_ARB_point_sprite / GL_NV_point_sprite */
507
      if (!ctx->Extensions.NV_point_sprite
508
	  && !ctx->Extensions.ARB_point_sprite) {
509
	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
510
	 return;
511
      }
512
      if (pname == GL_COORD_REPLACE_NV) {
513
         const GLenum value = (GLenum) param[0];
514
         if (value == GL_TRUE || value == GL_FALSE) {
515
            /* It's kind of weird to set point state via glTexEnv,
516
             * but that's what the spec calls for.
517
             */
518
            const GLboolean state = (GLboolean) value;
519
            if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
520
               return;
521
            FLUSH_VERTICES(ctx, _NEW_POINT);
522
            ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
523
         }
524
         else {
525
            _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
526
            return;
527
         }
528
      }
529
      else {
530
         _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
531
         return;
532
      }
533
   }
534
   else {
535
      _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
536
      return;
537
   }
538
 
539
   if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
540
      _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
541
                  _mesa_lookup_enum_by_nr(target),
542
                  _mesa_lookup_enum_by_nr(pname),
543
                  *param,
544
                  _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
545
 
546
   /* Tell device driver about the new texture environment */
547
   if (ctx->Driver.TexEnv) {
548
      (*ctx->Driver.TexEnv)( ctx, target, pname, param );
549
   }
550
}
551
 
552
 
553
void GLAPIENTRY
554
_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
555
{
556
   GLfloat p[4];
557
   p[0] = param;
558
   p[1] = p[2] = p[3] = 0.0;
559
   _mesa_TexEnvfv( target, pname, p );
560
}
561
 
562
 
563
 
564
void GLAPIENTRY
565
_mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
566
{
567
   GLfloat p[4];
568
   p[0] = (GLfloat) param;
569
   p[1] = p[2] = p[3] = 0.0;
570
   _mesa_TexEnvfv( target, pname, p );
571
}
572
 
573
 
574
void GLAPIENTRY
575
_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
576
{
577
   GLfloat p[4];
578
   if (pname == GL_TEXTURE_ENV_COLOR) {
579
      p[0] = INT_TO_FLOAT( param[0] );
580
      p[1] = INT_TO_FLOAT( param[1] );
581
      p[2] = INT_TO_FLOAT( param[2] );
582
      p[3] = INT_TO_FLOAT( param[3] );
583
   }
584
   else {
585
      p[0] = (GLfloat) param[0];
586
      p[1] = p[2] = p[3] = 0;  /* init to zero, just to be safe */
587
   }
588
   _mesa_TexEnvfv( target, pname, p );
589
}
590
 
591
 
592
 
593
/**
594
 * Helper for glGetTexEnvi/f()
595
 * \return  value of queried pname or -1 if error.
596
 */
597
static GLint
598
get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
599
            GLenum pname)
600
{
601
   switch (pname) {
602
   case GL_TEXTURE_ENV_MODE:
603
      return texUnit->EnvMode;
604
      break;
605
   case GL_COMBINE_RGB:
606
      if (ctx->Extensions.EXT_texture_env_combine ||
607
          ctx->Extensions.ARB_texture_env_combine) {
608
         return texUnit->Combine.ModeRGB;
609
      }
610
      else {
611
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
612
      }
613
      break;
614
   case GL_COMBINE_ALPHA:
615
      if (ctx->Extensions.EXT_texture_env_combine ||
616
          ctx->Extensions.ARB_texture_env_combine) {
617
         return texUnit->Combine.ModeA;
618
      }
619
      else {
620
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
621
      }
622
      break;
623
   case GL_SOURCE0_RGB:
624
   case GL_SOURCE1_RGB:
625
   case GL_SOURCE2_RGB:
626
      if (ctx->Extensions.EXT_texture_env_combine ||
627
          ctx->Extensions.ARB_texture_env_combine) {
628
         const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
629
         return texUnit->Combine.SourceRGB[rgb_idx];
630
      }
631
      else {
632
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
633
      }
634
      break;
635
   case GL_SOURCE3_RGB_NV:
636
      if (ctx->Extensions.NV_texture_env_combine4) {
637
         return texUnit->Combine.SourceRGB[3];
638
      }
639
      else {
640
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
641
      }
642
      break;
643
   case GL_SOURCE0_ALPHA:
644
   case GL_SOURCE1_ALPHA:
645
   case GL_SOURCE2_ALPHA:
646
      if (ctx->Extensions.EXT_texture_env_combine ||
647
          ctx->Extensions.ARB_texture_env_combine) {
648
         const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
649
         return texUnit->Combine.SourceA[alpha_idx];
650
      }
651
      else {
652
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
653
      }
654
      break;
655
   case GL_SOURCE3_ALPHA_NV:
656
      if (ctx->Extensions.NV_texture_env_combine4) {
657
         return texUnit->Combine.SourceA[3];
658
      }
659
      else {
660
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
661
      }
662
      break;
663
   case GL_OPERAND0_RGB:
664
   case GL_OPERAND1_RGB:
665
   case GL_OPERAND2_RGB:
666
      if (ctx->Extensions.EXT_texture_env_combine ||
667
          ctx->Extensions.ARB_texture_env_combine) {
668
         const unsigned op_rgb = pname - GL_OPERAND0_RGB;
669
         return texUnit->Combine.OperandRGB[op_rgb];
670
      }
671
      else {
672
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
673
      }
674
      break;
675
   case GL_OPERAND3_RGB_NV:
676
      if (ctx->Extensions.NV_texture_env_combine4) {
677
         return texUnit->Combine.OperandRGB[3];
678
      }
679
      else {
680
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
681
      }
682
      break;
683
   case GL_OPERAND0_ALPHA:
684
   case GL_OPERAND1_ALPHA:
685
   case GL_OPERAND2_ALPHA:
686
      if (ctx->Extensions.EXT_texture_env_combine ||
687
          ctx->Extensions.ARB_texture_env_combine) {
688
         const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
689
         return texUnit->Combine.OperandA[op_alpha];
690
      }
691
      else {
692
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
693
      }
694
      break;
695
   case GL_OPERAND3_ALPHA_NV:
696
      if (ctx->Extensions.NV_texture_env_combine4) {
697
         return texUnit->Combine.OperandA[3];
698
      }
699
      else {
700
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
701
      }
702
      break;
703
   case GL_RGB_SCALE:
704
      if (ctx->Extensions.EXT_texture_env_combine ||
705
          ctx->Extensions.ARB_texture_env_combine) {
706
         return 1 << texUnit->Combine.ScaleShiftRGB;
707
      }
708
      else {
709
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
710
      }
711
      break;
712
   case GL_ALPHA_SCALE:
713
      if (ctx->Extensions.EXT_texture_env_combine ||
714
          ctx->Extensions.ARB_texture_env_combine) {
715
         return 1 << texUnit->Combine.ScaleShiftA;
716
      }
717
      else {
718
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
719
      }
720
      break;
721
   case GL_BUMP_TARGET_ATI:
722
      /* spec doesn't say so, but I think this should be queryable */
723
      if (ctx->Extensions.ATI_envmap_bumpmap) {
724
         return texUnit->BumpTarget;
725
      }
726
      else {
727
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
728
      }
729
      break;
730
 
731
   default:
732
      ;
733
   }
734
 
735
   return -1; /* error */
736
}
737
 
738
 
739
 
740
void GLAPIENTRY
741
_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
742
{
743
   GLuint maxUnit;
744
   const struct gl_texture_unit *texUnit;
745
   GET_CURRENT_CONTEXT(ctx);
746
   ASSERT_OUTSIDE_BEGIN_END(ctx);
747
 
748
   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
749
      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
750
   if (ctx->Texture.CurrentUnit >= maxUnit) {
751
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
752
      return;
753
   }
754
 
755
   texUnit = _mesa_get_current_tex_unit(ctx);
756
 
757
   if (target == GL_TEXTURE_ENV) {
758
      if (pname == GL_TEXTURE_ENV_COLOR) {
759
         COPY_4FV( params, texUnit->EnvColor );
760
      }
761
      else {
762
         GLint val = get_texenvi(ctx, texUnit, pname);
763
         if (val >= 0) {
764
            *params = (GLfloat) val;
765
         }
766
      }
767
   }
768
   else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
769
      /* GL_EXT_texture_lod_bias */
770
      if (!ctx->Extensions.EXT_texture_lod_bias) {
771
	 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
772
	 return;
773
      }
774
      if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
775
         *params = texUnit->LodBias;
776
      }
777
      else {
778
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
779
	 return;
780
      }
781
   }
782
   else if (target == GL_POINT_SPRITE_NV) {
783
      /* GL_ARB_point_sprite / GL_NV_point_sprite */
784
      if (!ctx->Extensions.NV_point_sprite
785
	  && !ctx->Extensions.ARB_point_sprite) {
786
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
787
         return;
788
      }
789
      if (pname == GL_COORD_REPLACE_NV) {
790
         *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
791
      }
792
      else {
793
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
794
         return;
795
      }
796
   }
797
   else {
798
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
799
      return;
800
   }
801
}
802
 
803
 
804
void GLAPIENTRY
805
_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
806
{
807
   GLuint maxUnit;
808
   const struct gl_texture_unit *texUnit;
809
   GET_CURRENT_CONTEXT(ctx);
810
   ASSERT_OUTSIDE_BEGIN_END(ctx);
811
 
812
   maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
813
      ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
814
   if (ctx->Texture.CurrentUnit >= maxUnit) {
815
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
816
      return;
817
   }
818
 
819
   texUnit = _mesa_get_current_tex_unit(ctx);
820
 
821
   if (target == GL_TEXTURE_ENV) {
822
      if (pname == GL_TEXTURE_ENV_COLOR) {
823
         params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
824
         params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
825
         params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
826
         params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
827
      }
828
      else {
829
         GLint val = get_texenvi(ctx, texUnit, pname);
830
         if (val >= 0) {
831
            *params = val;
832
         }
833
      }
834
   }
835
   else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
836
      /* GL_EXT_texture_lod_bias */
837
      if (!ctx->Extensions.EXT_texture_lod_bias) {
838
	 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
839
	 return;
840
      }
841
      if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
842
         *params = (GLint) texUnit->LodBias;
843
      }
844
      else {
845
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
846
	 return;
847
      }
848
   }
849
   else if (target == GL_POINT_SPRITE_NV) {
850
      /* GL_ARB_point_sprite / GL_NV_point_sprite */
851
      if (!ctx->Extensions.NV_point_sprite
852
	  && !ctx->Extensions.ARB_point_sprite) {
853
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
854
         return;
855
      }
856
      if (pname == GL_COORD_REPLACE_NV) {
857
         *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
858
      }
859
      else {
860
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
861
         return;
862
      }
863
   }
864
   else {
865
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
866
      return;
867
   }
868
}
869
 
870
 
871
/**
872
 * Why does ATI_envmap_bumpmap require new entrypoints? Should just
873
 * reuse TexEnv ones...
874
 */
875
void GLAPIENTRY
876
_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
877
{
878
   GLfloat p[4];
879
   GET_CURRENT_CONTEXT(ctx);
880
   ASSERT_OUTSIDE_BEGIN_END(ctx);
881
 
882
   if (!ctx->Extensions.ATI_envmap_bumpmap) {
883
      /* This isn't an "official" error case, but let's tell the user
884
       * that something's wrong.
885
       */
886
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterivATI");
887
      return;
888
   }
889
 
890
   if (pname == GL_BUMP_ROT_MATRIX_ATI) {
891
      /* hope that conversion is correct here */
892
      p[0] = INT_TO_FLOAT( param[0] );
893
      p[1] = INT_TO_FLOAT( param[1] );
894
      p[2] = INT_TO_FLOAT( param[2] );
895
      p[3] = INT_TO_FLOAT( param[3] );
896
   }
897
   else {
898
      p[0] = (GLfloat) param[0];
899
      p[1] = p[2] = p[3] = 0.0F;  /* init to zero, just to be safe */
900
   }
901
   _mesa_TexBumpParameterfvATI( pname, p );
902
}
903
 
904
 
905
void GLAPIENTRY
906
_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
907
{
908
   struct gl_texture_unit *texUnit;
909
   GET_CURRENT_CONTEXT(ctx);
910
   ASSERT_OUTSIDE_BEGIN_END(ctx);
911
 
912
   if (!ctx->Extensions.ATI_envmap_bumpmap) {
913
      _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterfvATI");
914
      return;
915
   }
916
 
917
   texUnit = _mesa_get_current_tex_unit(ctx);
918
 
919
   if (pname == GL_BUMP_ROT_MATRIX_ATI) {
920
      if (TEST_EQ_4V(param, texUnit->RotMatrix))
921
         return;
922
      FLUSH_VERTICES(ctx, _NEW_TEXTURE);
923
      COPY_4FV(texUnit->RotMatrix, param);
924
   }
925
   else {
926
      _mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
927
      return;
928
   }
929
   /* Drivers might want to know about this, instead of dedicated function
930
      just shove it into TexEnv where it really belongs anyway */
931
   if (ctx->Driver.TexEnv) {
932
      (*ctx->Driver.TexEnv)( ctx, 0, pname, param );
933
   }
934
}
935
 
936
 
937
void GLAPIENTRY
938
_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
939
{
940
   const struct gl_texture_unit *texUnit;
941
   GLuint i;
942
   GET_CURRENT_CONTEXT(ctx);
943
   ASSERT_OUTSIDE_BEGIN_END(ctx);
944
 
945
   if (!ctx->Extensions.ATI_envmap_bumpmap) {
946
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterivATI");
947
      return;
948
   }
949
 
950
   texUnit = _mesa_get_current_tex_unit(ctx);
951
 
952
   if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
953
      /* spec leaves open to support larger matrices.
954
         Don't think anyone would ever want to use it
955
         (and apps almost certainly would not understand it and
956
         thus fail to submit matrices correctly) so hardcode this. */
957
      *param = 4;
958
   }
959
   else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
960
      /* hope that conversion is correct here */
961
      param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
962
      param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
963
      param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
964
      param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
965
   }
966
   else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
967
      GLint count = 0;
968
      for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
969
         if (ctx->Const.SupportedBumpUnits & (1 << i)) {
970
            count++;
971
         }
972
      }
973
      *param = count;
974
   }
975
   else if (pname == GL_BUMP_TEX_UNITS_ATI) {
976
      for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
977
         if (ctx->Const.SupportedBumpUnits & (1 << i)) {
978
            *param++ = i + GL_TEXTURE0;
979
         }
980
      }
981
   }
982
   else {
983
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
984
      return;
985
   }
986
}
987
 
988
 
989
void GLAPIENTRY
990
_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
991
{
992
   const struct gl_texture_unit *texUnit;
993
   GLuint i;
994
   GET_CURRENT_CONTEXT(ctx);
995
   ASSERT_OUTSIDE_BEGIN_END(ctx);
996
 
997
   if (!ctx->Extensions.ATI_envmap_bumpmap) {
998
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterfvATI");
999
      return;
1000
   }
1001
 
1002
   texUnit = _mesa_get_current_tex_unit(ctx);
1003
 
1004
   if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
1005
      /* spec leaves open to support larger matrices.
1006
         Don't think anyone would ever want to use it
1007
         (and apps might not understand it) so hardcode this. */
1008
      *param = 4.0F;
1009
   }
1010
   else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
1011
      param[0] = texUnit->RotMatrix[0];
1012
      param[1] = texUnit->RotMatrix[1];
1013
      param[2] = texUnit->RotMatrix[2];
1014
      param[3] = texUnit->RotMatrix[3];
1015
   }
1016
   else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
1017
      GLint count = 0;
1018
      for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1019
         if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1020
            count++;
1021
         }
1022
      }
1023
      *param = (GLfloat) count;
1024
   }
1025
   else if (pname == GL_BUMP_TEX_UNITS_ATI) {
1026
      for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1027
         if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1028
            *param++ = (GLfloat) (i + GL_TEXTURE0);
1029
         }
1030
      }
1031
   }
1032
   else {
1033
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
1034
      return;
1035
   }
1036
}