Fixed typo
[reactos.git] / dll / opengl / 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 #include <precomp.h>
33
34 #define TE_ERROR(errCode, msg, value) \
35 _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value));
36
37
38 /** Set texture env mode */
39 static void
40 set_env_mode(struct gl_context *ctx,
41 struct gl_texture_unit *texUnit,
42 GLenum mode)
43 {
44 GLboolean legal;
45
46 if (texUnit->EnvMode == mode)
47 return;
48
49 switch (mode) {
50 case GL_MODULATE:
51 case GL_BLEND:
52 case GL_DECAL:
53 case GL_REPLACE:
54 case GL_ADD:
55 case GL_COMBINE:
56 legal = GL_TRUE;
57 break;
58 case GL_REPLACE_EXT:
59 mode = GL_REPLACE; /* GL_REPLACE_EXT != GL_REPLACE */
60 legal = GL_TRUE;
61 break;
62 case GL_COMBINE4_NV:
63 legal = ctx->Extensions.NV_texture_env_combine4;
64 break;
65 default:
66 legal = GL_FALSE;
67 }
68
69 if (legal) {
70 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
71 texUnit->EnvMode = mode;
72 }
73 else {
74 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
75 }
76 }
77
78
79 static void
80 set_env_color(struct gl_context *ctx,
81 struct gl_texture_unit *texUnit,
82 const GLfloat *color)
83 {
84 if (TEST_EQ_4V(color, texUnit->EnvColor))
85 return;
86 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
87 COPY_4FV(texUnit->EnvColor, color);
88 }
89
90
91 /** Set an RGB or A combiner mode/function */
92 static void
93 set_combiner_mode(struct gl_context *ctx,
94 struct gl_texture_unit *texUnit,
95 GLenum pname, GLenum mode)
96 {
97 GLboolean legal;
98
99 switch (mode) {
100 case GL_REPLACE:
101 case GL_MODULATE:
102 case GL_ADD:
103 case GL_ADD_SIGNED:
104 case GL_INTERPOLATE:
105 legal = GL_TRUE;
106 break;
107 case GL_SUBTRACT:
108 legal = ctx->Extensions.ARB_texture_env_combine;
109 break;
110 case GL_DOT3_RGB_EXT:
111 case GL_DOT3_RGBA_EXT:
112 legal = (ctx->Extensions.EXT_texture_env_dot3 &&
113 pname == GL_COMBINE_RGB);
114 break;
115 case GL_DOT3_RGB:
116 case GL_DOT3_RGBA:
117 legal = (ctx->Extensions.ARB_texture_env_dot3 &&
118 pname == GL_COMBINE_RGB);
119 break;
120 case GL_MODULATE_ADD_ATI:
121 case GL_MODULATE_SIGNED_ADD_ATI:
122 case GL_MODULATE_SUBTRACT_ATI:
123 legal = ctx->Extensions.ATI_texture_env_combine3;
124 break;
125 default:
126 legal = GL_FALSE;
127 }
128
129 if (!legal) {
130 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode);
131 return;
132 }
133
134 switch (pname) {
135 case GL_COMBINE_RGB:
136 if (texUnit->Combine.ModeRGB == mode)
137 return;
138 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
139 texUnit->Combine.ModeRGB = mode;
140 break;
141
142 case GL_COMBINE_ALPHA:
143 if (texUnit->Combine.ModeA == mode)
144 return;
145 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
146 texUnit->Combine.ModeA = mode;
147 break;
148 default:
149 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
150 }
151 }
152
153
154
155 /** Set an RGB or A combiner source term */
156 static void
157 set_combiner_source(struct gl_context *ctx,
158 struct gl_texture_unit *texUnit,
159 GLenum pname, GLenum param)
160 {
161 GLuint term;
162 GLboolean alpha, legal;
163
164 /*
165 * Translate pname to (term, alpha).
166 *
167 * The enums were given sequential values for a reason.
168 */
169 switch (pname) {
170 case GL_SOURCE0_RGB:
171 case GL_SOURCE1_RGB:
172 case GL_SOURCE2_RGB:
173 case GL_SOURCE3_RGB_NV:
174 term = pname - GL_SOURCE0_RGB;
175 alpha = GL_FALSE;
176 break;
177 case GL_SOURCE0_ALPHA:
178 case GL_SOURCE1_ALPHA:
179 case GL_SOURCE2_ALPHA:
180 case GL_SOURCE3_ALPHA_NV:
181 term = pname - GL_SOURCE0_ALPHA;
182 alpha = GL_TRUE;
183 break;
184 default:
185 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
186 return;
187 }
188
189 if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) {
190 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
191 return;
192 }
193
194 assert(term < MAX_COMBINER_TERMS);
195
196 /*
197 * Error-check param (the source term)
198 */
199 switch (param) {
200 case GL_TEXTURE:
201 case GL_CONSTANT:
202 case GL_PRIMARY_COLOR:
203 case GL_PREVIOUS:
204 legal = GL_TRUE;
205 break;
206 case GL_ZERO:
207 legal = (ctx->Extensions.ATI_texture_env_combine3 ||
208 ctx->Extensions.NV_texture_env_combine4);
209 break;
210 case GL_ONE:
211 legal = ctx->Extensions.ATI_texture_env_combine3;
212 break;
213 default:
214 legal = GL_FALSE;
215 }
216
217 if (!legal) {
218 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
219 return;
220 }
221
222 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
223
224 if (alpha)
225 texUnit->Combine.SourceA[term] = param;
226 else
227 texUnit->Combine.SourceRGB[term] = param;
228 }
229
230
231 /** Set an RGB or A combiner operand term */
232 static void
233 set_combiner_operand(struct gl_context *ctx,
234 struct gl_texture_unit *texUnit,
235 GLenum pname, GLenum param)
236 {
237 GLuint term;
238 GLboolean alpha, legal;
239
240 /* The enums were given sequential values for a reason.
241 */
242 switch (pname) {
243 case GL_OPERAND0_RGB:
244 case GL_OPERAND1_RGB:
245 case GL_OPERAND2_RGB:
246 case GL_OPERAND3_RGB_NV:
247 term = pname - GL_OPERAND0_RGB;
248 alpha = GL_FALSE;
249 break;
250 case GL_OPERAND0_ALPHA:
251 case GL_OPERAND1_ALPHA:
252 case GL_OPERAND2_ALPHA:
253 case GL_OPERAND3_ALPHA_NV:
254 term = pname - GL_OPERAND0_ALPHA;
255 alpha = GL_TRUE;
256 break;
257 default:
258 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
259 return;
260 }
261
262 if ((term == 3) && !ctx->Extensions.NV_texture_env_combine4) {
263 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
264 return;
265 }
266
267 assert(term < MAX_COMBINER_TERMS);
268
269 /*
270 * Error-check param (the source operand)
271 */
272 switch (param) {
273 case GL_SRC_COLOR:
274 case GL_ONE_MINUS_SRC_COLOR:
275 /* The color input can only be used with GL_OPERAND[01]_RGB in the EXT
276 * version. In the ARB and NV versions they can be used for any RGB
277 * operand.
278 */
279 legal = !alpha
280 && ((term < 2) || ctx->Extensions.ARB_texture_env_combine
281 || ctx->Extensions.NV_texture_env_combine4);
282 break;
283 case GL_ONE_MINUS_SRC_ALPHA:
284 /* GL_ONE_MINUS_SRC_ALPHA can only be used with
285 * GL_OPERAND[01]_(RGB|ALPHA) in the EXT version. In the ARB and NV
286 * versions it can be used for any operand.
287 */
288 legal = (term < 2) || ctx->Extensions.ARB_texture_env_combine
289 || ctx->Extensions.NV_texture_env_combine4;
290 break;
291 case GL_SRC_ALPHA:
292 legal = GL_TRUE;
293 break;
294 default:
295 legal = GL_FALSE;
296 }
297
298 if (!legal) {
299 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", param);
300 return;
301 }
302
303 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
304
305 if (alpha)
306 texUnit->Combine.OperandA[term] = param;
307 else
308 texUnit->Combine.OperandRGB[term] = param;
309 }
310
311
312 static void
313 set_combiner_scale(struct gl_context *ctx,
314 struct gl_texture_unit *texUnit,
315 GLenum pname, GLfloat scale)
316 {
317 GLuint shift;
318
319 if (scale == 1.0F) {
320 shift = 0;
321 }
322 else if (scale == 2.0F) {
323 shift = 1;
324 }
325 else if (scale == 4.0F) {
326 shift = 2;
327 }
328 else {
329 _mesa_error( ctx, GL_INVALID_VALUE,
330 "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" );
331 return;
332 }
333
334 switch (pname) {
335 case GL_RGB_SCALE:
336 if (texUnit->Combine.ScaleShiftRGB == shift)
337 return;
338 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
339 texUnit->Combine.ScaleShiftRGB = shift;
340 break;
341 case GL_ALPHA_SCALE:
342 if (texUnit->Combine.ScaleShiftA == shift)
343 return;
344 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
345 texUnit->Combine.ScaleShiftA = shift;
346 break;
347 default:
348 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
349 }
350 }
351
352
353
354 void GLAPIENTRY
355 _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
356 {
357 const GLint iparam0 = (GLint) param[0];
358 struct gl_texture_unit *texUnit;
359 GET_CURRENT_CONTEXT(ctx);
360 ASSERT_OUTSIDE_BEGIN_END(ctx);
361
362 texUnit = &ctx->Texture.Unit;
363
364 if (target == GL_TEXTURE_ENV) {
365 switch (pname) {
366 case GL_TEXTURE_ENV_MODE:
367 set_env_mode(ctx, texUnit, (GLenum) iparam0);
368 break;
369 case GL_TEXTURE_ENV_COLOR:
370 set_env_color(ctx, texUnit, param);
371 break;
372 case GL_COMBINE_RGB:
373 case GL_COMBINE_ALPHA:
374 set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0);
375 break;
376 case GL_SOURCE0_RGB:
377 case GL_SOURCE1_RGB:
378 case GL_SOURCE2_RGB:
379 case GL_SOURCE3_RGB_NV:
380 case GL_SOURCE0_ALPHA:
381 case GL_SOURCE1_ALPHA:
382 case GL_SOURCE2_ALPHA:
383 case GL_SOURCE3_ALPHA_NV:
384 set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0);
385 break;
386 case GL_OPERAND0_RGB:
387 case GL_OPERAND1_RGB:
388 case GL_OPERAND2_RGB:
389 case GL_OPERAND3_RGB_NV:
390 case GL_OPERAND0_ALPHA:
391 case GL_OPERAND1_ALPHA:
392 case GL_OPERAND2_ALPHA:
393 case GL_OPERAND3_ALPHA_NV:
394 set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0);
395 break;
396 case GL_RGB_SCALE:
397 case GL_ALPHA_SCALE:
398 set_combiner_scale(ctx, texUnit, pname, param[0]);
399 break;
400 default:
401 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
402 return;
403 }
404 }
405 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
406 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
407 if (texUnit->LodBias == param[0])
408 return;
409 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
410 texUnit->LodBias = param[0];
411 }
412 else {
413 TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname);
414 return;
415 }
416 }
417 else {
418 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target );
419 return;
420 }
421
422 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
423 _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n",
424 _mesa_lookup_enum_by_nr(target),
425 _mesa_lookup_enum_by_nr(pname),
426 *param,
427 _mesa_lookup_enum_by_nr((GLenum) iparam0));
428
429 /* Tell device driver about the new texture environment */
430 if (ctx->Driver.TexEnv) {
431 (*ctx->Driver.TexEnv)( ctx, target, pname, param );
432 }
433 }
434
435
436 void GLAPIENTRY
437 _mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param )
438 {
439 GLfloat p[4];
440 p[0] = param;
441 p[1] = p[2] = p[3] = 0.0;
442 _mesa_TexEnvfv( target, pname, p );
443 }
444
445
446
447 void GLAPIENTRY
448 _mesa_TexEnvi( GLenum target, GLenum pname, GLint param )
449 {
450 GLfloat p[4];
451 p[0] = (GLfloat) param;
452 p[1] = p[2] = p[3] = 0.0;
453 _mesa_TexEnvfv( target, pname, p );
454 }
455
456
457 void GLAPIENTRY
458 _mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param )
459 {
460 GLfloat p[4];
461 if (pname == GL_TEXTURE_ENV_COLOR) {
462 p[0] = INT_TO_FLOAT( param[0] );
463 p[1] = INT_TO_FLOAT( param[1] );
464 p[2] = INT_TO_FLOAT( param[2] );
465 p[3] = INT_TO_FLOAT( param[3] );
466 }
467 else {
468 p[0] = (GLfloat) param[0];
469 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
470 }
471 _mesa_TexEnvfv( target, pname, p );
472 }
473
474
475
476 /**
477 * Helper for glGetTexEnvi/f()
478 * \return value of queried pname or -1 if error.
479 */
480 static GLint
481 get_texenvi(struct gl_context *ctx, const struct gl_texture_unit *texUnit,
482 GLenum pname)
483 {
484 switch (pname) {
485 case GL_TEXTURE_ENV_MODE:
486 return texUnit->EnvMode;
487 break;
488 case GL_COMBINE_RGB:
489 return texUnit->Combine.ModeRGB;
490 case GL_COMBINE_ALPHA:
491 return texUnit->Combine.ModeA;
492 case GL_SOURCE0_RGB:
493 case GL_SOURCE1_RGB:
494 case GL_SOURCE2_RGB: {
495 const unsigned rgb_idx = pname - GL_SOURCE0_RGB;
496 return texUnit->Combine.SourceRGB[rgb_idx];
497 }
498 case GL_SOURCE3_RGB_NV:
499 if (ctx->Extensions.NV_texture_env_combine4) {
500 return texUnit->Combine.SourceRGB[3];
501 }
502 else {
503 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
504 }
505 break;
506 case GL_SOURCE0_ALPHA:
507 case GL_SOURCE1_ALPHA:
508 case GL_SOURCE2_ALPHA: {
509 const unsigned alpha_idx = pname - GL_SOURCE0_ALPHA;
510 return texUnit->Combine.SourceA[alpha_idx];
511 }
512 case GL_SOURCE3_ALPHA_NV:
513 if (ctx->Extensions.NV_texture_env_combine4) {
514 return texUnit->Combine.SourceA[3];
515 }
516 else {
517 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
518 }
519 break;
520 case GL_OPERAND0_RGB:
521 case GL_OPERAND1_RGB:
522 case GL_OPERAND2_RGB: {
523 const unsigned op_rgb = pname - GL_OPERAND0_RGB;
524 return texUnit->Combine.OperandRGB[op_rgb];
525 }
526 case GL_OPERAND3_RGB_NV:
527 if (ctx->Extensions.NV_texture_env_combine4) {
528 return texUnit->Combine.OperandRGB[3];
529 }
530 else {
531 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
532 }
533 break;
534 case GL_OPERAND0_ALPHA:
535 case GL_OPERAND1_ALPHA:
536 case GL_OPERAND2_ALPHA: {
537 const unsigned op_alpha = pname - GL_OPERAND0_ALPHA;
538 return texUnit->Combine.OperandA[op_alpha];
539 }
540 case GL_OPERAND3_ALPHA_NV:
541 if (ctx->Extensions.NV_texture_env_combine4) {
542 return texUnit->Combine.OperandA[3];
543 }
544 else {
545 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
546 }
547 break;
548 case GL_RGB_SCALE:
549 return 1 << texUnit->Combine.ScaleShiftRGB;
550 case GL_ALPHA_SCALE:
551 return 1 << texUnit->Combine.ScaleShiftA;
552
553 default:
554 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
555 break;
556 }
557
558 return -1; /* error */
559 }
560
561
562
563 void GLAPIENTRY
564 _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
565 {
566 GET_CURRENT_CONTEXT(ctx);
567 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit;
568 ASSERT_OUTSIDE_BEGIN_END(ctx);
569
570 if (target == GL_TEXTURE_ENV) {
571 if (pname == GL_TEXTURE_ENV_COLOR) {
572 if(ctx->NewState & _NEW_BUFFERS)
573 _mesa_update_state(ctx);
574 COPY_4FV( params, texUnit->EnvColor );
575 }
576 else {
577 GLint val = get_texenvi(ctx, texUnit, pname);
578 if (val >= 0) {
579 *params = (GLfloat) val;
580 }
581 }
582 }
583 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
584 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
585 *params = texUnit->LodBias;
586 }
587 else {
588 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
589 return;
590 }
591 }
592 else {
593 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
594 return;
595 }
596 }
597
598
599 void GLAPIENTRY
600 _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
601 {
602 GET_CURRENT_CONTEXT(ctx);
603 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit;;
604 ASSERT_OUTSIDE_BEGIN_END(ctx);
605
606 if (target == GL_TEXTURE_ENV) {
607 if (pname == GL_TEXTURE_ENV_COLOR) {
608 params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
609 params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
610 params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
611 params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
612 }
613 else {
614 GLint val = get_texenvi(ctx, texUnit, pname);
615 if (val >= 0) {
616 *params = val;
617 }
618 }
619 }
620 else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) {
621 if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
622 *params = (GLint) texUnit->LodBias;
623 }
624 else {
625 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
626 return;
627 }
628 }
629 else {
630 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
631 return;
632 }
633 }
634
635