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