shared.c revision 3464ebd5
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#include "imports.h" 313464ebd5Sriastradh#include "mfeatures.h" 324a49301eSmrg#include "mtypes.h" 334a49301eSmrg#include "hash.h" 343464ebd5Sriastradh#if FEATURE_ATI_fragment_shader 353464ebd5Sriastradh#include "atifragshader.h" 363464ebd5Sriastradh#endif 374a49301eSmrg#include "bufferobj.h" 384a49301eSmrg#include "shared.h" 393464ebd5Sriastradh#include "program/program.h" 404a49301eSmrg#include "dlist.h" 413464ebd5Sriastradh#if FEATURE_ARB_sampler_objects 423464ebd5Sriastradh#include "samplerobj.h" 434a49301eSmrg#endif 443464ebd5Sriastradh#include "shaderobj.h" 454a49301eSmrg#include "syncobj.h" 463464ebd5Sriastradh 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 * 583464ebd5Sriastradh_mesa_alloc_shared_state(struct gl_context *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 963464ebd5Sriastradh#if FEATURE_ARB_sampler_objects 973464ebd5Sriastradh /* GL_ARB_sampler_objects */ 983464ebd5Sriastradh shared->SamplerObjects = _mesa_NewHashTable(); 993464ebd5Sriastradh#endif 1003464ebd5Sriastradh 1014a49301eSmrg /* Allocate the default buffer object */ 1024a49301eSmrg shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); 1034a49301eSmrg 1044a49301eSmrg /* Create default texture objects */ 1054a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 1064a49301eSmrg /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ 1074a49301eSmrg static const GLenum targets[NUM_TEXTURE_TARGETS] = { 1083464ebd5Sriastradh GL_TEXTURE_BUFFER, 1094a49301eSmrg GL_TEXTURE_2D_ARRAY_EXT, 1104a49301eSmrg GL_TEXTURE_1D_ARRAY_EXT, 1114a49301eSmrg GL_TEXTURE_CUBE_MAP, 1124a49301eSmrg GL_TEXTURE_3D, 1134a49301eSmrg GL_TEXTURE_RECTANGLE_NV, 1144a49301eSmrg GL_TEXTURE_2D, 1154a49301eSmrg GL_TEXTURE_1D 1164a49301eSmrg }; 1173464ebd5Sriastradh assert(Elements(targets) == NUM_TEXTURE_TARGETS); 1184a49301eSmrg shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); 1194a49301eSmrg } 1204a49301eSmrg 1214a49301eSmrg /* sanity check */ 1224a49301eSmrg assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); 1234a49301eSmrg 1244a49301eSmrg /* Mutex and timestamp for texobj state validation */ 1254a49301eSmrg _glthread_INIT_MUTEX(shared->TexMutex); 1264a49301eSmrg shared->TextureStateStamp = 0; 1274a49301eSmrg 1284a49301eSmrg#if FEATURE_EXT_framebuffer_object 1294a49301eSmrg shared->FrameBuffers = _mesa_NewHashTable(); 1304a49301eSmrg shared->RenderBuffers = _mesa_NewHashTable(); 1314a49301eSmrg#endif 1324a49301eSmrg 1334a49301eSmrg make_empty_list(& shared->SyncObjects); 1344a49301eSmrg 1354a49301eSmrg return shared; 1364a49301eSmrg} 1374a49301eSmrg 1384a49301eSmrg 1394a49301eSmrg/** 1404a49301eSmrg * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). 1414a49301eSmrg */ 1424a49301eSmrgstatic void 1434a49301eSmrgdelete_displaylist_cb(GLuint id, void *data, void *userData) 1444a49301eSmrg{ 1454a49301eSmrg struct gl_display_list *list = (struct gl_display_list *) data; 1463464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1474a49301eSmrg _mesa_delete_list(ctx, list); 1484a49301eSmrg} 1494a49301eSmrg 1504a49301eSmrg 1514a49301eSmrg/** 1524a49301eSmrg * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). 1534a49301eSmrg */ 1544a49301eSmrgstatic void 1554a49301eSmrgdelete_texture_cb(GLuint id, void *data, void *userData) 1564a49301eSmrg{ 1574a49301eSmrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 1583464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1594a49301eSmrg ctx->Driver.DeleteTexture(ctx, texObj); 1604a49301eSmrg} 1614a49301eSmrg 1624a49301eSmrg 1634a49301eSmrg/** 1644a49301eSmrg * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). 1654a49301eSmrg */ 1664a49301eSmrgstatic void 1674a49301eSmrgdelete_program_cb(GLuint id, void *data, void *userData) 1684a49301eSmrg{ 1694a49301eSmrg struct gl_program *prog = (struct gl_program *) data; 1703464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1714a49301eSmrg if(prog != &_mesa_DummyProgram) { 1724a49301eSmrg ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ 1734a49301eSmrg prog->RefCount = 0; /* now going away */ 1744a49301eSmrg ctx->Driver.DeleteProgram(ctx, prog); 1754a49301eSmrg } 1764a49301eSmrg} 1774a49301eSmrg 1784a49301eSmrg 1794a49301eSmrg#if FEATURE_ATI_fragment_shader 1804a49301eSmrg/** 1814a49301eSmrg * Callback for deleting an ATI fragment shader object. 1824a49301eSmrg * Called by _mesa_HashDeleteAll(). 1834a49301eSmrg */ 1844a49301eSmrgstatic void 1854a49301eSmrgdelete_fragshader_cb(GLuint id, void *data, void *userData) 1864a49301eSmrg{ 1874a49301eSmrg struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; 1883464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1894a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shader); 1904a49301eSmrg} 1914a49301eSmrg#endif 1924a49301eSmrg 1934a49301eSmrg 1944a49301eSmrg/** 1954a49301eSmrg * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). 1964a49301eSmrg */ 1974a49301eSmrgstatic void 1984a49301eSmrgdelete_bufferobj_cb(GLuint id, void *data, void *userData) 1994a49301eSmrg{ 2004a49301eSmrg struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; 2013464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2024a49301eSmrg if (_mesa_bufferobj_mapped(bufObj)) { 2034a49301eSmrg ctx->Driver.UnmapBuffer(ctx, 0, bufObj); 2044a49301eSmrg bufObj->Pointer = NULL; 2054a49301eSmrg } 2064a49301eSmrg _mesa_reference_buffer_object(ctx, &bufObj, NULL); 2074a49301eSmrg} 2084a49301eSmrg 2094a49301eSmrg 2104a49301eSmrg/** 2114a49301eSmrg * Callback for freeing shader program data. Call it before delete_shader_cb 2124a49301eSmrg * to avoid memory access error. 2134a49301eSmrg */ 2144a49301eSmrgstatic void 2154a49301eSmrgfree_shader_program_data_cb(GLuint id, void *data, void *userData) 2164a49301eSmrg{ 2173464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2184a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2194a49301eSmrg 2204a49301eSmrg if (shProg->Type == GL_SHADER_PROGRAM_MESA) { 2214a49301eSmrg _mesa_free_shader_program_data(ctx, shProg); 2224a49301eSmrg } 2234a49301eSmrg} 2244a49301eSmrg 2254a49301eSmrg 2264a49301eSmrg/** 2274a49301eSmrg * Callback for deleting shader and shader programs objects. 2284a49301eSmrg * Called by _mesa_HashDeleteAll(). 2294a49301eSmrg */ 2304a49301eSmrgstatic void 2314a49301eSmrgdelete_shader_cb(GLuint id, void *data, void *userData) 2324a49301eSmrg{ 2333464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2344a49301eSmrg struct gl_shader *sh = (struct gl_shader *) data; 2354a49301eSmrg if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { 2363464ebd5Sriastradh ctx->Driver.DeleteShader(ctx, sh); 2374a49301eSmrg } 2384a49301eSmrg else { 2394a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2404a49301eSmrg ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); 2413464ebd5Sriastradh ctx->Driver.DeleteShaderProgram(ctx, shProg); 2424a49301eSmrg } 2434a49301eSmrg} 2444a49301eSmrg 2454a49301eSmrg 2464a49301eSmrg/** 2474a49301eSmrg * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() 2484a49301eSmrg */ 2494a49301eSmrgstatic void 2504a49301eSmrgdelete_framebuffer_cb(GLuint id, void *data, void *userData) 2514a49301eSmrg{ 2524a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2534a49301eSmrg /* The fact that the framebuffer is in the hashtable means its refcount 2544a49301eSmrg * is one, but we're removing from the hashtable now. So clear refcount. 2554a49301eSmrg */ 2564a49301eSmrg /*assert(fb->RefCount == 1);*/ 2574a49301eSmrg fb->RefCount = 0; 2584a49301eSmrg 2594a49301eSmrg /* NOTE: Delete should always be defined but there are two reports 2604a49301eSmrg * of it being NULL (bugs 13507, 14293). Work-around for now. 2614a49301eSmrg */ 2624a49301eSmrg if (fb->Delete) 2634a49301eSmrg fb->Delete(fb); 2644a49301eSmrg} 2654a49301eSmrg 2664a49301eSmrg 2674a49301eSmrg/** 2684a49301eSmrg * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() 2694a49301eSmrg */ 2704a49301eSmrgstatic void 2714a49301eSmrgdelete_renderbuffer_cb(GLuint id, void *data, void *userData) 2724a49301eSmrg{ 2734a49301eSmrg struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; 2744a49301eSmrg rb->RefCount = 0; /* see comment for FBOs above */ 2754a49301eSmrg if (rb->Delete) 2764a49301eSmrg rb->Delete(rb); 2774a49301eSmrg} 2784a49301eSmrg 2794a49301eSmrg 2803464ebd5Sriastradh#if FEATURE_ARB_sampler_objects 2813464ebd5Sriastradh/** 2823464ebd5Sriastradh * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll() 2833464ebd5Sriastradh */ 2843464ebd5Sriastradhstatic void 2853464ebd5Sriastradhdelete_sampler_object_cb(GLuint id, void *data, void *userData) 2863464ebd5Sriastradh{ 2873464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2883464ebd5Sriastradh struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data; 2893464ebd5Sriastradh _mesa_reference_sampler_object(ctx, &sampObj, NULL); 2903464ebd5Sriastradh} 2913464ebd5Sriastradh#endif 2923464ebd5Sriastradh 2933464ebd5Sriastradh 2944a49301eSmrg/** 2954a49301eSmrg * Deallocate a shared state object and all children structures. 2964a49301eSmrg * 2974a49301eSmrg * \param ctx GL context. 2984a49301eSmrg * \param shared shared state pointer. 2994a49301eSmrg * 3004a49301eSmrg * Frees the display lists, the texture objects (calling the driver texture 3014a49301eSmrg * deletion callback to free its private data) and the vertex programs, as well 3024a49301eSmrg * as their hash tables. 3034a49301eSmrg * 3044a49301eSmrg * \sa alloc_shared_state(). 3054a49301eSmrg */ 3064a49301eSmrgstatic void 3073464ebd5Sriastradhfree_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) 3084a49301eSmrg{ 3094a49301eSmrg GLuint i; 3104a49301eSmrg 3113464ebd5Sriastradh /* Free the dummy/fallback texture object */ 3123464ebd5Sriastradh if (shared->FallbackTex) 3133464ebd5Sriastradh ctx->Driver.DeleteTexture(ctx, shared->FallbackTex); 3143464ebd5Sriastradh 3154a49301eSmrg /* 3164a49301eSmrg * Free display lists 3174a49301eSmrg */ 3184a49301eSmrg _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); 3194a49301eSmrg _mesa_DeleteHashTable(shared->DisplayList); 3204a49301eSmrg 3214a49301eSmrg#if FEATURE_ARB_shader_objects 3224a49301eSmrg _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); 3234a49301eSmrg _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); 3244a49301eSmrg _mesa_DeleteHashTable(shared->ShaderObjects); 3254a49301eSmrg#endif 3264a49301eSmrg 3274a49301eSmrg _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); 3284a49301eSmrg _mesa_DeleteHashTable(shared->Programs); 3294a49301eSmrg 3304a49301eSmrg#if FEATURE_ARB_vertex_program 3314a49301eSmrg _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); 3324a49301eSmrg#endif 3334a49301eSmrg 3344a49301eSmrg#if FEATURE_ARB_fragment_program 3354a49301eSmrg _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); 3364a49301eSmrg#endif 3374a49301eSmrg 3384a49301eSmrg#if FEATURE_ATI_fragment_shader 3394a49301eSmrg _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); 3404a49301eSmrg _mesa_DeleteHashTable(shared->ATIShaders); 3414a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); 3424a49301eSmrg#endif 3434a49301eSmrg 3444a49301eSmrg#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object 3454a49301eSmrg _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); 3464a49301eSmrg _mesa_DeleteHashTable(shared->BufferObjects); 3474a49301eSmrg#endif 3484a49301eSmrg 3494a49301eSmrg#if FEATURE_EXT_framebuffer_object 3504a49301eSmrg _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); 3514a49301eSmrg _mesa_DeleteHashTable(shared->FrameBuffers); 3524a49301eSmrg _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); 3534a49301eSmrg _mesa_DeleteHashTable(shared->RenderBuffers); 3544a49301eSmrg#endif 3554a49301eSmrg 3564a49301eSmrg#if FEATURE_ARB_vertex_buffer_object 3574a49301eSmrg _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); 3584a49301eSmrg#endif 3594a49301eSmrg 3604a49301eSmrg { 3614a49301eSmrg struct simple_node *node; 3624a49301eSmrg struct simple_node *temp; 3634a49301eSmrg 3644a49301eSmrg foreach_s(node, temp, & shared->SyncObjects) { 3654a49301eSmrg _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node); 3664a49301eSmrg } 3674a49301eSmrg } 3683464ebd5Sriastradh 3693464ebd5Sriastradh#if FEATURE_ARB_sampler_objects 3703464ebd5Sriastradh _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx); 3713464ebd5Sriastradh _mesa_DeleteHashTable(shared->SamplerObjects); 3724a49301eSmrg#endif 3734a49301eSmrg 3744a49301eSmrg /* 3754a49301eSmrg * Free texture objects (after FBOs since some textures might have 3764a49301eSmrg * been bound to FBOs). 3774a49301eSmrg */ 3784a49301eSmrg ASSERT(ctx->Driver.DeleteTexture); 3794a49301eSmrg /* the default textures */ 3804a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 3814a49301eSmrg ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); 3824a49301eSmrg } 3834a49301eSmrg 3844a49301eSmrg /* all other textures */ 3854a49301eSmrg _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); 3864a49301eSmrg _mesa_DeleteHashTable(shared->TexObjects); 3874a49301eSmrg 3884a49301eSmrg _glthread_DESTROY_MUTEX(shared->Mutex); 3894a49301eSmrg _glthread_DESTROY_MUTEX(shared->TexMutex); 3904a49301eSmrg 391cdc920a0Smrg free(shared); 3924a49301eSmrg} 3934a49301eSmrg 3944a49301eSmrg 3954a49301eSmrg/** 3964a49301eSmrg * Decrement shared state object reference count and potentially free it 3974a49301eSmrg * and all children structures. 3984a49301eSmrg * 3994a49301eSmrg * \param ctx GL context. 4004a49301eSmrg * \param shared shared state pointer. 4014a49301eSmrg * 4024a49301eSmrg * \sa free_shared_state(). 4034a49301eSmrg */ 4044a49301eSmrgvoid 4053464ebd5Sriastradh_mesa_release_shared_state(struct gl_context *ctx, 4063464ebd5Sriastradh struct gl_shared_state *shared) 4074a49301eSmrg{ 4084a49301eSmrg GLint RefCount; 4094a49301eSmrg 4104a49301eSmrg _glthread_LOCK_MUTEX(shared->Mutex); 4114a49301eSmrg RefCount = --shared->RefCount; 4124a49301eSmrg _glthread_UNLOCK_MUTEX(shared->Mutex); 4134a49301eSmrg 4144a49301eSmrg assert(RefCount >= 0); 4154a49301eSmrg 4164a49301eSmrg if (RefCount == 0) { 4174a49301eSmrg /* free shared state */ 4184a49301eSmrg free_shared_state( ctx, shared ); 4194a49301eSmrg } 4204a49301eSmrg} 421