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