a99dd7ad7c7eabe80946385a9d5b749531381aaa
[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 GLboolean
814 _mesa_cube_level_complete(const struct gl_texture_object *texObj,
815 const GLint level)
816 {
817 const struct gl_texture_image *img0, *img;
818 GLuint face;
819
820 if (texObj->Target != GL_TEXTURE_CUBE_MAP)
821 return GL_FALSE;
822
823 if ((level < 0) || (level >= MAX_TEXTURE_LEVELS))
824 return GL_FALSE;
825
826 /* check first face */
827 img0 = texObj->Image[0][level];
828 if (!img0 ||
829 img0->Width < 1 ||
830 img0->Width != img0->Height)
831 return GL_FALSE;
832
833 /* check remaining faces vs. first face */
834 for (face = 1; face < 6; face++) {
835 img = texObj->Image[face][level];
836 if (!img ||
837 img->Width != img0->Width ||
838 img->Height != img0->Height ||
839 img->TexFormat != img0->TexFormat)
840 return GL_FALSE;
841 }
842
843 return GL_TRUE;
844 }
845
846 /**
847 * Check if the given cube map texture is "cube complete" as defined in
848 * the OpenGL specification.
849 */
850 GLboolean
851 _mesa_cube_complete(const struct gl_texture_object *texObj)
852 {
853 return _mesa_cube_level_complete(texObj, texObj->BaseLevel);
854 }
855
856 /**
857 * Mark a texture object dirty. It forces the object to be incomplete
858 * and forces the context to re-validate its state.
859 *
860 * \param ctx GL context.
861 * \param texObj texture object.
862 */
863 void
864 _mesa_dirty_texobj(struct gl_context *ctx, struct gl_texture_object *texObj)
865 {
866 texObj->_BaseComplete = GL_FALSE;
867 texObj->_MipmapComplete = GL_FALSE;
868 ctx->NewState |= _NEW_TEXTURE;
869 }
870
871
872 /**
873 * Return pointer to a default/fallback texture of the given type/target.
874 * The texture is an RGBA texture with all texels = (0,0,0,1).
875 * That's the value a GLSL sampler should get when sampling from an
876 * incomplete texture.
877 */
878 struct gl_texture_object *
879 _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex)
880 {
881 if (!ctx->Shared->FallbackTex[tex]) {
882 /* create fallback texture now */
883 const GLsizei width = 1, height = 1;
884 GLsizei depth = 1;
885 GLubyte texel[24];
886 struct gl_texture_object *texObj;
887 struct gl_texture_image *texImage;
888 mesa_format texFormat;
889 GLuint dims, face, numFaces = 1;
890 GLenum target;
891
892 for (face = 0; face < 6; face++) {
893 texel[4*face + 0] =
894 texel[4*face + 1] =
895 texel[4*face + 2] = 0x0;
896 texel[4*face + 3] = 0xff;
897 }
898
899 switch (tex) {
900 case TEXTURE_2D_ARRAY_INDEX:
901 dims = 3;
902 target = GL_TEXTURE_2D_ARRAY;
903 break;
904 case TEXTURE_1D_ARRAY_INDEX:
905 dims = 2;
906 target = GL_TEXTURE_1D_ARRAY;
907 break;
908 case TEXTURE_CUBE_INDEX:
909 dims = 2;
910 target = GL_TEXTURE_CUBE_MAP;
911 numFaces = 6;
912 break;
913 case TEXTURE_3D_INDEX:
914 dims = 3;
915 target = GL_TEXTURE_3D;
916 break;
917 case TEXTURE_RECT_INDEX:
918 dims = 2;
919 target = GL_TEXTURE_RECTANGLE;
920 break;
921 case TEXTURE_2D_INDEX:
922 dims = 2;
923 target = GL_TEXTURE_2D;
924 break;
925 case TEXTURE_1D_INDEX:
926 dims = 1;
927 target = GL_TEXTURE_1D;
928 break;
929 case TEXTURE_BUFFER_INDEX:
930 dims = 0;
931 target = GL_TEXTURE_BUFFER;
932 break;
933 case TEXTURE_CUBE_ARRAY_INDEX:
934 dims = 3;
935 target = GL_TEXTURE_CUBE_MAP_ARRAY;
936 depth = 6;
937 break;
938 case TEXTURE_EXTERNAL_INDEX:
939 dims = 2;
940 target = GL_TEXTURE_EXTERNAL_OES;
941 break;
942 case TEXTURE_2D_MULTISAMPLE_INDEX:
943 dims = 2;
944 target = GL_TEXTURE_2D_MULTISAMPLE;
945 break;
946 case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX:
947 dims = 3;
948 target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
949 break;
950 default:
951 /* no-op */
952 return NULL;
953 }
954
955 /* create texture object */
956 texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
957 if (!texObj)
958 return NULL;
959
960 assert(texObj->RefCount == 1);
961 texObj->Sampler.MinFilter = GL_NEAREST;
962 texObj->Sampler.MagFilter = GL_NEAREST;
963
964 texFormat = ctx->Driver.ChooseTextureFormat(ctx, target,
965 GL_RGBA, GL_RGBA,
966 GL_UNSIGNED_BYTE);
967
968 /* need a loop here just for cube maps */
969 for (face = 0; face < numFaces; face++) {
970 GLenum faceTarget;
971
972 if (target == GL_TEXTURE_CUBE_MAP)
973 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
974 else
975 faceTarget = target;
976
977 /* initialize level[0] texture image */
978 texImage = _mesa_get_tex_image(ctx, texObj, faceTarget, 0);
979
980 _mesa_init_teximage_fields(ctx, texImage,
981 width,
982 (dims > 1) ? height : 1,
983 (dims > 2) ? depth : 1,
984 0, /* border */
985 GL_RGBA, texFormat);
986
987 ctx->Driver.TexImage(ctx, dims, texImage,
988 GL_RGBA, GL_UNSIGNED_BYTE, texel,
989 &ctx->DefaultPacking);
990 }
991
992 _mesa_test_texobj_completeness(ctx, texObj);
993 assert(texObj->_BaseComplete);
994 assert(texObj->_MipmapComplete);
995
996 ctx->Shared->FallbackTex[tex] = texObj;
997 }
998 return ctx->Shared->FallbackTex[tex];
999 }
1000
1001
1002 /**
1003 * Compute the size of the given texture object, in bytes.
1004 */
1005 static GLuint
1006 texture_size(const struct gl_texture_object *texObj)
1007 {
1008 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1009 GLuint face, level, size = 0;
1010
1011 for (face = 0; face < numFaces; face++) {
1012 for (level = 0; level < MAX_TEXTURE_LEVELS; level++) {
1013 const struct gl_texture_image *img = texObj->Image[face][level];
1014 if (img) {
1015 GLuint sz = _mesa_format_image_size(img->TexFormat, img->Width,
1016 img->Height, img->Depth);
1017 size += sz;
1018 }
1019 }
1020 }
1021
1022 return size;
1023 }
1024
1025
1026 /**
1027 * Callback called from _mesa_HashWalk()
1028 */
1029 static void
1030 count_tex_size(GLuint key, void *data, void *userData)
1031 {
1032 const struct gl_texture_object *texObj =
1033 (const struct gl_texture_object *) data;
1034 GLuint *total = (GLuint *) userData;
1035
1036 (void) key;
1037
1038 *total = *total + texture_size(texObj);
1039 }
1040
1041
1042 /**
1043 * Compute total size (in bytes) of all textures for the given context.
1044 * For debugging purposes.
1045 */
1046 GLuint
1047 _mesa_total_texture_memory(struct gl_context *ctx)
1048 {
1049 GLuint tgt, total = 0;
1050
1051 _mesa_HashWalk(ctx->Shared->TexObjects, count_tex_size, &total);
1052
1053 /* plus, the default texture objects */
1054 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
1055 total += texture_size(ctx->Shared->DefaultTex[tgt]);
1056 }
1057
1058 return total;
1059 }
1060
1061
1062 /**
1063 * Return the base format for the given texture object by looking
1064 * at the base texture image.
1065 * \return base format (such as GL_RGBA) or GL_NONE if it can't be determined
1066 */
1067 GLenum
1068 _mesa_texture_base_format(const struct gl_texture_object *texObj)
1069 {
1070 const struct gl_texture_image *texImage = _mesa_base_tex_image(texObj);
1071
1072 return texImage ? texImage->_BaseFormat : GL_NONE;
1073 }
1074
1075
1076 static struct gl_texture_object *
1077 invalidate_tex_image_error_check(struct gl_context *ctx, GLuint texture,
1078 GLint level, const char *name)
1079 {
1080 /* The GL_ARB_invalidate_subdata spec says:
1081 *
1082 * "If <texture> is zero or is not the name of a texture, the error
1083 * INVALID_VALUE is generated."
1084 *
1085 * This performs the error check in a different order than listed in the
1086 * spec. We have to get the texture object before we can validate the
1087 * other parameters against values in the texture object.
1088 */
1089 struct gl_texture_object *const t = _mesa_lookup_texture(ctx, texture);
1090 if (texture == 0 || t == NULL) {
1091 _mesa_error(ctx, GL_INVALID_VALUE, "%s(texture)", name);
1092 return NULL;
1093 }
1094
1095 /* The GL_ARB_invalidate_subdata spec says:
1096 *
1097 * "If <level> is less than zero or greater than the base 2 logarithm
1098 * of the maximum texture width, height, or depth, the error
1099 * INVALID_VALUE is generated."
1100 */
1101 if (level < 0 || level > t->MaxLevel) {
1102 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1103 return NULL;
1104 }
1105
1106 /* The GL_ARB_invalidate_subdata spec says:
1107 *
1108 * "If the target of <texture> is TEXTURE_RECTANGLE, TEXTURE_BUFFER,
1109 * TEXTURE_2D_MULTISAMPLE, or TEXTURE_2D_MULTISAMPLE_ARRAY, and <level>
1110 * is not zero, the error INVALID_VALUE is generated."
1111 */
1112 if (level != 0) {
1113 switch (t->Target) {
1114 case GL_TEXTURE_RECTANGLE:
1115 case GL_TEXTURE_BUFFER:
1116 case GL_TEXTURE_2D_MULTISAMPLE:
1117 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1118 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level)", name);
1119 return NULL;
1120
1121 default:
1122 break;
1123 }
1124 }
1125
1126 return t;
1127 }
1128
1129 /**
1130 * Wrapper for the driver function. Need this because _mesa_new_texture_object
1131 * permits a target of 0 and does not initialize targetIndex.
1132 */
1133 struct gl_texture_object *
1134 _mesa_create_nameless_texture(struct gl_context *ctx, GLenum target)
1135 {
1136 struct gl_texture_object *texObj = NULL;
1137 GLint targetIndex;
1138
1139 if (target == 0)
1140 return texObj;
1141
1142 texObj = ctx->Driver.NewTextureObject(ctx, 0, target);
1143 targetIndex = _mesa_tex_target_to_index(ctx, texObj->Target);
1144 assert(targetIndex < NUM_TEXTURE_TARGETS);
1145 texObj->TargetIndex = targetIndex;
1146
1147 return texObj;
1148 }
1149
1150 /**
1151 * Helper function for glCreateTextures and glGenTextures. Need this because
1152 * glCreateTextures should throw errors if target = 0. This is not exposed to
1153 * the rest of Mesa to encourage Mesa internals to use nameless textures,
1154 * which do not require expensive hash lookups.
1155 */
1156 static void
1157 create_textures(struct gl_context *ctx, GLenum target,
1158 GLsizei n, GLuint *textures, bool dsa)
1159 {
1160 GLuint first;
1161 GLint i;
1162 const char *func = dsa ? "Create" : "Gen";
1163
1164 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1165 _mesa_debug(ctx, "gl%sTextures %d\n", func, n);
1166
1167 if (n < 0) {
1168 _mesa_error( ctx, GL_INVALID_VALUE, "gl%sTextures(n < 0)", func );
1169 return;
1170 }
1171
1172 if (!textures)
1173 return;
1174
1175 /*
1176 * This must be atomic (generation and allocation of texture IDs)
1177 */
1178 mtx_lock(&ctx->Shared->Mutex);
1179
1180 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
1181
1182 /* Allocate new, empty texture objects */
1183 for (i = 0; i < n; i++) {
1184 struct gl_texture_object *texObj;
1185 GLint targetIndex;
1186 GLuint name = first + i;
1187 texObj = ctx->Driver.NewTextureObject(ctx, name, target);
1188 if (!texObj) {
1189 mtx_unlock(&ctx->Shared->Mutex);
1190 _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sTextures", func);
1191 return;
1192 }
1193
1194 /* Initialize the target index if target is non-zero. */
1195 if (target != 0) {
1196 targetIndex = _mesa_tex_target_to_index(ctx, texObj->Target);
1197 if (targetIndex < 0) { /* Bad Target */
1198 mtx_unlock(&ctx->Shared->Mutex);
1199 _mesa_error(ctx, GL_INVALID_ENUM, "gl%sTextures(target = %s)",
1200 func, _mesa_lookup_enum_by_nr(texObj->Target));
1201 return;
1202 }
1203 assert(targetIndex < NUM_TEXTURE_TARGETS);
1204 texObj->TargetIndex = targetIndex;
1205 }
1206
1207 /* insert into hash table */
1208 _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj);
1209
1210 textures[i] = name;
1211 }
1212
1213 mtx_unlock(&ctx->Shared->Mutex);
1214 }
1215
1216 /*@}*/
1217
1218
1219 /***********************************************************************/
1220 /** \name API functions */
1221 /*@{*/
1222
1223
1224 /**
1225 * Generate texture names.
1226 *
1227 * \param n number of texture names to be generated.
1228 * \param textures an array in which will hold the generated texture names.
1229 *
1230 * \sa glGenTextures(), glCreateTextures().
1231 *
1232 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1233 * IDs which are stored in \p textures. Corresponding empty texture
1234 * objects are also generated.
1235 */
1236 void GLAPIENTRY
1237 _mesa_GenTextures(GLsizei n, GLuint *textures)
1238 {
1239 GET_CURRENT_CONTEXT(ctx);
1240 create_textures(ctx, 0, n, textures, false);
1241 }
1242
1243 /**
1244 * Create texture objects.
1245 *
1246 * \param target the texture target for each name to be generated.
1247 * \param n number of texture names to be generated.
1248 * \param textures an array in which will hold the generated texture names.
1249 *
1250 * \sa glCreateTextures(), glGenTextures().
1251 *
1252 * Calls _mesa_HashFindFreeKeyBlock() to find a block of free texture
1253 * IDs which are stored in \p textures. Corresponding empty texture
1254 * objects are also generated.
1255 */
1256 void GLAPIENTRY
1257 _mesa_CreateTextures(GLenum target, GLsizei n, GLuint *textures)
1258 {
1259 GLint targetIndex;
1260 GET_CURRENT_CONTEXT(ctx);
1261
1262 /*
1263 * The 4.5 core profile spec (30.10.2014) doesn't specify what
1264 * glCreateTextures should do with invalid targets, which was probably an
1265 * oversight. This conforms to the spec for glBindTexture.
1266 */
1267 targetIndex = _mesa_tex_target_to_index(ctx, target);
1268 if (targetIndex < 0) {
1269 _mesa_error(ctx, GL_INVALID_ENUM, "glCreateTextures(target)");
1270 return;
1271 }
1272
1273 create_textures(ctx, target, n, textures, true);
1274 }
1275
1276 /**
1277 * Check if the given texture object is bound to the current draw or
1278 * read framebuffer. If so, Unbind it.
1279 */
1280 static void
1281 unbind_texobj_from_fbo(struct gl_context *ctx,
1282 struct gl_texture_object *texObj)
1283 {
1284 bool progress = false;
1285
1286 /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection
1287 * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec
1288 * says:
1289 *
1290 * "If a texture object is deleted while its image is attached to one
1291 * or more attachment points in the currently bound framebuffer, then
1292 * it is as if FramebufferTexture* had been called, with a texture of
1293 * zero, for each attachment point to which this image was attached in
1294 * the currently bound framebuffer. In other words, this texture image
1295 * is first detached from all attachment points in the currently bound
1296 * framebuffer. Note that the texture image is specifically not
1297 * detached from any other framebuffer objects. Detaching the texture
1298 * image from any other framebuffer objects is the responsibility of
1299 * the application."
1300 */
1301 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1302 progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj);
1303 }
1304 if (_mesa_is_user_fbo(ctx->ReadBuffer)
1305 && ctx->ReadBuffer != ctx->DrawBuffer) {
1306 progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj)
1307 || progress;
1308 }
1309
1310 if (progress)
1311 /* Vertices are already flushed by _mesa_DeleteTextures */
1312 ctx->NewState |= _NEW_BUFFERS;
1313 }
1314
1315
1316 /**
1317 * Check if the given texture object is bound to any texture image units and
1318 * unbind it if so (revert to default textures).
1319 */
1320 static void
1321 unbind_texobj_from_texunits(struct gl_context *ctx,
1322 struct gl_texture_object *texObj)
1323 {
1324 const gl_texture_index index = texObj->TargetIndex;
1325 GLuint u;
1326
1327 if (texObj->Target == 0)
1328 return;
1329
1330 for (u = 0; u < ctx->Texture.NumCurrentTexUsed; u++) {
1331 struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
1332
1333 if (texObj == unit->CurrentTex[index]) {
1334 /* Bind the default texture for this unit/target */
1335 _mesa_reference_texobj(&unit->CurrentTex[index],
1336 ctx->Shared->DefaultTex[index]);
1337 unit->_BoundTextures &= ~(1 << index);
1338 }
1339 }
1340 }
1341
1342
1343 /**
1344 * Check if the given texture object is bound to any shader image unit
1345 * and unbind it if that's the case.
1346 */
1347 static void
1348 unbind_texobj_from_image_units(struct gl_context *ctx,
1349 struct gl_texture_object *texObj)
1350 {
1351 GLuint i;
1352
1353 for (i = 0; i < ctx->Const.MaxImageUnits; i++) {
1354 struct gl_image_unit *unit = &ctx->ImageUnits[i];
1355
1356 if (texObj == unit->TexObj)
1357 _mesa_reference_texobj(&unit->TexObj, NULL);
1358 }
1359 }
1360
1361
1362 /**
1363 * Unbinds all textures bound to the given texture image unit.
1364 */
1365 static void
1366 unbind_textures_from_unit(struct gl_context *ctx, GLuint unit)
1367 {
1368 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1369
1370 while (texUnit->_BoundTextures) {
1371 const GLuint index = ffs(texUnit->_BoundTextures) - 1;
1372 struct gl_texture_object *texObj = ctx->Shared->DefaultTex[index];
1373
1374 _mesa_reference_texobj(&texUnit->CurrentTex[index], texObj);
1375
1376 /* Pass BindTexture call to device driver */
1377 if (ctx->Driver.BindTexture)
1378 ctx->Driver.BindTexture(ctx, unit, 0, texObj);
1379
1380 texUnit->_BoundTextures &= ~(1 << index);
1381 ctx->NewState |= _NEW_TEXTURE;
1382 }
1383 }
1384
1385
1386 /**
1387 * Delete named textures.
1388 *
1389 * \param n number of textures to be deleted.
1390 * \param textures array of texture IDs to be deleted.
1391 *
1392 * \sa glDeleteTextures().
1393 *
1394 * If we're about to delete a texture that's currently bound to any
1395 * texture unit, unbind the texture first. Decrement the reference
1396 * count on the texture object and delete it if it's zero.
1397 * Recall that texture objects can be shared among several rendering
1398 * contexts.
1399 */
1400 void GLAPIENTRY
1401 _mesa_DeleteTextures( GLsizei n, const GLuint *textures)
1402 {
1403 GET_CURRENT_CONTEXT(ctx);
1404 GLint i;
1405
1406 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1407 _mesa_debug(ctx, "glDeleteTextures %d\n", n);
1408
1409 if (n < 0) {
1410 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n < 0)");
1411 return;
1412 }
1413
1414 FLUSH_VERTICES(ctx, 0); /* too complex */
1415
1416 if (n < 0) {
1417 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteTextures(n)");
1418 return;
1419 }
1420
1421 if (!textures)
1422 return;
1423
1424 for (i = 0; i < n; i++) {
1425 if (textures[i] > 0) {
1426 struct gl_texture_object *delObj
1427 = _mesa_lookup_texture(ctx, textures[i]);
1428
1429 if (delObj) {
1430 _mesa_lock_texture(ctx, delObj);
1431
1432 /* Check if texture is bound to any framebuffer objects.
1433 * If so, unbind.
1434 * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1435 */
1436 unbind_texobj_from_fbo(ctx, delObj);
1437
1438 /* Check if this texture is currently bound to any texture units.
1439 * If so, unbind it.
1440 */
1441 unbind_texobj_from_texunits(ctx, delObj);
1442
1443 /* Check if this texture is currently bound to any shader
1444 * image unit. If so, unbind it.
1445 * See section 3.9.X of GL_ARB_shader_image_load_store.
1446 */
1447 unbind_texobj_from_image_units(ctx, delObj);
1448
1449 _mesa_unlock_texture(ctx, delObj);
1450
1451 ctx->NewState |= _NEW_TEXTURE;
1452
1453 /* The texture _name_ is now free for re-use.
1454 * Remove it from the hash table now.
1455 */
1456 mtx_lock(&ctx->Shared->Mutex);
1457 _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name);
1458 mtx_unlock(&ctx->Shared->Mutex);
1459
1460 /* Unreference the texobj. If refcount hits zero, the texture
1461 * will be deleted.
1462 */
1463 _mesa_reference_texobj(&delObj, NULL);
1464 }
1465 }
1466 }
1467 }
1468
1469 /**
1470 * This deletes a texObj without altering the hash table.
1471 */
1472 void
1473 _mesa_delete_nameless_texture(struct gl_context *ctx,
1474 struct gl_texture_object *texObj)
1475 {
1476 if (!texObj)
1477 return;
1478
1479 FLUSH_VERTICES(ctx, 0);
1480
1481 _mesa_lock_texture(ctx, texObj);
1482 {
1483 /* Check if texture is bound to any framebuffer objects.
1484 * If so, unbind.
1485 * See section 4.4.2.3 of GL_EXT_framebuffer_object.
1486 */
1487 unbind_texobj_from_fbo(ctx, texObj);
1488
1489 /* Check if this texture is currently bound to any texture units.
1490 * If so, unbind it.
1491 */
1492 unbind_texobj_from_texunits(ctx, texObj);
1493
1494 /* Check if this texture is currently bound to any shader
1495 * image unit. If so, unbind it.
1496 * See section 3.9.X of GL_ARB_shader_image_load_store.
1497 */
1498 unbind_texobj_from_image_units(ctx, texObj);
1499 }
1500 _mesa_unlock_texture(ctx, texObj);
1501
1502 ctx->NewState |= _NEW_TEXTURE;
1503
1504 /* Unreference the texobj. If refcount hits zero, the texture
1505 * will be deleted.
1506 */
1507 _mesa_reference_texobj(&texObj, NULL);
1508 }
1509
1510
1511 /**
1512 * Convert a GL texture target enum such as GL_TEXTURE_2D or GL_TEXTURE_3D
1513 * into the corresponding Mesa texture target index.
1514 * Note that proxy targets are not valid here.
1515 * \return TEXTURE_x_INDEX or -1 if target is invalid
1516 */
1517 int
1518 _mesa_tex_target_to_index(const struct gl_context *ctx, GLenum target)
1519 {
1520 switch (target) {
1521 case GL_TEXTURE_1D:
1522 return _mesa_is_desktop_gl(ctx) ? TEXTURE_1D_INDEX : -1;
1523 case GL_TEXTURE_2D:
1524 return TEXTURE_2D_INDEX;
1525 case GL_TEXTURE_3D:
1526 return ctx->API != API_OPENGLES ? TEXTURE_3D_INDEX : -1;
1527 case GL_TEXTURE_CUBE_MAP:
1528 return ctx->Extensions.ARB_texture_cube_map
1529 ? TEXTURE_CUBE_INDEX : -1;
1530 case GL_TEXTURE_RECTANGLE:
1531 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_texture_rectangle
1532 ? TEXTURE_RECT_INDEX : -1;
1533 case GL_TEXTURE_1D_ARRAY:
1534 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array
1535 ? TEXTURE_1D_ARRAY_INDEX : -1;
1536 case GL_TEXTURE_2D_ARRAY:
1537 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1538 || _mesa_is_gles3(ctx)
1539 ? TEXTURE_2D_ARRAY_INDEX : -1;
1540 case GL_TEXTURE_BUFFER:
1541 return ctx->API == API_OPENGL_CORE &&
1542 ctx->Extensions.ARB_texture_buffer_object ?
1543 TEXTURE_BUFFER_INDEX : -1;
1544 case GL_TEXTURE_EXTERNAL_OES:
1545 return _mesa_is_gles(ctx) && ctx->Extensions.OES_EGL_image_external
1546 ? TEXTURE_EXTERNAL_INDEX : -1;
1547 case GL_TEXTURE_CUBE_MAP_ARRAY:
1548 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_cube_map_array
1549 ? TEXTURE_CUBE_ARRAY_INDEX : -1;
1550 case GL_TEXTURE_2D_MULTISAMPLE:
1551 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample
1552 ? TEXTURE_2D_MULTISAMPLE_INDEX: -1;
1553 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1554 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample
1555 ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: -1;
1556 default:
1557 return -1;
1558 }
1559 }
1560
1561
1562 /**
1563 * Bind a named texture to a texturing target.
1564 *
1565 * \param target texture target.
1566 * \param texName texture name.
1567 *
1568 * \sa glBindTexture().
1569 *
1570 * Determines the old texture object bound and returns immediately if rebinding
1571 * the same texture. Get the current texture which is either a default texture
1572 * if name is null, a named texture from the hash, or a new texture if the
1573 * given texture name is new. Increments its reference count, binds it, and
1574 * calls dd_function_table::BindTexture. Decrements the old texture reference
1575 * count and deletes it if it reaches zero.
1576 */
1577 void GLAPIENTRY
1578 _mesa_BindTexture( GLenum target, GLuint texName )
1579 {
1580 GET_CURRENT_CONTEXT(ctx);
1581 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
1582 struct gl_texture_object *newTexObj = NULL;
1583 GLint targetIndex;
1584
1585 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1586 _mesa_debug(ctx, "glBindTexture %s %d\n",
1587 _mesa_lookup_enum_by_nr(target), (GLint) texName);
1588
1589 targetIndex = _mesa_tex_target_to_index(ctx, target);
1590 if (targetIndex < 0) {
1591 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTexture(target)");
1592 return;
1593 }
1594 assert(targetIndex < NUM_TEXTURE_TARGETS);
1595
1596 /*
1597 * Get pointer to new texture object (newTexObj)
1598 */
1599 if (texName == 0) {
1600 /* Use a default texture object */
1601 newTexObj = ctx->Shared->DefaultTex[targetIndex];
1602 }
1603 else {
1604 /* non-default texture object */
1605 newTexObj = _mesa_lookup_texture(ctx, texName);
1606 if (newTexObj) {
1607 /* error checking */
1608 if (newTexObj->Target != 0 && newTexObj->Target != target) {
1609 /* The named texture object's target doesn't match the
1610 * given target
1611 */
1612 _mesa_error( ctx, GL_INVALID_OPERATION,
1613 "glBindTexture(target mismatch)" );
1614 return;
1615 }
1616 if (newTexObj->Target == 0) {
1617 finish_texture_init(ctx, target, newTexObj);
1618 }
1619 }
1620 else {
1621 if (ctx->API == API_OPENGL_CORE) {
1622 _mesa_error(ctx, GL_INVALID_OPERATION,
1623 "glBindTexture(non-gen name)");
1624 return;
1625 }
1626
1627 /* if this is a new texture id, allocate a texture object now */
1628 newTexObj = ctx->Driver.NewTextureObject(ctx, texName, target);
1629 if (!newTexObj) {
1630 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture");
1631 return;
1632 }
1633
1634 /* and insert it into hash table */
1635 mtx_lock(&ctx->Shared->Mutex);
1636 _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj);
1637 mtx_unlock(&ctx->Shared->Mutex);
1638 }
1639 newTexObj->Target = target;
1640 newTexObj->TargetIndex = targetIndex;
1641 }
1642
1643 assert(valid_texture_object(newTexObj));
1644
1645 /* Check if this texture is only used by this context and is already bound.
1646 * If so, just return.
1647 */
1648 {
1649 GLboolean early_out;
1650 mtx_lock(&ctx->Shared->Mutex);
1651 early_out = ((ctx->Shared->RefCount == 1)
1652 && (newTexObj == texUnit->CurrentTex[targetIndex]));
1653 mtx_unlock(&ctx->Shared->Mutex);
1654 if (early_out) {
1655 return;
1656 }
1657 }
1658
1659 /* flush before changing binding */
1660 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1661
1662 /* Do the actual binding. The refcount on the previously bound
1663 * texture object will be decremented. It'll be deleted if the
1664 * count hits zero.
1665 */
1666 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex], newTexObj);
1667 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1668 ctx->Texture.CurrentUnit + 1);
1669 ASSERT(texUnit->CurrentTex[targetIndex]);
1670
1671 if (texName != 0)
1672 texUnit->_BoundTextures |= (1 << targetIndex);
1673 else
1674 texUnit->_BoundTextures &= ~(1 << targetIndex);
1675
1676 /* Pass BindTexture call to device driver */
1677 if (ctx->Driver.BindTexture)
1678 ctx->Driver.BindTexture(ctx, ctx->Texture.CurrentUnit, target, newTexObj);
1679 }
1680
1681 /**
1682 * Do the actual binding to a numbered texture unit.
1683 * The refcount on the previously bound
1684 * texture object will be decremented. It'll be deleted if the
1685 * count hits zero.
1686 */
1687 void
1688 _mesa_bind_texture_unit(struct gl_context *ctx,
1689 GLuint unit,
1690 struct gl_texture_object *texObj)
1691 {
1692 struct gl_texture_unit *texUnit;
1693
1694 /* Get the texture unit (this is an array look-up) */
1695 texUnit = _mesa_get_tex_unit_err(ctx, unit, "glBindTextureUnit");
1696 if (!texUnit)
1697 return;
1698
1699 /* Check if this texture is only used by this context and is already bound.
1700 * If so, just return.
1701 */
1702 {
1703 bool early_out;
1704 mtx_lock(&ctx->Shared->Mutex);
1705 early_out = ((ctx->Shared->RefCount == 1)
1706 && (texObj == texUnit->CurrentTex[texObj->TargetIndex]));
1707 mtx_unlock(&ctx->Shared->Mutex);
1708 if (early_out) {
1709 return;
1710 }
1711 }
1712
1713 /* flush before changing binding */
1714 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1715
1716 _mesa_reference_texobj(&texUnit->CurrentTex[texObj->TargetIndex],
1717 texObj);
1718 ASSERT(texUnit->CurrentTex[texObj->TargetIndex]);
1719 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1720 unit + 1);
1721 texUnit->_BoundTextures |= (1 << texObj->TargetIndex);
1722
1723
1724 /* Pass BindTexture call to device driver */
1725 if (ctx->Driver.BindTexture) {
1726 ctx->Driver.BindTexture(ctx, unit, texObj->Target, texObj);
1727 }
1728 }
1729
1730 /**
1731 * Bind a named texture to the specified texture unit.
1732 *
1733 * \param unit texture unit.
1734 * \param texture texture name.
1735 *
1736 * \sa glBindTexture().
1737 *
1738 * If the named texture is 0, this will reset each target for the specified
1739 * texture unit to its default texture.
1740 * If the named texture is not 0 or a recognized texture name, this throws
1741 * GL_INVALID_OPERATION.
1742 */
1743 void GLAPIENTRY
1744 _mesa_BindTextureUnit(GLuint unit, GLuint texture)
1745 {
1746 GET_CURRENT_CONTEXT(ctx);
1747 struct gl_texture_object *texObj;
1748
1749 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1750 _mesa_debug(ctx, "glBindTextureUnit %s %d\n",
1751 _mesa_lookup_enum_by_nr(GL_TEXTURE0+unit), (GLint) texture);
1752
1753 /* Section 8.1 (Texture Objects) of the OpenGL 4.5 core profile spec
1754 * (20141030) says:
1755 * "When texture is zero, each of the targets enumerated at the
1756 * beginning of this section is reset to its default texture for the
1757 * corresponding texture image unit."
1758 */
1759 if (texture == 0) {
1760 unbind_textures_from_unit(ctx, unit);
1761 return;
1762 }
1763
1764 /* Get the non-default texture object */
1765 texObj = _mesa_lookup_texture(ctx, texture);
1766
1767 /* Error checking */
1768 if (!texObj) {
1769 _mesa_error(ctx, GL_INVALID_OPERATION,
1770 "glBindTextureUnit(non-gen name)");
1771 return;
1772 }
1773 if (texObj->Target == 0) {
1774 _mesa_error(ctx, GL_INVALID_ENUM, "glBindTextureUnit(target)");
1775 return;
1776 }
1777 assert(valid_texture_object(texObj));
1778
1779 _mesa_bind_texture_unit(ctx, unit, texObj);
1780 }
1781
1782
1783 void GLAPIENTRY
1784 _mesa_BindTextures(GLuint first, GLsizei count, const GLuint *textures)
1785 {
1786 GET_CURRENT_CONTEXT(ctx);
1787 GLint i;
1788
1789 /* The ARB_multi_bind spec says:
1790 *
1791 * "An INVALID_OPERATION error is generated if <first> + <count>
1792 * is greater than the number of texture image units supported
1793 * by the implementation."
1794 */
1795 if (first + count > ctx->Const.MaxCombinedTextureImageUnits) {
1796 _mesa_error(ctx, GL_INVALID_OPERATION,
1797 "glBindTextures(first=%u + count=%d > the value of "
1798 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS=%u)",
1799 first, count, ctx->Const.MaxCombinedTextureImageUnits);
1800 return;
1801 }
1802
1803 /* Flush before changing bindings */
1804 FLUSH_VERTICES(ctx, 0);
1805
1806 ctx->Texture.NumCurrentTexUsed = MAX2(ctx->Texture.NumCurrentTexUsed,
1807 first + count);
1808
1809 if (textures) {
1810 /* Note that the error semantics for multi-bind commands differ from
1811 * those of other GL commands.
1812 *
1813 * The issues section in the ARB_multi_bind spec says:
1814 *
1815 * "(11) Typically, OpenGL specifies that if an error is generated by
1816 * a command, that command has no effect. This is somewhat
1817 * unfortunate for multi-bind commands, because it would require
1818 * a first pass to scan the entire list of bound objects for
1819 * errors and then a second pass to actually perform the
1820 * bindings. Should we have different error semantics?
1821 *
1822 * RESOLVED: Yes. In this specification, when the parameters for
1823 * one of the <count> binding points are invalid, that binding
1824 * point is not updated and an error will be generated. However,
1825 * other binding points in the same command will be updated if
1826 * their parameters are valid and no other error occurs."
1827 */
1828
1829 _mesa_begin_texture_lookups(ctx);
1830
1831 for (i = 0; i < count; i++) {
1832 if (textures[i] != 0) {
1833 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[first + i];
1834 struct gl_texture_object *current = texUnit->_Current;
1835 struct gl_texture_object *texObj;
1836
1837 if (current && current->Name == textures[i])
1838 texObj = current;
1839 else
1840 texObj = _mesa_lookup_texture_locked(ctx, textures[i]);
1841
1842 if (texObj && texObj->Target != 0) {
1843 const gl_texture_index targetIndex = texObj->TargetIndex;
1844
1845 if (texUnit->CurrentTex[targetIndex] != texObj) {
1846 /* Do the actual binding. The refcount on the previously
1847 * bound texture object will be decremented. It will be
1848 * deleted if the count hits zero.
1849 */
1850 _mesa_reference_texobj(&texUnit->CurrentTex[targetIndex],
1851 texObj);
1852
1853 texUnit->_BoundTextures |= (1 << targetIndex);
1854 ctx->NewState |= _NEW_TEXTURE;
1855
1856 /* Pass the BindTexture call to the device driver */
1857 if (ctx->Driver.BindTexture)
1858 ctx->Driver.BindTexture(ctx, first + i,
1859 texObj->Target, texObj);
1860 }
1861 } else {
1862 /* The ARB_multi_bind spec says:
1863 *
1864 * "An INVALID_OPERATION error is generated if any value
1865 * in <textures> is not zero or the name of an existing
1866 * texture object (per binding)."
1867 */
1868 _mesa_error(ctx, GL_INVALID_OPERATION,
1869 "glBindTextures(textures[%d]=%u is not zero "
1870 "or the name of an existing texture object)",
1871 i, textures[i]);
1872 }
1873 } else {
1874 unbind_textures_from_unit(ctx, first + i);
1875 }
1876 }
1877
1878 _mesa_end_texture_lookups(ctx);
1879 } else {
1880 /* Unbind all textures in the range <first> through <first>+<count>-1 */
1881 for (i = 0; i < count; i++)
1882 unbind_textures_from_unit(ctx, first + i);
1883 }
1884 }
1885
1886
1887 /**
1888 * Set texture priorities.
1889 *
1890 * \param n number of textures.
1891 * \param texName texture names.
1892 * \param priorities corresponding texture priorities.
1893 *
1894 * \sa glPrioritizeTextures().
1895 *
1896 * Looks up each texture in the hash, clamps the corresponding priority between
1897 * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture.
1898 */
1899 void GLAPIENTRY
1900 _mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
1901 const GLclampf *priorities )
1902 {
1903 GET_CURRENT_CONTEXT(ctx);
1904 GLint i;
1905
1906 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1907 _mesa_debug(ctx, "glPrioritizeTextures %d\n", n);
1908
1909 FLUSH_VERTICES(ctx, 0);
1910
1911 if (n < 0) {
1912 _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
1913 return;
1914 }
1915
1916 if (!priorities)
1917 return;
1918
1919 for (i = 0; i < n; i++) {
1920 if (texName[i] > 0) {
1921 struct gl_texture_object *t = _mesa_lookup_texture(ctx, texName[i]);
1922 if (t) {
1923 t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
1924 }
1925 }
1926 }
1927
1928 ctx->NewState |= _NEW_TEXTURE;
1929 }
1930
1931
1932
1933 /**
1934 * See if textures are loaded in texture memory.
1935 *
1936 * \param n number of textures to query.
1937 * \param texName array with the texture names.
1938 * \param residences array which will hold the residence status.
1939 *
1940 * \return GL_TRUE if all textures are resident and
1941 * residences is left unchanged,
1942 *
1943 * Note: we assume all textures are always resident
1944 */
1945 GLboolean GLAPIENTRY
1946 _mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
1947 GLboolean *residences)
1948 {
1949 GET_CURRENT_CONTEXT(ctx);
1950 GLboolean allResident = GL_TRUE;
1951 GLint i;
1952 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1953
1954 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
1955 _mesa_debug(ctx, "glAreTexturesResident %d\n", n);
1956
1957 if (n < 0) {
1958 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
1959 return GL_FALSE;
1960 }
1961
1962 if (!texName || !residences)
1963 return GL_FALSE;
1964
1965 /* We only do error checking on the texture names */
1966 for (i = 0; i < n; i++) {
1967 struct gl_texture_object *t;
1968 if (texName[i] == 0) {
1969 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1970 return GL_FALSE;
1971 }
1972 t = _mesa_lookup_texture(ctx, texName[i]);
1973 if (!t) {
1974 _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident");
1975 return GL_FALSE;
1976 }
1977 }
1978
1979 return allResident;
1980 }
1981
1982
1983 /**
1984 * See if a name corresponds to a texture.
1985 *
1986 * \param texture texture name.
1987 *
1988 * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE
1989 * otherwise.
1990 *
1991 * \sa glIsTexture().
1992 *
1993 * Calls _mesa_HashLookup().
1994 */
1995 GLboolean GLAPIENTRY
1996 _mesa_IsTexture( GLuint texture )
1997 {
1998 struct gl_texture_object *t;
1999 GET_CURRENT_CONTEXT(ctx);
2000 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2001
2002 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2003 _mesa_debug(ctx, "glIsTexture %d\n", texture);
2004
2005 if (!texture)
2006 return GL_FALSE;
2007
2008 t = _mesa_lookup_texture(ctx, texture);
2009
2010 /* IsTexture is true only after object has been bound once. */
2011 return t && t->Target;
2012 }
2013
2014
2015 /**
2016 * Simplest implementation of texture locking: grab the shared tex
2017 * mutex. Examine the shared context state timestamp and if there has
2018 * been a change, set the appropriate bits in ctx->NewState.
2019 *
2020 * This is used to deal with synchronizing things when a texture object
2021 * is used/modified by different contexts (or threads) which are sharing
2022 * the texture.
2023 *
2024 * See also _mesa_lock/unlock_texture() in teximage.h
2025 */
2026 void
2027 _mesa_lock_context_textures( struct gl_context *ctx )
2028 {
2029 mtx_lock(&ctx->Shared->TexMutex);
2030
2031 if (ctx->Shared->TextureStateStamp != ctx->TextureStateTimestamp) {
2032 ctx->NewState |= _NEW_TEXTURE;
2033 ctx->TextureStateTimestamp = ctx->Shared->TextureStateStamp;
2034 }
2035 }
2036
2037
2038 void
2039 _mesa_unlock_context_textures( struct gl_context *ctx )
2040 {
2041 assert(ctx->Shared->TextureStateStamp == ctx->TextureStateTimestamp);
2042 mtx_unlock(&ctx->Shared->TexMutex);
2043 }
2044
2045
2046 void GLAPIENTRY
2047 _mesa_InvalidateTexSubImage(GLuint texture, GLint level, GLint xoffset,
2048 GLint yoffset, GLint zoffset, GLsizei width,
2049 GLsizei height, GLsizei depth)
2050 {
2051 struct gl_texture_object *t;
2052 struct gl_texture_image *image;
2053 GET_CURRENT_CONTEXT(ctx);
2054
2055 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2056 _mesa_debug(ctx, "glInvalidateTexSubImage %d\n", texture);
2057
2058 t = invalidate_tex_image_error_check(ctx, texture, level,
2059 "glInvalidateTexSubImage");
2060
2061 /* The GL_ARB_invalidate_subdata spec says:
2062 *
2063 * "...the specified subregion must be between -<b> and <dim>+<b> where
2064 * <dim> is the size of the dimension of the texture image, and <b> is
2065 * the size of the border of that texture image, otherwise
2066 * INVALID_VALUE is generated (border is not applied to dimensions that
2067 * don't exist in a given texture target)."
2068 */
2069 image = t->Image[0][level];
2070 if (image) {
2071 int xBorder;
2072 int yBorder;
2073 int zBorder;
2074 int imageWidth;
2075 int imageHeight;
2076 int imageDepth;
2077
2078 /* The GL_ARB_invalidate_subdata spec says:
2079 *
2080 * "For texture targets that don't have certain dimensions, this
2081 * command treats those dimensions as having a size of 1. For
2082 * example, to invalidate a portion of a two-dimensional texture,
2083 * the application would use <zoffset> equal to zero and <depth>
2084 * equal to one."
2085 */
2086 switch (t->Target) {
2087 case GL_TEXTURE_BUFFER:
2088 xBorder = 0;
2089 yBorder = 0;
2090 zBorder = 0;
2091 imageWidth = 1;
2092 imageHeight = 1;
2093 imageDepth = 1;
2094 break;
2095 case GL_TEXTURE_1D:
2096 xBorder = image->Border;
2097 yBorder = 0;
2098 zBorder = 0;
2099 imageWidth = image->Width;
2100 imageHeight = 1;
2101 imageDepth = 1;
2102 break;
2103 case GL_TEXTURE_1D_ARRAY:
2104 xBorder = image->Border;
2105 yBorder = 0;
2106 zBorder = 0;
2107 imageWidth = image->Width;
2108 imageHeight = image->Height;
2109 imageDepth = 1;
2110 break;
2111 case GL_TEXTURE_2D:
2112 case GL_TEXTURE_CUBE_MAP:
2113 case GL_TEXTURE_RECTANGLE:
2114 case GL_TEXTURE_2D_MULTISAMPLE:
2115 xBorder = image->Border;
2116 yBorder = image->Border;
2117 zBorder = 0;
2118 imageWidth = image->Width;
2119 imageHeight = image->Height;
2120 imageDepth = 1;
2121 break;
2122 case GL_TEXTURE_2D_ARRAY:
2123 case GL_TEXTURE_CUBE_MAP_ARRAY:
2124 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2125 xBorder = image->Border;
2126 yBorder = image->Border;
2127 zBorder = 0;
2128 imageWidth = image->Width;
2129 imageHeight = image->Height;
2130 imageDepth = image->Depth;
2131 break;
2132 case GL_TEXTURE_3D:
2133 xBorder = image->Border;
2134 yBorder = image->Border;
2135 zBorder = image->Border;
2136 imageWidth = image->Width;
2137 imageHeight = image->Height;
2138 imageDepth = image->Depth;
2139 break;
2140 default:
2141 assert(!"Should not get here.");
2142 xBorder = 0;
2143 yBorder = 0;
2144 zBorder = 0;
2145 imageWidth = 0;
2146 imageHeight = 0;
2147 imageDepth = 0;
2148 break;
2149 }
2150
2151 if (xoffset < -xBorder) {
2152 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(xoffset)");
2153 return;
2154 }
2155
2156 if (xoffset + width > imageWidth + xBorder) {
2157 _mesa_error(ctx, GL_INVALID_VALUE,
2158 "glInvalidateSubTexImage(xoffset+width)");
2159 return;
2160 }
2161
2162 if (yoffset < -yBorder) {
2163 _mesa_error(ctx, GL_INVALID_VALUE, "glInvalidateSubTexImage(yoffset)");
2164 return;
2165 }
2166
2167 if (yoffset + height > imageHeight + yBorder) {
2168 _mesa_error(ctx, GL_INVALID_VALUE,
2169 "glInvalidateSubTexImage(yoffset+height)");
2170 return;
2171 }
2172
2173 if (zoffset < -zBorder) {
2174 _mesa_error(ctx, GL_INVALID_VALUE,
2175 "glInvalidateSubTexImage(zoffset)");
2176 return;
2177 }
2178
2179 if (zoffset + depth > imageDepth + zBorder) {
2180 _mesa_error(ctx, GL_INVALID_VALUE,
2181 "glInvalidateSubTexImage(zoffset+depth)");
2182 return;
2183 }
2184 }
2185
2186 /* We don't actually do anything for this yet. Just return after
2187 * validating the parameters and generating the required errors.
2188 */
2189 return;
2190 }
2191
2192
2193 void GLAPIENTRY
2194 _mesa_InvalidateTexImage(GLuint texture, GLint level)
2195 {
2196 GET_CURRENT_CONTEXT(ctx);
2197
2198 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2199 _mesa_debug(ctx, "glInvalidateTexImage(%d, %d)\n", texture, level);
2200
2201 invalidate_tex_image_error_check(ctx, texture, level,
2202 "glInvalidateTexImage");
2203
2204 /* We don't actually do anything for this yet. Just return after
2205 * validating the parameters and generating the required errors.
2206 */
2207 return;
2208 }
2209
2210 /*@}*/