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