shared.c revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/** 26848b8605Smrg * \file shared.c 27848b8605Smrg * Shared-context state 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg#include "imports.h" 31848b8605Smrg#include "mtypes.h" 32848b8605Smrg#include "hash.h" 33848b8605Smrg#include "atifragshader.h" 34848b8605Smrg#include "bufferobj.h" 35848b8605Smrg#include "shared.h" 36848b8605Smrg#include "program/program.h" 37848b8605Smrg#include "dlist.h" 38848b8605Smrg#include "samplerobj.h" 39848b8605Smrg#include "set.h" 40848b8605Smrg#include "shaderapi.h" 41848b8605Smrg#include "shaderobj.h" 42848b8605Smrg#include "syncobj.h" 43848b8605Smrg 44848b8605Smrg#include "util/hash_table.h" 45848b8605Smrg 46848b8605Smrg/** 47848b8605Smrg * Allocate and initialize a shared context state structure. 48848b8605Smrg * Initializes the display list, texture objects and vertex programs hash 49848b8605Smrg * tables, allocates the texture objects. If it runs out of memory, frees 50848b8605Smrg * everything already allocated before returning NULL. 51848b8605Smrg * 52848b8605Smrg * \return pointer to a gl_shared_state structure on success, or NULL on 53848b8605Smrg * failure. 54848b8605Smrg */ 55848b8605Smrgstruct gl_shared_state * 56848b8605Smrg_mesa_alloc_shared_state(struct gl_context *ctx) 57848b8605Smrg{ 58848b8605Smrg struct gl_shared_state *shared; 59848b8605Smrg GLuint i; 60848b8605Smrg 61848b8605Smrg shared = CALLOC_STRUCT(gl_shared_state); 62848b8605Smrg if (!shared) 63848b8605Smrg return NULL; 64848b8605Smrg 65848b8605Smrg mtx_init(&shared->Mutex, mtx_plain); 66848b8605Smrg 67848b8605Smrg shared->DisplayList = _mesa_NewHashTable(); 68848b8605Smrg shared->TexObjects = _mesa_NewHashTable(); 69848b8605Smrg shared->Programs = _mesa_NewHashTable(); 70848b8605Smrg 71848b8605Smrg shared->DefaultVertexProgram = 72848b8605Smrg gl_vertex_program(ctx->Driver.NewProgram(ctx, 73848b8605Smrg GL_VERTEX_PROGRAM_ARB, 0)); 74848b8605Smrg shared->DefaultFragmentProgram = 75848b8605Smrg gl_fragment_program(ctx->Driver.NewProgram(ctx, 76848b8605Smrg GL_FRAGMENT_PROGRAM_ARB, 0)); 77848b8605Smrg 78848b8605Smrg shared->ATIShaders = _mesa_NewHashTable(); 79848b8605Smrg shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0); 80848b8605Smrg 81848b8605Smrg shared->ShaderObjects = _mesa_NewHashTable(); 82848b8605Smrg 83848b8605Smrg shared->BufferObjects = _mesa_NewHashTable(); 84848b8605Smrg 85848b8605Smrg /* GL_ARB_sampler_objects */ 86848b8605Smrg shared->SamplerObjects = _mesa_NewHashTable(); 87848b8605Smrg 88848b8605Smrg /* Allocate the default buffer object */ 89848b8605Smrg shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); 90848b8605Smrg 91848b8605Smrg /* Create default texture objects */ 92848b8605Smrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 93848b8605Smrg /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ 94848b8605Smrg static const GLenum targets[] = { 95848b8605Smrg GL_TEXTURE_2D_MULTISAMPLE, 96848b8605Smrg GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 97848b8605Smrg GL_TEXTURE_CUBE_MAP_ARRAY, 98848b8605Smrg GL_TEXTURE_BUFFER, 99848b8605Smrg GL_TEXTURE_2D_ARRAY_EXT, 100848b8605Smrg GL_TEXTURE_1D_ARRAY_EXT, 101848b8605Smrg GL_TEXTURE_EXTERNAL_OES, 102848b8605Smrg GL_TEXTURE_CUBE_MAP, 103848b8605Smrg GL_TEXTURE_3D, 104848b8605Smrg GL_TEXTURE_RECTANGLE_NV, 105848b8605Smrg GL_TEXTURE_2D, 106848b8605Smrg GL_TEXTURE_1D 107848b8605Smrg }; 108848b8605Smrg STATIC_ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS); 109848b8605Smrg shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); 110848b8605Smrg } 111848b8605Smrg 112848b8605Smrg /* sanity check */ 113848b8605Smrg assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); 114848b8605Smrg 115848b8605Smrg /* Mutex and timestamp for texobj state validation */ 116848b8605Smrg mtx_init(&shared->TexMutex, mtx_recursive); 117848b8605Smrg shared->TextureStateStamp = 0; 118848b8605Smrg 119848b8605Smrg shared->FrameBuffers = _mesa_NewHashTable(); 120848b8605Smrg shared->RenderBuffers = _mesa_NewHashTable(); 121848b8605Smrg 122848b8605Smrg shared->SyncObjects = _mesa_set_create(NULL, _mesa_key_pointer_equal); 123848b8605Smrg 124848b8605Smrg return shared; 125848b8605Smrg} 126848b8605Smrg 127848b8605Smrg 128848b8605Smrg/** 129848b8605Smrg * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). 130848b8605Smrg */ 131848b8605Smrgstatic void 132848b8605Smrgdelete_displaylist_cb(GLuint id, void *data, void *userData) 133848b8605Smrg{ 134848b8605Smrg struct gl_display_list *list = (struct gl_display_list *) data; 135848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 136848b8605Smrg _mesa_delete_list(ctx, list); 137848b8605Smrg} 138848b8605Smrg 139848b8605Smrg 140848b8605Smrg/** 141848b8605Smrg * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). 142848b8605Smrg */ 143848b8605Smrgstatic void 144848b8605Smrgdelete_texture_cb(GLuint id, void *data, void *userData) 145848b8605Smrg{ 146848b8605Smrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 147848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 148848b8605Smrg ctx->Driver.DeleteTexture(ctx, texObj); 149848b8605Smrg} 150848b8605Smrg 151848b8605Smrg 152848b8605Smrg/** 153848b8605Smrg * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). 154848b8605Smrg */ 155848b8605Smrgstatic void 156848b8605Smrgdelete_program_cb(GLuint id, void *data, void *userData) 157848b8605Smrg{ 158848b8605Smrg struct gl_program *prog = (struct gl_program *) data; 159848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 160848b8605Smrg if(prog != &_mesa_DummyProgram) { 161848b8605Smrg ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ 162848b8605Smrg prog->RefCount = 0; /* now going away */ 163848b8605Smrg ctx->Driver.DeleteProgram(ctx, prog); 164848b8605Smrg } 165848b8605Smrg} 166848b8605Smrg 167848b8605Smrg 168848b8605Smrg/** 169848b8605Smrg * Callback for deleting an ATI fragment shader object. 170848b8605Smrg * Called by _mesa_HashDeleteAll(). 171848b8605Smrg */ 172848b8605Smrgstatic void 173848b8605Smrgdelete_fragshader_cb(GLuint id, void *data, void *userData) 174848b8605Smrg{ 175848b8605Smrg struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; 176848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 177848b8605Smrg _mesa_delete_ati_fragment_shader(ctx, shader); 178848b8605Smrg} 179848b8605Smrg 180848b8605Smrg 181848b8605Smrg/** 182848b8605Smrg * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). 183848b8605Smrg */ 184848b8605Smrgstatic void 185848b8605Smrgdelete_bufferobj_cb(GLuint id, void *data, void *userData) 186848b8605Smrg{ 187848b8605Smrg struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; 188848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 189848b8605Smrg 190848b8605Smrg _mesa_buffer_unmap_all_mappings(ctx, bufObj); 191848b8605Smrg _mesa_reference_buffer_object(ctx, &bufObj, NULL); 192848b8605Smrg} 193848b8605Smrg 194848b8605Smrg 195848b8605Smrg/** 196848b8605Smrg * Callback for freeing shader program data. Call it before delete_shader_cb 197848b8605Smrg * to avoid memory access error. 198848b8605Smrg */ 199848b8605Smrgstatic void 200848b8605Smrgfree_shader_program_data_cb(GLuint id, void *data, void *userData) 201848b8605Smrg{ 202848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 203848b8605Smrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 204848b8605Smrg 205848b8605Smrg if (shProg->Type == GL_SHADER_PROGRAM_MESA) { 206848b8605Smrg _mesa_free_shader_program_data(ctx, shProg); 207848b8605Smrg } 208848b8605Smrg} 209848b8605Smrg 210848b8605Smrg 211848b8605Smrg/** 212848b8605Smrg * Callback for deleting shader and shader programs objects. 213848b8605Smrg * Called by _mesa_HashDeleteAll(). 214848b8605Smrg */ 215848b8605Smrgstatic void 216848b8605Smrgdelete_shader_cb(GLuint id, void *data, void *userData) 217848b8605Smrg{ 218848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 219848b8605Smrg struct gl_shader *sh = (struct gl_shader *) data; 220848b8605Smrg if (_mesa_validate_shader_target(ctx, sh->Type)) { 221848b8605Smrg ctx->Driver.DeleteShader(ctx, sh); 222848b8605Smrg } 223848b8605Smrg else { 224848b8605Smrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 225848b8605Smrg ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); 226848b8605Smrg ctx->Driver.DeleteShaderProgram(ctx, shProg); 227848b8605Smrg } 228848b8605Smrg} 229848b8605Smrg 230848b8605Smrg 231848b8605Smrg/** 232848b8605Smrg * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() 233848b8605Smrg */ 234848b8605Smrgstatic void 235848b8605Smrgdelete_framebuffer_cb(GLuint id, void *data, void *userData) 236848b8605Smrg{ 237848b8605Smrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 238848b8605Smrg /* The fact that the framebuffer is in the hashtable means its refcount 239848b8605Smrg * is one, but we're removing from the hashtable now. So clear refcount. 240848b8605Smrg */ 241848b8605Smrg /*assert(fb->RefCount == 1);*/ 242848b8605Smrg fb->RefCount = 0; 243848b8605Smrg 244848b8605Smrg /* NOTE: Delete should always be defined but there are two reports 245848b8605Smrg * of it being NULL (bugs 13507, 14293). Work-around for now. 246848b8605Smrg */ 247848b8605Smrg if (fb->Delete) 248848b8605Smrg fb->Delete(fb); 249848b8605Smrg} 250848b8605Smrg 251848b8605Smrg 252848b8605Smrg/** 253848b8605Smrg * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() 254848b8605Smrg */ 255848b8605Smrgstatic void 256848b8605Smrgdelete_renderbuffer_cb(GLuint id, void *data, void *userData) 257848b8605Smrg{ 258848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 259848b8605Smrg struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; 260848b8605Smrg rb->RefCount = 0; /* see comment for FBOs above */ 261848b8605Smrg if (rb->Delete) 262848b8605Smrg rb->Delete(ctx, rb); 263848b8605Smrg} 264848b8605Smrg 265848b8605Smrg 266848b8605Smrg/** 267848b8605Smrg * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll() 268848b8605Smrg */ 269848b8605Smrgstatic void 270848b8605Smrgdelete_sampler_object_cb(GLuint id, void *data, void *userData) 271848b8605Smrg{ 272848b8605Smrg struct gl_context *ctx = (struct gl_context *) userData; 273848b8605Smrg struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data; 274848b8605Smrg _mesa_reference_sampler_object(ctx, &sampObj, NULL); 275848b8605Smrg} 276848b8605Smrg 277848b8605Smrg 278848b8605Smrg/** 279848b8605Smrg * Deallocate a shared state object and all children structures. 280848b8605Smrg * 281848b8605Smrg * \param ctx GL context. 282848b8605Smrg * \param shared shared state pointer. 283848b8605Smrg * 284848b8605Smrg * Frees the display lists, the texture objects (calling the driver texture 285848b8605Smrg * deletion callback to free its private data) and the vertex programs, as well 286848b8605Smrg * as their hash tables. 287848b8605Smrg * 288848b8605Smrg * \sa alloc_shared_state(). 289848b8605Smrg */ 290848b8605Smrgstatic void 291848b8605Smrgfree_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) 292848b8605Smrg{ 293848b8605Smrg GLuint i; 294848b8605Smrg 295848b8605Smrg /* Free the dummy/fallback texture objects */ 296848b8605Smrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 297848b8605Smrg if (shared->FallbackTex[i]) 298848b8605Smrg ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]); 299848b8605Smrg } 300848b8605Smrg 301848b8605Smrg /* 302848b8605Smrg * Free display lists 303848b8605Smrg */ 304848b8605Smrg _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); 305848b8605Smrg _mesa_DeleteHashTable(shared->DisplayList); 306848b8605Smrg 307848b8605Smrg _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); 308848b8605Smrg _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); 309848b8605Smrg _mesa_DeleteHashTable(shared->ShaderObjects); 310848b8605Smrg 311848b8605Smrg _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); 312848b8605Smrg _mesa_DeleteHashTable(shared->Programs); 313848b8605Smrg 314848b8605Smrg _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); 315848b8605Smrg _mesa_reference_geomprog(ctx, &shared->DefaultGeometryProgram, NULL); 316848b8605Smrg _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); 317848b8605Smrg 318848b8605Smrg _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); 319848b8605Smrg _mesa_DeleteHashTable(shared->ATIShaders); 320848b8605Smrg _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); 321848b8605Smrg 322848b8605Smrg _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); 323848b8605Smrg _mesa_DeleteHashTable(shared->BufferObjects); 324848b8605Smrg 325848b8605Smrg _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); 326848b8605Smrg _mesa_DeleteHashTable(shared->FrameBuffers); 327848b8605Smrg _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); 328848b8605Smrg _mesa_DeleteHashTable(shared->RenderBuffers); 329848b8605Smrg 330848b8605Smrg _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); 331848b8605Smrg 332848b8605Smrg { 333848b8605Smrg struct set_entry *entry; 334848b8605Smrg 335848b8605Smrg set_foreach(shared->SyncObjects, entry) { 336848b8605Smrg _mesa_unref_sync_object(ctx, (struct gl_sync_object *) entry->key); 337848b8605Smrg } 338848b8605Smrg } 339848b8605Smrg _mesa_set_destroy(shared->SyncObjects, NULL); 340848b8605Smrg 341848b8605Smrg _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx); 342848b8605Smrg _mesa_DeleteHashTable(shared->SamplerObjects); 343848b8605Smrg 344848b8605Smrg /* 345848b8605Smrg * Free texture objects (after FBOs since some textures might have 346848b8605Smrg * been bound to FBOs). 347848b8605Smrg */ 348848b8605Smrg ASSERT(ctx->Driver.DeleteTexture); 349848b8605Smrg /* the default textures */ 350848b8605Smrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 351848b8605Smrg ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); 352848b8605Smrg } 353848b8605Smrg 354848b8605Smrg /* all other textures */ 355848b8605Smrg _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); 356848b8605Smrg _mesa_DeleteHashTable(shared->TexObjects); 357848b8605Smrg 358848b8605Smrg mtx_destroy(&shared->Mutex); 359848b8605Smrg mtx_destroy(&shared->TexMutex); 360848b8605Smrg 361848b8605Smrg free(shared); 362848b8605Smrg} 363848b8605Smrg 364848b8605Smrg 365848b8605Smrg/** 366848b8605Smrg * gl_shared_state objects are ref counted. 367848b8605Smrg * If ptr's refcount goes to zero, free the shared state. 368848b8605Smrg */ 369848b8605Smrgvoid 370848b8605Smrg_mesa_reference_shared_state(struct gl_context *ctx, 371848b8605Smrg struct gl_shared_state **ptr, 372848b8605Smrg struct gl_shared_state *state) 373848b8605Smrg{ 374848b8605Smrg if (*ptr == state) 375848b8605Smrg return; 376848b8605Smrg 377848b8605Smrg if (*ptr) { 378848b8605Smrg /* unref old state */ 379848b8605Smrg struct gl_shared_state *old = *ptr; 380848b8605Smrg GLboolean delete; 381848b8605Smrg 382848b8605Smrg mtx_lock(&old->Mutex); 383848b8605Smrg assert(old->RefCount >= 1); 384848b8605Smrg old->RefCount--; 385848b8605Smrg delete = (old->RefCount == 0); 386848b8605Smrg mtx_unlock(&old->Mutex); 387848b8605Smrg 388848b8605Smrg if (delete) { 389848b8605Smrg free_shared_state(ctx, old); 390848b8605Smrg } 391848b8605Smrg 392848b8605Smrg *ptr = NULL; 393848b8605Smrg } 394848b8605Smrg 395848b8605Smrg if (state) { 396848b8605Smrg /* reference new state */ 397848b8605Smrg mtx_lock(&state->Mutex); 398848b8605Smrg state->RefCount++; 399848b8605Smrg *ptr = state; 400848b8605Smrg mtx_unlock(&state->Mutex); 401848b8605Smrg } 402848b8605Smrg} 403