shared.c revision af69d88d
14a49301eSmrg/* 24a49301eSmrg * Mesa 3-D graphics library 34a49301eSmrg * 44a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the "Software"), 84a49301eSmrg * to deal in the Software without restriction, including without limitation 94a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 104a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the 114a49301eSmrg * Software is furnished to do so, subject to the following conditions: 124a49301eSmrg * 134a49301eSmrg * The above copyright notice and this permission notice shall be included 144a49301eSmrg * in all copies or substantial portions of the Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 174a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 234a49301eSmrg */ 244a49301eSmrg 254a49301eSmrg/** 264a49301eSmrg * \file shared.c 274a49301eSmrg * Shared-context state 284a49301eSmrg */ 294a49301eSmrg 304a49301eSmrg#include "imports.h" 314a49301eSmrg#include "mtypes.h" 324a49301eSmrg#include "hash.h" 333464ebd5Sriastradh#include "atifragshader.h" 344a49301eSmrg#include "bufferobj.h" 354a49301eSmrg#include "shared.h" 363464ebd5Sriastradh#include "program/program.h" 374a49301eSmrg#include "dlist.h" 383464ebd5Sriastradh#include "samplerobj.h" 39af69d88dSmrg#include "set.h" 40af69d88dSmrg#include "shaderapi.h" 413464ebd5Sriastradh#include "shaderobj.h" 424a49301eSmrg#include "syncobj.h" 433464ebd5Sriastradh 44af69d88dSmrg#include "util/hash_table.h" 454a49301eSmrg 464a49301eSmrg/** 474a49301eSmrg * Allocate and initialize a shared context state structure. 484a49301eSmrg * Initializes the display list, texture objects and vertex programs hash 494a49301eSmrg * tables, allocates the texture objects. If it runs out of memory, frees 504a49301eSmrg * everything already allocated before returning NULL. 514a49301eSmrg * 524a49301eSmrg * \return pointer to a gl_shared_state structure on success, or NULL on 534a49301eSmrg * failure. 544a49301eSmrg */ 554a49301eSmrgstruct gl_shared_state * 563464ebd5Sriastradh_mesa_alloc_shared_state(struct gl_context *ctx) 574a49301eSmrg{ 584a49301eSmrg struct gl_shared_state *shared; 594a49301eSmrg GLuint i; 604a49301eSmrg 614a49301eSmrg shared = CALLOC_STRUCT(gl_shared_state); 624a49301eSmrg if (!shared) 634a49301eSmrg return NULL; 644a49301eSmrg 65af69d88dSmrg mtx_init(&shared->Mutex, mtx_plain); 664a49301eSmrg 674a49301eSmrg shared->DisplayList = _mesa_NewHashTable(); 684a49301eSmrg shared->TexObjects = _mesa_NewHashTable(); 694a49301eSmrg shared->Programs = _mesa_NewHashTable(); 704a49301eSmrg 71af69d88dSmrg shared->DefaultVertexProgram = 72af69d88dSmrg gl_vertex_program(ctx->Driver.NewProgram(ctx, 73af69d88dSmrg GL_VERTEX_PROGRAM_ARB, 0)); 74af69d88dSmrg shared->DefaultFragmentProgram = 75af69d88dSmrg gl_fragment_program(ctx->Driver.NewProgram(ctx, 76af69d88dSmrg GL_FRAGMENT_PROGRAM_ARB, 0)); 774a49301eSmrg 784a49301eSmrg shared->ATIShaders = _mesa_NewHashTable(); 794a49301eSmrg shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0); 804a49301eSmrg 814a49301eSmrg shared->ShaderObjects = _mesa_NewHashTable(); 824a49301eSmrg 834a49301eSmrg shared->BufferObjects = _mesa_NewHashTable(); 844a49301eSmrg 853464ebd5Sriastradh /* GL_ARB_sampler_objects */ 863464ebd5Sriastradh shared->SamplerObjects = _mesa_NewHashTable(); 873464ebd5Sriastradh 884a49301eSmrg /* Allocate the default buffer object */ 894a49301eSmrg shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); 904a49301eSmrg 914a49301eSmrg /* Create default texture objects */ 924a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 934a49301eSmrg /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ 94af69d88dSmrg static const GLenum targets[] = { 95af69d88dSmrg GL_TEXTURE_2D_MULTISAMPLE, 96af69d88dSmrg GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 97af69d88dSmrg GL_TEXTURE_CUBE_MAP_ARRAY, 983464ebd5Sriastradh GL_TEXTURE_BUFFER, 994a49301eSmrg GL_TEXTURE_2D_ARRAY_EXT, 1004a49301eSmrg GL_TEXTURE_1D_ARRAY_EXT, 101af69d88dSmrg GL_TEXTURE_EXTERNAL_OES, 1024a49301eSmrg GL_TEXTURE_CUBE_MAP, 1034a49301eSmrg GL_TEXTURE_3D, 1044a49301eSmrg GL_TEXTURE_RECTANGLE_NV, 1054a49301eSmrg GL_TEXTURE_2D, 1064a49301eSmrg GL_TEXTURE_1D 1074a49301eSmrg }; 108af69d88dSmrg STATIC_ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS); 1094a49301eSmrg shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); 1104a49301eSmrg } 1114a49301eSmrg 1124a49301eSmrg /* sanity check */ 1134a49301eSmrg assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); 1144a49301eSmrg 1154a49301eSmrg /* Mutex and timestamp for texobj state validation */ 116af69d88dSmrg mtx_init(&shared->TexMutex, mtx_recursive); 1174a49301eSmrg shared->TextureStateStamp = 0; 1184a49301eSmrg 1194a49301eSmrg shared->FrameBuffers = _mesa_NewHashTable(); 1204a49301eSmrg shared->RenderBuffers = _mesa_NewHashTable(); 1214a49301eSmrg 122af69d88dSmrg shared->SyncObjects = _mesa_set_create(NULL, _mesa_key_pointer_equal); 1234a49301eSmrg 1244a49301eSmrg return shared; 1254a49301eSmrg} 1264a49301eSmrg 1274a49301eSmrg 1284a49301eSmrg/** 1294a49301eSmrg * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). 1304a49301eSmrg */ 1314a49301eSmrgstatic void 1324a49301eSmrgdelete_displaylist_cb(GLuint id, void *data, void *userData) 1334a49301eSmrg{ 1344a49301eSmrg struct gl_display_list *list = (struct gl_display_list *) data; 1353464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1364a49301eSmrg _mesa_delete_list(ctx, list); 1374a49301eSmrg} 1384a49301eSmrg 1394a49301eSmrg 1404a49301eSmrg/** 1414a49301eSmrg * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). 1424a49301eSmrg */ 1434a49301eSmrgstatic void 1444a49301eSmrgdelete_texture_cb(GLuint id, void *data, void *userData) 1454a49301eSmrg{ 1464a49301eSmrg struct gl_texture_object *texObj = (struct gl_texture_object *) data; 1473464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1484a49301eSmrg ctx->Driver.DeleteTexture(ctx, texObj); 1494a49301eSmrg} 1504a49301eSmrg 1514a49301eSmrg 1524a49301eSmrg/** 1534a49301eSmrg * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). 1544a49301eSmrg */ 1554a49301eSmrgstatic void 1564a49301eSmrgdelete_program_cb(GLuint id, void *data, void *userData) 1574a49301eSmrg{ 1584a49301eSmrg struct gl_program *prog = (struct gl_program *) data; 1593464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1604a49301eSmrg if(prog != &_mesa_DummyProgram) { 1614a49301eSmrg ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ 1624a49301eSmrg prog->RefCount = 0; /* now going away */ 1634a49301eSmrg ctx->Driver.DeleteProgram(ctx, prog); 1644a49301eSmrg } 1654a49301eSmrg} 1664a49301eSmrg 1674a49301eSmrg 1684a49301eSmrg/** 1694a49301eSmrg * Callback for deleting an ATI fragment shader object. 1704a49301eSmrg * Called by _mesa_HashDeleteAll(). 1714a49301eSmrg */ 1724a49301eSmrgstatic void 1734a49301eSmrgdelete_fragshader_cb(GLuint id, void *data, void *userData) 1744a49301eSmrg{ 1754a49301eSmrg struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; 1763464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 1774a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shader); 1784a49301eSmrg} 1794a49301eSmrg 1804a49301eSmrg 1814a49301eSmrg/** 1824a49301eSmrg * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). 1834a49301eSmrg */ 1844a49301eSmrgstatic void 1854a49301eSmrgdelete_bufferobj_cb(GLuint id, void *data, void *userData) 1864a49301eSmrg{ 1874a49301eSmrg struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; 1883464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 189af69d88dSmrg 190af69d88dSmrg _mesa_buffer_unmap_all_mappings(ctx, bufObj); 1914a49301eSmrg _mesa_reference_buffer_object(ctx, &bufObj, NULL); 1924a49301eSmrg} 1934a49301eSmrg 1944a49301eSmrg 1954a49301eSmrg/** 1964a49301eSmrg * Callback for freeing shader program data. Call it before delete_shader_cb 1974a49301eSmrg * to avoid memory access error. 1984a49301eSmrg */ 1994a49301eSmrgstatic void 2004a49301eSmrgfree_shader_program_data_cb(GLuint id, void *data, void *userData) 2014a49301eSmrg{ 2023464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2034a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2044a49301eSmrg 2054a49301eSmrg if (shProg->Type == GL_SHADER_PROGRAM_MESA) { 2064a49301eSmrg _mesa_free_shader_program_data(ctx, shProg); 2074a49301eSmrg } 2084a49301eSmrg} 2094a49301eSmrg 2104a49301eSmrg 2114a49301eSmrg/** 2124a49301eSmrg * Callback for deleting shader and shader programs objects. 2134a49301eSmrg * Called by _mesa_HashDeleteAll(). 2144a49301eSmrg */ 2154a49301eSmrgstatic void 2164a49301eSmrgdelete_shader_cb(GLuint id, void *data, void *userData) 2174a49301eSmrg{ 2183464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2194a49301eSmrg struct gl_shader *sh = (struct gl_shader *) data; 220af69d88dSmrg if (_mesa_validate_shader_target(ctx, sh->Type)) { 2213464ebd5Sriastradh ctx->Driver.DeleteShader(ctx, sh); 2224a49301eSmrg } 2234a49301eSmrg else { 2244a49301eSmrg struct gl_shader_program *shProg = (struct gl_shader_program *) data; 2254a49301eSmrg ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); 2263464ebd5Sriastradh ctx->Driver.DeleteShaderProgram(ctx, shProg); 2274a49301eSmrg } 2284a49301eSmrg} 2294a49301eSmrg 2304a49301eSmrg 2314a49301eSmrg/** 2324a49301eSmrg * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() 2334a49301eSmrg */ 2344a49301eSmrgstatic void 2354a49301eSmrgdelete_framebuffer_cb(GLuint id, void *data, void *userData) 2364a49301eSmrg{ 2374a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2384a49301eSmrg /* The fact that the framebuffer is in the hashtable means its refcount 2394a49301eSmrg * is one, but we're removing from the hashtable now. So clear refcount. 2404a49301eSmrg */ 2414a49301eSmrg /*assert(fb->RefCount == 1);*/ 2424a49301eSmrg fb->RefCount = 0; 2434a49301eSmrg 2444a49301eSmrg /* NOTE: Delete should always be defined but there are two reports 2454a49301eSmrg * of it being NULL (bugs 13507, 14293). Work-around for now. 2464a49301eSmrg */ 2474a49301eSmrg if (fb->Delete) 2484a49301eSmrg fb->Delete(fb); 2494a49301eSmrg} 2504a49301eSmrg 2514a49301eSmrg 2524a49301eSmrg/** 2534a49301eSmrg * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() 2544a49301eSmrg */ 2554a49301eSmrgstatic void 2564a49301eSmrgdelete_renderbuffer_cb(GLuint id, void *data, void *userData) 2574a49301eSmrg{ 258af69d88dSmrg struct gl_context *ctx = (struct gl_context *) userData; 2594a49301eSmrg struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; 2604a49301eSmrg rb->RefCount = 0; /* see comment for FBOs above */ 2614a49301eSmrg if (rb->Delete) 262af69d88dSmrg rb->Delete(ctx, rb); 2634a49301eSmrg} 2644a49301eSmrg 2654a49301eSmrg 2663464ebd5Sriastradh/** 2673464ebd5Sriastradh * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll() 2683464ebd5Sriastradh */ 2693464ebd5Sriastradhstatic void 2703464ebd5Sriastradhdelete_sampler_object_cb(GLuint id, void *data, void *userData) 2713464ebd5Sriastradh{ 2723464ebd5Sriastradh struct gl_context *ctx = (struct gl_context *) userData; 2733464ebd5Sriastradh struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data; 2743464ebd5Sriastradh _mesa_reference_sampler_object(ctx, &sampObj, NULL); 2753464ebd5Sriastradh} 2763464ebd5Sriastradh 2773464ebd5Sriastradh 2784a49301eSmrg/** 2794a49301eSmrg * Deallocate a shared state object and all children structures. 2804a49301eSmrg * 2814a49301eSmrg * \param ctx GL context. 2824a49301eSmrg * \param shared shared state pointer. 2834a49301eSmrg * 2844a49301eSmrg * Frees the display lists, the texture objects (calling the driver texture 2854a49301eSmrg * deletion callback to free its private data) and the vertex programs, as well 2864a49301eSmrg * as their hash tables. 2874a49301eSmrg * 2884a49301eSmrg * \sa alloc_shared_state(). 2894a49301eSmrg */ 2904a49301eSmrgstatic void 2913464ebd5Sriastradhfree_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) 2924a49301eSmrg{ 2934a49301eSmrg GLuint i; 2944a49301eSmrg 295af69d88dSmrg /* Free the dummy/fallback texture objects */ 296af69d88dSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 297af69d88dSmrg if (shared->FallbackTex[i]) 298af69d88dSmrg ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]); 299af69d88dSmrg } 3003464ebd5Sriastradh 3014a49301eSmrg /* 3024a49301eSmrg * Free display lists 3034a49301eSmrg */ 3044a49301eSmrg _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); 3054a49301eSmrg _mesa_DeleteHashTable(shared->DisplayList); 3064a49301eSmrg 3074a49301eSmrg _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); 3084a49301eSmrg _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); 3094a49301eSmrg _mesa_DeleteHashTable(shared->ShaderObjects); 3104a49301eSmrg 3114a49301eSmrg _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); 3124a49301eSmrg _mesa_DeleteHashTable(shared->Programs); 3134a49301eSmrg 3144a49301eSmrg _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); 315af69d88dSmrg _mesa_reference_geomprog(ctx, &shared->DefaultGeometryProgram, NULL); 3164a49301eSmrg _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); 3174a49301eSmrg 3184a49301eSmrg _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); 3194a49301eSmrg _mesa_DeleteHashTable(shared->ATIShaders); 3204a49301eSmrg _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); 3214a49301eSmrg 3224a49301eSmrg _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); 3234a49301eSmrg _mesa_DeleteHashTable(shared->BufferObjects); 3244a49301eSmrg 3254a49301eSmrg _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); 3264a49301eSmrg _mesa_DeleteHashTable(shared->FrameBuffers); 3274a49301eSmrg _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); 3284a49301eSmrg _mesa_DeleteHashTable(shared->RenderBuffers); 3294a49301eSmrg 3304a49301eSmrg _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); 3314a49301eSmrg 3324a49301eSmrg { 333af69d88dSmrg struct set_entry *entry; 3344a49301eSmrg 335af69d88dSmrg set_foreach(shared->SyncObjects, entry) { 336af69d88dSmrg _mesa_unref_sync_object(ctx, (struct gl_sync_object *) entry->key); 3374a49301eSmrg } 3384a49301eSmrg } 339af69d88dSmrg _mesa_set_destroy(shared->SyncObjects, NULL); 3403464ebd5Sriastradh 3413464ebd5Sriastradh _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx); 3423464ebd5Sriastradh _mesa_DeleteHashTable(shared->SamplerObjects); 3434a49301eSmrg 3444a49301eSmrg /* 3454a49301eSmrg * Free texture objects (after FBOs since some textures might have 3464a49301eSmrg * been bound to FBOs). 3474a49301eSmrg */ 3484a49301eSmrg ASSERT(ctx->Driver.DeleteTexture); 3494a49301eSmrg /* the default textures */ 3504a49301eSmrg for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { 3514a49301eSmrg ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); 3524a49301eSmrg } 3534a49301eSmrg 3544a49301eSmrg /* all other textures */ 3554a49301eSmrg _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); 3564a49301eSmrg _mesa_DeleteHashTable(shared->TexObjects); 3574a49301eSmrg 358af69d88dSmrg mtx_destroy(&shared->Mutex); 359af69d88dSmrg mtx_destroy(&shared->TexMutex); 3604a49301eSmrg 361cdc920a0Smrg free(shared); 3624a49301eSmrg} 3634a49301eSmrg 3644a49301eSmrg 3654a49301eSmrg/** 366af69d88dSmrg * gl_shared_state objects are ref counted. 367af69d88dSmrg * If ptr's refcount goes to zero, free the shared state. 3684a49301eSmrg */ 3694a49301eSmrgvoid 370af69d88dSmrg_mesa_reference_shared_state(struct gl_context *ctx, 371af69d88dSmrg struct gl_shared_state **ptr, 372af69d88dSmrg struct gl_shared_state *state) 3734a49301eSmrg{ 374af69d88dSmrg if (*ptr == state) 375af69d88dSmrg return; 376af69d88dSmrg 377af69d88dSmrg if (*ptr) { 378af69d88dSmrg /* unref old state */ 379af69d88dSmrg struct gl_shared_state *old = *ptr; 380af69d88dSmrg GLboolean delete; 381af69d88dSmrg 382af69d88dSmrg mtx_lock(&old->Mutex); 383af69d88dSmrg assert(old->RefCount >= 1); 384af69d88dSmrg old->RefCount--; 385af69d88dSmrg delete = (old->RefCount == 0); 386af69d88dSmrg mtx_unlock(&old->Mutex); 387af69d88dSmrg 388af69d88dSmrg if (delete) { 389af69d88dSmrg free_shared_state(ctx, old); 390af69d88dSmrg } 3914a49301eSmrg 392af69d88dSmrg *ptr = NULL; 393af69d88dSmrg } 3944a49301eSmrg 395af69d88dSmrg if (state) { 396af69d88dSmrg /* reference new state */ 397af69d88dSmrg mtx_lock(&state->Mutex); 398af69d88dSmrg state->RefCount++; 399af69d88dSmrg *ptr = state; 400af69d88dSmrg mtx_unlock(&state->Mutex); 4014a49301eSmrg } 4024a49301eSmrg} 403