blob: e06f8cd277cc992c23dfd99c5be1780bf80d11d9 [file] [log] [blame]
Brian Paul507d83e2000-08-03 14:03:17 +00001/* $Id: texobj.c,v 1.26 2000/08/03 14:03:17 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paul6d047252000-08-02 00:38:25 +00005 * Version: 3.5
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paulbb797902000-01-24 16:19:54 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
jtgafb833d1999-08-19 00:55:39 +000026
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
Brian Paul4bdcfe52000-04-17 17:57:04 +000032#include "colortab.h"
jtgafb833d1999-08-19 00:55:39 +000033#include "context.h"
34#include "enums.h"
35#include "hash.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000036#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000037#include "teximage.h"
38#include "texstate.h"
39#include "texobj.h"
40#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000041#endif
42
43
44
45/*
46 * Allocate a new texture object and add it to the linked list of texture
47 * objects. If name>0 then also insert the new texture object into the hash
48 * table.
49 * Input: shared - the shared GL state structure to contain the texture object
50 * name - integer name for the texture object
Brian Paulfc4b4432000-05-23 15:17:12 +000051 * dimensions - either 1, 2, 3 or 6 (cube map)
jtgafb833d1999-08-19 00:55:39 +000052 * Return: pointer to new texture object
53 */
54struct gl_texture_object *
55gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name,
56 GLuint dimensions)
57{
58 struct gl_texture_object *obj;
59
Brian Paulfc4b4432000-05-23 15:17:12 +000060 ASSERT(dimensions <= 3 || dimensions == 6);
jtgafb833d1999-08-19 00:55:39 +000061
Brian Paul420ef641999-12-01 21:10:08 +000062 obj = CALLOC_STRUCT(gl_texture_object);
63
jtgafb833d1999-08-19 00:55:39 +000064 if (obj) {
65 /* init the non-zero fields */
Brian Paul6e6d4c61999-10-09 20:17:07 +000066 obj->RefCount = 1;
jtgafb833d1999-08-19 00:55:39 +000067 obj->Name = name;
68 obj->Dimensions = dimensions;
Brian Paul6d047252000-08-02 00:38:25 +000069 obj->Priority = 1.0F;
jtgafb833d1999-08-19 00:55:39 +000070 obj->WrapS = GL_REPEAT;
71 obj->WrapT = GL_REPEAT;
72 obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
73 obj->MagFilter = GL_LINEAR;
74 obj->MinLod = -1000.0;
75 obj->MaxLod = 1000.0;
76 obj->BaseLevel = 0;
77 obj->MaxLevel = 1000;
78 obj->MinMagThresh = 0.0F;
Brian Paul4bdcfe52000-04-17 17:57:04 +000079 _mesa_init_colortable(&obj->Palette);
jtgafb833d1999-08-19 00:55:39 +000080
81 /* insert into linked list */
82 if (shared) {
Brian Paul9560f052000-01-31 23:11:39 +000083 _glthread_LOCK_MUTEX(shared->Mutex);
jtgafb833d1999-08-19 00:55:39 +000084 obj->Next = shared->TexObjectList;
85 shared->TexObjectList = obj;
Brian Paul9560f052000-01-31 23:11:39 +000086 _glthread_UNLOCK_MUTEX(shared->Mutex);
jtgafb833d1999-08-19 00:55:39 +000087 }
88
89 if (name > 0) {
90 /* insert into hash table */
Brian Paulbb797902000-01-24 16:19:54 +000091 _mesa_HashInsert(shared->TexObjects, name, obj);
jtgafb833d1999-08-19 00:55:39 +000092 }
93 }
94 return obj;
95}
96
97
98/*
99 * Deallocate a texture object struct and remove it from the given
100 * shared GL state.
101 * Input: shared - the shared GL state to which the object belongs
102 * t - the texture object to delete
103 */
104void gl_free_texture_object( struct gl_shared_state *shared,
105 struct gl_texture_object *t )
106{
107 struct gl_texture_object *tprev, *tcurr;
108
109 assert(t);
110
111 /* Remove t from dirty list so we don't touch free'd memory later.
112 * Test for shared since Proxy texture aren't in global linked list.
113 */
114 if (shared)
115 gl_remove_texobj_from_dirty_list( shared, t );
116
117 /* unlink t from the linked list */
118 if (shared) {
Brian Paul9560f052000-01-31 23:11:39 +0000119 _glthread_LOCK_MUTEX(shared->Mutex);
jtgafb833d1999-08-19 00:55:39 +0000120 tprev = NULL;
121 tcurr = shared->TexObjectList;
122 while (tcurr) {
123 if (tcurr==t) {
124 if (tprev) {
125 tprev->Next = t->Next;
126 }
127 else {
128 shared->TexObjectList = t->Next;
129 }
130 break;
131 }
132 tprev = tcurr;
133 tcurr = tcurr->Next;
134 }
Brian Paul9560f052000-01-31 23:11:39 +0000135 _glthread_UNLOCK_MUTEX(shared->Mutex);
jtgafb833d1999-08-19 00:55:39 +0000136 }
137
138 if (t->Name) {
139 /* remove from hash table */
Brian Paulbb797902000-01-24 16:19:54 +0000140 _mesa_HashRemove(shared->TexObjects, t->Name);
jtgafb833d1999-08-19 00:55:39 +0000141 }
142
Brian Paul4bdcfe52000-04-17 17:57:04 +0000143 _mesa_free_colortable_data(&t->Palette);
144
145 /* free texture images */
jtgafb833d1999-08-19 00:55:39 +0000146 {
147 GLuint i;
148 for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
149 if (t->Image[i]) {
Brian Paul021a5252000-03-27 17:54:17 +0000150 _mesa_free_texture_image( t->Image[i] );
jtgafb833d1999-08-19 00:55:39 +0000151 }
152 }
153 }
154 /* free this object */
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000155 FREE( t );
jtgafb833d1999-08-19 00:55:39 +0000156}
157
158
159
160/*
161 * Examine a texture object to determine if it is complete or not.
162 * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly.
163 */
Brian Paul35d53012000-05-23 17:14:49 +0000164void
165_mesa_test_texobj_completeness( const GLcontext *ctx,
166 struct gl_texture_object *t )
jtgafb833d1999-08-19 00:55:39 +0000167{
Brian Paul63ec4232000-06-12 16:09:49 +0000168 const GLint baseLevel = t->BaseLevel;
169
jtgafb833d1999-08-19 00:55:39 +0000170 t->Complete = GL_TRUE; /* be optimistic */
171
172 /* Always need level zero image */
Brian Paul63ec4232000-06-12 16:09:49 +0000173 if (!t->Image[baseLevel]) {
jtgafb833d1999-08-19 00:55:39 +0000174 t->Complete = GL_FALSE;
175 return;
176 }
177
178 /* Compute number of mipmap levels */
Brian Paulad817702000-05-30 00:27:24 +0000179 if (t->Dimensions == 1) {
Brian Paul63ec4232000-06-12 16:09:49 +0000180 t->P = t->Image[baseLevel]->WidthLog2;
jtgafb833d1999-08-19 00:55:39 +0000181 }
Brian Paulfc4b4432000-05-23 15:17:12 +0000182 else if (t->Dimensions == 2 || t->Dimensions == 6) {
Brian Paul63ec4232000-06-12 16:09:49 +0000183 t->P = MAX2(t->Image[baseLevel]->WidthLog2,
184 t->Image[baseLevel]->HeightLog2);
jtgafb833d1999-08-19 00:55:39 +0000185 }
Brian Paulad817702000-05-30 00:27:24 +0000186 else if (t->Dimensions == 3) {
Brian Paul63ec4232000-06-12 16:09:49 +0000187 GLint max = MAX2(t->Image[baseLevel]->WidthLog2,
188 t->Image[baseLevel]->HeightLog2);
189 max = MAX2(max, (GLint)(t->Image[baseLevel]->DepthLog2));
jtgafb833d1999-08-19 00:55:39 +0000190 t->P = max;
191 }
192
193 /* Compute M (see the 1.2 spec) used during mipmapping */
194 t->M = (GLfloat) (MIN2(t->MaxLevel, t->P) - t->BaseLevel);
195
196
Brian Paulad817702000-05-30 00:27:24 +0000197 if (t->Dimensions == 6) {
198 /* make sure all six level 0 images are same size */
Brian Paul63ec4232000-06-12 16:09:49 +0000199 const GLint w = t->Image[baseLevel]->Width2;
200 const GLint h = t->Image[baseLevel]->Height2;
201 if (!t->NegX[baseLevel] ||
202 t->NegX[baseLevel]->Width2 != w ||
203 t->NegX[baseLevel]->Height2 != h ||
204 !t->PosY[baseLevel] ||
205 t->PosY[baseLevel]->Width2 != w ||
206 t->PosY[baseLevel]->Height2 != h ||
207 !t->NegY[baseLevel] ||
208 t->NegY[baseLevel]->Width2 != w ||
209 t->NegY[baseLevel]->Height2 != h ||
210 !t->PosZ[baseLevel] ||
211 t->PosZ[baseLevel]->Width2 != w ||
212 t->PosZ[baseLevel]->Height2 != h ||
213 !t->NegZ[baseLevel] ||
214 t->NegZ[baseLevel]->Width2 != w ||
215 t->NegZ[baseLevel]->Height2 != h) {
Brian Paulad817702000-05-30 00:27:24 +0000216 t->Complete = GL_FALSE;
217 return;
218 }
219 }
220
221 if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) {
jtgafb833d1999-08-19 00:55:39 +0000222 /*
223 * Mipmapping: determine if we have a complete set of mipmaps
224 */
225 GLint i;
Brian Paul63ec4232000-06-12 16:09:49 +0000226 GLint minLevel = baseLevel;
jtgafb833d1999-08-19 00:55:39 +0000227 GLint maxLevel = MIN2(t->P, ctx->Const.MaxTextureLevels-1);
228 maxLevel = MIN2(maxLevel, t->MaxLevel);
229
230 if (minLevel > maxLevel) {
231 t->Complete = GL_FALSE;
232 return;
233 }
234
235 /* Test dimension-independent attributes */
236 for (i = minLevel; i <= maxLevel; i++) {
237 if (t->Image[i]) {
Brian Paul63ec4232000-06-12 16:09:49 +0000238 if (t->Image[i]->Format != t->Image[baseLevel]->Format) {
jtgafb833d1999-08-19 00:55:39 +0000239 t->Complete = GL_FALSE;
240 return;
241 }
Brian Paul63ec4232000-06-12 16:09:49 +0000242 if (t->Image[i]->Border != t->Image[baseLevel]->Border) {
jtgafb833d1999-08-19 00:55:39 +0000243 t->Complete = GL_FALSE;
244 return;
245 }
246 }
247 }
248
249 /* Test things which depend on number of texture image dimensions */
Brian Paulad817702000-05-30 00:27:24 +0000250 if (t->Dimensions == 1) {
jtgafb833d1999-08-19 00:55:39 +0000251 /* Test 1-D mipmaps */
Brian Paul63ec4232000-06-12 16:09:49 +0000252 GLuint width = t->Image[baseLevel]->Width2;
253 for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
Brian Paulad817702000-05-30 00:27:24 +0000254 if (width > 1) {
jtgafb833d1999-08-19 00:55:39 +0000255 width /= 2;
256 }
257 if (i >= minLevel && i <= maxLevel) {
258 if (!t->Image[i]) {
259 t->Complete = GL_FALSE;
260 return;
261 }
jtgafb833d1999-08-19 00:55:39 +0000262 if (t->Image[i]->Width2 != width ) {
263 t->Complete = GL_FALSE;
264 return;
265 }
266 }
Brian Paulad817702000-05-30 00:27:24 +0000267 if (width == 1) {
jtgafb833d1999-08-19 00:55:39 +0000268 return; /* found smallest needed mipmap, all done! */
269 }
270 }
271 }
Brian Paulad817702000-05-30 00:27:24 +0000272 else if (t->Dimensions == 2) {
jtgafb833d1999-08-19 00:55:39 +0000273 /* Test 2-D mipmaps */
Brian Paul63ec4232000-06-12 16:09:49 +0000274 GLuint width = t->Image[baseLevel]->Width2;
275 GLuint height = t->Image[baseLevel]->Height2;
276 for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
Brian Paulad817702000-05-30 00:27:24 +0000277 if (width > 1) {
jtgafb833d1999-08-19 00:55:39 +0000278 width /= 2;
279 }
Brian Paulad817702000-05-30 00:27:24 +0000280 if (height > 1) {
jtgafb833d1999-08-19 00:55:39 +0000281 height /= 2;
282 }
283 if (i >= minLevel && i <= maxLevel) {
284 if (!t->Image[i]) {
285 t->Complete = GL_FALSE;
286 return;
287 }
288 if (t->Image[i]->Width2 != width) {
289 t->Complete = GL_FALSE;
290 return;
291 }
292 if (t->Image[i]->Height2 != height) {
293 t->Complete = GL_FALSE;
294 return;
295 }
296 if (width==1 && height==1) {
297 return; /* found smallest needed mipmap, all done! */
298 }
299 }
300 }
301 }
Brian Paulad817702000-05-30 00:27:24 +0000302 else if (t->Dimensions == 3) {
jtgafb833d1999-08-19 00:55:39 +0000303 /* Test 3-D mipmaps */
Brian Paul63ec4232000-06-12 16:09:49 +0000304 GLuint width = t->Image[baseLevel]->Width2;
305 GLuint height = t->Image[baseLevel]->Height2;
306 GLuint depth = t->Image[baseLevel]->Depth2;
307 for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
Brian Paulad817702000-05-30 00:27:24 +0000308 if (width > 1) {
jtgafb833d1999-08-19 00:55:39 +0000309 width /= 2;
310 }
Brian Paulad817702000-05-30 00:27:24 +0000311 if (height > 1) {
jtgafb833d1999-08-19 00:55:39 +0000312 height /= 2;
313 }
Brian Paulad817702000-05-30 00:27:24 +0000314 if (depth > 1) {
jtgafb833d1999-08-19 00:55:39 +0000315 depth /= 2;
316 }
317 if (i >= minLevel && i <= maxLevel) {
318 if (!t->Image[i]) {
319 t->Complete = GL_FALSE;
320 return;
321 }
322 if (t->Image[i]->Width2 != width) {
323 t->Complete = GL_FALSE;
324 return;
325 }
326 if (t->Image[i]->Height2 != height) {
327 t->Complete = GL_FALSE;
328 return;
329 }
330 if (t->Image[i]->Depth2 != depth) {
331 t->Complete = GL_FALSE;
332 return;
333 }
334 }
Brian Paulad817702000-05-30 00:27:24 +0000335 if (width == 1 && height == 1 && depth == 1) {
jtgafb833d1999-08-19 00:55:39 +0000336 return; /* found smallest needed mipmap, all done! */
337 }
338 }
339 }
Brian Paulad817702000-05-30 00:27:24 +0000340 else if (t->Dimensions == 6) {
341 /* make sure 6 cube faces are consistant */
Brian Paul63ec4232000-06-12 16:09:49 +0000342 GLuint width = t->Image[baseLevel]->Width2;
343 GLuint height = t->Image[baseLevel]->Height2;
344 for (i = baseLevel + 1; i < ctx->Const.MaxTextureLevels; i++) {
Brian Paulad817702000-05-30 00:27:24 +0000345 if (width > 1) {
346 width /= 2;
347 }
348 if (height > 1) {
349 height /= 2;
350 }
351 if (i >= minLevel && i <= maxLevel) {
352 /* check that we have images defined */
353 if (!t->Image[i] || !t->NegX[i] ||
354 !t->PosY[i] || !t->NegY[i] ||
355 !t->PosZ[i] || !t->NegZ[i]) {
356 t->Complete = GL_FALSE;
357 return;
358 }
359 /* check that all six images have same size */
360 if (t->NegX[i]->Width2!=width || t->NegX[i]->Height2!=height ||
361 t->PosY[i]->Width2!=width || t->PosY[i]->Height2!=height ||
362 t->NegY[i]->Width2!=width || t->NegY[i]->Height2!=height ||
363 t->PosZ[i]->Width2!=width || t->PosZ[i]->Height2!=height ||
364 t->NegZ[i]->Width2!=width || t->NegZ[i]->Height2!=height) {
365 t->Complete = GL_FALSE;
366 return;
367 }
368 }
369 if (width == 1 && height == 1) {
370 return; /* found smallest needed mipmap, all done! */
371 }
372 }
Brian Paul413d6a22000-05-26 14:44:59 +0000373 }
jtgafb833d1999-08-19 00:55:39 +0000374 else {
375 /* Dimensions = ??? */
376 gl_problem(NULL, "Bug in gl_test_texture_object_completeness\n");
377 }
378 }
379}
380
381
Brian Paul832179c2000-03-21 17:42:27 +0000382_glthread_DECLARE_STATIC_MUTEX(GenTexturesLock);
383
jtgafb833d1999-08-19 00:55:39 +0000384
385/*
386 * Execute glGenTextures
387 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000388void
389_mesa_GenTextures( GLsizei n, GLuint *texName )
jtgafb833d1999-08-19 00:55:39 +0000390{
Brian Paulfbd8f211999-11-11 01:22:25 +0000391 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000392 GLuint first;
393 GLint i;
394
395 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGenTextures");
Brian Paul507d83e2000-08-03 14:03:17 +0000396 if (n < 0) {
jtgafb833d1999-08-19 00:55:39 +0000397 gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
398 return;
399 }
400
Brian Paul507d83e2000-08-03 14:03:17 +0000401 if (!texName)
402 return;
Brian Paul832179c2000-03-21 17:42:27 +0000403
404 /*
405 * This must be atomic (generation and allocation of texture IDs)
406 */
407 _glthread_LOCK_MUTEX(GenTexturesLock);
408
Brian Paulbb797902000-01-24 16:19:54 +0000409 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
jtgafb833d1999-08-19 00:55:39 +0000410
411 /* Return the texture names */
412 for (i=0;i<n;i++) {
413 texName[i] = first + i;
414 }
415
416 /* Allocate new, empty texture objects */
417 for (i=0;i<n;i++) {
418 GLuint name = first + i;
419 GLuint dims = 0;
420 (void) gl_alloc_texture_object(ctx->Shared, name, dims);
421 }
Brian Paul832179c2000-03-21 17:42:27 +0000422
423 _glthread_UNLOCK_MUTEX(GenTexturesLock);
jtgafb833d1999-08-19 00:55:39 +0000424}
425
426
427
428/*
429 * Execute glDeleteTextures
430 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000431void
432_mesa_DeleteTextures( GLsizei n, const GLuint *texName)
jtgafb833d1999-08-19 00:55:39 +0000433{
Brian Paulfbd8f211999-11-11 01:22:25 +0000434 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000435 GLint i;
436
437 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDeleteTextures");
438
Brian Paul507d83e2000-08-03 14:03:17 +0000439 if (!texName)
440 return;
441
jtgafb833d1999-08-19 00:55:39 +0000442 for (i=0;i<n;i++) {
443 struct gl_texture_object *t;
444 if (texName[i]>0) {
445 t = (struct gl_texture_object *)
Brian Paulbb797902000-01-24 16:19:54 +0000446 _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
jtgafb833d1999-08-19 00:55:39 +0000447 if (t) {
Brian Paul59d6da52000-02-12 01:59:19 +0000448 /* First check if this texture is currently bound.
449 * If so, unbind it and decrement the reference count.
450 */
jtgafb833d1999-08-19 00:55:39 +0000451 GLuint u;
Brian Paul59d6da52000-02-12 01:59:19 +0000452 for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
jtgafb833d1999-08-19 00:55:39 +0000453 struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
454 GLuint d;
455 for (d = 1 ; d <= 3 ; d++) {
Brian Paul59d6da52000-02-12 01:59:19 +0000456 if (unit->CurrentD[d] == t) {
Brian Paul6e6d4c61999-10-09 20:17:07 +0000457 unit->CurrentD[d] = ctx->Shared->DefaultD[d];
458 ctx->Shared->DefaultD[d]->RefCount++;
jtgafb833d1999-08-19 00:55:39 +0000459 t->RefCount--;
Brian Paul59d6da52000-02-12 01:59:19 +0000460 ASSERT( t->RefCount >= 0 );
jtgafb833d1999-08-19 00:55:39 +0000461 }
462 }
463 }
464
Brian Paul59d6da52000-02-12 01:59:19 +0000465 /* Decrement reference count and delete if zero */
466 t->RefCount--;
467 ASSERT( t->RefCount >= 0 );
468 if (t->RefCount == 0) {
469 if (ctx->Driver.DeleteTexture)
470 (*ctx->Driver.DeleteTexture)( ctx, t );
jtgafb833d1999-08-19 00:55:39 +0000471 gl_free_texture_object(ctx->Shared, t);
472 }
473 }
474 }
475 }
476}
477
478
479
480/*
481 * Execute glBindTexture
482 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000483void
484_mesa_BindTexture( GLenum target, GLuint texName )
jtgafb833d1999-08-19 00:55:39 +0000485{
Brian Paulfbd8f211999-11-11 01:22:25 +0000486 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000487 GLuint unit = ctx->Texture.CurrentUnit;
488 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
489 struct gl_texture_object *oldTexObj;
490 struct gl_texture_object *newTexObj;
Brian Paul5b37c321999-11-05 06:43:10 +0000491 GLuint dim;
jtgafb833d1999-08-19 00:55:39 +0000492
493 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
494 fprintf(stderr, "glBindTexture %s %d\n",
495 gl_lookup_enum_by_nr(target), (GLint) texName);
496
497 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBindTexture");
498
Brian Paul420ef641999-12-01 21:10:08 +0000499 switch (target) {
500 case GL_TEXTURE_1D:
501 dim = 1;
Brian Paulfc4b4432000-05-23 15:17:12 +0000502 oldTexObj = texUnit->CurrentD[1];
Brian Paul420ef641999-12-01 21:10:08 +0000503 break;
504 case GL_TEXTURE_2D:
505 dim = 2;
Brian Paulfc4b4432000-05-23 15:17:12 +0000506 oldTexObj = texUnit->CurrentD[2];
Brian Paul420ef641999-12-01 21:10:08 +0000507 break;
508 case GL_TEXTURE_3D:
509 dim = 3;
Brian Paulfc4b4432000-05-23 15:17:12 +0000510 oldTexObj = texUnit->CurrentD[3];
Brian Paul420ef641999-12-01 21:10:08 +0000511 break;
Brian Paulfc4b4432000-05-23 15:17:12 +0000512 case GL_TEXTURE_CUBE_MAP_ARB:
513 if (ctx->Extensions.HaveTextureCubeMap) {
514 dim = 6;
515 oldTexObj = texUnit->CurrentCubeMap;
516 break;
517 }
518 /* fallthrough */
Brian Paul420ef641999-12-01 21:10:08 +0000519 default:
520 gl_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" );
521 return;
jtgafb833d1999-08-19 00:55:39 +0000522 }
523
jtgafb833d1999-08-19 00:55:39 +0000524 if (oldTexObj->Name == texName)
525 return;
526
Brian Paulfc4b4432000-05-23 15:17:12 +0000527 if (texName == 0) {
528 if (target == GL_TEXTURE_CUBE_MAP_ARB)
529 newTexObj = ctx->Shared->DefaultCubeMap;
530 else
531 newTexObj = ctx->Shared->DefaultD[dim];
532 }
jtgafb833d1999-08-19 00:55:39 +0000533 else {
Brian Paulbb797902000-01-24 16:19:54 +0000534 struct _mesa_HashTable *hash = ctx->Shared->TexObjects;
Brian Paulc79fab42000-01-24 20:53:32 +0000535 newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName);
jtgafb833d1999-08-19 00:55:39 +0000536
537 if (!newTexObj)
538 newTexObj = gl_alloc_texture_object(ctx->Shared, texName, dim);
539
540 if (newTexObj->Dimensions != dim) {
541 if (newTexObj->Dimensions) {
Brian Paul420ef641999-12-01 21:10:08 +0000542 /* the named texture object's dimensions don't match the target */
jtgafb833d1999-08-19 00:55:39 +0000543 gl_error( ctx, GL_INVALID_OPERATION, "glBindTexture" );
544 return;
545 }
546 newTexObj->Dimensions = dim;
547 }
548 }
549
jtgafb833d1999-08-19 00:55:39 +0000550 newTexObj->RefCount++;
Brian Paul6e6d4c61999-10-09 20:17:07 +0000551
Brian Paulfc4b4432000-05-23 15:17:12 +0000552 switch (target) {
553 case GL_TEXTURE_1D:
554 texUnit->CurrentD[1] = newTexObj;
555 break;
556 case GL_TEXTURE_2D:
557 texUnit->CurrentD[2] = newTexObj;
558 break;
559 case GL_TEXTURE_3D:
560 texUnit->CurrentD[3] = newTexObj;
561 break;
562 case GL_TEXTURE_CUBE_MAP_ARB:
563 texUnit->CurrentCubeMap = newTexObj;
564 break;
565 default:
566 gl_problem(ctx, "bad target in BindTexture");
567 }
jtgafb833d1999-08-19 00:55:39 +0000568
569 /* If we've changed the CurrentD[123] texture object then update the
570 * ctx->Texture.Current pointer to point to the new texture object.
571 */
572 texUnit->Current = texUnit->CurrentD[texUnit->CurrentDimension];
573
574 /* Check if we may have to use a new triangle rasterizer */
575 if ((ctx->IndirectTriangles & DD_SW_RASTERIZE) &&
576 ( oldTexObj->WrapS != newTexObj->WrapS
577 || oldTexObj->WrapT != newTexObj->WrapT
578 || oldTexObj->WrapR != newTexObj->WrapR
579 || oldTexObj->MinFilter != newTexObj->MinFilter
580 || oldTexObj->MagFilter != newTexObj->MagFilter
581 || (oldTexObj->Image[0] && newTexObj->Image[0] &&
582 (oldTexObj->Image[0]->Format!=newTexObj->Image[0]->Format))))
583 {
584 ctx->NewState |= (NEW_RASTER_OPS | NEW_TEXTURING);
585 }
586
587 if (oldTexObj->Complete != newTexObj->Complete)
588 ctx->NewState |= NEW_TEXTURING;
589
590 /* Pass BindTexture call to device driver */
591 if (ctx->Driver.BindTexture) {
592 (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
593 }
Brian Paul6e6d4c61999-10-09 20:17:07 +0000594
595 if (oldTexObj->Name > 0) {
596 /* never delete default (id=0) texture objects */
597 oldTexObj->RefCount--;
598 if (oldTexObj->RefCount <= 0) {
599 if (ctx->Driver.DeleteTexture) {
600 (*ctx->Driver.DeleteTexture)( ctx, oldTexObj );
601 }
602 gl_free_texture_object(ctx->Shared, oldTexObj);
603 }
604 }
jtgafb833d1999-08-19 00:55:39 +0000605}
606
607
608
609/*
610 * Execute glPrioritizeTextures
611 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000612void
613_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName,
614 const GLclampf *priorities )
jtgafb833d1999-08-19 00:55:39 +0000615{
Brian Paulfbd8f211999-11-11 01:22:25 +0000616 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000617 GLint i;
618
619 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPrioritizeTextures");
Brian Paul6d047252000-08-02 00:38:25 +0000620 if (n < 0) {
jtgafb833d1999-08-19 00:55:39 +0000621 gl_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
622 return;
623 }
624
Brian Paul507d83e2000-08-03 14:03:17 +0000625 if (!priorities)
626 return;
627
Brian Paul6d047252000-08-02 00:38:25 +0000628 for (i = 0; i < n; i++) {
629 if (texName[i] > 0) {
630 struct gl_texture_object *t = (struct gl_texture_object *)
Brian Paulbb797902000-01-24 16:19:54 +0000631 _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
jtgafb833d1999-08-19 00:55:39 +0000632 if (t) {
633 t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000634 if (ctx->Driver.PrioritizeTexture)
635 ctx->Driver.PrioritizeTexture( ctx, t, t->Priority );
jtgafb833d1999-08-19 00:55:39 +0000636 }
637 }
638 }
639}
640
641
642
643/*
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000644 * Execute glAreTexturesResident
jtgafb833d1999-08-19 00:55:39 +0000645 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000646GLboolean
Brian Paulbd0f7f42000-08-02 20:16:03 +0000647_mesa_AreTexturesResident(GLsizei n, const GLuint *texName,
648 GLboolean *residences)
jtgafb833d1999-08-19 00:55:39 +0000649{
Brian Paulfbd8f211999-11-11 01:22:25 +0000650 GET_CURRENT_CONTEXT(ctx);
Brian Paulbd0f7f42000-08-02 20:16:03 +0000651 GLboolean allResident = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000652 GLint i;
653
654 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx,
Brian Paulbd0f7f42000-08-02 20:16:03 +0000655 "glAreTexturesResident", GL_FALSE);
656 if (n < 0) {
657 gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)");
jtgafb833d1999-08-19 00:55:39 +0000658 return GL_FALSE;
659 }
660
Brian Paul507d83e2000-08-03 14:03:17 +0000661 if (!texName || !residences)
662 return GL_FALSE;
663
Brian Paulbd0f7f42000-08-02 20:16:03 +0000664 for (i = 0; i < n; i++) {
jtgafb833d1999-08-19 00:55:39 +0000665 struct gl_texture_object *t;
Brian Paulbd0f7f42000-08-02 20:16:03 +0000666 if (texName[i] == 0) {
667 gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
jtgafb833d1999-08-19 00:55:39 +0000668 return GL_FALSE;
669 }
670 t = (struct gl_texture_object *)
Brian Paulbb797902000-01-24 16:19:54 +0000671 _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]);
jtgafb833d1999-08-19 00:55:39 +0000672 if (t) {
Brian Paulbd0f7f42000-08-02 20:16:03 +0000673 if (ctx->Driver.IsTextureResident) {
674 residences[i] = ctx->Driver.IsTextureResident(ctx, t);
675 if (!residences[i])
676 allResident = GL_FALSE;
677 }
678 else {
Keith Whitwell69cfdb21999-09-30 11:18:21 +0000679 residences[i] = GL_TRUE;
Brian Paulbd0f7f42000-08-02 20:16:03 +0000680 }
jtgafb833d1999-08-19 00:55:39 +0000681 }
682 else {
Brian Paulbd0f7f42000-08-02 20:16:03 +0000683 gl_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)");
jtgafb833d1999-08-19 00:55:39 +0000684 return GL_FALSE;
685 }
686 }
Brian Paulbd0f7f42000-08-02 20:16:03 +0000687 return allResident;
jtgafb833d1999-08-19 00:55:39 +0000688}
689
690
691
692/*
693 * Execute glIsTexture
694 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000695GLboolean
696_mesa_IsTexture( GLuint texture )
jtgafb833d1999-08-19 00:55:39 +0000697{
Brian Paulfbd8f211999-11-11 01:22:25 +0000698 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000699 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glIsTextures",
700 GL_FALSE);
Brian Paulbd0f7f42000-08-02 20:16:03 +0000701 if (texture > 0 && _mesa_HashLookup(ctx->Shared->TexObjects, texture)) {
jtgafb833d1999-08-19 00:55:39 +0000702 return GL_TRUE;
703 }
704 else {
705 return GL_FALSE;
706 }
707}
708