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