mesa: refactor: move glTexEnv-related functions into new texenv.c file
[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 #include "math/m_xform.h"
46
47
48 #define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
49 #define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
50
51
52 /**
53 * Default texture combine environment state. This is used to initialize
54 * a context's texture units and as the basis for converting "classic"
55 * texture environmnets to ARB_texture_env_combine style values.
56 */
57 static const struct gl_tex_env_combine_state default_combine_state = {
58 GL_MODULATE, GL_MODULATE,
59 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
60 { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT },
61 { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA },
62 { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
63 0, 0,
64 2, 2
65 };
66
67
68
69 /**
70 * Used by glXCopyContext to copy texture state from one context to another.
71 */
72 void
73 _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
74 {
75 GLuint i;
76
77 ASSERT(src);
78 ASSERT(dst);
79
80 dst->Texture.CurrentUnit = src->Texture.CurrentUnit;
81 dst->Texture._GenFlags = src->Texture._GenFlags;
82 dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled;
83 dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled;
84 dst->Texture.SharedPalette = src->Texture.SharedPalette;
85
86 /* per-unit state */
87 for (i = 0; i < src->Const.MaxTextureUnits; i++) {
88 dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled;
89 dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode;
90 COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor);
91 dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled;
92 dst->Texture.Unit[i].GenModeS = src->Texture.Unit[i].GenModeS;
93 dst->Texture.Unit[i].GenModeT = src->Texture.Unit[i].GenModeT;
94 dst->Texture.Unit[i].GenModeR = src->Texture.Unit[i].GenModeR;
95 dst->Texture.Unit[i].GenModeQ = src->Texture.Unit[i].GenModeQ;
96 dst->Texture.Unit[i]._GenBitS = src->Texture.Unit[i]._GenBitS;
97 dst->Texture.Unit[i]._GenBitT = src->Texture.Unit[i]._GenBitT;
98 dst->Texture.Unit[i]._GenBitR = src->Texture.Unit[i]._GenBitR;
99 dst->Texture.Unit[i]._GenBitQ = src->Texture.Unit[i]._GenBitQ;
100 dst->Texture.Unit[i]._GenFlags = src->Texture.Unit[i]._GenFlags;
101 COPY_4V(dst->Texture.Unit[i].ObjectPlaneS, src->Texture.Unit[i].ObjectPlaneS);
102 COPY_4V(dst->Texture.Unit[i].ObjectPlaneT, src->Texture.Unit[i].ObjectPlaneT);
103 COPY_4V(dst->Texture.Unit[i].ObjectPlaneR, src->Texture.Unit[i].ObjectPlaneR);
104 COPY_4V(dst->Texture.Unit[i].ObjectPlaneQ, src->Texture.Unit[i].ObjectPlaneQ);
105 COPY_4V(dst->Texture.Unit[i].EyePlaneS, src->Texture.Unit[i].EyePlaneS);
106 COPY_4V(dst->Texture.Unit[i].EyePlaneT, src->Texture.Unit[i].EyePlaneT);
107 COPY_4V(dst->Texture.Unit[i].EyePlaneR, src->Texture.Unit[i].EyePlaneR);
108 COPY_4V(dst->Texture.Unit[i].EyePlaneQ, src->Texture.Unit[i].EyePlaneQ);
109 dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias;
110
111 /* GL_EXT_texture_env_combine */
112 dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB;
113 dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA;
114 COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB);
115 COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA);
116 COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB);
117 COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA);
118 dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB;
119 dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA;
120
121 /* copy texture object bindings, not contents of texture objects */
122 _mesa_lock_context_textures(dst);
123
124 _mesa_reference_texobj(&dst->Texture.Unit[i].Current1D,
125 src->Texture.Unit[i].Current1D);
126 _mesa_reference_texobj(&dst->Texture.Unit[i].Current2D,
127 src->Texture.Unit[i].Current2D);
128 _mesa_reference_texobj(&dst->Texture.Unit[i].Current3D,
129 src->Texture.Unit[i].Current3D);
130 _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentCubeMap,
131 src->Texture.Unit[i].CurrentCubeMap);
132 _mesa_reference_texobj(&dst->Texture.Unit[i].CurrentRect,
133 src->Texture.Unit[i].CurrentRect);
134 _mesa_reference_texobj(&dst->Texture.Unit[i].Current1DArray,
135 src->Texture.Unit[i].Current1DArray);
136 _mesa_reference_texobj(&dst->Texture.Unit[i].Current2DArray,
137 src->Texture.Unit[i].Current2DArray);
138
139 _mesa_unlock_context_textures(dst);
140 }
141 }
142
143
144 /*
145 * For debugging
146 */
147 void
148 _mesa_print_texunit_state( GLcontext *ctx, GLuint unit )
149 {
150 const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit;
151 _mesa_printf("Texture Unit %d\n", unit);
152 _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
153 _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
154 _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
155 _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
156 _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
157 _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
158 _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
159 _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
160 _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
161 _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
162 _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
163 _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
164 _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
165 _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
166 _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
167 _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
168 _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
169 _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]);
170 }
171
172
173
174 /**********************************************************************/
175 /* Texture Environment */
176 /**********************************************************************/
177
178 /**
179 * Convert "classic" texture environment to ARB_texture_env_combine style
180 * environments.
181 *
182 * \param state texture_env_combine state vector to be filled-in.
183 * \param mode Classic texture environment mode (i.e., \c GL_REPLACE,
184 * \c GL_BLEND, \c GL_DECAL, etc.).
185 * \param texBaseFormat Base format of the texture associated with the
186 * texture unit.
187 */
188 static void
189 calculate_derived_texenv( struct gl_tex_env_combine_state *state,
190 GLenum mode, GLenum texBaseFormat )
191 {
192 GLenum mode_rgb;
193 GLenum mode_a;
194
195 *state = default_combine_state;
196
197 switch (texBaseFormat) {
198 case GL_ALPHA:
199 state->SourceRGB[0] = GL_PREVIOUS;
200 break;
201
202 case GL_LUMINANCE_ALPHA:
203 case GL_INTENSITY:
204 case GL_RGBA:
205 break;
206
207 case GL_LUMINANCE:
208 case GL_RGB:
209 case GL_YCBCR_MESA:
210 state->SourceA[0] = GL_PREVIOUS;
211 break;
212
213 default:
214 _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv");
215 return;
216 }
217
218 if (mode == GL_REPLACE_EXT)
219 mode = GL_REPLACE;
220
221 switch (mode) {
222 case GL_REPLACE:
223 case GL_MODULATE:
224 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode;
225 mode_a = mode;
226 break;
227
228 case GL_DECAL:
229 mode_rgb = GL_INTERPOLATE;
230 mode_a = GL_REPLACE;
231
232 state->SourceA[0] = GL_PREVIOUS;
233
234 /* Having alpha / luminance / intensity textures replace using the
235 * incoming fragment color matches the definition in NV_texture_shader.
236 * The 1.5 spec simply marks these as "undefined".
237 */
238 switch (texBaseFormat) {
239 case GL_ALPHA:
240 case GL_LUMINANCE:
241 case GL_LUMINANCE_ALPHA:
242 case GL_INTENSITY:
243 state->SourceRGB[0] = GL_PREVIOUS;
244 break;
245 case GL_RGB:
246 case GL_YCBCR_MESA:
247 mode_rgb = GL_REPLACE;
248 break;
249 case GL_RGBA:
250 state->SourceRGB[2] = GL_TEXTURE;
251 break;
252 }
253 break;
254
255 case GL_BLEND:
256 mode_rgb = GL_INTERPOLATE;
257 mode_a = GL_MODULATE;
258
259 switch (texBaseFormat) {
260 case GL_ALPHA:
261 mode_rgb = GL_REPLACE;
262 break;
263 case GL_INTENSITY:
264 mode_a = GL_INTERPOLATE;
265 state->SourceA[0] = GL_CONSTANT;
266 state->OperandA[2] = GL_SRC_ALPHA;
267 /* FALLTHROUGH */
268 case GL_LUMINANCE:
269 case GL_RGB:
270 case GL_LUMINANCE_ALPHA:
271 case GL_RGBA:
272 case GL_YCBCR_MESA:
273 state->SourceRGB[2] = GL_TEXTURE;
274 state->SourceA[2] = GL_TEXTURE;
275 state->SourceRGB[0] = GL_CONSTANT;
276 state->OperandRGB[2] = GL_SRC_COLOR;
277 break;
278 }
279 break;
280
281 case GL_ADD:
282 mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD;
283 mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE;
284 break;
285
286 default:
287 _mesa_problem(NULL,
288 "Invalid texture env mode in calculate_derived_texenv");
289 return;
290 }
291
292 state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS)
293 ? mode_rgb : GL_REPLACE;
294 state->ModeA = (state->SourceA[0] != GL_PREVIOUS)
295 ? mode_a : GL_REPLACE;
296 }
297
298
299 /**********************************************************************/
300 /* Texture Parameters */
301 /**********************************************************************/
302
303 /**
304 * Check if a coordinate wrap mode is supported for the texture target.
305 * \return GL_TRUE if legal, GL_FALSE otherwise
306 */
307 static GLboolean
308 validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
309 {
310 const struct gl_extensions * const e = & ctx->Extensions;
311
312 if (wrap == GL_CLAMP || wrap == GL_CLAMP_TO_EDGE ||
313 (wrap == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) {
314 /* any texture target */
315 return GL_TRUE;
316 }
317 else if (target != GL_TEXTURE_RECTANGLE_NV &&
318 (wrap == GL_REPEAT ||
319 (wrap == GL_MIRRORED_REPEAT &&
320 e->ARB_texture_mirrored_repeat) ||
321 (wrap == GL_MIRROR_CLAMP_EXT &&
322 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
323 (wrap == GL_MIRROR_CLAMP_TO_EDGE_EXT &&
324 (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) ||
325 (wrap == GL_MIRROR_CLAMP_TO_BORDER_EXT &&
326 (e->EXT_texture_mirror_clamp)))) {
327 /* non-rectangle texture */
328 return GL_TRUE;
329 }
330
331 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
332 return GL_FALSE;
333 }
334
335
336 void GLAPIENTRY
337 _mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param )
338 {
339 _mesa_TexParameterfv(target, pname, &param);
340 }
341
342
343 void GLAPIENTRY
344 _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params )
345 {
346 const GLenum eparam = (GLenum) (GLint) params[0];
347 struct gl_texture_unit *texUnit;
348 struct gl_texture_object *texObj;
349 GET_CURRENT_CONTEXT(ctx);
350 ASSERT_OUTSIDE_BEGIN_END(ctx);
351
352 if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
353 _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n",
354 _mesa_lookup_enum_by_nr(target),
355 _mesa_lookup_enum_by_nr(pname),
356 *params,
357 _mesa_lookup_enum_by_nr(eparam));
358
359 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
360 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameterfv(current unit)");
361 return;
362 }
363
364 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
365
366 switch (target) {
367 case GL_TEXTURE_1D:
368 texObj = texUnit->Current1D;
369 break;
370 case GL_TEXTURE_2D:
371 texObj = texUnit->Current2D;
372 break;
373 case GL_TEXTURE_3D:
374 texObj = texUnit->Current3D;
375 break;
376 case GL_TEXTURE_CUBE_MAP:
377 if (!ctx->Extensions.ARB_texture_cube_map) {
378 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
379 return;
380 }
381 texObj = texUnit->CurrentCubeMap;
382 break;
383 case GL_TEXTURE_RECTANGLE_NV:
384 if (!ctx->Extensions.NV_texture_rectangle) {
385 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
386 return;
387 }
388 texObj = texUnit->CurrentRect;
389 break;
390 case GL_TEXTURE_1D_ARRAY_EXT:
391 if (!ctx->Extensions.MESA_texture_array) {
392 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
393 return;
394 }
395 texObj = texUnit->Current1DArray;
396 break;
397 case GL_TEXTURE_2D_ARRAY_EXT:
398 if (!ctx->Extensions.MESA_texture_array) {
399 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
400 return;
401 }
402 texObj = texUnit->Current2DArray;
403 break;
404 default:
405 _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
406 return;
407 }
408
409 switch (pname) {
410 case GL_TEXTURE_MIN_FILTER:
411 /* A small optimization */
412 if (texObj->MinFilter == eparam)
413 return;
414 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
415 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
416 texObj->MinFilter = eparam;
417 }
418 else if ((eparam==GL_NEAREST_MIPMAP_NEAREST ||
419 eparam==GL_LINEAR_MIPMAP_NEAREST ||
420 eparam==GL_NEAREST_MIPMAP_LINEAR ||
421 eparam==GL_LINEAR_MIPMAP_LINEAR) &&
422 texObj->Target != GL_TEXTURE_RECTANGLE_NV) {
423 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
424 texObj->MinFilter = eparam;
425 }
426 else {
427 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
428 return;
429 }
430 break;
431 case GL_TEXTURE_MAG_FILTER:
432 /* A small optimization */
433 if (texObj->MagFilter == eparam)
434 return;
435
436 if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
437 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
438 texObj->MagFilter = eparam;
439 }
440 else {
441 _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
442 return;
443 }
444 break;
445 case GL_TEXTURE_WRAP_S:
446 if (texObj->WrapS == eparam)
447 return;
448 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
449 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
450 texObj->WrapS = eparam;
451 }
452 else {
453 return;
454 }
455 break;
456 case GL_TEXTURE_WRAP_T:
457 if (texObj->WrapT == eparam)
458 return;
459 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
460 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
461 texObj->WrapT = eparam;
462 }
463 else {
464 return;
465 }
466 break;
467 case GL_TEXTURE_WRAP_R:
468 if (texObj->WrapR == eparam)
469 return;
470 if (validate_texture_wrap_mode(ctx, texObj->Target, eparam)) {
471 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
472 texObj->WrapR = eparam;
473 }
474 else {
475 return;
476 }
477 break;
478 case GL_TEXTURE_BORDER_COLOR:
479 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
480 texObj->BorderColor[RCOMP] = params[0];
481 texObj->BorderColor[GCOMP] = params[1];
482 texObj->BorderColor[BCOMP] = params[2];
483 texObj->BorderColor[ACOMP] = params[3];
484 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]);
485 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]);
486 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]);
487 UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]);
488 break;
489 case GL_TEXTURE_MIN_LOD:
490 if (texObj->MinLod == params[0])
491 return;
492 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
493 texObj->MinLod = params[0];
494 break;
495 case GL_TEXTURE_MAX_LOD:
496 if (texObj->MaxLod == params[0])
497 return;
498 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
499 texObj->MaxLod = params[0];
500 break;
501 case GL_TEXTURE_BASE_LEVEL:
502 if (params[0] < 0.0) {
503 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
504 return;
505 }
506 if (target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0.0) {
507 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
508 return;
509 }
510 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
511 texObj->BaseLevel = (GLint) params[0];
512 break;
513 case GL_TEXTURE_MAX_LEVEL:
514 if (params[0] < 0.0) {
515 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
516 return;
517 }
518 if (target == GL_TEXTURE_RECTANGLE_ARB) {
519 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
520 return;
521 }
522 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
523 texObj->MaxLevel = (GLint) params[0];
524 break;
525 case GL_TEXTURE_PRIORITY:
526 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
527 texObj->Priority = CLAMP( params[0], 0.0F, 1.0F );
528 break;
529 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
530 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
531 if (params[0] < 1.0) {
532 _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
533 return;
534 }
535 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
536 /* clamp to max, that's what NVIDIA does */
537 texObj->MaxAnisotropy = MIN2(params[0],
538 ctx->Const.MaxTextureMaxAnisotropy);
539 }
540 else {
541 _mesa_error(ctx, GL_INVALID_ENUM,
542 "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
543 return;
544 }
545 break;
546 case GL_TEXTURE_COMPARE_SGIX:
547 if (ctx->Extensions.SGIX_shadow) {
548 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
549 texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE;
550 }
551 else {
552 _mesa_error(ctx, GL_INVALID_ENUM,
553 "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)");
554 return;
555 }
556 break;
557 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
558 if (ctx->Extensions.SGIX_shadow) {
559 GLenum op = (GLenum) params[0];
560 if (op == GL_TEXTURE_LEQUAL_R_SGIX ||
561 op == GL_TEXTURE_GEQUAL_R_SGIX) {
562 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
563 texObj->CompareOperator = op;
564 }
565 else {
566 _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
567 }
568 }
569 else {
570 _mesa_error(ctx, GL_INVALID_ENUM,
571 "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)");
572 return;
573 }
574 break;
575 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
576 if (ctx->Extensions.SGIX_shadow_ambient) {
577 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
578 texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F);
579 }
580 else {
581 _mesa_error(ctx, GL_INVALID_ENUM,
582 "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)");
583 return;
584 }
585 break;
586 case GL_GENERATE_MIPMAP_SGIS:
587 if (ctx->Extensions.SGIS_generate_mipmap) {
588 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
589 texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE;
590 }
591 else {
592 _mesa_error(ctx, GL_INVALID_ENUM,
593 "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)");
594 return;
595 }
596 break;
597 case GL_TEXTURE_COMPARE_MODE_ARB:
598 if (ctx->Extensions.ARB_shadow) {
599 const GLenum mode = (GLenum) params[0];
600 if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) {
601 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
602 texObj->CompareMode = mode;
603 }
604 else {
605 _mesa_error(ctx, GL_INVALID_ENUM,
606 "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode);
607 return;
608 }
609 }
610 else {
611 _mesa_error(ctx, GL_INVALID_ENUM,
612 "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)");
613 return;
614 }
615 break;
616 case GL_TEXTURE_COMPARE_FUNC_ARB:
617 if (ctx->Extensions.ARB_shadow) {
618 const GLenum func = (GLenum) params[0];
619 if (func == GL_LEQUAL || func == GL_GEQUAL) {
620 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
621 texObj->CompareFunc = func;
622 }
623 else if (ctx->Extensions.EXT_shadow_funcs &&
624 (func == GL_EQUAL ||
625 func == GL_NOTEQUAL ||
626 func == GL_LESS ||
627 func == GL_GREATER ||
628 func == GL_ALWAYS ||
629 func == GL_NEVER)) {
630 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
631 texObj->CompareFunc = func;
632 }
633 else {
634 _mesa_error(ctx, GL_INVALID_ENUM,
635 "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)");
636 return;
637 }
638 }
639 else {
640 _mesa_error(ctx, GL_INVALID_ENUM,
641 "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)");
642 return;
643 }
644 break;
645 case GL_DEPTH_TEXTURE_MODE_ARB:
646 if (ctx->Extensions.ARB_depth_texture) {
647 const GLenum result = (GLenum) params[0];
648 if (result == GL_LUMINANCE || result == GL_INTENSITY
649 || result == GL_ALPHA) {
650 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
651 texObj->DepthMode = result;
652 }
653 else {
654 _mesa_error(ctx, GL_INVALID_ENUM,
655 "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)");
656 return;
657 }
658 }
659 else {
660 _mesa_error(ctx, GL_INVALID_ENUM,
661 "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)");
662 return;
663 }
664 break;
665 case GL_TEXTURE_LOD_BIAS:
666 /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/
667 if (ctx->Extensions.EXT_texture_lod_bias) {
668 if (texObj->LodBias != params[0]) {
669 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
670 texObj->LodBias = params[0];
671 }
672 }
673 break;
674
675 default:
676 _mesa_error(ctx, GL_INVALID_ENUM,
677 "glTexParameter(pname=0x%x)", pname);
678 return;
679 }
680
681 texObj->_Complete = GL_FALSE;
682
683 if (ctx->Driver.TexParameter) {
684 (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
685 }
686 }
687
688
689 void GLAPIENTRY
690 _mesa_TexParameteri( GLenum target, GLenum pname, GLint param )
691 {
692 GLfloat fparam[4];
693 if (pname == GL_TEXTURE_PRIORITY)
694 fparam[0] = INT_TO_FLOAT(param);
695 else
696 fparam[0] = (GLfloat) param;
697 fparam[1] = fparam[2] = fparam[3] = 0.0;
698 _mesa_TexParameterfv(target, pname, fparam);
699 }
700
701
702 void GLAPIENTRY
703 _mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params )
704 {
705 GLfloat fparam[4];
706 if (pname == GL_TEXTURE_BORDER_COLOR) {
707 fparam[0] = INT_TO_FLOAT(params[0]);
708 fparam[1] = INT_TO_FLOAT(params[1]);
709 fparam[2] = INT_TO_FLOAT(params[2]);
710 fparam[3] = INT_TO_FLOAT(params[3]);
711 }
712 else {
713 if (pname == GL_TEXTURE_PRIORITY)
714 fparam[0] = INT_TO_FLOAT(params[0]);
715 else
716 fparam[0] = (GLfloat) params[0];
717 fparam[1] = fparam[2] = fparam[3] = 0.0F;
718 }
719 _mesa_TexParameterfv(target, pname, fparam);
720 }
721
722
723 void GLAPIENTRY
724 _mesa_GetTexLevelParameterfv( GLenum target, GLint level,
725 GLenum pname, GLfloat *params )
726 {
727 GLint iparam;
728 _mesa_GetTexLevelParameteriv( target, level, pname, &iparam );
729 *params = (GLfloat) iparam;
730 }
731
732
733 static GLuint
734 tex_image_dimensions(GLcontext *ctx, GLenum target)
735 {
736 switch (target) {
737 case GL_TEXTURE_1D:
738 case GL_PROXY_TEXTURE_1D:
739 return 1;
740 case GL_TEXTURE_2D:
741 case GL_PROXY_TEXTURE_2D:
742 return 2;
743 case GL_TEXTURE_3D:
744 case GL_PROXY_TEXTURE_3D:
745 return 3;
746 case GL_TEXTURE_CUBE_MAP:
747 case GL_PROXY_TEXTURE_CUBE_MAP:
748 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
749 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
750 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
751 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
752 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
753 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
754 return ctx->Extensions.ARB_texture_cube_map ? 2 : 0;
755 case GL_TEXTURE_RECTANGLE_NV:
756 case GL_PROXY_TEXTURE_RECTANGLE_NV:
757 return ctx->Extensions.NV_texture_rectangle ? 2 : 0;
758 case GL_TEXTURE_1D_ARRAY_EXT:
759 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
760 return ctx->Extensions.MESA_texture_array ? 2 : 0;
761 case GL_TEXTURE_2D_ARRAY_EXT:
762 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
763 return ctx->Extensions.MESA_texture_array ? 3 : 0;
764 default:
765 _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()");
766 return 0;
767 }
768 }
769
770
771 void GLAPIENTRY
772 _mesa_GetTexLevelParameteriv( GLenum target, GLint level,
773 GLenum pname, GLint *params )
774 {
775 const struct gl_texture_unit *texUnit;
776 struct gl_texture_object *texObj;
777 const struct gl_texture_image *img = NULL;
778 GLuint dimensions;
779 GLboolean isProxy;
780 GLint maxLevels;
781 GET_CURRENT_CONTEXT(ctx);
782 ASSERT_OUTSIDE_BEGIN_END(ctx);
783
784 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
785 _mesa_error(ctx, GL_INVALID_OPERATION,
786 "glGetTexLevelParameteriv(current unit)");
787 return;
788 }
789
790 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
791
792 /* this will catch bad target values */
793 dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */
794 if (dimensions == 0) {
795 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
796 return;
797 }
798
799 maxLevels = _mesa_max_texture_levels(ctx, target);
800 if (maxLevels == 0) {
801 /* should not happen since <target> was just checked above */
802 _mesa_problem(ctx, "maxLevels=0 in _mesa_GetTexLevelParameter");
803 return;
804 }
805
806 if (level < 0 || level >= maxLevels) {
807 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
808 return;
809 }
810
811 texObj = _mesa_select_tex_object(ctx, texUnit, target);
812 _mesa_lock_texture(ctx, texObj);
813
814 img = _mesa_select_tex_image(ctx, texObj, target, level);
815 if (!img || !img->TexFormat) {
816 /* undefined texture image */
817 if (pname == GL_TEXTURE_COMPONENTS)
818 *params = 1;
819 else
820 *params = 0;
821 goto out;
822 }
823
824 isProxy = _mesa_is_proxy_texture(target);
825
826 switch (pname) {
827 case GL_TEXTURE_WIDTH:
828 *params = img->Width;
829 break;
830 case GL_TEXTURE_HEIGHT:
831 *params = img->Height;
832 break;
833 case GL_TEXTURE_DEPTH:
834 *params = img->Depth;
835 break;
836 case GL_TEXTURE_INTERNAL_FORMAT:
837 *params = img->InternalFormat;
838 break;
839 case GL_TEXTURE_BORDER:
840 *params = img->Border;
841 break;
842 case GL_TEXTURE_RED_SIZE:
843 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
844 *params = img->TexFormat->RedBits;
845 else
846 *params = 0;
847 break;
848 case GL_TEXTURE_GREEN_SIZE:
849 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
850 *params = img->TexFormat->GreenBits;
851 else
852 *params = 0;
853 break;
854 case GL_TEXTURE_BLUE_SIZE:
855 if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
856 *params = img->TexFormat->BlueBits;
857 else
858 *params = 0;
859 break;
860 case GL_TEXTURE_ALPHA_SIZE:
861 if (img->_BaseFormat == GL_ALPHA ||
862 img->_BaseFormat == GL_LUMINANCE_ALPHA ||
863 img->_BaseFormat == GL_RGBA)
864 *params = img->TexFormat->AlphaBits;
865 else
866 *params = 0;
867 break;
868 case GL_TEXTURE_INTENSITY_SIZE:
869 if (img->_BaseFormat != GL_INTENSITY)
870 *params = 0;
871 else if (img->TexFormat->IntensityBits > 0)
872 *params = img->TexFormat->IntensityBits;
873 else /* intensity probably stored as rgb texture */
874 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
875 break;
876 case GL_TEXTURE_LUMINANCE_SIZE:
877 if (img->_BaseFormat != GL_LUMINANCE &&
878 img->_BaseFormat != GL_LUMINANCE_ALPHA)
879 *params = 0;
880 else if (img->TexFormat->LuminanceBits > 0)
881 *params = img->TexFormat->LuminanceBits;
882 else /* luminance probably stored as rgb texture */
883 *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits);
884 break;
885 case GL_TEXTURE_INDEX_SIZE_EXT:
886 if (img->_BaseFormat == GL_COLOR_INDEX)
887 *params = img->TexFormat->IndexBits;
888 else
889 *params = 0;
890 break;
891 case GL_TEXTURE_DEPTH_SIZE_ARB:
892 if (ctx->Extensions.SGIX_depth_texture ||
893 ctx->Extensions.ARB_depth_texture)
894 *params = img->TexFormat->DepthBits;
895 else
896 _mesa_error(ctx, GL_INVALID_ENUM,
897 "glGetTexLevelParameter[if]v(pname)");
898 break;
899 case GL_TEXTURE_STENCIL_SIZE_EXT:
900 if (ctx->Extensions.EXT_packed_depth_stencil) {
901 *params = img->TexFormat->StencilBits;
902 }
903 else {
904 _mesa_error(ctx, GL_INVALID_ENUM,
905 "glGetTexLevelParameter[if]v(pname)");
906 }
907 break;
908
909 /* GL_ARB_texture_compression */
910 case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
911 if (ctx->Extensions.ARB_texture_compression) {
912 if (img->IsCompressed && !isProxy) {
913 /* Don't use ctx->Driver.CompressedTextureSize() since that
914 * may returned a padded hardware size.
915 */
916 *params = _mesa_compressed_texture_size(ctx, img->Width,
917 img->Height, img->Depth,
918 img->TexFormat->MesaFormat);
919 }
920 else {
921 _mesa_error(ctx, GL_INVALID_OPERATION,
922 "glGetTexLevelParameter[if]v(pname)");
923 }
924 }
925 else {
926 _mesa_error(ctx, GL_INVALID_ENUM,
927 "glGetTexLevelParameter[if]v(pname)");
928 }
929 break;
930 case GL_TEXTURE_COMPRESSED:
931 if (ctx->Extensions.ARB_texture_compression) {
932 *params = (GLint) img->IsCompressed;
933 }
934 else {
935 _mesa_error(ctx, GL_INVALID_ENUM,
936 "glGetTexLevelParameter[if]v(pname)");
937 }
938 break;
939
940 /* GL_ARB_texture_float */
941 case GL_TEXTURE_RED_TYPE_ARB:
942 if (ctx->Extensions.ARB_texture_float) {
943 *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE;
944 }
945 else {
946 _mesa_error(ctx, GL_INVALID_ENUM,
947 "glGetTexLevelParameter[if]v(pname)");
948 }
949 break;
950 case GL_TEXTURE_GREEN_TYPE_ARB:
951 if (ctx->Extensions.ARB_texture_float) {
952 *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE;
953 }
954 else {
955 _mesa_error(ctx, GL_INVALID_ENUM,
956 "glGetTexLevelParameter[if]v(pname)");
957 }
958 break;
959 case GL_TEXTURE_BLUE_TYPE_ARB:
960 if (ctx->Extensions.ARB_texture_float) {
961 *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE;
962 }
963 else {
964 _mesa_error(ctx, GL_INVALID_ENUM,
965 "glGetTexLevelParameter[if]v(pname)");
966 }
967 break;
968 case GL_TEXTURE_ALPHA_TYPE_ARB:
969 if (ctx->Extensions.ARB_texture_float) {
970 *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE;
971 }
972 else {
973 _mesa_error(ctx, GL_INVALID_ENUM,
974 "glGetTexLevelParameter[if]v(pname)");
975 }
976 break;
977 case GL_TEXTURE_LUMINANCE_TYPE_ARB:
978 if (ctx->Extensions.ARB_texture_float) {
979 *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE;
980 }
981 else {
982 _mesa_error(ctx, GL_INVALID_ENUM,
983 "glGetTexLevelParameter[if]v(pname)");
984 }
985 break;
986 case GL_TEXTURE_INTENSITY_TYPE_ARB:
987 if (ctx->Extensions.ARB_texture_float) {
988 *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE;
989 }
990 else {
991 _mesa_error(ctx, GL_INVALID_ENUM,
992 "glGetTexLevelParameter[if]v(pname)");
993 }
994 break;
995 case GL_TEXTURE_DEPTH_TYPE_ARB:
996 if (ctx->Extensions.ARB_texture_float) {
997 *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE;
998 }
999 else {
1000 _mesa_error(ctx, GL_INVALID_ENUM,
1001 "glGetTexLevelParameter[if]v(pname)");
1002 }
1003 break;
1004
1005 default:
1006 _mesa_error(ctx, GL_INVALID_ENUM,
1007 "glGetTexLevelParameter[if]v(pname)");
1008 }
1009
1010 out:
1011 _mesa_unlock_texture(ctx, texObj);
1012 }
1013
1014
1015
1016 void GLAPIENTRY
1017 _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
1018 {
1019 struct gl_texture_unit *texUnit;
1020 struct gl_texture_object *obj;
1021 GLboolean error = GL_FALSE;
1022 GET_CURRENT_CONTEXT(ctx);
1023 ASSERT_OUTSIDE_BEGIN_END(ctx);
1024
1025 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
1026 _mesa_error(ctx, GL_INVALID_OPERATION,
1027 "glGetTexParameterfv(current unit)");
1028 return;
1029 }
1030
1031 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1032
1033 obj = _mesa_select_tex_object(ctx, texUnit, target);
1034 if (!obj) {
1035 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
1036 return;
1037 }
1038
1039 _mesa_lock_texture(ctx, obj);
1040 switch (pname) {
1041 case GL_TEXTURE_MAG_FILTER:
1042 *params = ENUM_TO_FLOAT(obj->MagFilter);
1043 break;
1044 case GL_TEXTURE_MIN_FILTER:
1045 *params = ENUM_TO_FLOAT(obj->MinFilter);
1046 break;
1047 case GL_TEXTURE_WRAP_S:
1048 *params = ENUM_TO_FLOAT(obj->WrapS);
1049 break;
1050 case GL_TEXTURE_WRAP_T:
1051 *params = ENUM_TO_FLOAT(obj->WrapT);
1052 break;
1053 case GL_TEXTURE_WRAP_R:
1054 *params = ENUM_TO_FLOAT(obj->WrapR);
1055 break;
1056 case GL_TEXTURE_BORDER_COLOR:
1057 params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
1058 params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
1059 params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
1060 params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
1061 break;
1062 case GL_TEXTURE_RESIDENT:
1063 {
1064 GLboolean resident;
1065 if (ctx->Driver.IsTextureResident)
1066 resident = ctx->Driver.IsTextureResident(ctx, obj);
1067 else
1068 resident = GL_TRUE;
1069 *params = ENUM_TO_FLOAT(resident);
1070 }
1071 break;
1072 case GL_TEXTURE_PRIORITY:
1073 *params = obj->Priority;
1074 break;
1075 case GL_TEXTURE_MIN_LOD:
1076 *params = obj->MinLod;
1077 break;
1078 case GL_TEXTURE_MAX_LOD:
1079 *params = obj->MaxLod;
1080 break;
1081 case GL_TEXTURE_BASE_LEVEL:
1082 *params = (GLfloat) obj->BaseLevel;
1083 break;
1084 case GL_TEXTURE_MAX_LEVEL:
1085 *params = (GLfloat) obj->MaxLevel;
1086 break;
1087 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1088 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
1089 *params = obj->MaxAnisotropy;
1090 }
1091 else
1092 error = 1;
1093 break;
1094 case GL_TEXTURE_COMPARE_SGIX:
1095 if (ctx->Extensions.SGIX_shadow) {
1096 *params = (GLfloat) obj->CompareFlag;
1097 }
1098 else
1099 error = 1;
1100 break;
1101 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
1102 if (ctx->Extensions.SGIX_shadow) {
1103 *params = (GLfloat) obj->CompareOperator;
1104 }
1105 else
1106 error = 1;
1107 break;
1108 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
1109 if (ctx->Extensions.SGIX_shadow_ambient) {
1110 *params = obj->ShadowAmbient;
1111 }
1112 else
1113 error = 1;
1114 break;
1115 case GL_GENERATE_MIPMAP_SGIS:
1116 if (ctx->Extensions.SGIS_generate_mipmap) {
1117 *params = (GLfloat) obj->GenerateMipmap;
1118 }
1119 else
1120 error = 1;
1121 break;
1122 case GL_TEXTURE_COMPARE_MODE_ARB:
1123 if (ctx->Extensions.ARB_shadow) {
1124 *params = (GLfloat) obj->CompareMode;
1125 }
1126 else
1127 error = 1;
1128 break;
1129 case GL_TEXTURE_COMPARE_FUNC_ARB:
1130 if (ctx->Extensions.ARB_shadow) {
1131 *params = (GLfloat) obj->CompareFunc;
1132 }
1133 else
1134 error = 1;
1135 break;
1136 case GL_DEPTH_TEXTURE_MODE_ARB:
1137 if (ctx->Extensions.ARB_depth_texture) {
1138 *params = (GLfloat) obj->DepthMode;
1139 }
1140 else
1141 error = 1;
1142 break;
1143 case GL_TEXTURE_LOD_BIAS:
1144 if (ctx->Extensions.EXT_texture_lod_bias) {
1145 *params = obj->LodBias;
1146 }
1147 else
1148 error = 1;
1149 break;
1150 default:
1151 error = 1;
1152 break;
1153 }
1154 if (error)
1155 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)",
1156 pname);
1157
1158 _mesa_unlock_texture(ctx, obj);
1159 }
1160
1161
1162 void GLAPIENTRY
1163 _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )
1164 {
1165 struct gl_texture_unit *texUnit;
1166 struct gl_texture_object *obj;
1167 GET_CURRENT_CONTEXT(ctx);
1168 ASSERT_OUTSIDE_BEGIN_END(ctx);
1169
1170 if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureImageUnits) {
1171 _mesa_error(ctx, GL_INVALID_OPERATION,
1172 "glGetTexParameteriv(current unit)");
1173 return;
1174 }
1175
1176 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1177
1178 obj = _mesa_select_tex_object(ctx, texUnit, target);
1179 if (!obj) {
1180 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)");
1181 return;
1182 }
1183
1184 switch (pname) {
1185 case GL_TEXTURE_MAG_FILTER:
1186 *params = (GLint) obj->MagFilter;
1187 return;
1188 case GL_TEXTURE_MIN_FILTER:
1189 *params = (GLint) obj->MinFilter;
1190 return;
1191 case GL_TEXTURE_WRAP_S:
1192 *params = (GLint) obj->WrapS;
1193 return;
1194 case GL_TEXTURE_WRAP_T:
1195 *params = (GLint) obj->WrapT;
1196 return;
1197 case GL_TEXTURE_WRAP_R:
1198 *params = (GLint) obj->WrapR;
1199 return;
1200 case GL_TEXTURE_BORDER_COLOR:
1201 {
1202 GLfloat b[4];
1203 b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F);
1204 b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F);
1205 b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F);
1206 b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F);
1207 params[0] = FLOAT_TO_INT(b[0]);
1208 params[1] = FLOAT_TO_INT(b[1]);
1209 params[2] = FLOAT_TO_INT(b[2]);
1210 params[3] = FLOAT_TO_INT(b[3]);
1211 }
1212 return;
1213 case GL_TEXTURE_RESIDENT:
1214 {
1215 GLboolean resident;
1216 if (ctx->Driver.IsTextureResident)
1217 resident = ctx->Driver.IsTextureResident(ctx, obj);
1218 else
1219 resident = GL_TRUE;
1220 *params = (GLint) resident;
1221 }
1222 return;
1223 case GL_TEXTURE_PRIORITY:
1224 *params = FLOAT_TO_INT(obj->Priority);
1225 return;
1226 case GL_TEXTURE_MIN_LOD:
1227 *params = (GLint) obj->MinLod;
1228 return;
1229 case GL_TEXTURE_MAX_LOD:
1230 *params = (GLint) obj->MaxLod;
1231 return;
1232 case GL_TEXTURE_BASE_LEVEL:
1233 *params = obj->BaseLevel;
1234 return;
1235 case GL_TEXTURE_MAX_LEVEL:
1236 *params = obj->MaxLevel;
1237 return;
1238 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1239 if (ctx->Extensions.EXT_texture_filter_anisotropic) {
1240 *params = (GLint) obj->MaxAnisotropy;
1241 return;
1242 }
1243 break;
1244 case GL_TEXTURE_COMPARE_SGIX:
1245 if (ctx->Extensions.SGIX_shadow) {
1246 *params = (GLint) obj->CompareFlag;
1247 return;
1248 }
1249 break;
1250 case GL_TEXTURE_COMPARE_OPERATOR_SGIX:
1251 if (ctx->Extensions.SGIX_shadow) {
1252 *params = (GLint) obj->CompareOperator;
1253 return;
1254 }
1255 break;
1256 case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */
1257 if (ctx->Extensions.SGIX_shadow_ambient) {
1258 *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient);
1259 return;
1260 }
1261 break;
1262 case GL_GENERATE_MIPMAP_SGIS:
1263 if (ctx->Extensions.SGIS_generate_mipmap) {
1264 *params = (GLint) obj->GenerateMipmap;
1265 return;
1266 }
1267 break;
1268 case GL_TEXTURE_COMPARE_MODE_ARB:
1269 if (ctx->Extensions.ARB_shadow) {
1270 *params = (GLint) obj->CompareMode;
1271 return;
1272 }
1273 break;
1274 case GL_TEXTURE_COMPARE_FUNC_ARB:
1275 if (ctx->Extensions.ARB_shadow) {
1276 *params = (GLint) obj->CompareFunc;
1277 return;
1278 }
1279 break;
1280 case GL_DEPTH_TEXTURE_MODE_ARB:
1281 if (ctx->Extensions.ARB_depth_texture) {
1282 *params = (GLint) obj->DepthMode;
1283 return;
1284 }
1285 break;
1286 case GL_TEXTURE_LOD_BIAS:
1287 if (ctx->Extensions.EXT_texture_lod_bias) {
1288 *params = (GLint) obj->LodBias;
1289 return;
1290 }
1291 break;
1292 default:
1293 ; /* silence warnings */
1294 }
1295 /* If we get here, pname was an unrecognized enum */
1296 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname);
1297 }
1298
1299
1300
1301 /* GL_ARB_multitexture */
1302 void GLAPIENTRY
1303 _mesa_ActiveTextureARB(GLenum texture)
1304 {
1305 GET_CURRENT_CONTEXT(ctx);
1306 const GLuint texUnit = texture - GL_TEXTURE0;
1307 ASSERT_OUTSIDE_BEGIN_END(ctx);
1308
1309 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1310 _mesa_debug(ctx, "glActiveTexture %s\n",
1311 _mesa_lookup_enum_by_nr(texture));
1312
1313 /* XXX error-check against max(coordunits, imageunits) */
1314 if (texUnit >= ctx->Const.MaxTextureUnits) {
1315 _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(texture)");
1316 return;
1317 }
1318
1319 if (ctx->Texture.CurrentUnit == texUnit)
1320 return;
1321
1322 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1323
1324 ctx->Texture.CurrentUnit = texUnit;
1325 if (ctx->Transform.MatrixMode == GL_TEXTURE) {
1326 /* update current stack pointer */
1327 ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit];
1328 }
1329
1330 if (ctx->Driver.ActiveTexture) {
1331 (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
1332 }
1333 }
1334
1335
1336 /* GL_ARB_multitexture */
1337 void GLAPIENTRY
1338 _mesa_ClientActiveTextureARB(GLenum texture)
1339 {
1340 GET_CURRENT_CONTEXT(ctx);
1341 GLuint texUnit = texture - GL_TEXTURE0;
1342 ASSERT_OUTSIDE_BEGIN_END(ctx);
1343
1344 if (texUnit >= ctx->Const.MaxTextureCoordUnits) {
1345 _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(texture)");
1346 return;
1347 }
1348
1349 FLUSH_VERTICES(ctx, _NEW_ARRAY);
1350 ctx->Array.ActiveTexture = texUnit;
1351 }
1352
1353
1354
1355 /**********************************************************************/
1356 /***** State management *****/
1357 /**********************************************************************/
1358
1359
1360 /**
1361 * \note This routine refers to derived texture attribute values to
1362 * compute the ENABLE_TEXMAT flags, but is only called on
1363 * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT
1364 * flags are updated by _mesa_update_textures(), below.
1365 *
1366 * \param ctx GL context.
1367 */
1368 static void
1369 update_texture_matrices( GLcontext *ctx )
1370 {
1371 GLuint i;
1372
1373 ctx->Texture._TexMatEnabled = 0;
1374
1375 for (i=0; i < ctx->Const.MaxTextureUnits; i++) {
1376 if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) {
1377 _math_matrix_analyse( ctx->TextureMatrixStack[i].Top );
1378
1379 if (ctx->Texture.Unit[i]._ReallyEnabled &&
1380 ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY)
1381 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i);
1382
1383 if (ctx->Driver.TextureMatrix)
1384 ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top);
1385 }
1386 }
1387 }
1388
1389
1390 /**
1391 * Update texture object's _Function field. We need to do this
1392 * whenever any of the texture object's shadow-related fields change
1393 * or when we start/stop using a fragment program.
1394 *
1395 * This function could be expanded someday to update additional per-object
1396 * fields that depend on assorted state changes.
1397 */
1398 static void
1399 update_texture_compare_function(GLcontext *ctx,
1400 struct gl_texture_object *tObj)
1401 {
1402 /* XXX temporarily disable this test since it breaks the GLSL
1403 * shadow2D(), etc. functions.
1404 */
1405 if (0 /*ctx->FragmentProgram._Current*/) {
1406 /* Texel/coordinate comparison is ignored for programs.
1407 * See GL_ARB_fragment_program/shader spec for details.
1408 */
1409 tObj->_Function = GL_NONE;
1410 }
1411 else if (tObj->CompareFlag) {
1412 /* GL_SGIX_shadow */
1413 if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
1414 tObj->_Function = GL_LEQUAL;
1415 }
1416 else {
1417 ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
1418 tObj->_Function = GL_GEQUAL;
1419 }
1420 }
1421 else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
1422 /* GL_ARB_shadow */
1423 tObj->_Function = tObj->CompareFunc;
1424 }
1425 else {
1426 tObj->_Function = GL_NONE; /* pass depth through as grayscale */
1427 }
1428 }
1429
1430
1431 /**
1432 * Helper function for determining which texture object (1D, 2D, cube, etc)
1433 * should actually be used.
1434 */
1435 static void
1436 texture_override(GLcontext *ctx,
1437 struct gl_texture_unit *texUnit, GLbitfield enableBits,
1438 struct gl_texture_object *texObj, GLuint textureBit)
1439 {
1440 if (!texUnit->_ReallyEnabled && (enableBits & textureBit)) {
1441 if (!texObj->_Complete) {
1442 _mesa_test_texobj_completeness(ctx, texObj);
1443 }
1444 if (texObj->_Complete) {
1445 texUnit->_ReallyEnabled = textureBit;
1446 texUnit->_Current = texObj;
1447 update_texture_compare_function(ctx, texObj);
1448 }
1449 }
1450 }
1451
1452
1453 /**
1454 * \note This routine refers to derived texture matrix values to
1455 * compute the ENABLE_TEXMAT flags, but is only called on
1456 * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT
1457 * flags are updated by _mesa_update_texture_matrices, above.
1458 *
1459 * \param ctx GL context.
1460 */
1461 static void
1462 update_texture_state( GLcontext *ctx )
1463 {
1464 GLuint unit;
1465 struct gl_fragment_program *fprog = NULL;
1466 struct gl_vertex_program *vprog = NULL;
1467
1468 if (ctx->Shader.CurrentProgram &&
1469 ctx->Shader.CurrentProgram->LinkStatus) {
1470 fprog = ctx->Shader.CurrentProgram->FragmentProgram;
1471 vprog = ctx->Shader.CurrentProgram->VertexProgram;
1472 }
1473 else {
1474 if (ctx->FragmentProgram._Enabled) {
1475 fprog = ctx->FragmentProgram.Current;
1476 }
1477 if (ctx->VertexProgram._Enabled) {
1478 /* XXX enable this if/when non-shader vertex programs get
1479 * texture fetches:
1480 vprog = ctx->VertexProgram.Current;
1481 */
1482 }
1483 }
1484
1485 ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are
1486 * actual changes.
1487 */
1488
1489 ctx->Texture._EnabledUnits = 0;
1490 ctx->Texture._GenFlags = 0;
1491 ctx->Texture._TexMatEnabled = 0;
1492 ctx->Texture._TexGenEnabled = 0;
1493
1494 /*
1495 * Update texture unit state.
1496 */
1497 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1498 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1499 GLbitfield enableBits;
1500
1501 texUnit->_Current = NULL;
1502 texUnit->_ReallyEnabled = 0;
1503 texUnit->_GenFlags = 0;
1504
1505 /* Get the bitmask of texture enables.
1506 * enableBits will be a mask of the TEXTURE_*_BIT flags indicating
1507 * which texture targets are enabled (fixed function) or referenced
1508 * by a fragment shader/program. When multiple flags are set, we'll
1509 * settle on the one with highest priority (see texture_override below).
1510 */
1511 if (fprog || vprog) {
1512 enableBits = 0x0;
1513 if (fprog)
1514 enableBits |= fprog->Base.TexturesUsed[unit];
1515 if (vprog)
1516 enableBits |= vprog->Base.TexturesUsed[unit];
1517 }
1518 else {
1519 if (!texUnit->Enabled)
1520 continue;
1521 enableBits = texUnit->Enabled;
1522 }
1523
1524 /* Look for the highest-priority texture target that's enabled and
1525 * complete. That's the one we'll use for texturing. If we're using
1526 * a fragment program we're guaranteed that bitcount(enabledBits) <= 1.
1527 */
1528 texture_override(ctx, texUnit, enableBits,
1529 texUnit->Current2DArray, TEXTURE_2D_ARRAY_BIT);
1530 texture_override(ctx, texUnit, enableBits,
1531 texUnit->Current1DArray, TEXTURE_1D_ARRAY_BIT);
1532 texture_override(ctx, texUnit, enableBits,
1533 texUnit->CurrentCubeMap, TEXTURE_CUBE_BIT);
1534 texture_override(ctx, texUnit, enableBits,
1535 texUnit->Current3D, TEXTURE_3D_BIT);
1536 texture_override(ctx, texUnit, enableBits,
1537 texUnit->CurrentRect, TEXTURE_RECT_BIT);
1538 texture_override(ctx, texUnit, enableBits,
1539 texUnit->Current2D, TEXTURE_2D_BIT);
1540 texture_override(ctx, texUnit, enableBits,
1541 texUnit->Current1D, TEXTURE_1D_BIT);
1542
1543 if (!texUnit->_ReallyEnabled) {
1544 continue;
1545 }
1546
1547 if (texUnit->_ReallyEnabled)
1548 ctx->Texture._EnabledUnits |= (1 << unit);
1549
1550 if (texUnit->EnvMode == GL_COMBINE) {
1551 texUnit->_CurrentCombine = & texUnit->Combine;
1552 }
1553 else {
1554 const struct gl_texture_object *texObj = texUnit->_Current;
1555 GLenum format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
1556 if (format == GL_COLOR_INDEX) {
1557 format = GL_RGBA; /* a bit of a hack */
1558 }
1559 else if (format == GL_DEPTH_COMPONENT
1560 || format == GL_DEPTH_STENCIL_EXT) {
1561 format = texObj->DepthMode;
1562 }
1563 calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format);
1564 texUnit->_CurrentCombine = & texUnit->_EnvMode;
1565 }
1566
1567 switch (texUnit->_CurrentCombine->ModeRGB) {
1568 case GL_REPLACE:
1569 texUnit->_CurrentCombine->_NumArgsRGB = 1;
1570 break;
1571 case GL_MODULATE:
1572 case GL_ADD:
1573 case GL_ADD_SIGNED:
1574 case GL_SUBTRACT:
1575 case GL_DOT3_RGB:
1576 case GL_DOT3_RGBA:
1577 case GL_DOT3_RGB_EXT:
1578 case GL_DOT3_RGBA_EXT:
1579 texUnit->_CurrentCombine->_NumArgsRGB = 2;
1580 break;
1581 case GL_INTERPOLATE:
1582 case GL_MODULATE_ADD_ATI:
1583 case GL_MODULATE_SIGNED_ADD_ATI:
1584 case GL_MODULATE_SUBTRACT_ATI:
1585 texUnit->_CurrentCombine->_NumArgsRGB = 3;
1586 break;
1587 default:
1588 texUnit->_CurrentCombine->_NumArgsRGB = 0;
1589 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
1590 return;
1591 }
1592
1593 switch (texUnit->_CurrentCombine->ModeA) {
1594 case GL_REPLACE:
1595 texUnit->_CurrentCombine->_NumArgsA = 1;
1596 break;
1597 case GL_MODULATE:
1598 case GL_ADD:
1599 case GL_ADD_SIGNED:
1600 case GL_SUBTRACT:
1601 texUnit->_CurrentCombine->_NumArgsA = 2;
1602 break;
1603 case GL_INTERPOLATE:
1604 case GL_MODULATE_ADD_ATI:
1605 case GL_MODULATE_SIGNED_ADD_ATI:
1606 case GL_MODULATE_SUBTRACT_ATI:
1607 texUnit->_CurrentCombine->_NumArgsA = 3;
1608 break;
1609 default:
1610 texUnit->_CurrentCombine->_NumArgsA = 0;
1611 _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state");
1612 break;
1613 }
1614 }
1615
1616 /* Determine which texture coordinate sets are actually needed */
1617 if (fprog) {
1618 const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1;
1619 ctx->Texture._EnabledCoordUnits
1620 = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask;
1621 }
1622 else {
1623 ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits;
1624 }
1625
1626 /* Setup texgen for those texture coordinate sets that are in use */
1627 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1628 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1629
1630 if (!(ctx->Texture._EnabledCoordUnits & (1 << unit)))
1631 continue;
1632
1633 if (texUnit->TexGenEnabled) {
1634 if (texUnit->TexGenEnabled & S_BIT) {
1635 texUnit->_GenFlags |= texUnit->_GenBitS;
1636 }
1637 if (texUnit->TexGenEnabled & T_BIT) {
1638 texUnit->_GenFlags |= texUnit->_GenBitT;
1639 }
1640 if (texUnit->TexGenEnabled & Q_BIT) {
1641 texUnit->_GenFlags |= texUnit->_GenBitQ;
1642 }
1643 if (texUnit->TexGenEnabled & R_BIT) {
1644 texUnit->_GenFlags |= texUnit->_GenBitR;
1645 }
1646
1647 ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit);
1648 ctx->Texture._GenFlags |= texUnit->_GenFlags;
1649 }
1650
1651 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY)
1652 ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit);
1653 }
1654 }
1655
1656
1657 /**
1658 * Update texture-related derived state.
1659 */
1660 void
1661 _mesa_update_texture( GLcontext *ctx, GLuint new_state )
1662 {
1663 if (new_state & _NEW_TEXTURE_MATRIX)
1664 update_texture_matrices( ctx );
1665
1666 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM))
1667 update_texture_state( ctx );
1668 }
1669
1670
1671 /**********************************************************************/
1672 /***** Initialization *****/
1673 /**********************************************************************/
1674
1675 /**
1676 * Allocate the proxy textures for the given context.
1677 *
1678 * \param ctx the context to allocate proxies for.
1679 *
1680 * \return GL_TRUE on success, or GL_FALSE on failure
1681 *
1682 * If run out of memory part way through the allocations, clean up and return
1683 * GL_FALSE.
1684 */
1685 static GLboolean
1686 alloc_proxy_textures( GLcontext *ctx )
1687 {
1688 static const GLenum targets[] = {
1689 GL_TEXTURE_1D,
1690 GL_TEXTURE_2D,
1691 GL_TEXTURE_3D,
1692 GL_TEXTURE_CUBE_MAP_ARB,
1693 GL_TEXTURE_RECTANGLE_NV,
1694 GL_TEXTURE_1D_ARRAY_EXT,
1695 GL_TEXTURE_2D_ARRAY_EXT
1696 };
1697 GLint tgt;
1698
1699 ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
1700
1701 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1702 if (!(ctx->Texture.ProxyTex[tgt]
1703 = ctx->Driver.NewTextureObject(ctx, 0, targets[tgt]))) {
1704 /* out of memory, free what we did allocate */
1705 while (--tgt >= 0) {
1706 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
1707 }
1708 return GL_FALSE;
1709 }
1710 }
1711
1712 assert(ctx->Texture.ProxyTex[0]->RefCount == 1); /* sanity check */
1713 return GL_TRUE;
1714 }
1715
1716
1717 /**
1718 * Initialize a texture unit.
1719 *
1720 * \param ctx GL context.
1721 * \param unit texture unit number to be initialized.
1722 */
1723 static void
1724 init_texture_unit( GLcontext *ctx, GLuint unit )
1725 {
1726 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1727
1728 texUnit->EnvMode = GL_MODULATE;
1729 ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
1730
1731 texUnit->Combine = default_combine_state;
1732 texUnit->_EnvMode = default_combine_state;
1733 texUnit->_CurrentCombine = & texUnit->_EnvMode;
1734
1735 texUnit->TexGenEnabled = 0;
1736 texUnit->GenModeS = GL_EYE_LINEAR;
1737 texUnit->GenModeT = GL_EYE_LINEAR;
1738 texUnit->GenModeR = GL_EYE_LINEAR;
1739 texUnit->GenModeQ = GL_EYE_LINEAR;
1740 texUnit->_GenBitS = TEXGEN_EYE_LINEAR;
1741 texUnit->_GenBitT = TEXGEN_EYE_LINEAR;
1742 texUnit->_GenBitR = TEXGEN_EYE_LINEAR;
1743 texUnit->_GenBitQ = TEXGEN_EYE_LINEAR;
1744
1745 /* Yes, these plane coefficients are correct! */
1746 ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
1747 ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
1748 ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
1749 ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
1750 ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
1751 ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
1752 ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
1753 ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
1754
1755 /* initialize current texture object ptrs to the shared default objects */
1756 _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
1757 _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
1758 _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
1759 _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
1760 _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
1761 _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
1762 _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
1763 }
1764
1765
1766 /**
1767 * Initialize texture state for the given context.
1768 */
1769 GLboolean
1770 _mesa_init_texture(GLcontext *ctx)
1771 {
1772 GLuint i;
1773
1774 assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS);
1775 assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS);
1776
1777 /* Texture group */
1778 ctx->Texture.CurrentUnit = 0; /* multitexture */
1779 ctx->Texture._EnabledUnits = 0;
1780 ctx->Texture.SharedPalette = GL_FALSE;
1781 #if FEATURE_colortable
1782 _mesa_init_colortable(&ctx->Texture.Palette);
1783 #endif
1784
1785 for (i = 0; i < MAX_TEXTURE_UNITS; i++)
1786 init_texture_unit( ctx, i );
1787
1788 /* After we're done initializing the context's texture state the default
1789 * texture objects' refcounts should be at least MAX_TEXTURE_UNITS + 1.
1790 */
1791 assert(ctx->Shared->Default1D->RefCount >= MAX_TEXTURE_UNITS + 1);
1792
1793 /* Allocate proxy textures */
1794 if (!alloc_proxy_textures( ctx ))
1795 return GL_FALSE;
1796
1797 return GL_TRUE;
1798 }
1799
1800
1801 /**
1802 * Free dynamically-allocted texture data attached to the given context.
1803 */
1804 void
1805 _mesa_free_texture_data(GLcontext *ctx)
1806 {
1807 GLuint u, tgt;
1808
1809 /* unreference current textures */
1810 for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
1811 struct gl_texture_unit *unit = ctx->Texture.Unit + u;
1812 _mesa_reference_texobj(&unit->Current1D, NULL);
1813 _mesa_reference_texobj(&unit->Current2D, NULL);
1814 _mesa_reference_texobj(&unit->Current3D, NULL);
1815 _mesa_reference_texobj(&unit->CurrentCubeMap, NULL);
1816 _mesa_reference_texobj(&unit->CurrentRect, NULL);
1817 _mesa_reference_texobj(&unit->Current1DArray, NULL);
1818 _mesa_reference_texobj(&unit->Current2DArray, NULL);
1819 }
1820
1821 /* Free proxy texture objects */
1822 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++)
1823 ctx->Driver.DeleteTexture(ctx, ctx->Texture.ProxyTex[tgt]);
1824
1825 #if FEATURE_colortable
1826 {
1827 GLuint i;
1828 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
1829 _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable );
1830 }
1831 #endif
1832 }
1833
1834
1835 /**
1836 * Update the default texture objects in the given context to reference those
1837 * specified in the shared state and release those referencing the old
1838 * shared state.
1839 */
1840 void
1841 _mesa_update_default_objects_texture(GLcontext *ctx)
1842 {
1843 GLuint i;
1844
1845 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
1846 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
1847
1848 _mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
1849 _mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
1850 _mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
1851 _mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
1852 _mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
1853 _mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
1854 _mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
1855 }
1856 }