Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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 | #if FEATURE_ATI_fragment_shader |
||
36 | #include "atifragshader.h" |
||
37 | #endif |
||
38 | #include "bufferobj.h" |
||
39 | #include "shared.h" |
||
40 | #include "program/program.h" |
||
41 | #include "dlist.h" |
||
42 | #include "shaderobj.h" |
||
43 | #include "syncobj.h" |
||
44 | |||
45 | /** |
||
46 | * Allocate and initialize a shared context state structure. |
||
47 | * Initializes the display list, texture objects and vertex programs hash |
||
48 | * tables, allocates the texture objects. If it runs out of memory, frees |
||
49 | * everything already allocated before returning NULL. |
||
50 | * |
||
51 | * \return pointer to a gl_shared_state structure on success, or NULL on |
||
52 | * failure. |
||
53 | */ |
||
54 | struct gl_shared_state * |
||
55 | _mesa_alloc_shared_state(struct gl_context *ctx) |
||
56 | { |
||
57 | struct gl_shared_state *shared; |
||
58 | GLuint i; |
||
59 | |||
60 | shared = CALLOC_STRUCT(gl_shared_state); |
||
61 | if (!shared) |
||
62 | return NULL; |
||
63 | |||
64 | _glthread_INIT_MUTEX(shared->Mutex); |
||
65 | |||
66 | shared->DisplayList = _mesa_NewHashTable(); |
||
67 | shared->TexObjects = _mesa_NewHashTable(); |
||
68 | shared->Programs = _mesa_NewHashTable(); |
||
69 | |||
70 | #if FEATURE_ARB_vertex_program |
||
71 | shared->DefaultVertexProgram = (struct gl_vertex_program *) |
||
72 | ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); |
||
73 | #endif |
||
74 | |||
75 | #if FEATURE_ARB_fragment_program |
||
76 | shared->DefaultFragmentProgram = (struct gl_fragment_program *) |
||
77 | ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); |
||
78 | #endif |
||
79 | |||
80 | #if FEATURE_ATI_fragment_shader |
||
81 | shared->ATIShaders = _mesa_NewHashTable(); |
||
82 | shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0); |
||
83 | #endif |
||
84 | |||
85 | #if FEATURE_ARB_shader_objects |
||
86 | shared->ShaderObjects = _mesa_NewHashTable(); |
||
87 | #endif |
||
88 | |||
89 | #if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object |
||
90 | shared->BufferObjects = _mesa_NewHashTable(); |
||
91 | #endif |
||
92 | |||
93 | /* Allocate the default buffer object */ |
||
94 | shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0, 0); |
||
95 | |||
96 | /* Create default texture objects */ |
||
97 | for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { |
||
98 | /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */ |
||
99 | static const GLenum targets[NUM_TEXTURE_TARGETS] = { |
||
100 | GL_TEXTURE_2D_ARRAY_EXT, |
||
101 | GL_TEXTURE_1D_ARRAY_EXT, |
||
102 | GL_TEXTURE_CUBE_MAP, |
||
103 | GL_TEXTURE_3D, |
||
104 | GL_TEXTURE_RECTANGLE_NV, |
||
105 | GL_TEXTURE_2D, |
||
106 | GL_TEXTURE_1D |
||
107 | }; |
||
108 | shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]); |
||
109 | } |
||
110 | |||
111 | /* sanity check */ |
||
112 | assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1); |
||
113 | |||
114 | /* Mutex and timestamp for texobj state validation */ |
||
115 | _glthread_INIT_MUTEX(shared->TexMutex); |
||
116 | shared->TextureStateStamp = 0; |
||
117 | |||
118 | #if FEATURE_EXT_framebuffer_object |
||
119 | shared->FrameBuffers = _mesa_NewHashTable(); |
||
120 | shared->RenderBuffers = _mesa_NewHashTable(); |
||
121 | #endif |
||
122 | |||
123 | make_empty_list(& shared->SyncObjects); |
||
124 | |||
125 | return shared; |
||
126 | } |
||
127 | |||
128 | |||
129 | /** |
||
130 | * Callback for deleting a display list. Called by _mesa_HashDeleteAll(). |
||
131 | */ |
||
132 | static void |
||
133 | delete_displaylist_cb(GLuint id, void *data, void *userData) |
||
134 | { |
||
135 | struct gl_display_list *list = (struct gl_display_list *) data; |
||
136 | struct gl_context *ctx = (struct gl_context *) userData; |
||
137 | _mesa_delete_list(ctx, list); |
||
138 | } |
||
139 | |||
140 | |||
141 | /** |
||
142 | * Callback for deleting a texture object. Called by _mesa_HashDeleteAll(). |
||
143 | */ |
||
144 | static void |
||
145 | delete_texture_cb(GLuint id, void *data, void *userData) |
||
146 | { |
||
147 | struct gl_texture_object *texObj = (struct gl_texture_object *) data; |
||
148 | struct gl_context *ctx = (struct gl_context *) userData; |
||
149 | ctx->Driver.DeleteTexture(ctx, texObj); |
||
150 | } |
||
151 | |||
152 | |||
153 | /** |
||
154 | * Callback for deleting a program object. Called by _mesa_HashDeleteAll(). |
||
155 | */ |
||
156 | static void |
||
157 | delete_program_cb(GLuint id, void *data, void *userData) |
||
158 | { |
||
159 | struct gl_program *prog = (struct gl_program *) data; |
||
160 | struct gl_context *ctx = (struct gl_context *) userData; |
||
161 | if(prog != &_mesa_DummyProgram) { |
||
162 | ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */ |
||
163 | prog->RefCount = 0; /* now going away */ |
||
164 | ctx->Driver.DeleteProgram(ctx, prog); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | |||
169 | #if FEATURE_ATI_fragment_shader |
||
170 | /** |
||
171 | * Callback for deleting an ATI fragment shader object. |
||
172 | * Called by _mesa_HashDeleteAll(). |
||
173 | */ |
||
174 | static void |
||
175 | delete_fragshader_cb(GLuint id, void *data, void *userData) |
||
176 | { |
||
177 | struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data; |
||
178 | struct gl_context *ctx = (struct gl_context *) userData; |
||
179 | _mesa_delete_ati_fragment_shader(ctx, shader); |
||
180 | } |
||
181 | #endif |
||
182 | |||
183 | |||
184 | /** |
||
185 | * Callback for deleting a buffer object. Called by _mesa_HashDeleteAll(). |
||
186 | */ |
||
187 | static void |
||
188 | delete_bufferobj_cb(GLuint id, void *data, void *userData) |
||
189 | { |
||
190 | struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; |
||
191 | struct gl_context *ctx = (struct gl_context *) userData; |
||
192 | if (_mesa_bufferobj_mapped(bufObj)) { |
||
193 | ctx->Driver.UnmapBuffer(ctx, 0, bufObj); |
||
194 | bufObj->Pointer = NULL; |
||
195 | } |
||
196 | _mesa_reference_buffer_object(ctx, &bufObj, NULL); |
||
197 | } |
||
198 | |||
199 | |||
200 | /** |
||
201 | * Callback for freeing shader program data. Call it before delete_shader_cb |
||
202 | * to avoid memory access error. |
||
203 | */ |
||
204 | static void |
||
205 | free_shader_program_data_cb(GLuint id, void *data, void *userData) |
||
206 | { |
||
207 | struct gl_context *ctx = (struct gl_context *) userData; |
||
208 | struct gl_shader_program *shProg = (struct gl_shader_program *) data; |
||
209 | |||
210 | if (shProg->Type == GL_SHADER_PROGRAM_MESA) { |
||
211 | _mesa_free_shader_program_data(ctx, shProg); |
||
212 | } |
||
213 | } |
||
214 | |||
215 | |||
216 | /** |
||
217 | * Callback for deleting shader and shader programs objects. |
||
218 | * Called by _mesa_HashDeleteAll(). |
||
219 | */ |
||
220 | static void |
||
221 | delete_shader_cb(GLuint id, void *data, void *userData) |
||
222 | { |
||
223 | struct gl_context *ctx = (struct gl_context *) userData; |
||
224 | struct gl_shader *sh = (struct gl_shader *) data; |
||
225 | if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { |
||
226 | ctx->Driver.DeleteShader(ctx, sh); |
||
227 | } |
||
228 | else { |
||
229 | struct gl_shader_program *shProg = (struct gl_shader_program *) data; |
||
230 | ASSERT(shProg->Type == GL_SHADER_PROGRAM_MESA); |
||
231 | ctx->Driver.DeleteShaderProgram(ctx, shProg); |
||
232 | } |
||
233 | } |
||
234 | |||
235 | |||
236 | /** |
||
237 | * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll() |
||
238 | */ |
||
239 | static void |
||
240 | delete_framebuffer_cb(GLuint id, void *data, void *userData) |
||
241 | { |
||
242 | struct gl_framebuffer *fb = (struct gl_framebuffer *) data; |
||
243 | /* The fact that the framebuffer is in the hashtable means its refcount |
||
244 | * is one, but we're removing from the hashtable now. So clear refcount. |
||
245 | */ |
||
246 | /*assert(fb->RefCount == 1);*/ |
||
247 | fb->RefCount = 0; |
||
248 | |||
249 | /* NOTE: Delete should always be defined but there are two reports |
||
250 | * of it being NULL (bugs 13507, 14293). Work-around for now. |
||
251 | */ |
||
252 | if (fb->Delete) |
||
253 | fb->Delete(fb); |
||
254 | } |
||
255 | |||
256 | |||
257 | /** |
||
258 | * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll() |
||
259 | */ |
||
260 | static void |
||
261 | delete_renderbuffer_cb(GLuint id, void *data, void *userData) |
||
262 | { |
||
263 | struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data; |
||
264 | rb->RefCount = 0; /* see comment for FBOs above */ |
||
265 | if (rb->Delete) |
||
266 | rb->Delete(rb); |
||
267 | } |
||
268 | |||
269 | |||
270 | /** |
||
271 | * Deallocate a shared state object and all children structures. |
||
272 | * |
||
273 | * \param ctx GL context. |
||
274 | * \param shared shared state pointer. |
||
275 | * |
||
276 | * Frees the display lists, the texture objects (calling the driver texture |
||
277 | * deletion callback to free its private data) and the vertex programs, as well |
||
278 | * as their hash tables. |
||
279 | * |
||
280 | * \sa alloc_shared_state(). |
||
281 | */ |
||
282 | static void |
||
283 | free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) |
||
284 | { |
||
285 | GLuint i; |
||
286 | |||
287 | /* Free the dummy/fallback texture object */ |
||
288 | if (shared->FallbackTex) |
||
289 | ctx->Driver.DeleteTexture(ctx, shared->FallbackTex); |
||
290 | |||
291 | /* |
||
292 | * Free display lists |
||
293 | */ |
||
294 | _mesa_HashDeleteAll(shared->DisplayList, delete_displaylist_cb, ctx); |
||
295 | _mesa_DeleteHashTable(shared->DisplayList); |
||
296 | |||
297 | #if FEATURE_ARB_shader_objects |
||
298 | _mesa_HashWalk(shared->ShaderObjects, free_shader_program_data_cb, ctx); |
||
299 | _mesa_HashDeleteAll(shared->ShaderObjects, delete_shader_cb, ctx); |
||
300 | _mesa_DeleteHashTable(shared->ShaderObjects); |
||
301 | #endif |
||
302 | |||
303 | _mesa_HashDeleteAll(shared->Programs, delete_program_cb, ctx); |
||
304 | _mesa_DeleteHashTable(shared->Programs); |
||
305 | |||
306 | #if FEATURE_ARB_vertex_program |
||
307 | _mesa_reference_vertprog(ctx, &shared->DefaultVertexProgram, NULL); |
||
308 | #endif |
||
309 | |||
310 | #if FEATURE_ARB_fragment_program |
||
311 | _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL); |
||
312 | #endif |
||
313 | |||
314 | #if FEATURE_ATI_fragment_shader |
||
315 | _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx); |
||
316 | _mesa_DeleteHashTable(shared->ATIShaders); |
||
317 | _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader); |
||
318 | #endif |
||
319 | |||
320 | #if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object |
||
321 | _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx); |
||
322 | _mesa_DeleteHashTable(shared->BufferObjects); |
||
323 | #endif |
||
324 | |||
325 | #if FEATURE_EXT_framebuffer_object |
||
326 | _mesa_HashDeleteAll(shared->FrameBuffers, delete_framebuffer_cb, ctx); |
||
327 | _mesa_DeleteHashTable(shared->FrameBuffers); |
||
328 | _mesa_HashDeleteAll(shared->RenderBuffers, delete_renderbuffer_cb, ctx); |
||
329 | _mesa_DeleteHashTable(shared->RenderBuffers); |
||
330 | #endif |
||
331 | |||
332 | #if FEATURE_ARB_vertex_buffer_object |
||
333 | _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); |
||
334 | #endif |
||
335 | |||
336 | { |
||
337 | struct simple_node *node; |
||
338 | struct simple_node *temp; |
||
339 | |||
340 | foreach_s(node, temp, & shared->SyncObjects) { |
||
341 | _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node); |
||
342 | } |
||
343 | } |
||
344 | |||
345 | /* |
||
346 | * Free texture objects (after FBOs since some textures might have |
||
347 | * been bound to FBOs). |
||
348 | */ |
||
349 | ASSERT(ctx->Driver.DeleteTexture); |
||
350 | /* the default textures */ |
||
351 | for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { |
||
352 | ctx->Driver.DeleteTexture(ctx, shared->DefaultTex[i]); |
||
353 | } |
||
354 | |||
355 | /* all other textures */ |
||
356 | _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx); |
||
357 | _mesa_DeleteHashTable(shared->TexObjects); |
||
358 | |||
359 | _glthread_DESTROY_MUTEX(shared->Mutex); |
||
360 | _glthread_DESTROY_MUTEX(shared->TexMutex); |
||
361 | |||
362 | free(shared); |
||
363 | } |
||
364 | |||
365 | |||
366 | /** |
||
367 | * Decrement shared state object reference count and potentially free it |
||
368 | * and all children structures. |
||
369 | * |
||
370 | * \param ctx GL context. |
||
371 | * \param shared shared state pointer. |
||
372 | * |
||
373 | * \sa free_shared_state(). |
||
374 | */ |
||
375 | void |
||
376 | _mesa_release_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) |
||
377 | { |
||
378 | GLint RefCount; |
||
379 | |||
380 | _glthread_LOCK_MUTEX(shared->Mutex); |
||
381 | RefCount = --shared->RefCount; |
||
382 | _glthread_UNLOCK_MUTEX(shared->Mutex); |
||
383 | |||
384 | assert(RefCount >= 0); |
||
385 | |||
386 | if (RefCount == 0) { |
||
387 | /* free shared state */ |
||
388 | free_shared_state( ctx, shared ); |
||
389 | } |
||
390 | }>> |