mesa: simplify texture combine state copying in _mesa_copy_texture_state()
[mesa.git] / src / mesa / main / texstate.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file texstate.c
27 *
28 * Texture state handling.
29 */
30
31 #include "glheader.h"
32 #include "colormac.h"
33 #if FEATURE_colortable
34 #include "colortab.h"
35 #endif
36 #include "context.h"
37 #include "enums.h"
38 #include "macros.h"
39 #include "texcompress.h"
40 #include "texobj.h"
41 #include "teximage.h"
42 #include "texstate.h"
43 #include "texenvprogram.h"
44 #include "mtypes.h"
45
46
47
48 /**
49 * Default texture combine environment state. This is used to initialize
50 * a context's texture units and as the basis for converting "classic"
51 * texture environmnets to ARB_texture_env_combine style values.
52 */
53 static const struct gl_tex_env_combine_state default_combine_state = {
54 GL_MODULATE, GL_MODULATE,
55 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
56 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT, GL_CONSTANT },
57 { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_ALPHA },
58 { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
59 0, 0,
60 2, 2
61 };
62
63
64
65 /**
66 * Used by glXCopyContext to copy texture state from one context to another.
67 */
68 void
69 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
70 {
71 GLuint i, tex;
72
73 ASSERT(src);
74 ASSERT(dst);
75
76 dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
77 dst->Texture._GenFlags = src->Texture._GenFlags;
78 dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
79 dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
80 dst->Texture.SharedPalette = src->Texture.SharedPalette;
81
82 /* per-unit state */
83 for (i = 0; i < src->Const.MaxTextureImageUnits; i++) {
84 dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
85 dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
86 COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
87 dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
88 dst->Texture.Unit[i].GenS = src->Texture.Unit[i].GenS;
89 dst->Texture.Unit[i].GenT = src->Texture.Unit[i].GenT;
90 dst->Texture.Unit[i].GenR = src->Texture.Unit[i].GenR;
91 dst->Texture.Unit[i].GenQ = src->Texture.Unit[i].GenQ;
92 dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
93
94 /* GL_EXT_texture_env_combine */
95 dst->Texture.Unit[i].Combine = src->Texture.Unit[i].Combine;
96
97 /* copy texture object bindings, not contents of texture objects */
98 _mesa_lock_context_textures(dst);
99
100 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
101 _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentTex[tex],
102 src->Texture.Unit[i].CurrentTex[tex]);
103 }
104
105 _mesa_unlock_context_textures(dst);
106 }
107 }
108
109
110 /*
111 * For debugging
112 */
113 void
114 _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
115 {
116 const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
117 _mesa_printf("Texture Unit %d\n", unit);
118 _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
119 _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
120 _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
121 _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
122 _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
123 _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
124 _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
125 _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
126 _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
127 _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
128 _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
129 _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
130 _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
131 _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
132 _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
133 _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
134 _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
135 _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
136 }
137
138
139
140 /**********************************************************************/
141 /* Texture Environment */
142 /**********************************************************************/
143
144 /**
145 * Convert "classic" texture environment to ARB_texture_env_combine style
146 * environments.
147 *
148 * \param state texture_env_combine state vector to be filled-in.
149 * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
150 * \c GL_BLEND, \c GL_DECAL, etc.).
151 * \param texBaseFormat Base format of the texture associated with the
152 * texture unit.
153 */
154 static void
155 calculate_derived_texenv( struct gl_tex_env_combine_state *state,
156 GLenum mode, GLenum texBaseFormat )
157 {
158 GLenum mode_rgb;
159 GLenum mode_a;
160
161 *state = default_combine_state;
162
163 switch (texBaseFormat) {
164 case GL_ALPHA:
165 state->SourceRGB[0] = GL_PREVIOUS;
166 break;
167
168 case GL_LUMINANCE_ALPHA:
169 case GL_INTENSITY:
170 case GL_RGBA:
171 break;
172
173 case GL_LUMINANCE:
174 case GL_RGB:
175 case GL_YCBCR_MESA:
176 state->SourceA[0] = GL_PREVIOUS;
177 break;
178
179 default:
180 _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
181 return;
182 }
183
184 if (mode == GL_REPLACE_EXT)
185 mode = GL_REPLACE;
186
187 switch (mode) {
188 case GL_REPLACE:
189 case GL_MODULATE:
190 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
191 mode_a = mode;
192 break;
193
194 case GL_DECAL:
195 mode_rgb = GL_INTERPOLATE;
196 mode_a = GL_REPLACE;
197
198 state->SourceA[0] = GL_PREVIOUS;
199
200 /* Having alpha / luminance / intensity textures replace using the
201 * incoming fragment color matches the definition in NV_texture_shader.
202 * The 1.5 spec simply marks these as "undefined".
203 */
204 switch (texBaseFormat) {
205 case GL_ALPHA:
206 case GL_LUMINANCE:
207 case GL_LUMINANCE_ALPHA:
208 case GL_INTENSITY:
209 state->SourceRGB[0] = GL_PREVIOUS;
210 break;
211 case GL_RGB:
212 case GL_YCBCR_MESA:
213 mode_rgb = GL_REPLACE;
214 break;
215 case GL_RGBA:
216 state->SourceRGB[2] = GL_TEXTURE;
217 break;
218 }
219 break;
220
221 case GL_BLEND:
222 mode_rgb = GL_INTERPOLATE;
223 mode_a = GL_MODULATE;
224
225 switch (texBaseFormat) {
226 case GL_ALPHA:
227 mode_rgb = GL_REPLACE;
228 break;
229 case GL_INTENSITY:
230 mode_a = GL_INTERPOLATE;
231 state->SourceA[0] = GL_CONSTANT;
232 state->OperandA[2] = GL_SRC_ALPHA;
233 /* FALLTHROUGH */
234 case GL_LUMINANCE:
235 case GL_RGB:
236 case GL_LUMINANCE_ALPHA:
237 case GL_RGBA:
238 case GL_YCBCR_MESA:
239 state->SourceRGB[2] = GL_TEXTURE;
240 state->SourceA[2] = GL_TEXTURE;
241 state->SourceRGB[0] = GL_CONSTANT;
242 state->OperandRGB[2] = GL_SRC_COLOR;
243 break;
244 }
245 break;
246
247 case GL_ADD:
248 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
249 mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
250 break;
251
252 default:
253 _mesa_problem(NULL,
254 "Invalid texture env mode in calculate_derived_texenv");
255 return;
256 }
257
258 state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
259 ? mode_rgb : GL_REPLACE;
260 state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
261 ? mode_a : GL_REPLACE;
262 }
263
264
265
266
267 /* GL_ARB_multitexture */
268 void GLAPIENTRY
269 _mesa_ActiveTextureARB(GLenum texture)
270 {
271 GET_CURRENT_CONTEXT(ctx);
272 const GLuint texUnit = texture - GL_TEXTURE0;
273 ASSERT_OUTSIDE_BEGIN_END(ctx);
274
275 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
276 _mesa_debug(ctx, "glActiveTexture %s\n",
277 _mesa_lookup_enum_by_nr(texture));
278
279 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
280 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
281 return;
282 }
283
284 if (ctx->Texture.CurrentUnit == texUnit)
285 return;
286
287 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
288
289 ctx->Texture.CurrentUnit = texUnit;
290 if (ctx->Transform.MatrixMode == GL_TEXTURE) {
291 /* update current stack pointer */
292 ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
293 }
294
295 if (ctx->Driver.ActiveTexture) {
296 (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
297 }
298 }
299
300
301 /* GL_ARB_multitexture */
302 void GLAPIENTRY
303 _mesa_ClientActiveTextureARB(GLenum texture)
304 {
305 GET_CURRENT_CONTEXT(ctx);
306 GLuint texUnit = texture - GL_TEXTURE0;
307 ASSERT_OUTSIDE_BEGIN_END(ctx);
308
309 if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
310 _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
311 return;
312 }
313
314 FLUSH_VERTICES(ctx, _NEW_ARRAY);
315 ctx->Array.ActiveTexture = texUnit;
316 }
317
318
319
320 /**********************************************************************/
321 /***** State management *****/
322 /**********************************************************************/
323
324
325 /**
326 * \note This routine refers to derived texture attribute values to
327 * compute the ENABLE_TEXMAT flags, but is only called on
328 * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
329 * flags are updated by _mesa_update_textures(), below.
330 *
331 * \param ctx GL context.
332 */
333 static void
334 update_texture_matrices( GLcontext *ctx )
335 {
336 GLuint i;
337
338 ctx->Texture._TexMatEnabled = 0;
339
340 for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) {
341 if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
342 _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
343
344 if (ctx->Texture.Unit[i]._ReallyEnabled &&
345 ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
346 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
347
348 if (ctx->Driver.TextureMatrix)
349 ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
350 }
351 }
352 }
353
354
355 /**
356 * Update texture object's _Function field. We need to do this
357 * whenever any of the texture object's shadow-related fields change
358 * or when we start/stop using a fragment program.
359 *
360 * This function could be expanded someday to update additional per-object
361 * fields that depend on assorted state changes.
362 */
363 static void
364 update_texture_compare_function(GLcontext *ctx,
365 struct gl_texture_object *tObj)
366 {
367 /* XXX temporarily disable this test since it breaks the GLSL
368 * shadow2D(), etc. functions.
369 */
370 if (0 /*ctx->FragmentProgram._Current*/) {
371 /* Texel/coordinate comparison is ignored for programs.
372 * See GL_ARB_fragment_program/shader spec for details.
373 */
374 tObj->_Function = GL_NONE;
375 }
376 else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
377 /* GL_ARB_shadow */
378 tObj->_Function = tObj->CompareFunc;
379 }
380 else {
381 tObj->_Function = GL_NONE; /* pass depth through as grayscale */
382 }
383 }
384
385
386 /**
387 * Helper function for determining which texture object (1D, 2D, cube, etc)
388 * should actually be used.
389 */
390 static void
391 texture_override(GLcontext *ctx,
392 struct gl_texture_unit *texUnit, GLbitfield enableBits,
393 struct gl_texture_object *texObj, GLuint textureBit)
394 {
395 if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
396 if (!texObj->_Complete) {
397 _mesa_test_texobj_completeness(ctx, texObj);
398 }
399 if (texObj->_Complete) {
400 texUnit->_ReallyEnabled = textureBit;
401 texUnit->_Current = texObj;
402 update_texture_compare_function(ctx, texObj);
403 }
404 }
405 }
406
407
408 /**
409 * Examine texture unit's combine/env state to update derived state.
410 */
411 static void
412 update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
413 {
414 /* Set the texUnit->_CurrentCombine field to point to the user's combiner
415 * state, or the combiner state which is derived from traditional texenv
416 * mode.
417 */
418 if (texUnit->EnvMode == GL_COMBINE ||
419 texUnit->EnvMode == GL_COMBINE4_NV) {
420 texUnit->_CurrentCombine = & texUnit->Combine;
421 }
422 else {
423 const struct gl_texture_object *texObj = texUnit->_Current;
424 GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
425 if (format == GL_COLOR_INDEX) {
426 format = GL_RGBA; /* a bit of a hack */
427 }
428 else if (format == GL_DEPTH_COMPONENT ||
429 format == GL_DEPTH_STENCIL_EXT) {
430 format = texObj->DepthMode;
431 }
432 calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
433 texUnit->_CurrentCombine = & texUnit->_EnvMode;
434 }
435
436 /* Determine number of source RGB terms in the combiner function */
437 switch (texUnit->_CurrentCombine->ModeRGB) {
438 case GL_REPLACE:
439 texUnit->_CurrentCombine->_NumArgsRGB = 1;
440 break;
441 case GL_ADD:
442 case GL_ADD_SIGNED:
443 if (texUnit->EnvMode == GL_COMBINE4_NV)
444 texUnit->_CurrentCombine->_NumArgsRGB = 4;
445 else
446 texUnit->_CurrentCombine->_NumArgsRGB = 2;
447 break;
448 case GL_MODULATE:
449 case GL_SUBTRACT:
450 case GL_DOT3_RGB:
451 case GL_DOT3_RGBA:
452 case GL_DOT3_RGB_EXT:
453 case GL_DOT3_RGBA_EXT:
454 texUnit->_CurrentCombine->_NumArgsRGB = 2;
455 break;
456 case GL_INTERPOLATE:
457 case GL_MODULATE_ADD_ATI:
458 case GL_MODULATE_SIGNED_ADD_ATI:
459 case GL_MODULATE_SUBTRACT_ATI:
460 texUnit->_CurrentCombine->_NumArgsRGB = 3;
461 break;
462 default:
463 texUnit->_CurrentCombine->_NumArgsRGB = 0;
464 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
465 return;
466 }
467
468 /* Determine number of source Alpha terms in the combiner function */
469 switch (texUnit->_CurrentCombine->ModeA) {
470 case GL_REPLACE:
471 texUnit->_CurrentCombine->_NumArgsA = 1;
472 break;
473 case GL_ADD:
474 case GL_ADD_SIGNED:
475 if (texUnit->EnvMode == GL_COMBINE4_NV)
476 texUnit->_CurrentCombine->_NumArgsA = 4;
477 else
478 texUnit->_CurrentCombine->_NumArgsA = 2;
479 break;
480 case GL_MODULATE:
481 case GL_SUBTRACT:
482 texUnit->_CurrentCombine->_NumArgsA = 2;
483 break;
484 case GL_INTERPOLATE:
485 case GL_MODULATE_ADD_ATI:
486 case GL_MODULATE_SIGNED_ADD_ATI:
487 case GL_MODULATE_SUBTRACT_ATI:
488 texUnit->_CurrentCombine->_NumArgsA = 3;
489 break;
490 default:
491 texUnit->_CurrentCombine->_NumArgsA = 0;
492 _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
493 break;
494 }
495 }
496
497
498 /**
499 * \note This routine refers to derived texture matrix values to
500 * compute the ENABLE_TEXMAT flags, but is only called on
501 * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
502 * flags are updated by _mesa_update_texture_matrices, above.
503 *
504 * \param ctx GL context.
505 */
506 static void
507 update_texture_state( GLcontext *ctx )
508 {
509 GLuint unit;
510 struct gl_fragment_program *fprog = NULL;
511 struct gl_vertex_program *vprog = NULL;
512
513 if (ctx->Shader.CurrentProgram &&
514 ctx->Shader.CurrentProgram->LinkStatus) {
515 fprog = ctx->Shader.CurrentProgram->FragmentProgram;
516 vprog = ctx->Shader.CurrentProgram->VertexProgram;
517 }
518 else {
519 if (ctx->FragmentProgram._Enabled) {
520 fprog = ctx->FragmentProgram.Current;
521 }
522 if (ctx->VertexProgram._Enabled) {
523 /* XXX enable this if/when non-shader vertex programs get
524 * texture fetches:
525 vprog = ctx->VertexProgram.Current;
526 */
527 }
528 }
529
530 /* TODO: only set this if there are actual changes */
531 ctx->NewState |= _NEW_TEXTURE;
532
533 ctx->Texture._EnabledUnits = 0;
534 ctx->Texture._GenFlags = 0;
535 ctx->Texture._TexMatEnabled = 0;
536 ctx->Texture._TexGenEnabled = 0;
537
538 /*
539 * Update texture unit state.
540 */
541 for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) {
542 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
543 GLbitfield enableBits;
544 GLuint texIndex;
545
546 texUnit->_Current = NULL;
547 texUnit->_ReallyEnabled = 0;
548 texUnit->_GenFlags = 0;
549
550 /* Get the bitmask of texture target enables.
551 * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
552 * which texture targets are enabled (fixed function) or referenced
553 * by a fragment shader/program. When multiple flags are set, we'll
554 * settle on the one with highest priority (see texture_override below).
555 */
556 enableBits = 0x0;
557 if (vprog) {
558 enableBits |= vprog->Base.TexturesUsed[unit];
559 }
560 if (fprog) {
561 enableBits |= fprog->Base.TexturesUsed[unit];
562 }
563 else {
564 /* fixed-function fragment program */
565 enableBits |= texUnit->Enabled;
566 }
567
568 if (enableBits == 0x0)
569 continue;
570
571 /* Look for the highest-priority texture target that's enabled and
572 * complete. That's the one we'll use for texturing. If we're using
573 * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
574 * Note that the TEXTURE_x_INDEX values are in high to low priority.
575 */
576 for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) {
577 texture_override(ctx, texUnit, enableBits,
578 texUnit->CurrentTex[texIndex], 1 << texIndex);
579 }
580
581 if (!texUnit->_ReallyEnabled) {
582 continue;
583 }
584
585 /* if we get here, we know this texture unit is enabled */
586
587 ctx->Texture._EnabledUnits |= (1 << unit);
588
589 update_tex_combine(ctx, texUnit);
590 }
591
592
593 /* Determine which texture coordinate sets are actually needed */
594 if (fprog) {
595 const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
596 ctx->Texture._EnabledCoordUnits
597 = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
598 }
599 else {
600 ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
601 }
602
603 /* Setup texgen for those texture coordinate sets that are in use */
604 for (unit = 0; unit < ctx->Const.MaxTextureCoordUnits; unit++) {
605 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
606
607 if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
608 continue;
609
610 if (texUnit->TexGenEnabled) {
611 if (texUnit->TexGenEnabled & S_BIT) {
612 texUnit->_GenFlags |= texUnit->GenS._ModeBit;
613 }
614 if (texUnit->TexGenEnabled & T_BIT) {
615 texUnit->_GenFlags |= texUnit->GenT._ModeBit;
616 }
617 if (texUnit->TexGenEnabled & R_BIT) {
618 texUnit->_GenFlags |= texUnit->GenR._ModeBit;
619 }
620 if (texUnit->TexGenEnabled & Q_BIT) {
621 texUnit->_GenFlags |= texUnit->GenQ._ModeBit;
622 }
623
624 ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
625 ctx->Texture._GenFlags |= texUnit->_GenFlags;
626 }
627
628 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
629 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
630 }
631 }
632
633
634 /**
635 * Update texture-related derived state.
636 */
637 void
638 _mesa_update_texture( GLcontext *ctx, GLuint new_state )
639 {
640 if (new_state & _NEW_TEXTURE_MATRIX)
641 update_texture_matrices( ctx );
642
643 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
644 update_texture_state( ctx );
645 }
646
647
648 /**********************************************************************/
649 /***** Initialization *****/
650 /**********************************************************************/
651
652 /**
653 * Allocate the proxy textures for the given context.
654 *
655 * \param ctx the context to allocate proxies for.
656 *
657 * \return GL_TRUE on success, or GL_FALSE on failure
658 *
659 * If run out of memory part way through the allocations, clean up and return
660 * GL_FALSE.
661 */
662 static GLboolean
663 alloc_proxy_textures( GLcontext *ctx )
664 {
665 static const GLenum targets[] = {
666 GL_TEXTURE_1D,
667 GL_TEXTURE_2D,
668 GL_TEXTURE_3D,
669 GL_TEXTURE_CUBE_MAP_ARB,
670 GL_TEXTURE_RECTANGLE_NV,
671 GL_TEXTURE_1D_ARRAY_EXT,
672 GL_TEXTURE_2D_ARRAY_EXT
673 };
674 GLint tgt;
675
676 ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
677
678 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
679 if (!(ctx->Texture.ProxyTex[tgt]
680 = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
681 /* out of memory, free what we did allocate */
682 while (--tgt >= 0) {
683 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
684 }
685 return GL_FALSE;
686 }
687 }
688
689 assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
690 return GL_TRUE;
691 }
692
693
694 /**
695 * Initialize a texture unit.
696 *
697 * \param ctx GL context.
698 * \param unit texture unit number to be initialized.
699 */
700 static void
701 init_texture_unit( GLcontext *ctx, GLuint unit )
702 {
703 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
704 GLuint tex;
705
706 texUnit->EnvMode = GL_MODULATE;
707 ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
708
709 texUnit->Combine = default_combine_state;
710 texUnit->_EnvMode = default_combine_state;
711 texUnit->_CurrentCombine = & texUnit->_EnvMode;
712
713 texUnit->TexGenEnabled = 0;
714 texUnit->GenS.Mode = GL_EYE_LINEAR;
715 texUnit->GenT.Mode = GL_EYE_LINEAR;
716 texUnit->GenR.Mode = GL_EYE_LINEAR;
717 texUnit->GenQ.Mode = GL_EYE_LINEAR;
718 texUnit->GenS._ModeBit = TEXGEN_EYE_LINEAR;
719 texUnit->GenT._ModeBit = TEXGEN_EYE_LINEAR;
720 texUnit->GenR._ModeBit = TEXGEN_EYE_LINEAR;
721 texUnit->GenQ._ModeBit = TEXGEN_EYE_LINEAR;
722
723 /* Yes, these plane coefficients are correct! */
724 ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
725 ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
726 ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
727 ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
728 ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
729 ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
730 ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
731 ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
732
733 /* initialize current texture object ptrs to the shared default objects */
734 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
735 _mesa_reference_texobj(&texUnit->CurrentTex[tex],
736 ctx->Shared->DefaultTex[tex]);
737 }
738 }
739
740
741 /**
742 * Initialize texture state for the given context.
743 */
744 GLboolean
745 _mesa_init_texture(GLcontext *ctx)
746 {
747 GLuint i;
748
749 /* Texture group */
750 ctx->Texture.CurrentUnit = 0; /* multitexture */
751 ctx->Texture._EnabledUnits = 0;
752 ctx->Texture.SharedPalette = GL_FALSE;
753 #if FEATURE_colortable
754 _mesa_init_colortable(&ctx->Texture.Palette);
755 #endif
756
757 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
758 init_texture_unit( ctx, i );
759
760 /* After we're done initializing the context's texture state the default
761 * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
762 */
763 assert(ctx->Shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount
764 >= MAX_TEXTURE_UNITS + 1);
765
766 /* Allocate proxy textures */
767 if (!alloc_proxy_textures( ctx ))
768 return GL_FALSE;
769
770 return GL_TRUE;
771 }
772
773
774 /**
775 * Free dynamically-allocted texture data attached to the given context.
776 */
777 void
778 _mesa_free_texture_data(GLcontext *ctx)
779 {
780 GLuint u, tgt;
781
782 /* unreference current textures */
783 for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
784 struct gl_texture_unit *unit = ctx->Texture.Unit + u;
785 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
786 _mesa_reference_texobj(&unit->CurrentTex[tgt], NULL);
787 }
788 }
789
790 /* Free proxy texture objects */
791 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
792 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
793
794 #if FEATURE_colortable
795 {
796 GLuint i;
797 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
798 _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
799 }
800 #endif
801 }
802
803
804 /**
805 * Update the default texture objects in the given context to reference those
806 * specified in the shared state and release those referencing the old
807 * shared state.
808 */
809 void
810 _mesa_update_default_objects_texture(GLcontext *ctx)
811 {
812 GLuint i, tex;
813
814 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
815 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
816 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
817 _mesa_reference_texobj(&texUnit->CurrentTex[tex],
818 ctx->Shared->DefaultTex[tex]);
819 }
820 }
821 }