Drop GLcontext typedef and use struct gl_context instead
[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(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 }