14045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/*
24045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Mesa 3-D graphics library
34045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Version:  7.5
44045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
54045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
64045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
74045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
84045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * copy of this software and associated documentation files (the "Software"),
94045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * to deal in the Software without restriction, including without limitation
104045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
114045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
124045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Software is furnished to do so, subject to the following conditions:
134045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
144045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * The above copyright notice and this permission notice shall be included
154045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * in all copies or substantial portions of the Software.
164045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
174045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
184045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
194045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
204045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
214045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
224045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
234045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
244045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
254045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
264045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * \file shared.c
274045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Shared-context state
284045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
294045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
304045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#include "imports.h"
31db61b9ce39bccc43140357652ceb78baaf2aea44Vinson Lee#include "mfeatures.h"
324045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#include "mtypes.h"
334045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#include "hash.h"
3470c8d29b6bb3214966892d51e6b2befa7040622dBrian Paul#if FEATURE_ATI_fragment_shader
3570c8d29b6bb3214966892d51e6b2befa7040622dBrian Paul#include "atifragshader.h"
3670c8d29b6bb3214966892d51e6b2befa7040622dBrian Paul#endif
374f6b704f9796775d8d9937c3cf75a2901b99b896Brian Paul#include "bufferobj.h"
384045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#include "shared.h"
39ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/program.h"
404045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#include "dlist.h"
416bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#if FEATURE_ARB_sampler_objects
426bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#include "samplerobj.h"
436bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#endif
44a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul#include "shaderobj.h"
4516b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick#include "syncobj.h"
464045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
47032a7ef0a1cb753defc11e97b11ea2e602bae5f2Brian Paul
484045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
494045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Allocate and initialize a shared context state structure.
504045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Initializes the display list, texture objects and vertex programs hash
514045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * tables, allocates the texture objects. If it runs out of memory, frees
524045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * everything already allocated before returning NULL.
534045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
544045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * \return pointer to a gl_shared_state structure on success, or NULL on
554045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * failure.
564045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
574045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstruct gl_shared_state *
58f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_alloc_shared_state(struct gl_context *ctx)
594045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
604045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_shared_state *shared;
614045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   GLuint i;
624045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
634045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared = CALLOC_STRUCT(gl_shared_state);
644045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   if (!shared)
654045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      return NULL;
664045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
674045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _glthread_INIT_MUTEX(shared->Mutex);
684045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
694045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->DisplayList = _mesa_NewHashTable();
704045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->TexObjects = _mesa_NewHashTable();
714045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->Programs = _mesa_NewHashTable();
724045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
734045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_vertex_program
74e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul   shared->DefaultVertexProgram =
75e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      gl_vertex_program(ctx->Driver.NewProgram(ctx,
76e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul                                               GL_VERTEX_PROGRAM_ARB, 0));
774045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
784045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
794045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_fragment_program
80e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul   shared->DefaultFragmentProgram =
81e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul      gl_fragment_program(ctx->Driver.NewProgram(ctx,
82e4f8d33aea7e0112dfbf3a38fdc36d11b2e7be10Brian Paul                                                 GL_FRAGMENT_PROGRAM_ARB, 0));
834045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
844045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
854045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ATI_fragment_shader
864045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->ATIShaders = _mesa_NewHashTable();
874045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
884045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
894045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
904045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_shader_objects
914045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->ShaderObjects = _mesa_NewHashTable();
924045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
934045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
944045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->BufferObjects = _mesa_NewHashTable();
954045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
966bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#if FEATURE_ARB_sampler_objects
976bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   /* GL_ARB_sampler_objects */
986bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   shared->SamplerObjects = _mesa_NewHashTable();
996bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#endif
1006bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul
10105ac187f305bb653d569b5c07446ec0f4cd7ff08José Fonseca   /* Allocate the default buffer object */
1026629a35559ff7e3b993966f697f7c7f68e5a38d9Brian Paul   shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0);
1034f6b704f9796775d8d9937c3cf75a2901b99b896Brian Paul
1044045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* Create default texture objects */
1054045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
1064045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */
1074045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      static const GLenum targets[NUM_TEXTURE_TARGETS] = {
108874a2c0b7da62f4dd08dedcec221f55b22e40e95Brian Paul         GL_TEXTURE_BUFFER,
1094045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_2D_ARRAY_EXT,
1104045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_1D_ARRAY_EXT,
1110c87f16817ff0bf1f05e0d634944fd47b097faeeChia-I Wu         GL_TEXTURE_EXTERNAL_OES,
1124045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_CUBE_MAP,
1134045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_3D,
1144045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_RECTANGLE_NV,
1154045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_2D,
1164045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul         GL_TEXTURE_1D
1174045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      };
1186bf5daf331f13ec9503615a2578247e72b7d2cbbBrian Paul      STATIC_ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
1194045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]);
1204045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   }
1214045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1224045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* sanity check */
1234045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
1244045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1254045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* Mutex and timestamp for texobj state validation */
1264045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _glthread_INIT_MUTEX(shared->TexMutex);
1274045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->TextureStateStamp = 0;
1284045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1294045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_EXT_framebuffer_object
1304045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->FrameBuffers = _mesa_NewHashTable();
1314045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   shared->RenderBuffers = _mesa_NewHashTable();
1324045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
1334045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
13416b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick   make_empty_list(& shared->SyncObjects);
13516b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick
1364045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   return shared;
1374045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
1384045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1394045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1404045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
1414045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a display list.  Called by _mesa_HashDeleteAll().
1424045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
1434045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
1444045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_displaylist_cb(GLuint id, void *data, void *userData)
1454045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
1464045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_display_list *list = (struct gl_display_list *) data;
147f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
1484045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_delete_list(ctx, list);
1494045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
1504045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1514045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1524045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
1534045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a texture object.  Called by _mesa_HashDeleteAll().
1544045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
1554045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
1564045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_texture_cb(GLuint id, void *data, void *userData)
1574045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
1584045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_texture_object *texObj = (struct gl_texture_object *) data;
159f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
1604045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   ctx->Driver.DeleteTexture(ctx, texObj);
1614045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
1624045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1634045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1644045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
1654045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a program object.  Called by _mesa_HashDeleteAll().
1664045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
1674045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
1684045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_program_cb(GLuint id, void *data, void *userData)
1694045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
1704045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_program *prog = (struct gl_program *) data;
171f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
172629700ed7eaaf63d2037a11b2931c91fdc22944aJosé Fonseca   if(prog != &_mesa_DummyProgram) {
173629700ed7eaaf63d2037a11b2931c91fdc22944aJosé Fonseca      ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
174629700ed7eaaf63d2037a11b2931c91fdc22944aJosé Fonseca      prog->RefCount = 0;  /* now going away */
175629700ed7eaaf63d2037a11b2931c91fdc22944aJosé Fonseca      ctx->Driver.DeleteProgram(ctx, prog);
176629700ed7eaaf63d2037a11b2931c91fdc22944aJosé Fonseca   }
1774045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
1784045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1794045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1804045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ATI_fragment_shader
1814045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
1824045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting an ATI fragment shader object.
1834045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Called by _mesa_HashDeleteAll().
1844045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
1854045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
1864045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_fragshader_cb(GLuint id, void *data, void *userData)
1874045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
1884045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
189f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
1904045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_delete_ati_fragment_shader(ctx, shader);
1914045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
1924045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
1934045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1944045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
1954045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
1964045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a buffer object.  Called by _mesa_HashDeleteAll().
1974045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
1984045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
1994045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_bufferobj_cb(GLuint id, void *data, void *userData)
2004045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
2014045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
202f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
2034482f96c59d7d0f0b19329e997fb59dba3e84119Brian Paul   if (_mesa_bufferobj_mapped(bufObj)) {
20456f0c00f125ee75caeadc1c9e8cab8a488635e5eIan Romanick      ctx->Driver.UnmapBuffer(ctx, bufObj);
205cc7170464493453ec8213decd21df95121b236e2Brian Paul      bufObj->Pointer = NULL;
206cc7170464493453ec8213decd21df95121b236e2Brian Paul   }
20705ac187f305bb653d569b5c07446ec0f4cd7ff08José Fonseca   _mesa_reference_buffer_object(ctx, &bufObj, NULL);
2084045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
2094045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2104045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2114045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
2124045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for freeing shader program data. Call it before delete_shader_cb
2134045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * to avoid memory access error.
2144045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
2154045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
2164045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulfree_shader_program_data_cb(GLuint id, void *data, void *userData)
2174045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
218f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
2194045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_shader_program *shProg = (struct gl_shader_program *) data;
2204045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2214045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
2224045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul       _mesa_free_shader_program_data(ctx, shProg);
2234045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   }
2244045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
2254045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2264045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2274045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
2284045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting shader and shader programs objects.
2294045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Called by _mesa_HashDeleteAll().
2304045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
2314045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
2324045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_shader_cb(GLuint id, void *data, void *userData)
2334045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
234f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg   struct gl_context *ctx = (struct gl_context *) userData;
2354045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_shader *sh = (struct gl_shader *) data;
2364045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
237a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul      ctx->Driver.DeleteShader(ctx, sh);
2384045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   }
2394045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   else {
2404045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      struct gl_shader_program *shProg = (struct gl_shader_program *) data;
2414045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
242a37b2219d6e3f299379c6434d65f300660d12c3eBrian Paul      ctx->Driver.DeleteShaderProgram(ctx, shProg);
2434045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   }
2444045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
2454045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2464045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2474045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
2484045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a framebuffer object.  Called by _mesa_HashDeleteAll()
2494045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
2504045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
2514045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_framebuffer_cb(GLuint id, void *data, void *userData)
2524045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
2534045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2544045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* The fact that the framebuffer is in the hashtable means its refcount
2554045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    * is one, but we're removing from the hashtable now.  So clear refcount.
2564045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    */
2574045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /*assert(fb->RefCount == 1);*/
2584045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   fb->RefCount = 0;
2594045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2604045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* NOTE: Delete should always be defined but there are two reports
2614045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    * of it being NULL (bugs 13507, 14293).  Work-around for now.
2624045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    */
2634045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   if (fb->Delete)
2644045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      fb->Delete(fb);
2654045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
2664045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2674045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2684045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
2694045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
2704045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
2714045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paulstatic void
2724045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Pauldelete_renderbuffer_cb(GLuint id, void *data, void *userData)
2734045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
2749d4ab9a663d4088ec553edaae0eeafb746d2490dBrian Paul   struct gl_context *ctx = (struct gl_context *) userData;
2754045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
2764045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   rb->RefCount = 0;  /* see comment for FBOs above */
2774045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   if (rb->Delete)
2789d4ab9a663d4088ec553edaae0eeafb746d2490dBrian Paul      rb->Delete(ctx, rb);
2794045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
2804045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2814045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
2826bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#if FEATURE_ARB_sampler_objects
2836bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul/**
2846bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll()
2856bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul */
2866bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paulstatic void
2876bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Pauldelete_sampler_object_cb(GLuint id, void *data, void *userData)
2886bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul{
2896bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   struct gl_context *ctx = (struct gl_context *) userData;
2906bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data;
2916bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   _mesa_reference_sampler_object(ctx, &sampObj, NULL);
2926bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul}
2936bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#endif
2946bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul
2956bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul
2964045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul/**
2974045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Deallocate a shared state object and all children structures.
2984045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
2994045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * \param ctx GL context.
3001eee1bac1f6d911e6124daafc9b9291666d91cefVinson Lee * \param shared shared state pointer.
3014045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
3024045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * Frees the display lists, the texture objects (calling the driver texture
3034045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * deletion callback to free its private data) and the vertex programs, as well
3044045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * as their hash tables.
3054045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul *
3064045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul * \sa alloc_shared_state().
3074045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul */
3081c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonsecastatic void
309f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergfree_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
3104045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul{
3114045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   GLuint i;
3124045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
313c04db7f7fad883891084d7f2e9a0040a17c48fe8Brian Paul   /* Free the dummy/fallback texture objects */
314c04db7f7fad883891084d7f2e9a0040a17c48fe8Brian Paul   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
315c04db7f7fad883891084d7f2e9a0040a17c48fe8Brian Paul      if (shared->FallbackTex[i])
316c04db7f7fad883891084d7f2e9a0040a17c48fe8Brian Paul         ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]);
317c04db7f7fad883891084d7f2e9a0040a17c48fe8Brian Paul   }
318c8e0970667d2b4d92abe22bf099cafee4acb717bBrian Paul
3194045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /*
3204045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    * Free display lists
3214045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    */
3224045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx);
3234045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->DisplayList);
3244045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3254045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_shader_objects
3264045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx);
3274045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx);
3284045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->ShaderObjects);
3294045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
3304045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3314045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx);
3324045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->Programs);
3334045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3344045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_vertex_program
3354045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL);
3364045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
3374045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3384045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ARB_fragment_program
3394045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
3404045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
3414045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3424045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_ATI_fragment_shader
3434045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
3444045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->ATIShaders);
3454045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
3464045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
3474045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3484045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
3494045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->BufferObjects);
3504045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3514045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#if FEATURE_EXT_framebuffer_object
3524045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx);
3534045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->FrameBuffers);
3544045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx);
3554045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->RenderBuffers);
3564045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul#endif
3574045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
35805ac187f305bb653d569b5c07446ec0f4cd7ff08José Fonseca   _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL);
3594f6b704f9796775d8d9937c3cf75a2901b99b896Brian Paul
36016b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick   {
36116b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick      struct simple_node *node;
36216b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick      struct simple_node *temp;
36316b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick
36416b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick      foreach_s(node, temp, & shared->SyncObjects) {
36516b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick	 _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node);
36616b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick      }
36716b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick   }
36816b393d05990b6e917e144f9de87d0103b4c3e6dIan Romanick
3696bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#if FEATURE_ARB_sampler_objects
3706bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx);
3716bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul   _mesa_DeleteHashTable(shared->SamplerObjects);
3726bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul#endif
3736bb4d807f7e80eaf899fd5c34c2c9ff0474eb80eBrian Paul
3744045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /*
3754045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    * Free texture objects (after FBOs since some textures might have
3764045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    * been bound to FBOs).
3774045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul    */
3784045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   ASSERT(ctx->Driver.DeleteTexture);
3794045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* the default textures */
3804045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
3814045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul      ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
3824045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   }
3834045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3844045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   /* all other textures */
3854045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
3864045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _mesa_DeleteHashTable(shared->TexObjects);
3874045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
3884045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _glthread_DESTROY_MUTEX(shared->Mutex);
3894045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul   _glthread_DESTROY_MUTEX(shared->TexMutex);
3904045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul
39132f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg   free(shared);
3924045a2c7d302352646c1ff2a01cd531aa1b55d31Brian Paul}
3931c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca
3941c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca
3951c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca/**
396361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul * gl_shared_state objects are ref counted.
397361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul * If ptr's refcount goes to zero, free the shared state.
3981c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca */
3991c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonsecavoid
400361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul_mesa_reference_shared_state(struct gl_context *ctx,
401361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul                             struct gl_shared_state **ptr,
402361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul                             struct gl_shared_state *state)
4031c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca{
404361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul   if (*ptr == state)
405361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      return;
406361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul
407361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul   if (*ptr) {
408361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      /* unref old state */
409361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      struct gl_shared_state *old = *ptr;
410361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      GLboolean delete;
411361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul
412361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      _glthread_LOCK_MUTEX(old->Mutex);
413361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      assert(old->RefCount >= 1);
414361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      old->RefCount--;
415361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      delete = (old->RefCount == 0);
416361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      _glthread_UNLOCK_MUTEX(old->Mutex);
417361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul
418361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      if (delete) {
419361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul         free_shared_state(ctx, old);
420361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      }
4211c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca
422361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      *ptr = NULL;
423361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul   }
4241c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca
425361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul   if (state) {
426361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      /* reference new state */
427361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      _glthread_LOCK_MUTEX(state->Mutex);
428361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      state->RefCount++;
429361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      *ptr = state;
430361cd53a77dd48fbf2a0321446c0b7c07365bff9Brian Paul      _glthread_UNLOCK_MUTEX(state->Mutex);
4311c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca   }
4321c39dbb90cefad8a5a97e75042466d66ea4270bcJosé Fonseca}
433