shared.c revision cdc920a0
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.5 4 * 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file shared.c 27 * Shared-context state 28 */ 29 30 31 32#include "imports.h" 33#include "mtypes.h" 34#include "hash.h" 35#include "arrayobj.h" 36#include "bufferobj.h" 37#include "shared.h" 38#include "shader/program.h" 39#include "shader/shader_api.h" 40#include "dlist.h" 41#if FEATURE_ATI_fragment_shader 42#include "shader/atifragshader.h" 43#endif 44#if FEATURE_ARB_sync 45#include "syncobj.h" 46#endif 47 48/** 49 * Allocate and initialize a shared context state structure. 50 * Initializes the display list, texture objects and vertex programs hash 51 * tables, allocates the texture objects. If it runs out of memory, frees 52 * everything already allocated before returning NULL. 53 * 54 * \return pointer to a gl_shared_state structure on success, or NULL on 55 * failure. 56 */ 57struct gl_shared_state * 58_mesa_alloc_shared_state(GLcontext *ctx) 59{ 60 struct gl_shared_state *shared; 61 GLuint i; 62 63 shared = CALLOC_STRUCT(gl_shared_state); 64 if (!shared) 65 return NULL; 66 67 _glthread_INIT_MUTEX(shared->Mutex); 68 69 shared->DisplayList = _mesa_NewHashTable(); 70 shared->TexObjects = _mesa_NewHashTable(); 71 shared->Programs = _mesa_NewHashTable(); 72 73#if FEATURE_ARB_vertex_program 74 shared->DefaultVertexProgram = (struct gl_vertex_program *) 75 ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 76#endif 77 78#if FEATURE_ARB_fragment_program 79 shared->DefaultFragmentProgram = (struct gl_fragment_program *) 80 ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 81#endif 82 83#if FEATURE_ATI_fragment_shader 84 shared->ATIShaders = _mesa_NewHashTable(); 85 shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0); 86#endif 87 88#if FEATURE_ARB_shader_objects 89 shared->ShaderObjects = _mesa_NewHashTable(); 90#endif 91 92#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object 93 shared->BufferObjects = _mesa_NewHashTable(); 94#endif 95 96 /* Allocate the default buffer object */ 97 shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); 98 99 /* Create default texture objects */ 100 for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 101 /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ 102 static const GLenum targets[NUM_TEXTURE_TARGETS] = { 103 GL_TEXTURE_2D_ARRAY_EXT, 104 GL_TEXTURE_1D_ARRAY_EXT, 105 GL_TEXTURE_CUBE_MAP, 106 GL_TEXTURE_3D, 107 GL_TEXTURE_RECTANGLE_NV, 108 GL_TEXTURE_2D, 109 GL_TEXTURE_1D 110 }; 111 shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); 112 } 113 114 /* sanity check */ 115 assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); 116 117 /* Mutex and timestamp for texobj state validation */ 118 _glthread_INIT_MUTEX(shared->TexMutex); 119 shared->TextureStateStamp = 0; 120 121#if FEATURE_EXT_framebuffer_object 122 shared->FrameBuffers = _mesa_NewHashTable(); 123 shared->RenderBuffers = _mesa_NewHashTable(); 124#endif 125 126#if FEATURE_ARB_sync 127 make_empty_list(& shared->SyncObjects); 128#endif 129 130 return shared; 131} 132 133 134/** 135 * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). 136 */ 137static void 138delete_displaylist_cb(GLuint id, void *data, void *userData) 139{ 140 struct gl_display_list *list = (struct gl_display_list *) data; 141 GLcontext *ctx = (GLcontext *) userData; 142 _mesa_delete_list(ctx, list); 143} 144 145 146/** 147 * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). 148 */ 149static void 150delete_texture_cb(GLuint id, void *data, void *userData) 151{ 152 struct gl_texture_object *texObj = (struct gl_texture_object *) data; 153 GLcontext *ctx = (GLcontext *) userData; 154 ctx->Driver.DeleteTexture(ctx, texObj); 155} 156 157 158/** 159 * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). 160 */ 161static void 162delete_program_cb(GLuint id, void *data, void *userData) 163{ 164 struct gl_program *prog = (struct gl_program *) data; 165 GLcontext *ctx = (GLcontext *) userData; 166 if(prog != &_mesa_DummyProgram) { 167 ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ 168 prog->RefCount = 0; /* now going away */ 169 ctx->Driver.DeleteProgram(ctx, prog); 170 } 171} 172 173 174#if FEATURE_ATI_fragment_shader 175/** 176 * Callback for deleting an ATI fragment shader object. 177 * Called by _mesa_HashDeleteAll(). 178 */ 179static void 180delete_fragshader_cb(GLuint id, void *data, void *userData) 181{ 182 struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; 183 GLcontext *ctx = (GLcontext *) userData; 184 _mesa_delete_ati_fragment_shader(ctx, shader); 185} 186#endif 187 188 189/** 190 * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). 191 */ 192static void 193delete_bufferobj_cb(GLuint id, void *data, void *userData) 194{ 195 struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; 196 GLcontext *ctx = (GLcontext *) userData; 197 if (_mesa_bufferobj_mapped(bufObj)) { 198 ctx->Driver.UnmapBuffer(ctx, 0, bufObj); 199 bufObj->Pointer = NULL; 200 } 201 _mesa_reference_buffer_object(ctx, &bufObj, NULL); 202} 203 204 205/** 206 * Callback for freeing shader program data. Call it before delete_shader_cb 207 * to avoid memory access error. 208 */ 209static void 210free_shader_program_data_cb(GLuint id, void *data, void *userData) 211{ 212 GLcontext *ctx = (GLcontext *) userData; 213 struct gl_shader_program *shProg = (struct gl_shader_program *) data; 214 215 if (shProg->Type == GL_SHADER_PROGRAM_MESA) { 216 _mesa_free_shader_program_data(ctx, shProg); 217 } 218} 219 220 221/** 222 * Callback for deleting shader and shader programs objects. 223 * Called by _mesa_HashDeleteAll(). 224 */ 225static void 226delete_shader_cb(GLuint id, void *data, void *userData) 227{ 228 GLcontext *ctx = (GLcontext *) userData; 229 struct gl_shader *sh = (struct gl_shader *) data; 230 if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { 231 _mesa_free_shader(ctx, sh); 232 } 233 else { 234 struct gl_shader_program *shProg = (struct gl_shader_program *) data; 235 ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); 236 _mesa_free_shader_program(ctx, shProg); 237 } 238} 239 240 241/** 242 * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() 243 */ 244static void 245delete_framebuffer_cb(GLuint id, void *data, void *userData) 246{ 247 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 248 /* The fact that the framebuffer is in the hashtable means its refcount 249 * is one, but we're removing from the hashtable now. So clear refcount. 250 */ 251 /*assert(fb->RefCount == 1);*/ 252 fb->RefCount = 0; 253 254 /* NOTE: Delete should always be defined but there are two reports 255 * of it being NULL (bugs 13507, 14293). Work-around for now. 256 */ 257 if (fb->Delete) 258 fb->Delete(fb); 259} 260 261 262/** 263 * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() 264 */ 265static void 266delete_renderbuffer_cb(GLuint id, void *data, void *userData) 267{ 268 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; 269 rb->RefCount = 0; /* see comment for FBOs above */ 270 if (rb->Delete) 271 rb->Delete(rb); 272} 273 274 275/** 276 * Deallocate a shared state object and all children structures. 277 * 278 * \param ctx GL context. 279 * \param shared shared state pointer. 280 * 281 * Frees the display lists, the texture objects (calling the driver texture 282 * deletion callback to free its private data) and the vertex programs, as well 283 * as their hash tables. 284 * 285 * \sa alloc_shared_state(). 286 */ 287static void 288free_shared_state(GLcontext *ctx, struct gl_shared_state *shared) 289{ 290 GLuint i; 291 292 /* 293 * Free display lists 294 */ 295 _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); 296 _mesa_DeleteHashTable(shared->DisplayList); 297 298#if FEATURE_ARB_shader_objects 299 _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); 300 _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); 301 _mesa_DeleteHashTable(shared->ShaderObjects); 302#endif 303 304 _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); 305 _mesa_DeleteHashTable(shared->Programs); 306 307#if FEATURE_ARB_vertex_program 308 _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); 309#endif 310 311#if FEATURE_ARB_fragment_program 312 _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); 313#endif 314 315#if FEATURE_ATI_fragment_shader 316 _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); 317 _mesa_DeleteHashTable(shared->ATIShaders); 318 _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); 319#endif 320 321#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object 322 _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); 323 _mesa_DeleteHashTable(shared->BufferObjects); 324#endif 325 326#if FEATURE_EXT_framebuffer_object 327 _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); 328 _mesa_DeleteHashTable(shared->FrameBuffers); 329 _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); 330 _mesa_DeleteHashTable(shared->RenderBuffers); 331#endif 332 333#if FEATURE_ARB_vertex_buffer_object 334 _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); 335#endif 336 337#if FEATURE_ARB_sync 338 { 339 struct simple_node *node; 340 struct simple_node *temp; 341 342 foreach_s(node, temp, & shared->SyncObjects) { 343 _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node); 344 } 345 } 346#endif 347 348 /* 349 * Free texture objects (after FBOs since some textures might have 350 * been bound to FBOs). 351 */ 352 ASSERT(ctx->Driver.DeleteTexture); 353 /* the default textures */ 354 for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 355 ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); 356 } 357 358 /* all other textures */ 359 _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); 360 _mesa_DeleteHashTable(shared->TexObjects); 361 362 _glthread_DESTROY_MUTEX(shared->Mutex); 363 _glthread_DESTROY_MUTEX(shared->TexMutex); 364 365 free(shared); 366} 367 368 369/** 370 * Decrement shared state object reference count and potentially free it 371 * and all children structures. 372 * 373 * \param ctx GL context. 374 * \param shared shared state pointer. 375 * 376 * \sa free_shared_state(). 377 */ 378void 379_mesa_release_shared_state(GLcontext *ctx, struct gl_shared_state *shared) 380{ 381 GLint RefCount; 382 383 _glthread_LOCK_MUTEX(shared->Mutex); 384 RefCount = --shared->RefCount; 385 _glthread_UNLOCK_MUTEX(shared->Mutex); 386 387 assert(RefCount >= 0); 388 389 if (RefCount == 0) { 390 /* free shared state */ 391 free_shared_state( ctx, shared ); 392 } 393} 394