1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * 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/blend.h"
36 #include "main/enums.h"
37 #include "main/macros.h"
38 #include "main/mtypes.h"
39 #include "main/state.h"
40 #include "main/texenv.h"
41 #include "main/texstate.h"
42 
43 
44 #define TE_ERROR(errCode, msg, value)				\
45    _mesa_error(ctx, errCode, msg, _mesa_enum_to_string(value));
46 
47 
48 /** Set texture env mode */
49 static void
set_env_mode(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum mode)50 set_env_mode(struct gl_context *ctx,
51              struct gl_texture_unit *texUnit,
52              GLenum mode)
53 {
54    GLboolean legal;
55 
56    if (texUnit->EnvMode == mode)
57       return;
58 
59    switch (mode) {
60    case GL_MODULATE:
61    case GL_BLEND:
62    case GL_DECAL:
63    case GL_REPLACE:
64    case GL_ADD:
65    case GL_COMBINE:
66       legal = GL_TRUE;
67       break;
68    case GL_REPLACE_EXT:
69       mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
70       legal = GL_TRUE;
71       break;
72    case GL_COMBINE4_NV:
73       legal = ctx->Extensions.NV_texture_env_combine4;
74       break;
75    default:
76       legal = GL_FALSE;
77    }
78 
79    if (legal) {
80       FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
81       texUnit->EnvMode = mode;
82    }
83    else {
84       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
85    }
86 }
87 
88 
89 static void
set_env_color(struct gl_context * ctx,struct gl_texture_unit * texUnit,const GLfloat * color)90 set_env_color(struct gl_context *ctx,
91               struct gl_texture_unit *texUnit,
92               const GLfloat *color)
93 {
94    if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped))
95       return;
96    FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
97    COPY_4FV(texUnit->EnvColorUnclamped, color);
98    texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F);
99    texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F);
100    texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F);
101    texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F);
102 }
103 
104 
105 /** Set an RGB or A combiner mode/function */
106 static void
set_combiner_mode(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum pname,GLenum mode)107 set_combiner_mode(struct gl_context *ctx,
108                   struct gl_texture_unit *texUnit,
109                   GLenum pname, GLenum mode)
110 {
111    GLboolean legal;
112 
113    switch (mode) {
114    case GL_REPLACE:
115    case GL_MODULATE:
116    case GL_ADD:
117    case GL_ADD_SIGNED:
118    case GL_INTERPOLATE:
119       legal = GL_TRUE;
120       break;
121    case GL_SUBTRACT:
122       legal = ctx->Extensions.ARB_texture_env_combine;
123       break;
124    case GL_DOT3_RGB_EXT:
125    case GL_DOT3_RGBA_EXT:
126       legal = (ctx->API == API_OPENGL_COMPAT &&
127                ctx->Extensions.EXT_texture_env_dot3 &&
128                pname == GL_COMBINE_RGB);
129       break;
130    case GL_DOT3_RGB:
131    case GL_DOT3_RGBA:
132       legal = (ctx->Extensions.ARB_texture_env_dot3 &&
133                pname == GL_COMBINE_RGB);
134       break;
135    case GL_MODULATE_ADD_ATI:
136    case GL_MODULATE_SIGNED_ADD_ATI:
137    case GL_MODULATE_SUBTRACT_ATI:
138       legal = (ctx->API == API_OPENGL_COMPAT &&
139                ctx->Extensions.ATI_texture_env_combine3);
140       break;
141    default:
142       legal = GL_FALSE;
143    }
144 
145    if (!legal) {
146       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
147       return;
148    }
149 
150    switch (pname) {
151    case GL_COMBINE_RGB:
152       if (texUnit->Combine.ModeRGB == mode)
153          return;
154       FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
155       texUnit->Combine.ModeRGB = mode;
156       break;
157 
158    case GL_COMBINE_ALPHA:
159       if (texUnit->Combine.ModeA == mode)
160          return;
161       FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
162       texUnit->Combine.ModeA = mode;
163       break;
164    default:
165       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
166    }
167 }
168 
169 
170 
171 /** Set an RGB or A combiner source term */
172 static void
set_combiner_source(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum pname,GLenum param)173 set_combiner_source(struct gl_context *ctx,
174                     struct gl_texture_unit *texUnit,
175                     GLenum pname, GLenum param)
176 {
177    GLuint term;
178    GLboolean alpha, legal;
179 
180    /*
181     * Translate pname to (term, alpha).
182     *
183     * The enums were given sequential values for a reason.
184     */
185    switch (pname) {
186    case GL_SOURCE0_RGB:
187    case GL_SOURCE1_RGB:
188    case GL_SOURCE2_RGB:
189    case GL_SOURCE3_RGB_NV:
190       term = pname - GL_SOURCE0_RGB;
191       alpha = GL_FALSE;
192       break;
193    case GL_SOURCE0_ALPHA:
194    case GL_SOURCE1_ALPHA:
195    case GL_SOURCE2_ALPHA:
196    case GL_SOURCE3_ALPHA_NV:
197       term = pname - GL_SOURCE0_ALPHA;
198       alpha = GL_TRUE;
199       break;
200    default:
201       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
202       return;
203    }
204 
205    if ((term == 3) && (ctx->API != API_OPENGL_COMPAT
206                        || !ctx->Extensions.NV_texture_env_combine4)) {
207       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
208       return;
209    }
210 
211    assert(term < MAX_COMBINER_TERMS);
212 
213    /*
214     * Error-check param (the source term)
215     */
216    switch (param) {
217    case GL_TEXTURE:
218    case GL_CONSTANT:
219    case GL_PRIMARY_COLOR:
220    case GL_PREVIOUS:
221       legal = GL_TRUE;
222       break;
223    case GL_TEXTURE0:
224    case GL_TEXTURE1:
225    case GL_TEXTURE2:
226    case GL_TEXTURE3:
227    case GL_TEXTURE4:
228    case GL_TEXTURE5:
229    case GL_TEXTURE6:
230    case GL_TEXTURE7:
231       legal = (ctx->Extensions.ARB_texture_env_crossbar &&
232                param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
233       break;
234    case GL_ZERO:
235       legal = (ctx->API == API_OPENGL_COMPAT &&
236                (ctx->Extensions.ATI_texture_env_combine3 ||
237                 ctx->Extensions.NV_texture_env_combine4));
238       break;
239    case GL_ONE:
240       legal = (ctx->API == API_OPENGL_COMPAT &&
241                ctx->Extensions.ATI_texture_env_combine3);
242       break;
243    default:
244       legal = GL_FALSE;
245    }
246 
247    if (!legal) {
248       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
249       return;
250    }
251 
252    FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
253 
254    if (alpha)
255       texUnit->Combine.SourceA[term] = param;
256    else
257       texUnit->Combine.SourceRGB[term] = param;
258 }
259 
260 
261 /** Set an RGB or A combiner operand term */
262 static void
set_combiner_operand(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum pname,GLenum param)263 set_combiner_operand(struct gl_context *ctx,
264                      struct gl_texture_unit *texUnit,
265                      GLenum pname, GLenum param)
266 {
267    GLuint term;
268    GLboolean alpha, legal;
269 
270    /* The enums were given sequential values for a reason.
271     */
272    switch (pname) {
273    case GL_OPERAND0_RGB:
274    case GL_OPERAND1_RGB:
275    case GL_OPERAND2_RGB:
276    case GL_OPERAND3_RGB_NV:
277       term = pname - GL_OPERAND0_RGB;
278       alpha = GL_FALSE;
279       break;
280    case GL_OPERAND0_ALPHA:
281    case GL_OPERAND1_ALPHA:
282    case GL_OPERAND2_ALPHA:
283    case GL_OPERAND3_ALPHA_NV:
284       term = pname - GL_OPERAND0_ALPHA;
285       alpha = GL_TRUE;
286       break;
287    default:
288       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
289       return;
290    }
291 
292    if ((term == 3) && (ctx->API != API_OPENGL_COMPAT
293                        || !ctx->Extensions.NV_texture_env_combine4)) {
294       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
295       return;
296    }
297 
298    assert(term < MAX_COMBINER_TERMS);
299 
300    /*
301     * Error-check param (the source operand)
302     */
303    switch (param) {
304    case GL_SRC_COLOR:
305    case GL_ONE_MINUS_SRC_COLOR:
306       /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT
307        * version.  In the ARB and NV versions and OpenGL ES 1.x they can be
308        * used for any RGB operand.
309        */
310       legal = !alpha
311 	 && ((term < 2) || ctx->Extensions.ARB_texture_env_combine
312 	     || ctx->Extensions.NV_texture_env_combine4);
313       break;
314    case GL_ONE_MINUS_SRC_ALPHA:
315       /* GL_ONE_MINUS_SRC_ALPHA can only be used with
316        * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version.  In the ARB and NV
317        * versions and OpenGL ES 1.x it can be used for any operand.
318        */
319       legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine
320 	 || ctx->Extensions.NV_texture_env_combine4;
321       break;
322    case GL_SRC_ALPHA:
323       legal = GL_TRUE;
324       break;
325    default:
326       legal = GL_FALSE;
327    }
328 
329    if (!legal) {
330       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
331       return;
332    }
333 
334    FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
335 
336    if (alpha)
337       texUnit->Combine.OperandA[term] = param;
338    else
339       texUnit->Combine.OperandRGB[term] = param;
340 }
341 
342 
343 static void
set_combiner_scale(struct gl_context * ctx,struct gl_texture_unit * texUnit,GLenum pname,GLfloat scale)344 set_combiner_scale(struct gl_context *ctx,
345                    struct gl_texture_unit *texUnit,
346                    GLenum pname, GLfloat scale)
347 {
348    GLuint shift;
349 
350    if (scale == 1.0F) {
351       shift = 0;
352    }
353    else if (scale == 2.0F) {
354       shift = 1;
355    }
356    else if (scale == 4.0F) {
357       shift = 2;
358    }
359    else {
360       _mesa_error( ctx, GL_INVALID_VALUE,
361                    "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
362       return;
363    }
364 
365    switch (pname) {
366    case GL_RGB_SCALE:
367       if (texUnit->Combine.ScaleShiftRGB == shift)
368          return;
369       FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
370       texUnit->Combine.ScaleShiftRGB = shift;
371       break;
372    case GL_ALPHA_SCALE:
373       if (texUnit->Combine.ScaleShiftA == shift)
374          return;
375       FLUSH_VERTICES(ctx, _NEW_TEXTURE_STATE);
376       texUnit->Combine.ScaleShiftA = shift;
377       break;
378    default:
379       TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
380    }
381 }
382 
383 
384 
385 void GLAPIENTRY
_mesa_TexEnvfv(GLenum target,GLenum pname,const GLfloat * param)386 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
387 {
388    const GLint iparam0 = (GLint) param[0];
389    struct gl_texture_unit *texUnit;
390    GLuint maxUnit;
391    GET_CURRENT_CONTEXT(ctx);
392 
393    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
394       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
395    if (ctx->Texture.CurrentUnit >= maxUnit) {
396       _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
397       return;
398    }
399 
400    texUnit = _mesa_get_current_tex_unit(ctx);
401 
402    if (target == GL_TEXTURE_ENV) {
403       switch (pname) {
404       case GL_TEXTURE_ENV_MODE:
405          set_env_mode(ctx, texUnit, (GLenum) iparam0);
406          break;
407       case GL_TEXTURE_ENV_COLOR:
408          set_env_color(ctx, texUnit, param);
409          break;
410       case GL_COMBINE_RGB:
411       case GL_COMBINE_ALPHA:
412          set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0);
413 	 break;
414       case GL_SOURCE0_RGB:
415       case GL_SOURCE1_RGB:
416       case GL_SOURCE2_RGB:
417       case GL_SOURCE3_RGB_NV:
418       case GL_SOURCE0_ALPHA:
419       case GL_SOURCE1_ALPHA:
420       case GL_SOURCE2_ALPHA:
421       case GL_SOURCE3_ALPHA_NV:
422          set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0);
423 	 break;
424       case GL_OPERAND0_RGB:
425       case GL_OPERAND1_RGB:
426       case GL_OPERAND2_RGB:
427       case GL_OPERAND3_RGB_NV:
428       case GL_OPERAND0_ALPHA:
429       case GL_OPERAND1_ALPHA:
430       case GL_OPERAND2_ALPHA:
431       case GL_OPERAND3_ALPHA_NV:
432          set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0);
433 	 break;
434       case GL_RGB_SCALE:
435       case GL_ALPHA_SCALE:
436          set_combiner_scale(ctx, texUnit, pname, param[0]);
437 	 break;
438       default:
439 	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
440 	 return;
441       }
442    }
443    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
444       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
445 	 if (texUnit->LodBias == param[0])
446 	    return;
447 	 FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT);
448          texUnit->LodBias = param[0];
449       }
450       else {
451          TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
452 	 return;
453       }
454    }
455    else if (target == GL_POINT_SPRITE_NV) {
456       /* GL_ARB_point_sprite / GL_NV_point_sprite */
457       if (!ctx->Extensions.NV_point_sprite
458 	  && !ctx->Extensions.ARB_point_sprite) {
459 	 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
460 	 return;
461       }
462       if (pname == GL_COORD_REPLACE_NV) {
463          /* It's kind of weird to set point state via glTexEnv,
464           * but that's what the spec calls for.
465           */
466          if (iparam0 == GL_TRUE) {
467             if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit))
468                return;
469             ctx->Point.CoordReplace |= (1u << ctx->Texture.CurrentUnit);
470          } else if (iparam0 == GL_FALSE) {
471             if (~(ctx->Point.CoordReplace) & (1u << ctx->Texture.CurrentUnit))
472                return;
473             ctx->Point.CoordReplace &= ~(1u << ctx->Texture.CurrentUnit);
474          } else {
475             _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0);
476             return;
477          }
478          FLUSH_VERTICES(ctx, _NEW_POINT);
479       }
480       else {
481          _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
482          return;
483       }
484    }
485    else {
486       _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(target=%s)",
487                   _mesa_enum_to_string(target));
488       return;
489    }
490 
491    if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
492       _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
493                   _mesa_enum_to_string(target),
494                   _mesa_enum_to_string(pname),
495                   *param,
496                   _mesa_enum_to_string((GLenum) iparam0));
497 
498    /* Tell device driver about the new texture environment */
499    if (ctx->Driver.TexEnv) {
500       ctx->Driver.TexEnv(ctx, target, pname, param);
501    }
502 }
503 
504 
505 void GLAPIENTRY
_mesa_TexEnvf(GLenum target,GLenum pname,GLfloat param)506 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
507 {
508    GLfloat p[4];
509    p[0] = param;
510    p[1] = p[2] = p[3] = 0.0;
511    _mesa_TexEnvfv( target, pname, p );
512 }
513 
514 
515 
516 void GLAPIENTRY
_mesa_TexEnvi(GLenum target,GLenum pname,GLint param)517 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
518 {
519    GLfloat p[4];
520    p[0] = (GLfloat) param;
521    p[1] = p[2] = p[3] = 0.0;
522    _mesa_TexEnvfv( target, pname, p );
523 }
524 
525 
526 void GLAPIENTRY
_mesa_TexEnviv(GLenum target,GLenum pname,const GLint * param)527 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
528 {
529    GLfloat p[4];
530    if (pname == GL_TEXTURE_ENV_COLOR) {
531       p[0] = INT_TO_FLOAT( param[0] );
532       p[1] = INT_TO_FLOAT( param[1] );
533       p[2] = INT_TO_FLOAT( param[2] );
534       p[3] = INT_TO_FLOAT( param[3] );
535    }
536    else {
537       p[0] = (GLfloat) param[0];
538       p[1] = p[2] = p[3] = 0;  /* init to zero, just to be safe */
539    }
540    _mesa_TexEnvfv( target, pname, p );
541 }
542 
543 
544 
545 /**
546  * Helper for glGetTexEnvi/f()
547  * \return  value of queried pname or -1 if error.
548  */
549 static GLint
get_texenvi(struct gl_context * ctx,const struct gl_texture_unit * texUnit,GLenum pname)550 get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
551             GLenum pname)
552 {
553    switch (pname) {
554    case GL_TEXTURE_ENV_MODE:
555       return texUnit->EnvMode;
556       break;
557    case GL_COMBINE_RGB:
558       return texUnit->Combine.ModeRGB;
559    case GL_COMBINE_ALPHA:
560       return texUnit->Combine.ModeA;
561    case GL_SOURCE0_RGB:
562    case GL_SOURCE1_RGB:
563    case GL_SOURCE2_RGB: {
564       const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
565       return texUnit->Combine.SourceRGB[rgb_idx];
566    }
567    case GL_SOURCE3_RGB_NV:
568       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
569          return texUnit->Combine.SourceRGB[3];
570       }
571       else {
572          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
573       }
574       break;
575    case GL_SOURCE0_ALPHA:
576    case GL_SOURCE1_ALPHA:
577    case GL_SOURCE2_ALPHA: {
578       const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
579       return texUnit->Combine.SourceA[alpha_idx];
580    }
581    case GL_SOURCE3_ALPHA_NV:
582       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
583          return texUnit->Combine.SourceA[3];
584       }
585       else {
586          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
587       }
588       break;
589    case GL_OPERAND0_RGB:
590    case GL_OPERAND1_RGB:
591    case GL_OPERAND2_RGB: {
592       const unsigned op_rgb = pname - GL_OPERAND0_RGB;
593       return texUnit->Combine.OperandRGB[op_rgb];
594    }
595    case GL_OPERAND3_RGB_NV:
596       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
597          return texUnit->Combine.OperandRGB[3];
598       }
599       else {
600          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
601       }
602       break;
603    case GL_OPERAND0_ALPHA:
604    case GL_OPERAND1_ALPHA:
605    case GL_OPERAND2_ALPHA: {
606       const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
607       return texUnit->Combine.OperandA[op_alpha];
608    }
609    case GL_OPERAND3_ALPHA_NV:
610       if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.NV_texture_env_combine4) {
611          return texUnit->Combine.OperandA[3];
612       }
613       else {
614          _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
615       }
616       break;
617    case GL_RGB_SCALE:
618       return 1 << texUnit->Combine.ScaleShiftRGB;
619    case GL_ALPHA_SCALE:
620       return 1 << texUnit->Combine.ScaleShiftA;
621    default:
622       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
623       break;
624    }
625 
626    return -1; /* error */
627 }
628 
629 
630 
631 void GLAPIENTRY
_mesa_GetTexEnvfv(GLenum target,GLenum pname,GLfloat * params)632 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
633 {
634    GLuint maxUnit;
635    const struct gl_texture_unit *texUnit;
636    GET_CURRENT_CONTEXT(ctx);
637 
638    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
639       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
640    if (ctx->Texture.CurrentUnit >= maxUnit) {
641       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
642       return;
643    }
644 
645    texUnit = _mesa_get_current_tex_unit(ctx);
646 
647    if (target == GL_TEXTURE_ENV) {
648       if (pname == GL_TEXTURE_ENV_COLOR) {
649          if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
650             _mesa_update_state(ctx);
651          if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
652             COPY_4FV( params, texUnit->EnvColor );
653          else
654             COPY_4FV( params, texUnit->EnvColorUnclamped );
655       }
656       else {
657          GLint val = get_texenvi(ctx, texUnit, pname);
658          if (val >= 0) {
659             *params = (GLfloat) val;
660          }
661       }
662    }
663    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
664       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
665          *params = texUnit->LodBias;
666       }
667       else {
668          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
669 	 return;
670       }
671    }
672    else if (target == GL_POINT_SPRITE_NV) {
673       /* GL_ARB_point_sprite / GL_NV_point_sprite */
674       if (!ctx->Extensions.NV_point_sprite
675 	  && !ctx->Extensions.ARB_point_sprite) {
676          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
677          return;
678       }
679       if (pname == GL_COORD_REPLACE_NV) {
680          if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit))
681             *params = 1.0f;
682          else
683             *params = 0.0f;
684       }
685       else {
686          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
687          return;
688       }
689    }
690    else {
691       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
692       return;
693    }
694 }
695 
696 
697 void GLAPIENTRY
_mesa_GetTexEnviv(GLenum target,GLenum pname,GLint * params)698 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
699 {
700    GLuint maxUnit;
701    const struct gl_texture_unit *texUnit;
702    GET_CURRENT_CONTEXT(ctx);
703 
704    maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
705       ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits;
706    if (ctx->Texture.CurrentUnit >= maxUnit) {
707       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
708       return;
709    }
710 
711    texUnit = _mesa_get_current_tex_unit(ctx);
712 
713    if (target == GL_TEXTURE_ENV) {
714       if (pname == GL_TEXTURE_ENV_COLOR) {
715          params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
716          params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
717          params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
718          params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
719       }
720       else {
721          GLint val = get_texenvi(ctx, texUnit, pname);
722          if (val >= 0) {
723             *params = val;
724          }
725       }
726    }
727    else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
728       if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
729          *params = (GLint) texUnit->LodBias;
730       }
731       else {
732          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
733 	 return;
734       }
735    }
736    else if (target == GL_POINT_SPRITE_NV) {
737       /* GL_ARB_point_sprite / GL_NV_point_sprite */
738       if (!ctx->Extensions.NV_point_sprite
739 	  && !ctx->Extensions.ARB_point_sprite) {
740          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
741          return;
742       }
743       if (pname == GL_COORD_REPLACE_NV) {
744          if (ctx->Point.CoordReplace & (1u << ctx->Texture.CurrentUnit))
745             *params = GL_TRUE;
746          else
747             *params = GL_FALSE;
748       }
749       else {
750          _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
751          return;
752       }
753    }
754    else {
755       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
756       return;
757    }
758 }
759 
760