Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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