Merge branch 'master' into asm-shader-rework-1
[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/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(GLcontext *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(GLcontext *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(GLcontext *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(GLcontext *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 switch (pname) {
201 case GL_SOURCE0_RGB:
202 term = 0;
203 alpha = GL_FALSE;
204 break;
205 case GL_SOURCE1_RGB:
206 term = 1;
207 alpha = GL_FALSE;
208 break;
209 case GL_SOURCE2_RGB:
210 term = 2;
211 alpha = GL_FALSE;
212 break;
213 case GL_SOURCE3_RGB_NV:
214 if (ctx->Extensions.NV_texture_env_combine4) {
215 term = 3;
216 alpha = GL_FALSE;
217 }
218 else {
219 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
220 return;
221 }
222 break;
223 case GL_SOURCE0_ALPHA:
224 term = 0;
225 alpha = GL_TRUE;
226 break;
227 case GL_SOURCE1_ALPHA:
228 term = 1;
229 alpha = GL_TRUE;
230 break;
231 case GL_SOURCE2_ALPHA:
232 term = 2;
233 alpha = GL_TRUE;
234 break;
235 case GL_SOURCE3_ALPHA_NV:
236 if (ctx->Extensions.NV_texture_env_combine4) {
237 term = 3;
238 alpha = GL_TRUE;
239 }
240 else {
241 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
242 return;
243 }
244 break;
245 default:
246 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
247 return;
248 }
249
250 assert(term < MAX_COMBINER_TERMS);
251
252 /*
253 * Error-check param (the source term)
254 */
255 switch (param) {
256 case GL_TEXTURE:
257 case GL_CONSTANT:
258 case GL_PRIMARY_COLOR:
259 case GL_PREVIOUS:
260 legal = GL_TRUE;
261 break;
262 case GL_TEXTURE0:
263 case GL_TEXTURE1:
264 case GL_TEXTURE2:
265 case GL_TEXTURE3:
266 case GL_TEXTURE4:
267 case GL_TEXTURE5:
268 case GL_TEXTURE6:
269 case GL_TEXTURE7:
270 legal = (ctx->Extensions.ARB_texture_env_crossbar &&
271 param - GL_TEXTURE0 < ctx->Const.MaxTextureUnits);
272 break;
273 case GL_ZERO:
274 legal = (ctx->Extensions.ATI_texture_env_combine3 ||
275 ctx->Extensions.NV_texture_env_combine4);
276 break;
277 case GL_ONE:
278 legal = ctx->Extensions.ATI_texture_env_combine3;
279 break;
280 default:
281 legal = GL_FALSE;
282 }
283
284 if (!legal) {
285 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
286 return;
287 }
288
289 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
290
291 if (alpha)
292 texUnit->Combine.SourceA[term] = param;
293 else
294 texUnit->Combine.SourceRGB[term] = param;
295 }
296
297
298 /** Set an RGB or A combiner operand term */
299 static void
300 set_combiner_operand(GLcontext *ctx,
301 struct gl_texture_unit *texUnit,
302 GLenum pname, GLenum param)
303 {
304 GLuint term;
305 GLboolean alpha, legal;
306
307 if (!ctx->Extensions.EXT_texture_env_combine &&
308 !ctx->Extensions.ARB_texture_env_combine) {
309 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
310 return;
311 }
312
313 switch (pname) {
314 case GL_OPERAND0_RGB:
315 term = 0;
316 alpha = GL_FALSE;
317 break;
318 case GL_OPERAND1_RGB:
319 term = 1;
320 alpha = GL_FALSE;
321 break;
322 case GL_OPERAND2_RGB:
323 if (ctx->Extensions.ARB_texture_env_combine) {
324 term = 2;
325 alpha = GL_FALSE;
326 }
327 else {
328 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
329 return;
330 }
331 break;
332 case GL_OPERAND3_RGB_NV:
333 if (ctx->Extensions.NV_texture_env_combine4) {
334 term = 3;
335 alpha = GL_FALSE;
336 }
337 else {
338 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
339 return;
340 }
341 break;
342 case GL_OPERAND0_ALPHA:
343 term = 0;
344 alpha = GL_TRUE;
345 break;
346 case GL_OPERAND1_ALPHA:
347 term = 1;
348 alpha = GL_TRUE;
349 break;
350 case GL_OPERAND2_ALPHA:
351 if (ctx->Extensions.ARB_texture_env_combine) {
352 term = 2;
353 alpha = GL_TRUE;
354 }
355 else {
356 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
357 return;
358 }
359 break;
360 case GL_OPERAND3_ALPHA_NV:
361 if (ctx->Extensions.NV_texture_env_combine4) {
362 term = 3;
363 alpha = GL_TRUE;
364 }
365 else {
366 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
367 return;
368 }
369 break;
370 default:
371 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
372 return;
373 }
374
375 assert(term < MAX_COMBINER_TERMS);
376
377 /*
378 * Error-check param (the source operand)
379 */
380 switch (param) {
381 case GL_SRC_COLOR:
382 case GL_ONE_MINUS_SRC_COLOR:
383 legal = !alpha;
384 break;
385 case GL_SRC_ALPHA:
386 case GL_ONE_MINUS_SRC_ALPHA:
387 legal = GL_TRUE;
388 break;
389 default:
390 legal = GL_FALSE;
391 }
392
393 if (!legal) {
394 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
395 return;
396 }
397
398 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
399
400 if (alpha)
401 texUnit->Combine.OperandA[term] = param;
402 else
403 texUnit->Combine.OperandRGB[term] = param;
404 }
405
406
407 static void
408 set_combiner_scale(GLcontext *ctx,
409 struct gl_texture_unit *texUnit,
410 GLenum pname, GLfloat scale)
411 {
412 GLuint shift;
413
414 if (!ctx->Extensions.EXT_texture_env_combine &&
415 !ctx->Extensions.ARB_texture_env_combine) {
416 _mesa_error(ctx, GL_INVALID_ENUM, "glTexEnv(pname)");
417 return;
418 }
419
420 if (scale == 1.0F) {
421 shift = 0;
422 }
423 else if (scale == 2.0F) {
424 shift = 1;
425 }
426 else if (scale == 4.0F) {
427 shift = 2;
428 }
429 else {
430 _mesa_error( ctx, GL_INVALID_VALUE,
431 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
432 return;
433 }
434
435 switch (pname) {
436 case GL_RGB_SCALE:
437 if (texUnit->Combine.ScaleShiftRGB == shift)
438 return;
439 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
440 texUnit->Combine.ScaleShiftRGB = shift;
441 break;
442 case GL_ALPHA_SCALE:
443 if (texUnit->Combine.ScaleShiftA == shift)
444 return;
445 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
446 texUnit->Combine.ScaleShiftA = shift;
447 break;
448 default:
449 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
450 }
451 }
452
453
454
455 void GLAPIENTRY
456 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
457 {
458 GLuint maxUnit;
459 GET_CURRENT_CONTEXT(ctx);
460 struct gl_texture_unit *texUnit;
461 ASSERT_OUTSIDE_BEGIN_END(ctx);
462
463 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
464 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
465 if (ctx->Texture.CurrentUnit >= maxUnit) {
466 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)");
467 return;
468 }
469
470 texUnit = _mesa_get_current_tex_unit(ctx);
471
472 if (target == GL_TEXTURE_ENV) {
473 switch (pname) {
474 case GL_TEXTURE_ENV_MODE:
475 set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]);
476 break;
477 case GL_TEXTURE_ENV_COLOR:
478 set_env_color(ctx, texUnit, param);
479 break;
480 case GL_COMBINE_RGB:
481 case GL_COMBINE_ALPHA:
482 set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
483 break;
484 case GL_SOURCE0_RGB:
485 case GL_SOURCE1_RGB:
486 case GL_SOURCE2_RGB:
487 case GL_SOURCE3_RGB_NV:
488 case GL_SOURCE0_ALPHA:
489 case GL_SOURCE1_ALPHA:
490 case GL_SOURCE2_ALPHA:
491 case GL_SOURCE3_ALPHA_NV:
492 set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
493 break;
494 case GL_OPERAND0_RGB:
495 case GL_OPERAND1_RGB:
496 case GL_OPERAND2_RGB:
497 case GL_OPERAND3_RGB_NV:
498 case GL_OPERAND0_ALPHA:
499 case GL_OPERAND1_ALPHA:
500 case GL_OPERAND2_ALPHA:
501 case GL_OPERAND3_ALPHA_NV:
502 set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
503 break;
504 case GL_RGB_SCALE:
505 case GL_ALPHA_SCALE:
506 set_combiner_scale(ctx, texUnit, pname, param[0]);
507 break;
508 case GL_BUMP_TARGET_ATI:
509 if (!ctx->Extensions.ATI_envmap_bumpmap) {
510 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
511 return;
512 }
513 if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
514 ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
515 /* spec doesn't say this but it seems logical */
516 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
517 return;
518 }
519 if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
520 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
521 return;
522 }
523 else {
524 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
525 texUnit->BumpTarget = (GLenum) (GLint) param[0];
526 }
527 break;
528 default:
529 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
530 return;
531 }
532 }
533 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
534 /* GL_EXT_texture_lod_bias */
535 if (!ctx->Extensions.EXT_texture_lod_bias) {
536 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
537 return;
538 }
539 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
540 if (texUnit->LodBias == param[0])
541 return;
542 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
543 texUnit->LodBias = param[0];
544 }
545 else {
546 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
547 return;
548 }
549 }
550 else if (target == GL_POINT_SPRITE_NV) {
551 /* GL_ARB_point_sprite / GL_NV_point_sprite */
552 if (!ctx->Extensions.NV_point_sprite
553 && !ctx->Extensions.ARB_point_sprite) {
554 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target );
555 return;
556 }
557 if (pname == GL_COORD_REPLACE_NV) {
558 const GLenum value = (GLenum) param[0];
559 if (value == GL_TRUE || value == GL_FALSE) {
560 /* It's kind of weird to set point state via glTexEnv,
561 * but that's what the spec calls for.
562 */
563 const GLboolean state = (GLboolean) value;
564 if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
565 return;
566 FLUSH_VERTICES(ctx, _NEW_POINT);
567 ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
568 }
569 else {
570 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
571 return;
572 }
573 }
574 else {
575 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
576 return;
577 }
578 }
579 else {
580 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
581 return;
582 }
583
584 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
585 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
586 _mesa_lookup_enum_by_nr(target),
587 _mesa_lookup_enum_by_nr(pname),
588 *param,
589 _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
590
591 /* Tell device driver about the new texture environment */
592 if (ctx->Driver.TexEnv) {
593 (*ctx->Driver.TexEnv)( ctx, target, pname, param );
594 }
595 }
596
597
598 void GLAPIENTRY
599 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
600 {
601 _mesa_TexEnvfv( target, pname, &param );
602 }
603
604
605
606 void GLAPIENTRY
607 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
608 {
609 GLfloat p[4];
610 p[0] = (GLfloat) param;
611 p[1] = p[2] = p[3] = 0.0;
612 _mesa_TexEnvfv( target, pname, p );
613 }
614
615
616 void GLAPIENTRY
617 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
618 {
619 GLfloat p[4];
620 if (pname == GL_TEXTURE_ENV_COLOR) {
621 p[0] = INT_TO_FLOAT( param[0] );
622 p[1] = INT_TO_FLOAT( param[1] );
623 p[2] = INT_TO_FLOAT( param[2] );
624 p[3] = INT_TO_FLOAT( param[3] );
625 }
626 else {
627 p[0] = (GLfloat) param[0];
628 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
629 }
630 _mesa_TexEnvfv( target, pname, p );
631 }
632
633
634
635 /**
636 * Helper for glGetTexEnvi/f()
637 * \return value of queried pname or -1 if error.
638 */
639 static GLint
640 get_texenvi(GLcontext *ctx, const struct gl_texture_unit *texUnit,
641 GLenum pname)
642 {
643 switch (pname) {
644 case GL_TEXTURE_ENV_MODE:
645 return texUnit->EnvMode;
646 break;
647 case GL_COMBINE_RGB:
648 if (ctx->Extensions.EXT_texture_env_combine ||
649 ctx->Extensions.ARB_texture_env_combine) {
650 return texUnit->Combine.ModeRGB;
651 }
652 else {
653 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
654 }
655 break;
656 case GL_COMBINE_ALPHA:
657 if (ctx->Extensions.EXT_texture_env_combine ||
658 ctx->Extensions.ARB_texture_env_combine) {
659 return texUnit->Combine.ModeA;
660 }
661 else {
662 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
663 }
664 break;
665 case GL_SOURCE0_RGB:
666 case GL_SOURCE1_RGB:
667 case GL_SOURCE2_RGB:
668 if (ctx->Extensions.EXT_texture_env_combine ||
669 ctx->Extensions.ARB_texture_env_combine) {
670 const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
671 return texUnit->Combine.SourceRGB[rgb_idx];
672 }
673 else {
674 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
675 }
676 break;
677 case GL_SOURCE3_RGB_NV:
678 if (ctx->Extensions.NV_texture_env_combine4) {
679 return texUnit->Combine.SourceRGB[3];
680 }
681 else {
682 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
683 }
684 break;
685 case GL_SOURCE0_ALPHA:
686 case GL_SOURCE1_ALPHA:
687 case GL_SOURCE2_ALPHA:
688 if (ctx->Extensions.EXT_texture_env_combine ||
689 ctx->Extensions.ARB_texture_env_combine) {
690 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
691 return texUnit->Combine.SourceA[alpha_idx];
692 }
693 else {
694 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
695 }
696 break;
697 case GL_SOURCE3_ALPHA_NV:
698 if (ctx->Extensions.NV_texture_env_combine4) {
699 return texUnit->Combine.SourceA[3];
700 }
701 else {
702 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
703 }
704 break;
705 case GL_OPERAND0_RGB:
706 case GL_OPERAND1_RGB:
707 case GL_OPERAND2_RGB:
708 if (ctx->Extensions.EXT_texture_env_combine ||
709 ctx->Extensions.ARB_texture_env_combine) {
710 const unsigned op_rgb = pname - GL_OPERAND0_RGB;
711 return texUnit->Combine.OperandRGB[op_rgb];
712 }
713 else {
714 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
715 }
716 break;
717 case GL_OPERAND3_RGB_NV:
718 if (ctx->Extensions.NV_texture_env_combine4) {
719 return texUnit->Combine.OperandRGB[3];
720 }
721 else {
722 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
723 }
724 break;
725 case GL_OPERAND0_ALPHA:
726 case GL_OPERAND1_ALPHA:
727 case GL_OPERAND2_ALPHA:
728 if (ctx->Extensions.EXT_texture_env_combine ||
729 ctx->Extensions.ARB_texture_env_combine) {
730 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
731 return texUnit->Combine.OperandA[op_alpha];
732 }
733 else {
734 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
735 }
736 break;
737 case GL_OPERAND3_ALPHA_NV:
738 if (ctx->Extensions.NV_texture_env_combine4) {
739 return texUnit->Combine.OperandA[3];
740 }
741 else {
742 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
743 }
744 break;
745 case GL_RGB_SCALE:
746 if (ctx->Extensions.EXT_texture_env_combine ||
747 ctx->Extensions.ARB_texture_env_combine) {
748 return 1 << texUnit->Combine.ScaleShiftRGB;
749 }
750 else {
751 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
752 }
753 break;
754 case GL_ALPHA_SCALE:
755 if (ctx->Extensions.EXT_texture_env_combine ||
756 ctx->Extensions.ARB_texture_env_combine) {
757 return 1 << texUnit->Combine.ScaleShiftA;
758 }
759 else {
760 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
761 }
762 break;
763 case GL_BUMP_TARGET_ATI:
764 /* spec doesn't say so, but I think this should be queryable */
765 if (ctx->Extensions.ATI_envmap_bumpmap) {
766 return texUnit->BumpTarget;
767 }
768 else {
769 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
770 }
771 break;
772
773 default:
774 ;
775 }
776
777 return -1; /* error */
778 }
779
780
781
782 void GLAPIENTRY
783 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
784 {
785 GLuint maxUnit;
786 const struct gl_texture_unit *texUnit;
787 GET_CURRENT_CONTEXT(ctx);
788 ASSERT_OUTSIDE_BEGIN_END(ctx);
789
790 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
791 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
792 if (ctx->Texture.CurrentUnit >= maxUnit) {
793 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)");
794 return;
795 }
796
797 texUnit = _mesa_get_current_tex_unit(ctx);
798
799 if (target == GL_TEXTURE_ENV) {
800 if (pname == GL_TEXTURE_ENV_COLOR) {
801 COPY_4FV( params, texUnit->EnvColor );
802 }
803 else {
804 GLint val = get_texenvi(ctx, texUnit, pname);
805 if (val >= 0) {
806 *params = (GLfloat) val;
807 }
808 }
809 }
810 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
811 /* GL_EXT_texture_lod_bias */
812 if (!ctx->Extensions.EXT_texture_lod_bias) {
813 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
814 return;
815 }
816 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
817 *params = texUnit->LodBias;
818 }
819 else {
820 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
821 return;
822 }
823 }
824 else if (target == GL_POINT_SPRITE_NV) {
825 /* GL_ARB_point_sprite / GL_NV_point_sprite */
826 if (!ctx->Extensions.NV_point_sprite
827 && !ctx->Extensions.ARB_point_sprite) {
828 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
829 return;
830 }
831 if (pname == GL_COORD_REPLACE_NV) {
832 *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
833 }
834 else {
835 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
836 return;
837 }
838 }
839 else {
840 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
841 return;
842 }
843 }
844
845
846 void GLAPIENTRY
847 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
848 {
849 GLuint maxUnit;
850 const struct gl_texture_unit *texUnit;
851 GET_CURRENT_CONTEXT(ctx);
852 ASSERT_OUTSIDE_BEGIN_END(ctx);
853
854 maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
855 ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits;
856 if (ctx->Texture.CurrentUnit >= maxUnit) {
857 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)");
858 return;
859 }
860
861 texUnit = _mesa_get_current_tex_unit(ctx);
862
863 if (target == GL_TEXTURE_ENV) {
864 if (pname == GL_TEXTURE_ENV_COLOR) {
865 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
866 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
867 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
868 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
869 }
870 else {
871 GLint val = get_texenvi(ctx, texUnit, pname);
872 if (val >= 0) {
873 *params = val;
874 }
875 }
876 }
877 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
878 /* GL_EXT_texture_lod_bias */
879 if (!ctx->Extensions.EXT_texture_lod_bias) {
880 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
881 return;
882 }
883 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
884 *params = (GLint) texUnit->LodBias;
885 }
886 else {
887 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
888 return;
889 }
890 }
891 else if (target == GL_POINT_SPRITE_NV) {
892 /* GL_ARB_point_sprite / GL_NV_point_sprite */
893 if (!ctx->Extensions.NV_point_sprite
894 && !ctx->Extensions.ARB_point_sprite) {
895 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
896 return;
897 }
898 if (pname == GL_COORD_REPLACE_NV) {
899 *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit];
900 }
901 else {
902 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
903 return;
904 }
905 }
906 else {
907 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
908 return;
909 }
910 }
911
912
913 /**
914 * Why does ATI_envmap_bumpmap require new entrypoints? Should just
915 * reuse TexEnv ones...
916 */
917 void GLAPIENTRY
918 _mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
919 {
920 GLfloat p[4];
921 GET_CURRENT_CONTEXT(ctx);
922 ASSERT_OUTSIDE_BEGIN_END(ctx);
923
924 if (!ctx->Extensions.ATI_envmap_bumpmap) {
925 /* This isn't an "official" error case, but let's tell the user
926 * that something's wrong.
927 */
928 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterivATI");
929 return;
930 }
931
932 if (pname == GL_BUMP_ROT_MATRIX_ATI) {
933 /* hope that conversion is correct here */
934 p[0] = INT_TO_FLOAT( param[0] );
935 p[1] = INT_TO_FLOAT( param[1] );
936 p[2] = INT_TO_FLOAT( param[2] );
937 p[3] = INT_TO_FLOAT( param[3] );
938 }
939 else {
940 p[0] = (GLfloat) param[0];
941 p[1] = p[2] = p[3] = 0.0F; /* init to zero, just to be safe */
942 }
943 _mesa_TexBumpParameterfvATI( pname, p );
944 }
945
946
947 void GLAPIENTRY
948 _mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
949 {
950 struct gl_texture_unit *texUnit;
951 GET_CURRENT_CONTEXT(ctx);
952 ASSERT_OUTSIDE_BEGIN_END(ctx);
953
954 if (!ctx->Extensions.ATI_envmap_bumpmap) {
955 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexBumpParameterfvATI");
956 return;
957 }
958
959 texUnit = _mesa_get_current_tex_unit(ctx);
960
961 if (pname == GL_BUMP_ROT_MATRIX_ATI) {
962 if (TEST_EQ_4V(param, texUnit->RotMatrix))
963 return;
964 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
965 COPY_4FV(texUnit->RotMatrix, param);
966 }
967 else {
968 _mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
969 return;
970 }
971 /* Drivers might want to know about this, instead of dedicated function
972 just shove it into TexEnv where it really belongs anyway */
973 if (ctx->Driver.TexEnv) {
974 (*ctx->Driver.TexEnv)( ctx, 0, pname, param );
975 }
976 }
977
978
979 void GLAPIENTRY
980 _mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
981 {
982 const struct gl_texture_unit *texUnit;
983 GLuint i;
984 GET_CURRENT_CONTEXT(ctx);
985 ASSERT_OUTSIDE_BEGIN_END(ctx);
986
987 if (!ctx->Extensions.ATI_envmap_bumpmap) {
988 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterivATI");
989 return;
990 }
991
992 texUnit = _mesa_get_current_tex_unit(ctx);
993
994 if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
995 /* spec leaves open to support larger matrices.
996 Don't think anyone would ever want to use it
997 (and apps almost certainly would not understand it and
998 thus fail to submit matrices correctly) so hardcode this. */
999 *param = 4;
1000 }
1001 else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
1002 /* hope that conversion is correct here */
1003 param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
1004 param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
1005 param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
1006 param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
1007 }
1008 else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
1009 GLint count = 0;
1010 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1011 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1012 count++;
1013 }
1014 }
1015 *param = count;
1016 }
1017 else if (pname == GL_BUMP_TEX_UNITS_ATI) {
1018 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1019 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1020 *param++ = i + GL_TEXTURE0;
1021 }
1022 }
1023 }
1024 else {
1025 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
1026 return;
1027 }
1028 }
1029
1030
1031 void GLAPIENTRY
1032 _mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
1033 {
1034 const struct gl_texture_unit *texUnit;
1035 GLuint i;
1036 GET_CURRENT_CONTEXT(ctx);
1037 ASSERT_OUTSIDE_BEGIN_END(ctx);
1038
1039 if (!ctx->Extensions.ATI_envmap_bumpmap) {
1040 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexBumpParameterfvATI");
1041 return;
1042 }
1043
1044 texUnit = _mesa_get_current_tex_unit(ctx);
1045
1046 if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
1047 /* spec leaves open to support larger matrices.
1048 Don't think anyone would ever want to use it
1049 (and apps might not understand it) so hardcode this. */
1050 *param = 4.0F;
1051 }
1052 else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
1053 param[0] = texUnit->RotMatrix[0];
1054 param[1] = texUnit->RotMatrix[1];
1055 param[2] = texUnit->RotMatrix[2];
1056 param[3] = texUnit->RotMatrix[3];
1057 }
1058 else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
1059 GLint count = 0;
1060 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1061 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1062 count++;
1063 }
1064 }
1065 *param = (GLfloat) count;
1066 }
1067 else if (pname == GL_BUMP_TEX_UNITS_ATI) {
1068 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1069 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1070 *param++ = (GLfloat) (i + GL_TEXTURE0);
1071 }
1072 }
1073 }
1074 else {
1075 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
1076 return;
1077 }
1078 }