1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Mesa 3-D graphics library
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Version:  7.5
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be included
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in all copies or substantial portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file shared.c
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Shared-context state
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "imports.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "mfeatures.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "mtypes.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "hash.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ATI_fragment_shader
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "atifragshader.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "bufferobj.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "shared.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program/program.h"
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "dlist.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_sampler_objects
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "samplerobj.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "shaderobj.h"
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "syncobj.h"
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Allocate and initialize a shared context state structure.
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initializes the display list, texture objects and vertex programs hash
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * tables, allocates the texture objects. If it runs out of memory, frees
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * everything already allocated before returning NULL.
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return pointer to a gl_shared_state structure on success, or NULL on
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * failure.
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct gl_shared_state *
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_mesa_alloc_shared_state(struct gl_context *ctx)
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_shared_state *shared;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared = CALLOC_STRUCT(gl_shared_state);
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!shared)
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _glthread_INIT_MUTEX(shared->Mutex);
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->DisplayList = _mesa_NewHashTable();
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->TexObjects = _mesa_NewHashTable();
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->Programs = _mesa_NewHashTable();
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_vertex_program
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->DefaultVertexProgram =
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_vertex_program(ctx->Driver.NewProgram(ctx,
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                               GL_VERTEX_PROGRAM_ARB, 0));
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_fragment_program
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->DefaultFragmentProgram =
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_fragment_program(ctx->Driver.NewProgram(ctx,
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                 GL_FRAGMENT_PROGRAM_ARB, 0));
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ATI_fragment_shader
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->ATIShaders = _mesa_NewHashTable();
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_shader_objects
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->ShaderObjects = _mesa_NewHashTable();
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->BufferObjects = _mesa_NewHashTable();
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_sampler_objects
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* GL_ARB_sampler_objects */
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->SamplerObjects = _mesa_NewHashTable();
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Allocate the default buffer object */
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0);
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Create default texture objects */
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      static const GLenum targets[NUM_TEXTURE_TARGETS] = {
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_BUFFER,
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_2D_ARRAY_EXT,
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_1D_ARRAY_EXT,
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_EXTERNAL_OES,
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_CUBE_MAP,
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_3D,
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_RECTANGLE_NV,
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_2D,
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         GL_TEXTURE_1D
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      };
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      STATIC_ASSERT(Elements(targets) == NUM_TEXTURE_TARGETS);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]);
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* sanity check */
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Mutex and timestamp for texobj state validation */
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _glthread_INIT_MUTEX(shared->TexMutex);
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->TextureStateStamp = 0;
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_EXT_framebuffer_object
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->FrameBuffers = _mesa_NewHashTable();
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shared->RenderBuffers = _mesa_NewHashTable();
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   make_empty_list(& shared->SyncObjects);
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return shared;
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a display list.  Called by _mesa_HashDeleteAll().
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_displaylist_cb(GLuint id, void *data, void *userData)
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_display_list *list = (struct gl_display_list *) data;
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_delete_list(ctx, list);
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a texture object.  Called by _mesa_HashDeleteAll().
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_texture_cb(GLuint id, void *data, void *userData)
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_texture_object *texObj = (struct gl_texture_object *) data;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ctx->Driver.DeleteTexture(ctx, texObj);
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a program object.  Called by _mesa_HashDeleteAll().
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_program_cb(GLuint id, void *data, void *userData)
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_program *prog = (struct gl_program *) data;
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(prog != &_mesa_DummyProgram) {
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->RefCount = 0;  /* now going away */
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.DeleteProgram(ctx, prog);
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ATI_fragment_shader
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting an ATI fragment shader object.
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Called by _mesa_HashDeleteAll().
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_fragshader_cb(GLuint id, void *data, void *userData)
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_delete_ati_fragment_shader(ctx, shader);
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a buffer object.  Called by _mesa_HashDeleteAll().
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_bufferobj_cb(GLuint id, void *data, void *userData)
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (_mesa_bufferobj_mapped(bufObj)) {
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.UnmapBuffer(ctx, bufObj);
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      bufObj->Pointer = NULL;
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_reference_buffer_object(ctx, &bufObj, NULL);
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for freeing shader program data. Call it before delete_shader_cb
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to avoid memory access error.
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfree_shader_program_data_cb(GLuint id, void *data, void *userData)
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_shader_program *shProg = (struct gl_shader_program *) data;
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       _mesa_free_shader_program_data(ctx, shProg);
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting shader and shader programs objects.
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Called by _mesa_HashDeleteAll().
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_shader_cb(GLuint id, void *data, void *userData)
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_shader *sh = (struct gl_shader *) data;
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) {
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.DeleteShader(ctx, sh);
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader_program *shProg = (struct gl_shader_program *) data;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA);
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.DeleteShaderProgram(ctx, shProg);
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a framebuffer object.  Called by _mesa_HashDeleteAll()
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_framebuffer_cb(GLuint id, void *data, void *userData)
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* The fact that the framebuffer is in the hashtable means its refcount
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * is one, but we're removing from the hashtable now.  So clear refcount.
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*assert(fb->RefCount == 1);*/
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   fb->RefCount = 0;
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* NOTE: Delete should always be defined but there are two reports
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * of it being NULL (bugs 13507, 14293).  Work-around for now.
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (fb->Delete)
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      fb->Delete(fb);
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_renderbuffer_cb(GLuint id, void *data, void *userData)
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   rb->RefCount = 0;  /* see comment for FBOs above */
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (rb->Delete)
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rb->Delete(ctx, rb);
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_sampler_objects
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Callback for deleting a sampler object. Called by _mesa_HashDeleteAll()
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdelete_sampler_object_cb(GLuint id, void *data, void *userData)
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_context *ctx = (struct gl_context *) userData;
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_sampler_object *sampObj = (struct gl_sampler_object *) data;
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_reference_sampler_object(ctx, &sampObj, NULL);
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Deallocate a shared state object and all children structures.
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param ctx GL context.
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param shared shared state pointer.
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Frees the display lists, the texture objects (calling the driver texture
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * deletion callback to free its private data) and the vertex programs, as well
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * as their hash tables.
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \sa alloc_shared_state().
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfree_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLuint i;
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Free the dummy/fallback texture objects */
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (shared->FallbackTex[i])
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ctx->Driver.DeleteTexture(ctx, shared->FallbackTex[i]);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Free display lists
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx);
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->DisplayList);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_shader_objects
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx);
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx);
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->ShaderObjects);
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx);
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->Programs);
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_vertex_program
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL);
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_fragment_program
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ATI_fragment_shader
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->ATIShaders);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->BufferObjects);
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_EXT_framebuffer_object
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx);
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->FrameBuffers);
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx);
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->RenderBuffers);
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL);
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct simple_node *node;
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct simple_node *temp;
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_s(node, temp, & shared->SyncObjects) {
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node);
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if FEATURE_ARB_sampler_objects
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx);
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->SamplerObjects);
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Free texture objects (after FBOs since some textures might have
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * been bound to FBOs).
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ASSERT(ctx->Driver.DeleteTexture);
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* the default textures */
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]);
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* all other textures */
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_DeleteHashTable(shared->TexObjects);
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _glthread_DESTROY_MUTEX(shared->Mutex);
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _glthread_DESTROY_MUTEX(shared->TexMutex);
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(shared);
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gl_shared_state objects are ref counted.
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If ptr's refcount goes to zero, free the shared state.
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org_mesa_reference_shared_state(struct gl_context *ctx,
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             struct gl_shared_state **ptr,
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             struct gl_shared_state *state)
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (*ptr == state)
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (*ptr) {
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* unref old state */
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shared_state *old = *ptr;
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLboolean delete;
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _glthread_LOCK_MUTEX(old->Mutex);
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(old->RefCount >= 1);
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      old->RefCount--;
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      delete = (old->RefCount == 0);
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _glthread_UNLOCK_MUTEX(old->Mutex);
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (delete) {
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         free_shared_state(ctx, old);
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *ptr = NULL;
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (state) {
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* reference new state */
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _glthread_LOCK_MUTEX(state->Mutex);
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      state->RefCount++;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *ptr = state;
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _glthread_UNLOCK_MUTEX(state->Mutex);
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
433