main: Added entry point for BindTextureUnit.
[mesa.git] / src / mesa / main / texobj.c
1 /**
2 * \file texobj.c
3 * Texture object management.
4 */
5
6 /*
7 * Mesa 3-D graphics library
8 *
9 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 */
29
30
31 #include "bufferobj.h"
32 #include "colortab.h"
33 #include "context.h"
34 #include "enums.h"
35 #include "fbobject.h"
36 #include "formats.h"
37 #include "hash.h"
38 #include "imports.h"
39 #include "macros.h"
40 #include "teximage.h"
41 #include "texobj.h"
42 #include "texstate.h"
43 #include "mtypes.h"
44 #include "program/prog_instruction.h"
45
46
47
48 /**********************************************************************/
49 /** \name Internal functions */
50 /*@{*/
51
52
53 /**
54 * Return the gl_texture_object for a given ID.
55 */
56 struct gl_texture_object *
57 _mesa_lookup_texture(struct gl_context *ctx, GLuint id)
58 {
59 return (struct gl_texture_object *)
60 _mesa_HashLookup(ctx->Shared->TexObjects, id);
61 }
62
63 /**
64 * Wrapper around _mesa_lookup_texture that throws GL_INVALID_OPERATION if id
65 * is not in the hash table. After calling _mesa_error, it returns NULL.
66 */
67 struct gl_texture_object *
68 _mesa_lookup_texture_err(struct gl_context *ctx, GLuint id, const char* func)
69 {
70 struct gl_texture_object *texObj;
71
72 texObj = _mesa_lookup_texture(ctx, id); /* Returns NULL if not found. */
73
74 if (!texObj)
75 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture)", func);
76
77 return texObj;
78 }
79
80 void
81 _mesa_begin_texture_lookups(struct gl_context *ctx)
82 {
83 _mesa_HashLockMutex(ctx->Shared->TexObjects);
84 }
85
86
87 void
88 _mesa_end_texture_lookups(struct gl_context *ctx)
89 {
90 _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
91 }
92
93
94 struct gl_texture_object *
95 _mesa_lookup_texture_locked(struct gl_context *ctx, GLuint id)
96 {
97 return (struct gl_texture_object *)
98 _mesa_HashLookupLocked(ctx->Shared->TexObjects, id);
99 }
100
101 /**
102 * Return a pointer to the current texture object for the given target
103 * on the current texture unit.
104 * Note: all <target> error checking should have been done by this point.
105 */
106 struct gl_texture_object *
107 _mesa_get_current_tex_object(struct gl_context *ctx, GLenum target)
108 {
109 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
110 const GLboolean arrayTex = ctx->Extensions.EXT_texture_array;
111
112 switch (target) {
113 case GL_TEXTURE_1D:
114 return texUnit->CurrentTex[TEXTURE_1D_INDEX];
115 case GL_PROXY_TEXTURE_1D:
116 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
117 case GL_TEXTURE_2D:
118 return texUnit->CurrentTex[TEXTURE_2D_INDEX];
119 case GL_PROXY_TEXTURE_2D:
120 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
121 case GL_TEXTURE_3D:
122 return texUnit->CurrentTex[TEXTURE_3D_INDEX];
123 case GL_PROXY_TEXTURE_3D:
124 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
125 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
126 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
127 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
128 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
129 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
130 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
131 case GL_TEXTURE_CUBE_MAP_ARB:
132 return ctx->Extensions.ARB_texture_cube_map
133 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
134 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
135 return ctx->Extensions.ARB_texture_cube_map
136 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
137 case GL_TEXTURE_CUBE_MAP_ARRAY:
138 return ctx->Extensions.ARB_texture_cube_map_array
139 ? texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
140 case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
141 return ctx->Extensions.ARB_texture_cube_map_array
142 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_ARRAY_INDEX] : NULL;
143 case GL_TEXTURE_RECTANGLE_NV:
144 return ctx->Extensions.NV_texture_rectangle
145 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
146 case GL_PROXY_TEXTURE_RECTANGLE_NV:
147 return ctx->Extensions.NV_texture_rectangle
148 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
149 case GL_TEXTURE_1D_ARRAY_EXT:
150 return arrayTex ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
151 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
152 return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
153 case GL_TEXTURE_2D_ARRAY_EXT:
154 return arrayTex ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
155 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
156 return arrayTex ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
157 case GL_TEXTURE_BUFFER:
158 return ctx->API == API_OPENGL_CORE &&
159 ctx->Extensions.ARB_texture_buffer_object ?
160 texUnit->CurrentTex[TEXTURE_BUFFER_INDEX] : NULL;
161 case GL_TEXTURE_EXTERNAL_OES:
162 return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
163 ? texUnit->CurrentTex[TEXTURE_EXTERNAL_INDEX] : NULL;
164 case GL_TEXTURE_2D_MULTISAMPLE:
165 return ctx->Extensions.ARB_texture_multisample
166 ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
167 case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
168 return ctx->Extensions.ARB_texture_multisample
169 ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_INDEX] : NULL;
170 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
171 return ctx->Extensions.ARB_texture_multisample
172 ? texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
173 case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
174 return ctx->Extensions.ARB_texture_multisample
175 ? ctx->Texture.ProxyTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX] : NULL;
176 default:
177 _mesa_problem(NULL, "bad target in _mesa_get_current_tex_object()");
178 return NULL;
179 }
180 }
181
182
183 /**
184 * Allocate and initialize a new texture object. But don't put it into the
185 * texture object hash table.
186 *
187 * Called via ctx->Driver.NewTextureObject, unless overridden by a device
188 * driver.
189 *
190 * \param shared the shared GL state structure to contain the texture object
191 * \param name integer name for the texture object
192 * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,
193 * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV. zero is ok for the sake
194 * of GenTextures()
195 *
196 * \return pointer to new texture object.
197 */
198 struct gl_texture_object *
199 _mesa_new_texture_object( struct gl_context *ctx, GLuint name, GLenum target )
200 {
201 struct gl_texture_object *obj;
202 (void) ctx;
203 obj = MALLOC_STRUCT(gl_texture_object);
204 _mesa_initialize_texture_object(ctx, obj, name, target);
205 return obj;
206 }
207
208
209 /**
210 * Initialize a new texture object to default values.
211 * \param obj the texture object
212 * \param name the texture name
213 * \param target the texture target
214 */
215 void
216 _mesa_initialize_texture_object( struct gl_context *ctx,
217 struct gl_texture_object *obj,
218 GLuint name, GLenum target )
219 {
220 ASSERT(target == 0 ||
221 target == GL_TEXTURE_1D ||
222 target == GL_TEXTURE_2D ||
223 target == GL_TEXTURE_3D ||
224 target == GL_TEXTURE_CUBE_MAP_ARB ||
225 target == GL_TEXTURE_RECTANGLE_NV ||
226 target == GL_TEXTURE_1D_ARRAY_EXT ||
227 target == GL_TEXTURE_2D_ARRAY_EXT ||
228 target == GL_TEXTURE_EXTERNAL_OES ||
229 target == GL_TEXTURE_CUBE_MAP_ARRAY ||
230 target == GL_TEXTURE_BUFFER ||
231 target == GL_TEXTURE_2D_MULTISAMPLE ||
232 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
233
234 memset(obj, 0, sizeof(*obj));
235 /* init the non-zero fields */
236 mtx_init(&obj->Mutex, mtx_plain);
237 obj->RefCount = 1;
238 obj->Name = name;
239 obj->Target = target;
240 obj->Priority = 1.0F;
241 obj->BaseLevel = 0;
242 obj->MaxLevel = 1000;
243
244 /* must be one; no support for (YUV) planes in separate buffers */
245 obj->RequiredTextureImageUnits = 1;
246
247 /* sampler state */
248 if (target == GL_TEXTURE_RECTANGLE_NV ||
249 target == GL_TEXTURE_EXTERNAL_OES) {
250 obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
251 obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
252 obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
253 obj->Sampler.MinFilter = GL_LINEAR;
254 }
255 else {
256 obj->Sampler.WrapS = GL_REPEAT;
257 obj->Sampler.WrapT = GL_REPEAT;
258 obj->Sampler.WrapR = GL_REPEAT;
259 obj->Sampler.MinFilter = GL_NEAREST_MIPMAP_LINEAR;
260 }
261 obj->Sampler.MagFilter = GL_LINEAR;
262 obj->Sampler.MinLod = -1000.0;
263 obj->Sampler.MaxLod = 1000.0;
264 obj->Sampler.LodBias = 0.0;
265 obj->Sampler.MaxAnisotropy = 1.0;
266 obj->Sampler.CompareMode = GL_NONE; /* ARB_shadow */
267 obj->Sampler.CompareFunc = GL_LEQUAL; /* ARB_shadow */
268 obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
269 obj->StencilSampling = false;
270 obj->Sampler.CubeMapSeamless = GL_FALSE;
271 obj->Swizzle[0] = GL_RED;
272 obj->Swizzle[1] = GL_GREEN;
273 obj->Swizzle[2] = GL_BLUE;
274 obj->Swizzle[3] = GL_ALPHA;
275 obj->_Swizzle = SWIZZLE_NOOP;
276 obj->Sampler.sRGBDecode = GL_DECODE_EXT;
277 obj->BufferObjectFormat = GL_R8;
278 obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
279 obj->ImageFormatCompatibilityType = GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
280 }
281
282
283 /**
284 * Some texture initialization can't be finished until we know which
285 * target it's getting bound to (GL_TEXTURE_1D/2D/etc).
286 */
287 static void
288 finish_texture_init(struct gl_context *ctx, GLenum target,
289 struct gl_texture_object *obj)
290 {
291 GLenum filter = GL_LINEAR;
292 assert(obj->Target == 0);
293
294 switch (target) {
295 case GL_TEXTURE_2D_MULTISAMPLE:
296 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
297 filter = GL_NEAREST;
298 /* fallthrough */
299
300 case GL_TEXTURE_RECTANGLE_NV:
301 case GL_TEXTURE_EXTERNAL_OES:
302 /* have to init wrap and filter state here - kind of klunky */
303 obj->Sampler.WrapS = GL_CLAMP_TO_EDGE;
304 obj->Sampler.WrapT = GL_CLAMP_TO_EDGE;
305 obj->Sampler.WrapR = GL_CLAMP_TO_EDGE;
306 obj->Sampler.MinFilter = filter;
307 obj->Sampler.MagFilter = filter;
308 if (ctx->Driver.TexParameter) {
309 static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE};
310 const GLfloat fparam_filter[1] = {(GLfloat) filter};
311 ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_S, fparam_wrap);
312 ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_T, fparam_wrap);
313 ctx->Driver.TexParameter(ctx, obj, GL_TEXTURE_WRAP_R, fparam_wrap);
314 ctx->Driver.TexParameter(ctx, obj,
315 GL_TEXTURE_MIN_FILTER, fparam_filter);
316 ctx->Driver.TexParameter(ctx, obj,
317 GL_TEXTURE_MAG_FILTER, fparam_filter);
318 }
319 break;
320
321 default:
322 /* nothing needs done */
323 break;
324 }
325 }
326
327
328 /**
329 * Deallocate a texture object struct. It should have already been
330 * removed from the texture object pool.
331 * Called via ctx->Driver.DeleteTexture() if not overriden by a driver.
332 *
333 * \param shared the shared GL state to which the object belongs.
334 * \param texObj the texture object to delete.
335 */
336 void
337 _mesa_delete_texture_object(struct gl_context *ctx,
338 struct gl_texture_object *texObj)
339 {
340 GLuint i, face;
341
342 /* Set Target to an invalid value. With some assertions elsewhere
343 * we can try to detect possible use of deleted textures.
344 */
345 texObj->Target = 0x99;
346
347 /* free the texture images */
348 for (face = 0; face < 6; face++) {
349 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
350 if (texObj->Image[face][i]) {
351 ctx->Driver.DeleteTextureImage(ctx, texObj->Image[face][i]);
352 }
353 }
354 }
355
356 _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
357
358 /* destroy the mutex -- it may have allocated memory (eg on bsd) */
359 mtx_destroy(&texObj->Mutex);
360
361 free(texObj->Label);
362
363 /* free this object */
364 free(texObj);
365 }
366
367
368 /**
369 * Copy texture object state from one texture object to another.
370 * Use for glPush/PopAttrib.
371 *
372 * \param dest destination texture object.
373 * \param src source texture object.
374 */
375 void
376 _mesa_copy_texture_object( struct gl_texture_object *dest,
377 const struct gl_texture_object *src )
378 {
379 dest->Target = src->Target;
380 dest->TargetIndex = src->TargetIndex;
381 dest->Name = src->Name;
382 dest->Priority = src->Priority;
383 dest->Sampler.BorderColor.f[0] = src->Sampler.BorderColor.f[0];
384 dest->Sampler.BorderColor.f[1] = src->Sampler.BorderColor.f[1];
385 dest->Sampler.BorderColor.f[2] = src->Sampler.BorderColor.f[2];
386 dest->Sampler.BorderColor.f[3] = src->Sampler.BorderColor.f[3];
387 dest->Sampler.WrapS = src->Sampler.WrapS;
388 dest->Sampler.WrapT = src->Sampler.WrapT;
389 dest->Sampler.WrapR = src->Sampler.WrapR;
390 dest->Sampler.MinFilter = src->Sampler.MinFilter;
391 dest->Sampler.MagFilter = src->Sampler.MagFilter;
392 dest->Sampler.MinLod = src->Sampler.MinLod;
393 dest->Sampler.MaxLod = src->Sampler.MaxLod;
394 dest->Sampler.LodBias = src->Sampler.LodBias;
395 dest->BaseLevel = src->BaseLevel;
396 dest->MaxLevel = src->MaxLevel;
397 dest->Sampler.MaxAnisotropy = src->Sampler.MaxAnisotropy;
398 dest->Sampler.CompareMode = src->Sampler.CompareMode;
399 dest->Sampler.CompareFunc = src->Sampler.CompareFunc;
400 dest->Sampler.CubeMapSeamless = src->Sampler.CubeMapSeamless;
401 dest->DepthMode = src->DepthMode;
402 dest->StencilSampling = src->StencilSampling;
403 dest->Sampler.sRGBDecode = src->Sampler.sRGBDecode;
404 dest->_MaxLevel = src->_MaxLevel;
405 dest->_MaxLambda = src->_MaxLambda;
406 dest->GenerateMipmap = src->GenerateMipmap;
407 dest->_BaseComplete = src->_BaseComplete;
408 dest->_MipmapComplete = src->_MipmapComplete;
409 COPY_4V(dest->Swizzle, src->Swizzle);
410 dest->_Swizzle = src->_Swizzle;
411
412 dest->RequiredTextureImageUnits = src->RequiredTextureImageUnits;
413 }
414
415
416 /**
417 * Free all texture images of the given texture object.
418 *
419 * \param ctx GL context.
420 * \param t texture object.
421 *
422 * \sa _mesa_clear_texture_image().
423 */
424 void
425 _mesa_clear_texture_object(struct gl_context *ctx,
426 struct gl_texture_object *texObj)
427 {
428 GLuint i, j;
429
430 if (texObj->Target == 0)
431 return;
432
433 for (i = 0; i < MAX_FACES; i++) {
434 for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
435 struct gl_texture_image *texImage = texObj->Image[i][j];
436 if (texImage)
437 _mesa_clear_texture_image(ctx, texImage);
438 }
439 }
440 }
441
442
443 /**
444 * Check if the given texture object is valid by examining its Target field.
445 * For debugging only.
446 */
447 static GLboolean
448 valid_texture_object(const struct gl_texture_object *tex)
449 {
450 switch (tex->Target) {
451 case 0:
452 case GL_TEXTURE_1D:
453 case GL_TEXTURE_2D:
454 case GL_TEXTURE_3D:
455 case GL_TEXTURE_CUBE_MAP_ARB:
456 case GL_TEXTURE_RECTANGLE_NV:
457 case GL_TEXTURE_1D_ARRAY_EXT:
458 case GL_TEXTURE_2D_ARRAY_EXT:
459 case GL_TEXTURE_BUFFER:
460 case GL_TEXTURE_EXTERNAL_OES:
461 case GL_TEXTURE_CUBE_MAP_ARRAY:
462 case GL_TEXTURE_2D_MULTISAMPLE:
463 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
464 return GL_TRUE;
465 case 0x99:
466 _mesa_problem(NULL, "invalid reference to a deleted texture object");
467 return GL_FALSE;
468 default:
469 _mesa_problem(NULL, "invalid texture object Target 0x%x, Id = %u",
470 tex->Target, tex->Name);
471 return GL_FALSE;
472 }
473 }
474
475
476 /**
477 * Reference (or unreference) a texture object.
478 * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
479 * If 'tex' is non-null, increment its refcount.
480 * This is normally only called from the _mesa_reference_texobj() macro
481 * when there's a real pointer change.
482 */
483 void
484 _mesa_reference_texobj_(struct gl_texture_object **ptr,
485 struct gl_texture_object *tex)
486 {
487 assert(ptr);
488
489 if (*ptr) {
490 /* Unreference the old texture */
491 GLboolean deleteFlag = GL_FALSE;
492 struct gl_texture_object *oldTex = *ptr;
493
494 ASSERT(valid_texture_object(oldTex));
495 (void) valid_texture_object; /* silence warning in release builds */
496
497 mtx_lock(&oldTex->Mutex);
498 ASSERT(oldTex->RefCount > 0);
499 oldTex->RefCount--;
500
501 deleteFlag = (oldTex->RefCount == 0);
502 mtx_unlock(&oldTex->Mutex);
503
504 if (deleteFlag) {
505 /* Passing in the context drastically changes the driver code for
506 * framebuffer deletion.
507 */
508 GET_CURRENT_CONTEXT(ctx);
509 if (ctx)
510 ctx->Driver.DeleteTexture(ctx, oldTex);
511 else
512 _mesa_problem(NULL, "Unable to delete texture, no context");
513 }
514
515 *ptr = NULL;
516 }
517 assert(!*ptr);
518
519 if (tex) {
520 /* reference new texture */
521 ASSERT(valid_texture_object(tex));
522 mtx_lock(&tex->Mutex);
523 if (tex->RefCount == 0) {
524 /* this texture's being deleted (look just above) */
525 /* Not sure this can every really happen. Warn if it does. */
526 _mesa_problem(NULL, "referencing deleted texture object");
527 *ptr = NULL;
528 }
529 else {
530 tex->RefCount++;
531 *ptr = tex;
532 }
533 mtx_unlock(&tex->Mutex);
534 }
535 }
536
537
538 enum base_mipmap { BASE, MIPMAP };
539
540
541 /**
542 * Mark a texture object as incomplete. There are actually three kinds of
543 * (in)completeness:
544 * 1. "base incomplete": the base level of the texture is invalid so no
545 * texturing is possible.
546 * 2. "mipmap incomplete": a non-base level of the texture is invalid so
547 * mipmap filtering isn't possible, but non-mipmap filtering is.
548 * 3. "texture incompleteness": some combination of texture state and
549 * sampler state renders the texture incomplete.
550 *
551 * \param t texture object
552 * \param bm either BASE or MIPMAP to indicate what's incomplete
553 * \param fmt... string describing why it's incomplete (for debugging).
554 */
555 static void
556 incomplete(struct gl_texture_object *t, enum base_mipmap bm,
557 const char *fmt, ...)
558 {
559 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_TEXTURE) {
560 va_list args;
561 char s[100];
562
563 va_start(args, fmt);
564 vsnprintf(s, sizeof(s), fmt, args);
565 va_end(args);
566
567 _mesa_debug(NULL, "Texture Obj %d incomplete because: %s\n", t->Name, s);
568 }
569
570 if (bm == BASE)
571 t->_BaseComplete = GL_FALSE;
572 t->_MipmapComplete = GL_FALSE;
573 }
574
575
576 /**
577 * Examine a texture object to determine if it is complete.
578 *
579 * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE
580 * accordingly.
581 *
582 * \param ctx GL context.
583 * \param t texture object.
584 *
585 * According to the texture target, verifies that each of the mipmaps is
586 * present and has the expected size.
587 */
588 void
589 _mesa_test_texobj_completeness( const struct gl_context *ctx,
590 struct gl_texture_object *t )
591 {
592 const GLint baseLevel = t->BaseLevel;
593 const struct gl_texture_image *baseImage;
594 GLint maxLevels = 0;
595
596 /* We'll set these to FALSE if tests fail below */
597 t->_BaseComplete = GL_TRUE;
598 t->_MipmapComplete = GL_TRUE;
599
600 if (t->Target == GL_TEXTURE_BUFFER) {
601 /* Buffer textures are always considered complete. The obvious case where
602 * they would be incomplete (no BO attached) is actually specced to be
603 * undefined rendering results.
604 */
605 return;
606 }
607
608 /* Detect cases where the application set the base level to an invalid
609 * value.
610 */
611 if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS)) {
612 incomplete(t, BASE, "base level = %d is invalid", baseLevel);
613 return;
614 }
615
616 if (t->MaxLevel < baseLevel) {
617 incomplete(t, MIPMAP, "MAX_LEVEL (%d) < BASE_LEVEL (%d)",
618 t->MaxLevel, baseLevel);
619 return;
620 }
621
622 baseImage = t->Image[0][baseLevel];
623
624 /* Always need the base level image */
625 if (!baseImage) {
626 incomplete(t, BASE, "Image[baseLevel=%d] == NULL", baseLevel);
627 return;
628 }
629
630 /* Check width/height/depth for zero */
631 if (baseImage->Width == 0 ||
632 baseImage->Height == 0 ||
633 baseImage->Depth == 0) {
634 incomplete(t, BASE, "texture width or height or depth = 0");
635 return;
636 }
637
638 /* Check if the texture values are integer */
639 {
640 GLenum datatype = _mesa_get_format_datatype(baseImage->TexFormat);
641 t->_IsIntegerFormat = datatype == GL_INT || datatype == GL_UNSIGNED_INT;
642 }
643
644 /* Compute _MaxLevel (the maximum mipmap level we'll sample from given the
645 * mipmap image sizes and GL_TEXTURE_MAX_LEVEL state).
646 */
647 switch (t->Target) {
648 case GL_TEXTURE_1D:
649 case GL_TEXTURE_1D_ARRAY_EXT:
650 maxLevels = ctx->Const.MaxTextureLevels;
651 break;
652 case GL_TEXTURE_2D:
653 case GL_TEXTURE_2D_ARRAY_EXT:
654 maxLevels = ctx->Const.MaxTextureLevels;
655 break;
656 case GL_TEXTURE_3D:
657 maxLevels = ctx->Const.Max3DTextureLevels;
658 break;
659 case GL_TEXTURE_CUBE_MAP_ARB:
660 case GL_TEXTURE_CUBE_MAP_ARRAY:
661 maxLevels = ctx->Const.MaxCubeTextureLevels;
662 break;
663 case GL_TEXTURE_RECTANGLE_NV:
664 case GL_TEXTURE_BUFFER:
665 case GL_TEXTURE_EXTERNAL_OES:
666 case GL_TEXTURE_2D_MULTISAMPLE:
667 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
668 maxLevels = 1; /* no mipmapping */
669 break;
670 default:
671 _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness");
672 return;
673 }
674
675 ASSERT(maxLevels > 0);
676
677 t->_MaxLevel = MIN3(t->MaxLevel,
678 /* 'p' in the GL spec */
679 (int) (baseLevel + baseImage->MaxNumLevels - 1),
680 /* 'q' in the GL spec */
681 maxLevels - 1);
682
683 if (t->Immutable) {
684 /* Adjust max level for views: the data store may have more levels than
685 * the view exposes.
686 */
687 t->_MaxLevel = MIN2(t->_MaxLevel, t->NumLevels - 1);
688 }
689
690 /* Compute _MaxLambda = q - p in the spec used during mipmapping */
691 t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel);
692
693 if (t->Immutable) {
694 /* This texture object was created with glTexStorage1/2/3D() so we
695 * know that all the mipmap levels are the right size and all cube
696 * map faces are the same size.
697 * We don't need to do any of the additional checks below.
698 */
699 return;
700 }
701
702 if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) {
703 /* Make sure that all six cube map level 0 images are the same size.
704 * Note: we know that the image's width==height (we enforce that
705 * at glTexImage time) so we only need to test the width here.
706 */
707 GLuint face;
708 assert(baseImage->Width2 == baseImage->Height);
709 for (face = 1; face < 6; face++) {
710 assert(t->Image[face][baseLevel] == NULL ||
711 t->Image[face][baseLevel]->Width2 ==
712 t->Image[face][baseLevel]->Height2);
713 if (t->Image[face][baseLevel] == NULL ||
714 t->Image[face][baseLevel]->Width2 != baseImage->Width2) {
715 incomplete(t, BASE, "Cube face missing or mismatched size");
716 return;
717 }
718 }
719 }
720
721 /*
722 * Do mipmap consistency checking.
723 * Note: we don't care about the current texture sampler state here.
724 * To determine texture completeness we'll either look at _BaseComplete
725 * or _MipmapComplete depending on the current minification filter mode.
726 */
727 {
728 GLint i;
729 const GLint minLevel = baseLevel;
730 const GLint maxLevel = t->_MaxLevel;
731 const GLuint numFaces = _mesa_num_tex_faces(t->Target);
732 GLuint width, height, depth, face;
733
734 if (minLevel > maxLevel) {
735 incomplete(t, MIPMAP, "minLevel > maxLevel");
736 return;
737 }
738
739 /* Get the base image's dimensions */
740 width = baseImage->Width2;
741 height = baseImage->Height2;
742 depth = baseImage->Depth2;
743
744 /* Note: this loop will be a no-op for RECT, BUFFER, EXTERNAL,
745 * MULTISAMPLE and MULTISAMPLE_ARRAY textures
746 */
747 for (i = baseLevel + 1; i < maxLevels; i++) {
748 /* Compute the expected size of image at level[i] */
749 if (width > 1) {
750 width /= 2;
751 }
752 if (height > 1 && t->Target != GL_TEXTURE_1D_ARRAY) {
753 height /= 2;
754 }
755 if (depth > 1 && t->Target != GL_TEXTURE_2D_ARRAY
756 && t->Target != GL_TEXTURE_CUBE_MAP_ARRAY) {
757 depth /= 2;
758 }
759
760 /* loop over cube faces (or single face otherwise) */
761 for (face = 0; face < numFaces; face++) {
762 if (i >= minLevel && i <= maxLevel) {
763 const struct gl_texture_image *img = t->Image[face][i];
764
765 if (!img) {
766 incomplete(t, MIPMAP, "TexImage[%d] is missing", i);
767 return;
768 }
769 if (img->TexFormat != baseImage->TexFormat) {
770 incomplete(t, MIPMAP, "Format[i] != Format[baseLevel]");
771 return;
772 }
773 if (img->Border != baseImage->Border) {
774 incomplete(t, MIPMAP, "Border[i] != Border[baseLevel]");
775 return;
776 }
777 if (img->Width2 != width) {
778 incomplete(t, MIPMAP, "TexImage[%d] bad width %u", i,
779 img->Width2);
780 return;
781 }
782 if (img->Height2 != height) {
783 incomplete(t, MIPMAP, "TexImage[%d] bad height %u", i,
784 img->Height2);
785 return;
786 }
787 if (img->Depth2 != depth) {
788 incomplete(t, MIPMAP, "TexImage[%d] bad depth %u", i,
789 img->Depth2);
790 return;
791 }
792
793 /* Extra checks for cube textures */
794 if (face > 0) {
795 /* check that cube faces are the same size */
796 if (img->Width2 != t->Image[0][i]->Width2 ||
797 img->Height2 != t->Image[0][i]->Height2) {
798 incomplete(t, MIPMAP, "CubeMap Image[n][i] bad size");
799 return;
800 }
801 }
802 }
803 }
804
805 if (width == 1 && height == 1 && depth == 1) {
806 return; /* found smallest needed mipmap, all done! */
807 }
808 }
809 }
810 }
811
812
813 /**
814 * Check if the given cube map texture is "cube complete" as defined in
815 * the OpenGL specification.
816 */
817 GLboolean
818 _mesa_cube_complete(const struct gl_texture_object *texObj)
819 {
820 const GLint baseLevel = texObj->BaseLevel;
821 const struct gl_texture_image *img0, *img;
822 GLuint face;
823
824 if (texObj->Target != GL_TEXTURE_CUBE_MAP)
825 return GL_FALSE;
826
827 if ((baseLevel < 0) || (baseLevel >= MAX_TEXTURE_LEVELS))
828 return GL_FALSE;
829
830 /* check first face */
831 img0 = texObj->Image[0][baseLevel];
832 if (!img0 ||
833 img0->Width < 1 ||
834 img0->Width != img0->Height)
835 return GL_FALSE;
836
837 /* check remaining faces vs. first face */
838 for (face = 1; face < 6; face++) {
839 img = texObj->Image[face][baseLevel];
840 if (!img ||
841 img->Width != img0->Width ||
842 img->Height != img0->Height ||
843 img->TexFormat != img0->TexFormat)
844 return GL_FALSE;
845 }
846
847 return GL_TRUE;
848 }
849
850
851 /**
852 * Mark a texture object dirty. It forces the object to be incomplete
853 * and forces the context to re-validate its state.
854 *
855 * \param ctx GL context.
856 * \param texObj texture object.
857 */
858 void
859 _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj)
860 {
861 texObj->_BaseComplete = GL_FALSE;
862 texObj->_MipmapComplete = GL_FALSE;
863 ctx->NewState |= _NEW_TEXTURE;
864 }
865
866
867 /**
868 * Return pointer to a default/fallback texture of the given type/target.
869 * The texture is an RGBA texture with all texels = (0,0,0,1).
870 * That's the value a GLSL sampler should get when sampling from an
871 * incomplete texture.
872 */
873 struct gl_texture_object *
874 _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
875 {
876 if (!ctx->Shared->FallbackTex[tex]) {
877 /* create fallback texture now */
878 const GLsizei width = 1, height = 1;
879 GLsizei depth = 1;
880 GLubyte texel[24];
881 struct gl_texture_object *texObj;
882 struct gl_texture_image *texImage;
883 mesa_format texFormat;
884 GLuint dims, face, numFaces = 1;
885 GLenum target;
886
887 for (face = 0; face < 6; face++) {
888 texel[4*face + 0] =
889 texel[4*face + 1] =
890 texel[4*face + 2] = 0x0;
891 texel[4*face + 3] = 0xff;
892 }
893
894 switch (tex) {
895 case TEXTURE_2D_ARRAY_INDEX:
896 dims = 3;
897 target = GL_TEXTURE_2D_ARRAY;
898 break;
899 case TEXTURE_1D_ARRAY_INDEX:
900 dims = 2;
901 target = GL_TEXTURE_1D_ARRAY;
902 break;
903 case TEXTURE_CUBE_INDEX:
904 dims = 2;
905 target = GL_TEXTURE_CUBE_MAP;
906 numFaces = 6;
907 break;
908 case TEXTURE_3D_INDEX:
909 dims = 3;
910 target = GL_TEXTURE_3D;
911 break;
912 case TEXTURE_RECT_INDEX:
913 dims = 2;
914 target = GL_TEXTURE_RECTANGLE;
915 break;
916 case TEXTURE_2D_INDEX:
917 dims = 2;
918 target = GL_TEXTURE_2D;
919 break;
920 case TEXTURE_1D_INDEX:
921 dims = 1;
922 target = GL_TEXTURE_1D;
923 break;
924 case TEXTURE_BUFFER_INDEX:
925 dims = 0;
926 target = GL_TEXTURE_BUFFER;
927 break;
928 case TEXTURE_CUBE_ARRAY_INDEX:
929 dims = 3;
930 target = GL_TEXTURE_CUBE_MAP_ARRAY;
931 depth = 6;
932 break;
933 case TEXTURE_EXTERNAL_INDEX:
934 dims = 2;
935 target = GL_TEXTURE_EXTERNAL_OES;
936 break;
937 case TEXTURE_2D_MULTISAMPLE_INDEX:
938 dims = 2;
939 target = GL_TEXTURE_2D_MULTISAMPLE;
940 break;
941 case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
942 dims = 3;
943 target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
944 break;
945 default:
946 /* no-op */
947 return NULL;
948 }
949
950 /* create texture object */
951 texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
952 if (!texObj)
953 return NULL;
954
955 assert(texObj->RefCount == 1);
956 texObj->Sampler.MinFilter = GL_NEAREST;
957 texObj->Sampler.MagFilter = GL_NEAREST;
958
959 texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
960 GL_RGBA, GL_RGBA,
961 GL_UNSIGNED_BYTE);
962
963 /* need a loop here just for cube maps */
964 for (face = 0; face < numFaces; face++) {
965 GLenum faceTarget;
966
967 if (target == GL_TEXTURE_CUBE_MAP)
968 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
969 else
970 faceTarget = target;
971
972 /* initialize level[0] texture image */
973 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
974
975 _mesa_init_teximage_fields(ctx, texImage,
976 width,
977 (dims > 1) ? height : 1,
978 (dims > 2) ? depth : 1,
979 0, /* border */
980 GL_RGBA, texFormat);
981
982 ctx->Driver.TexImage(ctx, dims, texImage,
983 GL_RGBA, GL_UNSIGNED_BYTE, texel,
984 &ctx->DefaultPacking);
985 }
986
987 _mesa_test_texobj_completeness(ctx, texObj);
988 assert(texObj->_BaseComplete);
989 assert(texObj->_MipmapComplete);
990
991 ctx->Shared->FallbackTex[tex] = texObj;
992 }
993 return ctx->Shared->FallbackTex[tex];
994 }
995
996
997 /**
998 * Compute the size of the given texture object, in bytes.
999 */
1000 static GLuint
1001 texture_size(const struct gl_texture_object *texObj)
1002 {
1003 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1004 GLuint face, level, size = 0;
1005
1006 for (face = 0; face < numFaces; face++) {
1007 for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
1008 const struct gl_texture_image *img = texObj->Image[face][level];
1009 if (img) {
1010 GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
1011 img->Height, img->Depth);
1012 size += sz;
1013 }
1014 }
1015 }
1016
1017 return size;
1018 }
1019
1020
1021 /**
1022 * Callback called from _mesa_HashWalk()
1023 */
1024 static void
1025 count_tex_size(GLuint key, void *data, void *userData)
1026 {
1027 const struct gl_texture_object *texObj =
1028 (const struct gl_texture_object *) data;
1029 GLuint *total = (GLuint *) userData;
1030
1031 (void) key;
1032
1033 *total = *total + texture_size(texObj);
1034 }
1035
1036
1037 /**
1038 * Compute total size (in bytes) of all textures for the given context.
1039 * For debugging purposes.
1040 */
1041 GLuint
1042 _mesa_total_texture_memory(struct gl_context *ctx)
1043 {
1044 GLuint tgt, total = 0;
1045
1046 _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
1047
1048 /* plus, the default texture objects */
1049 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1050 total += texture_size(ctx->Shared->DefaultTex[tgt]);
1051 }
1052
1053 return total;
1054 }
1055
1056
1057 /**
1058 * Return the base format for the given texture object by looking
1059 * at the base texture image.
1060 * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined
1061 */
1062 GLenum
1063 _mesa_texture_base_format(const struct gl_texture_object *texObj)
1064 {
1065 const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj);
1066
1067 return texImage ? texImage->_BaseFormat : GL_NONE;
1068 }
1069
1070
1071 static struct gl_texture_object *
1072 invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
1073 GLint level, const char *name)
1074 {
1075 /* The GL_ARB_invalidate_subdata spec says:
1076 *
1077 * "If <texture> is zero or is not the name of a texture, the error
1078 * INVALID_VALUE is generated."
1079 *
1080 * This performs the error check in a different order than listed in the
1081 * spec. We have to get the texture object before we can validate the
1082 * other parameters against values in the texture object.
1083 */
1084 struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
1085 if (texture == 0 || t == NULL) {
1086 _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
1087 return NULL;
1088 }
1089
1090 /* The GL_ARB_invalidate_subdata spec says:
1091 *
1092 * "If <level> is less than zero or greater than the base 2 logarithm
1093 * of the maximum texture width, height, or depth, the error
1094 * INVALID_VALUE is generated."
1095 */
1096 if (level < 0 || level > t->MaxLevel) {
1097 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1098 return NULL;
1099 }
1100
1101 /* The GL_ARB_invalidate_subdata spec says:
1102 *
1103 * "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
1104 * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
1105 * is not zero, the error INVALID_VALUE is generated."
1106 */
1107 if (level != 0) {
1108 switch (t->Target) {
1109 case GL_TEXTURE_RECTANGLE:
1110 case GL_TEXTURE_BUFFER:
1111 case GL_TEXTURE_2D_MULTISAMPLE:
1112 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1113 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1114 return NULL;
1115
1116 default:
1117 break;
1118 }
1119 }
1120
1121 return t;
1122 }
1123
1124 /**
1125 * Helper function for glCreateTextures and glGenTextures. Need this because
1126 * glCreateTextures should throw errors if target = 0. This is not exposed to
1127 * the rest of Mesa to encourage Mesa internals to use nameless textures,
1128 * which do not require expensive hash lookups.
1129 */
1130 static void
1131 create_textures(struct gl_context *ctx, GLenum target,
1132 GLsizei n, GLuint *textures, bool dsa)
1133 {
1134 GLuint first;
1135 GLint i;
1136 const char *func = dsa ? "Create" : "Gen";
1137
1138 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1139 _mesa_debug(ctx, "gl%sTextures %d\n", func, n);
1140
1141 if (n < 0) {
1142 _mesa_error( ctx, GL_INVALID_VALUE, "gl%sTextures(n < 0)", func );
1143 return;
1144 }
1145
1146 if (!textures)
1147 return;
1148
1149 /*
1150 * This must be atomic (generation and allocation of texture IDs)
1151 */
1152 mtx_lock(&ctx->Shared->Mutex);
1153
1154 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
1155
1156 /* Allocate new, empty texture objects */
1157 for (i = 0; i < n; i++) {
1158 struct gl_texture_object *texObj;
1159 GLint targetIndex;
1160 GLuint name = first + i;
1161 texObj = ctx->Driver.NewTextureObject(ctx, name, target);
1162 if (!texObj) {
1163 mtx_unlock(&ctx->Shared->Mutex);
1164 _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sTextures", func);
1165 return;
1166 }
1167
1168 /* Initialize the target index if target is non-zero. */
1169 if (target != 0) {
1170 targetIndex = _mesa_tex_target_to_index(ctx, texObj->Target);
1171 if (targetIndex < 0) { /* Bad Target */
1172 mtx_unlock(&ctx->Shared->Mutex);
1173 _mesa_error(ctx, GL_INVALID_ENUM, "gl%sTextures(target = %s)",
1174 func, _mesa_lookup_enum_by_nr(texObj->Target));
1175 return;
1176 }
1177 assert(targetIndex < NUM_TEXTURE_TARGETS);
1178 texObj->TargetIndex = targetIndex;
1179 }
1180
1181 /* insert into hash table */
1182 _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
1183
1184 textures[i] = name;
1185 }
1186
1187 mtx_unlock(&ctx->Shared->Mutex);
1188 }
1189
1190 /*@}*/
1191
1192
1193 /***********************************************************************/
1194 /** \name API functions */
1195 /*@{*/
1196
1197
1198 /**
1199 * Generate texture names.
1200 *
1201 * \param n number of texture names to be generated.
1202 * \param textures an array in which will hold the generated texture names.
1203 *
1204 * \sa glGenTextures(), glCreateTextures().
1205 *
1206 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1207 * IDs which are stored in \p textures. Corresponding empty texture
1208 * objects are also generated.
1209 */
1210 void GLAPIENTRY
1211 _mesa_GenTextures(GLsizei n, GLuint *textures)
1212 {
1213 GET_CURRENT_CONTEXT(ctx);
1214 create_textures(ctx, 0, n, textures, false);
1215 }
1216
1217 /**
1218 * Create texture objects.
1219 *
1220 * \param target the texture target for each name to be generated.
1221 * \param n number of texture names to be generated.
1222 * \param textures an array in which will hold the generated texture names.
1223 *
1224 * \sa glCreateTextures(), glGenTextures().
1225 *
1226 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1227 * IDs which are stored in \p textures. Corresponding empty texture
1228 * objects are also generated.
1229 */
1230 void GLAPIENTRY
1231 _mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
1232 {
1233 GLint targetIndex;
1234 GET_CURRENT_CONTEXT(ctx);
1235
1236 /*
1237 * The 4.5 core profile spec (30.10.2014) doesn't specify what
1238 * glCreateTextures should do with invalid targets, which was probably an
1239 * oversight. This conforms to the spec for glBindTexture.
1240 */
1241 targetIndex = _mesa_tex_target_to_index(ctx, target);
1242 if (targetIndex < 0) {
1243 _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)");
1244 return;
1245 }
1246
1247 create_textures(ctx, target, n, textures, true);
1248 }
1249
1250 /**
1251 * Check if the given texture object is bound to the current draw or
1252 * read framebuffer. If so, Unbind it.
1253 */
1254 static void
1255 unbind_texobj_from_fbo(struct gl_context *ctx,
1256 struct gl_texture_object *texObj)
1257 {
1258 bool progress = false;
1259
1260 /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
1261 * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
1262 * says:
1263 *
1264 * "If a texture object is deleted while its image is attached to one
1265 * or more attachment points in the currently bound framebuffer, then
1266 * it is as if FramebufferTexture* had been called, with a texture of
1267 * zero, for each attachment point to which this image was attached in
1268 * the currently bound framebuffer. In other words, this texture image
1269 * is first detached from all attachment points in the currently bound
1270 * framebuffer. Note that the texture image is specifically not
1271 * detached from any other framebuffer objects. Detaching the texture
1272 * image from any other framebuffer objects is the responsibility of
1273 * the application."
1274 */
1275 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1276 progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
1277 }
1278 if (_mesa_is_user_fbo(ctx->ReadBuffer)
1279 && ctx->ReadBuffer != ctx->DrawBuffer) {
1280 progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
1281 || progress;
1282 }
1283
1284 if (progress)
1285 /* Vertices are already flushed by _mesa_DeleteTextures */
1286 ctx->NewState |= _NEW_BUFFERS;
1287 }
1288
1289
1290 /**
1291 * Check if the given texture object is bound to any texture image units and
1292 * unbind it if so (revert to default textures).
1293 */
1294 static void
1295 unbind_texobj_from_texunits(struct gl_context *ctx,
1296 struct gl_texture_object *texObj)
1297 {
1298 const gl_texture_index index = texObj->TargetIndex;
1299 GLuint u;
1300
1301 if (texObj->Target == 0)
1302 return;
1303
1304 for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
1305 struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1306
1307 if (texObj == unit->CurrentTex[index]) {
1308 /* Bind the default texture for this unit/target */
1309 _mesa_reference_texobj(&unit->CurrentTex[index],
1310 ctx->Shared->DefaultTex[index]);
1311 unit->_BoundTextures &= ~(1 << index);
1312 }
1313 }
1314 }
1315
1316
1317 /**
1318 * Check if the given texture object is bound to any shader image unit
1319 * and unbind it if that's the case.
1320 */
1321 static void
1322 unbind_texobj_from_image_units(struct gl_context *ctx,
1323 struct gl_texture_object *texObj)
1324 {
1325 GLuint i;
1326
1327 for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
1328 struct gl_image_unit *unit = &ctx->ImageUnits[i];
1329
1330 if (texObj == unit->TexObj)
1331 _mesa_reference_texobj(&unit->TexObj, NULL);
1332 }
1333 }
1334
1335
1336 /**
1337 * Unbinds all textures bound to the given texture image unit.
1338 */
1339 static void
1340 unbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
1341 {
1342 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1343
1344 while (texUnit->_BoundTextures) {
1345 const GLuint index = ffs(texUnit->_BoundTextures) - 1;
1346 struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
1347
1348 _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
1349
1350 /* Pass BindTexture call to device driver */
1351 if (ctx->Driver.BindTexture)
1352 ctx->Driver.BindTexture(ctx, unit, 0, texObj);
1353
1354 texUnit->_BoundTextures &= ~(1 << index);
1355 ctx->NewState |= _NEW_TEXTURE;
1356 }
1357 }
1358
1359
1360 /**
1361 * Delete named textures.
1362 *
1363 * \param n number of textures to be deleted.
1364 * \param textures array of texture IDs to be deleted.
1365 *
1366 * \sa glDeleteTextures().
1367 *
1368 * If we're about to delete a texture that's currently bound to any
1369 * texture unit, unbind the texture first. Decrement the reference
1370 * count on the texture object and delete it if it's zero.
1371 * Recall that texture objects can be shared among several rendering
1372 * contexts.
1373 */
1374 void GLAPIENTRY
1375 _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
1376 {
1377 GET_CURRENT_CONTEXT(ctx);
1378 GLint i;
1379
1380 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1381 _mesa_debug(ctx, "glDeleteTextures %d\n", n);
1382
1383 FLUSH_VERTICES(ctx, 0); /* too complex */
1384
1385 if (!textures)
1386 return;
1387
1388 for (i = 0; i < n; i++) {
1389 if (textures[i] > 0) {
1390 struct gl_texture_object *delObj
1391 = _mesa_lookup_texture(ctx, textures[i]);
1392
1393 if (delObj) {
1394 _mesa_lock_texture(ctx, delObj);
1395
1396 /* Check if texture is bound to any framebuffer objects.
1397 * If so, unbind.
1398 * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1399 */
1400 unbind_texobj_from_fbo(ctx, delObj);
1401
1402 /* Check if this texture is currently bound to any texture units.
1403 * If so, unbind it.
1404 */
1405 unbind_texobj_from_texunits(ctx, delObj);
1406
1407 /* Check if this texture is currently bound to any shader
1408 * image unit. If so, unbind it.
1409 * See section 3.9.X of GL_ARB_shader_image_load_store.
1410 */
1411 unbind_texobj_from_image_units(ctx, delObj);
1412
1413 _mesa_unlock_texture(ctx, delObj);
1414
1415 ctx->NewState |= _NEW_TEXTURE;
1416
1417 /* The texture _name_ is now free for re-use.
1418 * Remove it from the hash table now.
1419 */
1420 mtx_lock(&ctx->Shared->Mutex);
1421 _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
1422 mtx_unlock(&ctx->Shared->Mutex);
1423
1424 /* Unreference the texobj. If refcount hits zero, the texture
1425 * will be deleted.
1426 */
1427 _mesa_reference_texobj(&delObj, NULL);
1428 }
1429 }
1430 }
1431 }
1432
1433
1434 /**
1435 * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1436 * into the corresponding Mesa texture target index.
1437 * Note that proxy targets are not valid here.
1438 * \return TEXTURE_x_INDEX or -1 if target is invalid
1439 */
1440 int
1441 _mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target)
1442 {
1443 switch (target) {
1444 case GL_TEXTURE_1D:
1445 return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1446 case GL_TEXTURE_2D:
1447 return TEXTURE_2D_INDEX;
1448 case GL_TEXTURE_3D:
1449 return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1;
1450 case GL_TEXTURE_CUBE_MAP:
1451 return ctx->Extensions.ARB_texture_cube_map
1452 ? TEXTURE_CUBE_INDEX : -1;
1453 case GL_TEXTURE_RECTANGLE:
1454 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1455 ? TEXTURE_RECT_INDEX : -1;
1456 case GL_TEXTURE_1D_ARRAY:
1457 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array
1458 ? TEXTURE_1D_ARRAY_INDEX : -1;
1459 case GL_TEXTURE_2D_ARRAY:
1460 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1461 || _mesa_is_gles3(ctx)
1462 ? TEXTURE_2D_ARRAY_INDEX : -1;
1463 case GL_TEXTURE_BUFFER:
1464 return ctx->API == API_OPENGL_CORE &&
1465 ctx->Extensions.ARB_texture_buffer_object ?
1466 TEXTURE_BUFFER_INDEX : -1;
1467 case GL_TEXTURE_EXTERNAL_OES:
1468 return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1469 ? TEXTURE_EXTERNAL_INDEX : -1;
1470 case GL_TEXTURE_CUBE_MAP_ARRAY:
1471 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_cube_map_array
1472 ? TEXTURE_CUBE_ARRAY_INDEX : -1;
1473 case GL_TEXTURE_2D_MULTISAMPLE:
1474 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample
1475 ? TEXTURE_2D_MULTISAMPLE_INDEX: -1;
1476 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1477 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample
1478 ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1;
1479 default:
1480 return -1;
1481 }
1482 }
1483
1484
1485 /**
1486 * Bind a named texture to a texturing target.
1487 *
1488 * \param target texture target.
1489 * \param texName texture name.
1490 *
1491 * \sa glBindTexture().
1492 *
1493 * Determines the old texture object bound and returns immediately if rebinding
1494 * the same texture. Get the current texture which is either a default texture
1495 * if name is null, a named texture from the hash, or a new texture if the
1496 * given texture name is new. Increments its reference count, binds it, and
1497 * calls dd_function_table::BindTexture. Decrements the old texture reference
1498 * count and deletes it if it reaches zero.
1499 */
1500 void GLAPIENTRY
1501 _mesa_BindTexture( GLenum target, GLuint texName )
1502 {
1503 GET_CURRENT_CONTEXT(ctx);
1504 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
1505 struct gl_texture_object *newTexObj = NULL;
1506 GLint targetIndex;
1507
1508 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1509 _mesa_debug(ctx, "glBindTexture %s %d\n",
1510 _mesa_lookup_enum_by_nr(target), (GLint) texName);
1511
1512 targetIndex = _mesa_tex_target_to_index(ctx, target);
1513 if (targetIndex < 0) {
1514 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
1515 return;
1516 }
1517 assert(targetIndex < NUM_TEXTURE_TARGETS);
1518
1519 /*
1520 * Get pointer to new texture object (newTexObj)
1521 */
1522 if (texName == 0) {
1523 /* Use a default texture object */
1524 newTexObj = ctx->Shared->DefaultTex[targetIndex];
1525 }
1526 else {
1527 /* non-default texture object */
1528 newTexObj = _mesa_lookup_texture(ctx, texName);
1529 if (newTexObj) {
1530 /* error checking */
1531 if (newTexObj->Target != 0 && newTexObj->Target != target) {
1532 /* The named texture object's target doesn't match the
1533 * given target
1534 */
1535 _mesa_error( ctx, GL_INVALID_OPERATION,
1536 "glBindTexture(target mismatch)" );
1537 return;
1538 }
1539 if (newTexObj->Target == 0) {
1540 finish_texture_init(ctx, target, newTexObj);
1541 }
1542 }
1543 else {
1544 if (ctx->API == API_OPENGL_CORE) {
1545 _mesa_error(ctx, GL_INVALID_OPERATION,
1546 "glBindTexture(non-gen name)");
1547 return;
1548 }
1549
1550 /* if this is a new texture id, allocate a texture object now */
1551 newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
1552 if (!newTexObj) {
1553 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
1554 return;
1555 }
1556
1557 /* and insert it into hash table */
1558 mtx_lock(&ctx->Shared->Mutex);
1559 _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
1560 mtx_unlock(&ctx->Shared->Mutex);
1561 }
1562 newTexObj->Target = target;
1563 newTexObj->TargetIndex = targetIndex;
1564 }
1565
1566 assert(valid_texture_object(newTexObj));
1567
1568 /* Check if this texture is only used by this context and is already bound.
1569 * If so, just return.
1570 */
1571 {
1572 GLboolean early_out;
1573 mtx_lock(&ctx->Shared->Mutex);
1574 early_out = ((ctx->Shared->RefCount == 1)
1575 && (newTexObj == texUnit->CurrentTex[targetIndex]));
1576 mtx_unlock(&ctx->Shared->Mutex);
1577 if (early_out) {
1578 return;
1579 }
1580 }
1581
1582 /* flush before changing binding */
1583 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1584
1585 /* Do the actual binding. The refcount on the previously bound
1586 * texture object will be decremented. It'll be deleted if the
1587 * count hits zero.
1588 */
1589 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
1590 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1591 ctx->Texture.CurrentUnit + 1);
1592 ASSERT(texUnit->CurrentTex[targetIndex]);
1593
1594 if (texName != 0)
1595 texUnit->_BoundTextures |= (1 << targetIndex);
1596 else
1597 texUnit->_BoundTextures &= ~(1 << targetIndex);
1598
1599 /* Pass BindTexture call to device driver */
1600 if (ctx->Driver.BindTexture)
1601 ctx->Driver.BindTexture(ctx, ctx->Texture.CurrentUnit, target, newTexObj);
1602 }
1603
1604 /**
1605 * Do the actual binding to a numbered texture unit.
1606 * The refcount on the previously bound
1607 * texture object will be decremented. It'll be deleted if the
1608 * count hits zero.
1609 */
1610 void
1611 _mesa_bind_texture_unit(struct gl_context *ctx,
1612 GLuint unit,
1613 struct gl_texture_object *texObj)
1614 {
1615 struct gl_texture_unit *texUnit;
1616
1617 /* Get the texture unit (this is an array look-up) */
1618 texUnit = _mesa_get_tex_unit_err(ctx, unit, "glBindTextureUnit");
1619 if (!texUnit)
1620 return;
1621
1622 /* Check if this texture is only used by this context and is already bound.
1623 * If so, just return.
1624 */
1625 {
1626 bool early_out;
1627 mtx_lock(&ctx->Shared->Mutex);
1628 early_out = ((ctx->Shared->RefCount == 1)
1629 && (texObj == texUnit->CurrentTex[texObj->TargetIndex]));
1630 mtx_unlock(&ctx->Shared->Mutex);
1631 if (early_out) {
1632 return;
1633 }
1634 }
1635
1636 /* flush before changing binding */
1637 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1638
1639 _mesa_reference_texobj(&texUnit->CurrentTex[texObj->TargetIndex],
1640 texObj);
1641 ASSERT(texUnit->CurrentTex[texObj->TargetIndex]);
1642 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1643 unit + 1);
1644 texUnit->_BoundTextures |= (1 << texObj->TargetIndex);
1645
1646
1647 /* Pass BindTexture call to device driver */
1648 if (ctx->Driver.BindTexture) {
1649 ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj);
1650 }
1651 }
1652
1653 /**
1654 * Bind a named texture to the specified texture unit.
1655 *
1656 * \param unit texture unit.
1657 * \param texture texture name.
1658 *
1659 * \sa glBindTexture().
1660 *
1661 * If the named texture is 0, this will reset each target for the specified
1662 * texture unit to its default texture.
1663 * If the named texture is not 0 or a recognized texture name, this throws
1664 * GL_INVALID_OPERATION.
1665 */
1666 void GLAPIENTRY
1667 _mesa_BindTextureUnit(GLuint unit, GLuint texture)
1668 {
1669 GET_CURRENT_CONTEXT(ctx);
1670 struct gl_texture_object *texObj;
1671
1672 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1673 _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
1674 _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture);
1675
1676 /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
1677 * (20141030) says:
1678 * "When texture is zero, each of the targets enumerated at the
1679 * beginning of this section is reset to its default texture for the
1680 * corresponding texture image unit."
1681 */
1682 if (texture == 0) {
1683 unbind_textures_from_unit(ctx, unit);
1684 return;
1685 }
1686
1687 /* Get the non-default texture object */
1688 texObj = _mesa_lookup_texture(ctx, texture);
1689
1690 /* Error checking */
1691 if (!texObj) {
1692 _mesa_error(ctx, GL_INVALID_OPERATION,
1693 "glBindTextureUnit(non-gen name)");
1694 return;
1695 }
1696 if (texObj->Target == 0) {
1697 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTextureUnit(target)");
1698 return;
1699 }
1700 assert(valid_texture_object(texObj));
1701
1702 _mesa_bind_texture_unit(ctx, unit, texObj);
1703 }
1704
1705
1706 void GLAPIENTRY
1707 _mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
1708 {
1709 GET_CURRENT_CONTEXT(ctx);
1710 GLint i;
1711
1712 /* The ARB_multi_bind spec says:
1713 *
1714 * "An INVALID_OPERATION error is generated if <first> + <count>
1715 * is greater than the number of texture image units supported
1716 * by the implementation."
1717 */
1718 if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
1719 _mesa_error(ctx, GL_INVALID_OPERATION,
1720 "glBindTextures(first=%u + count=%d > the value of "
1721 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
1722 first, count, ctx->Const.MaxCombinedTextureImageUnits);
1723 return;
1724 }
1725
1726 /* Flush before changing bindings */
1727 FLUSH_VERTICES(ctx, 0);
1728
1729 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1730 first + count);
1731
1732 if (textures) {
1733 /* Note that the error semantics for multi-bind commands differ from
1734 * those of other GL commands.
1735 *
1736 * The issues section in the ARB_multi_bind spec says:
1737 *
1738 * "(11) Typically, OpenGL specifies that if an error is generated by
1739 * a command, that command has no effect. This is somewhat
1740 * unfortunate for multi-bind commands, because it would require
1741 * a first pass to scan the entire list of bound objects for
1742 * errors and then a second pass to actually perform the
1743 * bindings. Should we have different error semantics?
1744 *
1745 * RESOLVED: Yes. In this specification, when the parameters for
1746 * one of the <count> binding points are invalid, that binding
1747 * point is not updated and an error will be generated. However,
1748 * other binding points in the same command will be updated if
1749 * their parameters are valid and no other error occurs."
1750 */
1751
1752 _mesa_begin_texture_lookups(ctx);
1753
1754 for (i = 0; i < count; i++) {
1755 if (textures[i] != 0) {
1756 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
1757 struct gl_texture_object *current = texUnit->_Current;
1758 struct gl_texture_object *texObj;
1759
1760 if (current && current->Name == textures[i])
1761 texObj = current;
1762 else
1763 texObj = _mesa_lookup_texture_locked(ctx, textures[i]);
1764
1765 if (texObj && texObj->Target != 0) {
1766 const gl_texture_index targetIndex = texObj->TargetIndex;
1767
1768 if (texUnit->CurrentTex[targetIndex] != texObj) {
1769 /* Do the actual binding. The refcount on the previously
1770 * bound texture object will be decremented. It will be
1771 * deleted if the count hits zero.
1772 */
1773 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex],
1774 texObj);
1775
1776 texUnit->_BoundTextures |= (1 << targetIndex);
1777 ctx->NewState |= _NEW_TEXTURE;
1778
1779 /* Pass the BindTexture call to the device driver */
1780 if (ctx->Driver.BindTexture)
1781 ctx->Driver.BindTexture(ctx, first + i,
1782 texObj->Target, texObj);
1783 }
1784 } else {
1785 /* The ARB_multi_bind spec says:
1786 *
1787 * "An INVALID_OPERATION error is generated if any value
1788 * in <textures> is not zero or the name of an existing
1789 * texture object (per binding)."
1790 */
1791 _mesa_error(ctx, GL_INVALID_OPERATION,
1792 "glBindTextures(textures[%d]=%u is not zero "
1793 "or the name of an existing texture object)",
1794 i, textures[i]);
1795 }
1796 } else {
1797 unbind_textures_from_unit(ctx, first + i);
1798 }
1799 }
1800
1801 _mesa_end_texture_lookups(ctx);
1802 } else {
1803 /* Unbind all textures in the range <first> through <first>+<count>-1 */
1804 for (i = 0; i < count; i++)
1805 unbind_textures_from_unit(ctx, first + i);
1806 }
1807 }
1808
1809
1810 /**
1811 * Set texture priorities.
1812 *
1813 * \param n number of textures.
1814 * \param texName texture names.
1815 * \param priorities corresponding texture priorities.
1816 *
1817 * \sa glPrioritizeTextures().
1818 *
1819 * Looks up each texture in the hash, clamps the corresponding priority between
1820 * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
1821 */
1822 void GLAPIENTRY
1823 _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
1824 const GLclampf *priorities )
1825 {
1826 GET_CURRENT_CONTEXT(ctx);
1827 GLint i;
1828
1829 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1830 _mesa_debug(ctx, "glPrioritizeTextures %d\n", n);
1831
1832 FLUSH_VERTICES(ctx, 0);
1833
1834 if (n < 0) {
1835 _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
1836 return;
1837 }
1838
1839 if (!priorities)
1840 return;
1841
1842 for (i = 0; i < n; i++) {
1843 if (texName[i] > 0) {
1844 struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
1845 if (t) {
1846 t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
1847 }
1848 }
1849 }
1850
1851 ctx->NewState |= _NEW_TEXTURE;
1852 }
1853
1854
1855
1856 /**
1857 * See if textures are loaded in texture memory.
1858 *
1859 * \param n number of textures to query.
1860 * \param texName array with the texture names.
1861 * \param residences array which will hold the residence status.
1862 *
1863 * \return GL_TRUE if all textures are resident and
1864 * residences is left unchanged,
1865 *
1866 * Note: we assume all textures are always resident
1867 */
1868 GLboolean GLAPIENTRY
1869 _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
1870 GLboolean *residences)
1871 {
1872 GET_CURRENT_CONTEXT(ctx);
1873 GLboolean allResident = GL_TRUE;
1874 GLint i;
1875 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1876
1877 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1878 _mesa_debug(ctx, "glAreTexturesResident %d\n", n);
1879
1880 if (n < 0) {
1881 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
1882 return GL_FALSE;
1883 }
1884
1885 if (!texName || !residences)
1886 return GL_FALSE;
1887
1888 /* We only do error checking on the texture names */
1889 for (i = 0; i < n; i++) {
1890 struct gl_texture_object *t;
1891 if (texName[i] == 0) {
1892 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1893 return GL_FALSE;
1894 }
1895 t = _mesa_lookup_texture(ctx, texName[i]);
1896 if (!t) {
1897 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1898 return GL_FALSE;
1899 }
1900 }
1901
1902 return allResident;
1903 }
1904
1905
1906 /**
1907 * See if a name corresponds to a texture.
1908 *
1909 * \param texture texture name.
1910 *
1911 * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
1912 * otherwise.
1913 *
1914 * \sa glIsTexture().
1915 *
1916 * Calls _mesa_HashLookup().
1917 */
1918 GLboolean GLAPIENTRY
1919 _mesa_IsTexture( GLuint texture )
1920 {
1921 struct gl_texture_object *t;
1922 GET_CURRENT_CONTEXT(ctx);
1923 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1924
1925 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1926 _mesa_debug(ctx, "glIsTexture %d\n", texture);
1927
1928 if (!texture)
1929 return GL_FALSE;
1930
1931 t = _mesa_lookup_texture(ctx, texture);
1932
1933 /* IsTexture is true only after object has been bound once. */
1934 return t && t->Target;
1935 }
1936
1937
1938 /**
1939 * Simplest implementation of texture locking: grab the shared tex
1940 * mutex. Examine the shared context state timestamp and if there has
1941 * been a change, set the appropriate bits in ctx->NewState.
1942 *
1943 * This is used to deal with synchronizing things when a texture object
1944 * is used/modified by different contexts (or threads) which are sharing
1945 * the texture.
1946 *
1947 * See also _mesa_lock/unlock_texture() in teximage.h
1948 */
1949 void
1950 _mesa_lock_context_textures( struct gl_context *ctx )
1951 {
1952 mtx_lock(&ctx->Shared->TexMutex);
1953
1954 if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
1955 ctx->NewState |= _NEW_TEXTURE;
1956 ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
1957 }
1958 }
1959
1960
1961 void
1962 _mesa_unlock_context_textures( struct gl_context *ctx )
1963 {
1964 assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
1965 mtx_unlock(&ctx->Shared->TexMutex);
1966 }
1967
1968
1969 void GLAPIENTRY
1970 _mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
1971 GLint yoffset, GLint zoffset, GLsizei width,
1972 GLsizei height, GLsizei depth)
1973 {
1974 struct gl_texture_object *t;
1975 struct gl_texture_image *image;
1976 GET_CURRENT_CONTEXT(ctx);
1977
1978 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1979 _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture);
1980
1981 t = invalidate_tex_image_error_check(ctx, texture, level,
1982 "glInvalidateTexSubImage");
1983
1984 /* The GL_ARB_invalidate_subdata spec says:
1985 *
1986 * "...the specified subregion must be between -<b> and <dim>+<b> where
1987 * <dim> is the size of the dimension of the texture image, and <b> is
1988 * the size of the border of that texture image, otherwise
1989 * INVALID_VALUE is generated (border is not applied to dimensions that
1990 * don't exist in a given texture target)."
1991 */
1992 image = t->Image[0][level];
1993 if (image) {
1994 int xBorder;
1995 int yBorder;
1996 int zBorder;
1997 int imageWidth;
1998 int imageHeight;
1999 int imageDepth;
2000
2001 /* The GL_ARB_invalidate_subdata spec says:
2002 *
2003 * "For texture targets that don't have certain dimensions, this
2004 * command treats those dimensions as having a size of 1. For
2005 * example, to invalidate a portion of a two-dimensional texture,
2006 * the application would use <zoffset> equal to zero and <depth>
2007 * equal to one."
2008 */
2009 switch (t->Target) {
2010 case GL_TEXTURE_BUFFER:
2011 xBorder = 0;
2012 yBorder = 0;
2013 zBorder = 0;
2014 imageWidth = 1;
2015 imageHeight = 1;
2016 imageDepth = 1;
2017 break;
2018 case GL_TEXTURE_1D:
2019 xBorder = image->Border;
2020 yBorder = 0;
2021 zBorder = 0;
2022 imageWidth = image->Width;
2023 imageHeight = 1;
2024 imageDepth = 1;
2025 break;
2026 case GL_TEXTURE_1D_ARRAY:
2027 xBorder = image->Border;
2028 yBorder = 0;
2029 zBorder = 0;
2030 imageWidth = image->Width;
2031 imageHeight = image->Height;
2032 imageDepth = 1;
2033 break;
2034 case GL_TEXTURE_2D:
2035 case GL_TEXTURE_CUBE_MAP:
2036 case GL_TEXTURE_RECTANGLE:
2037 case GL_TEXTURE_2D_MULTISAMPLE:
2038 xBorder = image->Border;
2039 yBorder = image->Border;
2040 zBorder = 0;
2041 imageWidth = image->Width;
2042 imageHeight = image->Height;
2043 imageDepth = 1;
2044 break;
2045 case GL_TEXTURE_2D_ARRAY:
2046 case GL_TEXTURE_CUBE_MAP_ARRAY:
2047 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2048 xBorder = image->Border;
2049 yBorder = image->Border;
2050 zBorder = 0;
2051 imageWidth = image->Width;
2052 imageHeight = image->Height;
2053 imageDepth = image->Depth;
2054 break;
2055 case GL_TEXTURE_3D:
2056 xBorder = image->Border;
2057 yBorder = image->Border;
2058 zBorder = image->Border;
2059 imageWidth = image->Width;
2060 imageHeight = image->Height;
2061 imageDepth = image->Depth;
2062 break;
2063 default:
2064 assert(!"Should not get here.");
2065 xBorder = 0;
2066 yBorder = 0;
2067 zBorder = 0;
2068 imageWidth = 0;
2069 imageHeight = 0;
2070 imageDepth = 0;
2071 break;
2072 }
2073
2074 if (xoffset < -xBorder) {
2075 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
2076 return;
2077 }
2078
2079 if (xoffset + width > imageWidth + xBorder) {
2080 _mesa_error(ctx, GL_INVALID_VALUE,
2081 "glInvalidateSubTexImage(xoffset+width)");
2082 return;
2083 }
2084
2085 if (yoffset < -yBorder) {
2086 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
2087 return;
2088 }
2089
2090 if (yoffset + height > imageHeight + yBorder) {
2091 _mesa_error(ctx, GL_INVALID_VALUE,
2092 "glInvalidateSubTexImage(yoffset+height)");
2093 return;
2094 }
2095
2096 if (zoffset < -zBorder) {
2097 _mesa_error(ctx, GL_INVALID_VALUE,
2098 "glInvalidateSubTexImage(zoffset)");
2099 return;
2100 }
2101
2102 if (zoffset + depth > imageDepth + zBorder) {
2103 _mesa_error(ctx, GL_INVALID_VALUE,
2104 "glInvalidateSubTexImage(zoffset+depth)");
2105 return;
2106 }
2107 }
2108
2109 /* We don't actually do anything for this yet. Just return after
2110 * validating the parameters and generating the required errors.
2111 */
2112 return;
2113 }
2114
2115
2116 void GLAPIENTRY
2117 _mesa_InvalidateTexImage(GLuint texture, GLint level)
2118 {
2119 GET_CURRENT_CONTEXT(ctx);
2120
2121 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2122 _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level);
2123
2124 invalidate_tex_image_error_check(ctx, texture, level,
2125 "glInvalidateTexImage");
2126
2127 /* We don't actually do anything for this yet. Just return after
2128 * validating the parameters and generating the required errors.
2129 */
2130 return;
2131 }
2132
2133 /*@}*/