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