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