shared.c revision cdc920a0
14a49301eSmrg/* 24a49301eSmrg * Mesa 3-D graphics library 34a49301eSmrg * Version: 7.5 44a49301eSmrg * 54a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 64a49301eSmrg * 74a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 84a49301eSmrg * copy of this software and associated documentation files (the "Software"), 94a49301eSmrg * to deal in the Software without restriction, including without limitation 104a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 114a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the 124a49301eSmrg * Software is furnished to do so, subject to the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice shall be included 154a49301eSmrg * in all copies or substantial portions of the Software. 164a49301eSmrg * 174a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 184a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 194a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 204a49301eSmrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 214a49301eSmrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 224a49301eSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 234a49301eSmrg */ 244a49301eSmrg 254a49301eSmrg/** 264a49301eSmrg * \file shared.c 274a49301eSmrg * Shared-context state 284a49301eSmrg */ 294a49301eSmrg 304a49301eSmrg 314a49301eSmrg 324a49301eSmrg#include "imports.h" 334a49301eSmrg#include "mtypes.h" 344a49301eSmrg#include "hash.h" 354a49301eSmrg#include "arrayobj.h" 364a49301eSmrg#include "bufferobj.h" 374a49301eSmrg#include "shared.h" 384a49301eSmrg#include "shader/program.h" 394a49301eSmrg#include "shader/shader_api.h" 404a49301eSmrg#include "dlist.h" 414a49301eSmrg#if FEATURE_ATI_fragment_shader 424a49301eSmrg#include "shader/atifragshader.h" 434a49301eSmrg#endif 444a49301eSmrg#if FEATURE_ARB_sync 454a49301eSmrg#include "syncobj.h" 464a49301eSmrg#endif 474a49301eSmrg 484a49301eSmrg/** 494a49301eSmrg * Allocate and initialize a shared context state structure. 504a49301eSmrg * Initializes the display list, texture objects and vertex programs hash 514a49301eSmrg * tables, allocates the texture objects. If it runs out of memory, frees 524a49301eSmrg * everything already allocated before returning NULL. 534a49301eSmrg * 544a49301eSmrg * \return pointer to a gl_shared_state structure on success, or NULL on 554a49301eSmrg * failure. 564a49301eSmrg */ 574a49301eSmrgstruct gl_shared_state * 584a49301eSmrg_mesa_alloc_shared_state(GLcontext *ctx) 594a49301eSmrg{ 604a49301eSmrg struct gl_shared_state *shared; 614a49301eSmrg GLuint i; 624a49301eSmrg 634a49301eSmrg shared = CALLOC_STRUCT(gl_shared_state); 644a49301eSmrg if (!shared) 654a49301eSmrg return NULL; 664a49301eSmrg 674a49301eSmrg _glthread_INIT_MUTEX(shared->Mutex); 684a49301eSmrg 694a49301eSmrg shared->DisplayList = _mesa_NewHashTable(); 704a49301eSmrg shared->TexObjects = _mesa_NewHashTable(); 714a49301eSmrg shared->Programs = _mesa_NewHashTable(); 724a49301eSmrg 734a49301eSmrg#if FEATURE_ARB_vertex_program 744a49301eSmrg shared->DefaultVertexProgram = (struct gl_vertex_program *) 754a49301eSmrg ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 764a49301eSmrg#endif 774a49301eSmrg 784a49301eSmrg#if FEATURE_ARB_fragment_program 794a49301eSmrg shared->DefaultFragmentProgram = (struct gl_fragment_program *) 804a49301eSmrg ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 814a49301eSmrg#endif 824a49301eSmrg 834a49301eSmrg#if FEATURE_ATI_fragment_shader 844a49301eSmrg shared->ATIShaders = _mesa_NewHashTable(); 854a49301eSmrg shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0); 864a49301eSmrg#endif 874a49301eSmrg 884a49301eSmrg#if FEATURE_ARB_shader_objects 894a49301eSmrg shared->ShaderObjects = _mesa_NewHashTable(); 904a49301eSmrg#endif 914a49301eSmrg 924a49301eSmrg#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object 934a49301eSmrg shared->BufferObjects = _mesa_NewHashTable(); 944a49301eSmrg#endif 954a49301eSmrg 964a49301eSmrg /* Allocate the default buffer object */ 974a49301eSmrg shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); 984a49301eSmrg 994a49301eSmrg /* Create default texture objects */ 1004a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 1014a49301eSmrg /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ 1024a49301eSmrg static const GLenum targets[NUM_TEXTURE_TARGETS] = { 1034a49301eSmrg GL_TEXTURE_2D_ARRAY_EXT, 1044a49301eSmrg GL_TEXTURE_1D_ARRAY_EXT, 1054a49301eSmrg GL_TEXTURE_CUBE_MAP, 1064a49301eSmrg GL_TEXTURE_3D, 1074a49301eSmrg GL_TEXTURE_RECTANGLE_NV, 1084a49301eSmrg GL_TEXTURE_2D, 1094a49301eSmrg GL_TEXTURE_1D 1104a49301eSmrg }; 1114a49301eSmrg shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); 1124a49301eSmrg } 1134a49301eSmrg 1144a49301eSmrg /* sanity check */ 1154a49301eSmrg assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); 1164a49301eSmrg 1174a49301eSmrg /* Mutex and timestamp for texobj state validation */ 1184a49301eSmrg _glthread_INIT_MUTEX(shared->TexMutex); 1194a49301eSmrg shared->TextureStateStamp = 0; 1204a49301eSmrg 1214a49301eSmrg#if FEATURE_EXT_framebuffer_object 1224a49301eSmrg shared->FrameBuffers = _mesa_NewHashTable(); 1234a49301eSmrg shared->RenderBuffers = _mesa_NewHashTable(); 1244a49301eSmrg#endif 1254a49301eSmrg 1264a49301eSmrg#if FEATURE_ARB_sync 1274a49301eSmrg make_empty_list(& shared->SyncObjects); 1284a49301eSmrg#endif 1294a49301eSmrg 1304a49301eSmrg return shared; 1314a49301eSmrg} 1324a49301eSmrg 1334a49301eSmrg 1344a49301eSmrg/** 1354a49301eSmrg * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). 1364a49301eSmrg */ 1374a49301eSmrgstatic void 1384a49301eSmrgdelete_displaylist_cb(GLuint id, void *data, void *userData) 1394a49301eSmrg{ 1404a49301eSmrg struct gl_display_list *list = (struct gl_display_list *) data; 1414a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 1424a49301eSmrg _mesa_delete_list(ctx, list); 1434a49301eSmrg} 1444a49301eSmrg 1454a49301eSmrg 1464a49301eSmrg/** 1474a49301eSmrg * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). 1484a49301eSmrg */ 1494a49301eSmrgstatic void 1504a49301eSmrgdelete_texture_cb(GLuint id, void *data, void *userData) 1514a49301eSmrg{ 1524a49301eSmrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 1534a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 1544a49301eSmrg ctx->Driver.DeleteTexture(ctx, texObj); 1554a49301eSmrg} 1564a49301eSmrg 1574a49301eSmrg 1584a49301eSmrg/** 1594a49301eSmrg * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). 1604a49301eSmrg */ 1614a49301eSmrgstatic void 1624a49301eSmrgdelete_program_cb(GLuint id, void *data, void *userData) 1634a49301eSmrg{ 1644a49301eSmrg struct gl_program *prog = (struct gl_program *) data; 1654a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 1664a49301eSmrg if(prog != &_mesa_DummyProgram) { 1674a49301eSmrg ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ 1684a49301eSmrg prog->RefCount = 0; /* now going away */ 1694a49301eSmrg ctx->Driver.DeleteProgram(ctx, prog); 1704a49301eSmrg } 1714a49301eSmrg} 1724a49301eSmrg 1734a49301eSmrg 1744a49301eSmrg#if FEATURE_ATI_fragment_shader 1754a49301eSmrg/** 1764a49301eSmrg * Callback for deleting an ATI fragment shader object. 1774a49301eSmrg * Called by _mesa_HashDeleteAll(). 1784a49301eSmrg */ 1794a49301eSmrgstatic void 1804a49301eSmrgdelete_fragshader_cb(GLuint id, void *data, void *userData) 1814a49301eSmrg{ 1824a49301eSmrg struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; 1834a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 1844a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shader); 1854a49301eSmrg} 1864a49301eSmrg#endif 1874a49301eSmrg 1884a49301eSmrg 1894a49301eSmrg/** 1904a49301eSmrg * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). 1914a49301eSmrg */ 1924a49301eSmrgstatic void 1934a49301eSmrgdelete_bufferobj_cb(GLuint id, void *data, void *userData) 1944a49301eSmrg{ 1954a49301eSmrg struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; 1964a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 1974a49301eSmrg if (_mesa_bufferobj_mapped(bufObj)) { 1984a49301eSmrg ctx->Driver.UnmapBuffer(ctx, 0, bufObj); 1994a49301eSmrg bufObj->Pointer = NULL; 2004a49301eSmrg } 2014a49301eSmrg _mesa_reference_buffer_object(ctx, &bufObj, NULL); 2024a49301eSmrg} 2034a49301eSmrg 2044a49301eSmrg 2054a49301eSmrg/** 2064a49301eSmrg * Callback for freeing shader program data. Call it before delete_shader_cb 2074a49301eSmrg * to avoid memory access error. 2084a49301eSmrg */ 2094a49301eSmrgstatic void 2104a49301eSmrgfree_shader_program_data_cb(GLuint id, void *data, void *userData) 2114a49301eSmrg{ 2124a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 2134a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2144a49301eSmrg 2154a49301eSmrg if (shProg->Type == GL_SHADER_PROGRAM_MESA) { 2164a49301eSmrg _mesa_free_shader_program_data(ctx, shProg); 2174a49301eSmrg } 2184a49301eSmrg} 2194a49301eSmrg 2204a49301eSmrg 2214a49301eSmrg/** 2224a49301eSmrg * Callback for deleting shader and shader programs objects. 2234a49301eSmrg * Called by _mesa_HashDeleteAll(). 2244a49301eSmrg */ 2254a49301eSmrgstatic void 2264a49301eSmrgdelete_shader_cb(GLuint id, void *data, void *userData) 2274a49301eSmrg{ 2284a49301eSmrg GLcontext *ctx = (GLcontext *) userData; 2294a49301eSmrg struct gl_shader *sh = (struct gl_shader *) data; 2304a49301eSmrg if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { 2314a49301eSmrg _mesa_free_shader(ctx, sh); 2324a49301eSmrg } 2334a49301eSmrg else { 2344a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2354a49301eSmrg ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); 2364a49301eSmrg _mesa_free_shader_program(ctx, shProg); 2374a49301eSmrg } 2384a49301eSmrg} 2394a49301eSmrg 2404a49301eSmrg 2414a49301eSmrg/** 2424a49301eSmrg * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() 2434a49301eSmrg */ 2444a49301eSmrgstatic void 2454a49301eSmrgdelete_framebuffer_cb(GLuint id, void *data, void *userData) 2464a49301eSmrg{ 2474a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2484a49301eSmrg /* The fact that the framebuffer is in the hashtable means its refcount 2494a49301eSmrg * is one, but we're removing from the hashtable now. So clear refcount. 2504a49301eSmrg */ 2514a49301eSmrg /*assert(fb->RefCount == 1);*/ 2524a49301eSmrg fb->RefCount = 0; 2534a49301eSmrg 2544a49301eSmrg /* NOTE: Delete should always be defined but there are two reports 2554a49301eSmrg * of it being NULL (bugs 13507, 14293). Work-around for now. 2564a49301eSmrg */ 2574a49301eSmrg if (fb->Delete) 2584a49301eSmrg fb->Delete(fb); 2594a49301eSmrg} 2604a49301eSmrg 2614a49301eSmrg 2624a49301eSmrg/** 2634a49301eSmrg * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() 2644a49301eSmrg */ 2654a49301eSmrgstatic void 2664a49301eSmrgdelete_renderbuffer_cb(GLuint id, void *data, void *userData) 2674a49301eSmrg{ 2684a49301eSmrg struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; 2694a49301eSmrg rb->RefCount = 0; /* see comment for FBOs above */ 2704a49301eSmrg if (rb->Delete) 2714a49301eSmrg rb->Delete(rb); 2724a49301eSmrg} 2734a49301eSmrg 2744a49301eSmrg 2754a49301eSmrg/** 2764a49301eSmrg * Deallocate a shared state object and all children structures. 2774a49301eSmrg * 2784a49301eSmrg * \param ctx GL context. 2794a49301eSmrg * \param shared shared state pointer. 2804a49301eSmrg * 2814a49301eSmrg * Frees the display lists, the texture objects (calling the driver texture 2824a49301eSmrg * deletion callback to free its private data) and the vertex programs, as well 2834a49301eSmrg * as their hash tables. 2844a49301eSmrg * 2854a49301eSmrg * \sa alloc_shared_state(). 2864a49301eSmrg */ 2874a49301eSmrgstatic void 2884a49301eSmrgfree_shared_state(GLcontext *ctx, struct gl_shared_state *shared) 2894a49301eSmrg{ 2904a49301eSmrg GLuint i; 2914a49301eSmrg 2924a49301eSmrg /* 2934a49301eSmrg * Free display lists 2944a49301eSmrg */ 2954a49301eSmrg _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); 2964a49301eSmrg _mesa_DeleteHashTable(shared->DisplayList); 2974a49301eSmrg 2984a49301eSmrg#if FEATURE_ARB_shader_objects 2994a49301eSmrg _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); 3004a49301eSmrg _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); 3014a49301eSmrg _mesa_DeleteHashTable(shared->ShaderObjects); 3024a49301eSmrg#endif 3034a49301eSmrg 3044a49301eSmrg _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); 3054a49301eSmrg _mesa_DeleteHashTable(shared->Programs); 3064a49301eSmrg 3074a49301eSmrg#if FEATURE_ARB_vertex_program 3084a49301eSmrg _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); 3094a49301eSmrg#endif 3104a49301eSmrg 3114a49301eSmrg#if FEATURE_ARB_fragment_program 3124a49301eSmrg _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); 3134a49301eSmrg#endif 3144a49301eSmrg 3154a49301eSmrg#if FEATURE_ATI_fragment_shader 3164a49301eSmrg _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); 3174a49301eSmrg _mesa_DeleteHashTable(shared->ATIShaders); 3184a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); 3194a49301eSmrg#endif 3204a49301eSmrg 3214a49301eSmrg#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object 3224a49301eSmrg _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); 3234a49301eSmrg _mesa_DeleteHashTable(shared->BufferObjects); 3244a49301eSmrg#endif 3254a49301eSmrg 3264a49301eSmrg#if FEATURE_EXT_framebuffer_object 3274a49301eSmrg _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); 3284a49301eSmrg _mesa_DeleteHashTable(shared->FrameBuffers); 3294a49301eSmrg _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); 3304a49301eSmrg _mesa_DeleteHashTable(shared->RenderBuffers); 3314a49301eSmrg#endif 3324a49301eSmrg 3334a49301eSmrg#if FEATURE_ARB_vertex_buffer_object 3344a49301eSmrg _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); 3354a49301eSmrg#endif 3364a49301eSmrg 3374a49301eSmrg#if FEATURE_ARB_sync 3384a49301eSmrg { 3394a49301eSmrg struct simple_node *node; 3404a49301eSmrg struct simple_node *temp; 3414a49301eSmrg 3424a49301eSmrg foreach_s(node, temp, & shared->SyncObjects) { 3434a49301eSmrg _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node); 3444a49301eSmrg } 3454a49301eSmrg } 3464a49301eSmrg#endif 3474a49301eSmrg 3484a49301eSmrg /* 3494a49301eSmrg * Free texture objects (after FBOs since some textures might have 3504a49301eSmrg * been bound to FBOs). 3514a49301eSmrg */ 3524a49301eSmrg ASSERT(ctx->Driver.DeleteTexture); 3534a49301eSmrg /* the default textures */ 3544a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 3554a49301eSmrg ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); 3564a49301eSmrg } 3574a49301eSmrg 3584a49301eSmrg /* all other textures */ 3594a49301eSmrg _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); 3604a49301eSmrg _mesa_DeleteHashTable(shared->TexObjects); 3614a49301eSmrg 3624a49301eSmrg _glthread_DESTROY_MUTEX(shared->Mutex); 3634a49301eSmrg _glthread_DESTROY_MUTEX(shared->TexMutex); 3644a49301eSmrg 365cdc920a0Smrg free(shared); 3664a49301eSmrg} 3674a49301eSmrg 3684a49301eSmrg 3694a49301eSmrg/** 3704a49301eSmrg * Decrement shared state object reference count and potentially free it 3714a49301eSmrg * and all children structures. 3724a49301eSmrg * 3734a49301eSmrg * \param ctx GL context. 3744a49301eSmrg * \param shared shared state pointer. 3754a49301eSmrg * 3764a49301eSmrg * \sa free_shared_state(). 3774a49301eSmrg */ 3784a49301eSmrgvoid 3794a49301eSmrg_mesa_release_shared_state(GLcontext *ctx, struct gl_shared_state *shared) 3804a49301eSmrg{ 3814a49301eSmrg GLint RefCount; 3824a49301eSmrg 3834a49301eSmrg _glthread_LOCK_MUTEX(shared->Mutex); 3844a49301eSmrg RefCount = --shared->RefCount; 3854a49301eSmrg _glthread_UNLOCK_MUTEX(shared->Mutex); 3864a49301eSmrg 3874a49301eSmrg assert(RefCount >= 0); 3884a49301eSmrg 3894a49301eSmrg if (RefCount == 0) { 3904a49301eSmrg /* free shared state */ 3914a49301eSmrg free_shared_state( ctx, shared ); 3924a49301eSmrg } 3934a49301eSmrg} 394