Subversion Repositories Kolibri OS

Rev

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 "atifragshader.h"
  34. #include "bufferobj.h"
  35. #include "shared.h"
  36. #include "program/program.h"
  37. #include "dlist.h"
  38. #include "samplerobj.h"
  39. #include "shaderapi.h"
  40. #include "shaderobj.h"
  41. #include "syncobj.h"
  42.  
  43. #include "util/hash_table.h"
  44. #include "util/set.h"
  45.  
  46. /**
  47.  * Allocate and initialize a shared context state structure.
  48.  * Initializes the display list, texture objects and vertex programs hash
  49.  * tables, allocates the texture objects. If it runs out of memory, frees
  50.  * everything already allocated before returning NULL.
  51.  *
  52.  * \return pointer to a gl_shared_state structure on success, or NULL on
  53.  * failure.
  54.  */
  55. struct gl_shared_state *
  56. _mesa_alloc_shared_state(struct gl_context *ctx)
  57. {
  58.    struct gl_shared_state *shared;
  59.    GLuint i;
  60.  
  61.    shared = CALLOC_STRUCT(gl_shared_state);
  62.    if (!shared)
  63.       return NULL;
  64.  
  65.    mtx_init(&shared->Mutex, mtx_plain);
  66.  
  67.    shared->DisplayList = _mesa_NewHashTable();
  68.    shared->TexObjects = _mesa_NewHashTable();
  69.    shared->Programs = _mesa_NewHashTable();
  70.  
  71.    shared->DefaultVertexProgram =
  72.       gl_vertex_program(ctx->Driver.NewProgram(ctx,
  73.                                                GL_VERTEX_PROGRAM_ARB, 0));
  74.    shared->DefaultFragmentProgram =
  75.       gl_fragment_program(ctx->Driver.NewProgram(ctx,
  76.                                                  GL_FRAGMENT_PROGRAM_ARB, 0));
  77.  
  78.    shared->ATIShaders = _mesa_NewHashTable();
  79.    shared->DefaultFragmentShader = _mesa_new_ati_fragment_shader(ctx, 0);
  80.  
  81.    shared->ShaderObjects = _mesa_NewHashTable();
  82.  
  83.    shared->BufferObjects = _mesa_NewHashTable();
  84.  
  85.    /* GL_ARB_sampler_objects */
  86.    shared->SamplerObjects = _mesa_NewHashTable();
  87.  
  88.    /* Allocate the default buffer object */
  89.    shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);
  90.  
  91.    /* Create default texture objects */
  92.    for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
  93.       /* NOTE: the order of these enums matches the TEXTURE_x_INDEX values */
  94.       static const GLenum targets[] = {
  95.          GL_TEXTURE_2D_MULTISAMPLE,
  96.          GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
  97.          GL_TEXTURE_CUBE_MAP_ARRAY,
  98.          GL_TEXTURE_BUFFER,
  99.          GL_TEXTURE_2D_ARRAY_EXT,
  100.          GL_TEXTURE_1D_ARRAY_EXT,
  101.          GL_TEXTURE_EXTERNAL_OES,
  102.          GL_TEXTURE_CUBE_MAP,
  103.          GL_TEXTURE_3D,
  104.          GL_TEXTURE_RECTANGLE_NV,
  105.          GL_TEXTURE_2D,
  106.          GL_TEXTURE_1D
  107.       };
  108.       STATIC_ASSERT(ARRAY_SIZE(targets) == NUM_TEXTURE_TARGETS);
  109.       shared->DefaultTex[i] = ctx->Driver.NewTextureObject(ctx, 0, targets[i]);
  110.    }
  111.  
  112.    /* sanity check */
  113.    assert(shared->DefaultTex[TEXTURE_1D_INDEX]->RefCount == 1);
  114.  
  115.    /* Mutex and timestamp for texobj state validation */
  116.    mtx_init(&shared->TexMutex, mtx_recursive);
  117.    shared->TextureStateStamp = 0;
  118.  
  119.    shared->FrameBuffers = _mesa_NewHashTable();
  120.    shared->RenderBuffers = _mesa_NewHashTable();
  121.  
  122.    shared->SyncObjects = _mesa_set_create(NULL, _mesa_hash_pointer,
  123.                                           _mesa_key_pointer_equal);
  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. /**
  170.  * Callback for deleting an ATI fragment shader object.
  171.  * Called by _mesa_HashDeleteAll().
  172.  */
  173. static void
  174. delete_fragshader_cb(GLuint id, void *data, void *userData)
  175. {
  176.    struct ati_fragment_shader *shader = (struct ati_fragment_shader *) data;
  177.    struct gl_context *ctx = (struct gl_context *) userData;
  178.    _mesa_delete_ati_fragment_shader(ctx, shader);
  179. }
  180.  
  181.  
  182. /**
  183.  * Callback for deleting a buffer object.  Called by _mesa_HashDeleteAll().
  184.  */
  185. static void
  186. delete_bufferobj_cb(GLuint id, void *data, void *userData)
  187. {
  188.    struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
  189.    struct gl_context *ctx = (struct gl_context *) userData;
  190.  
  191.    _mesa_buffer_unmap_all_mappings(ctx, bufObj);
  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 (_mesa_validate_shader_target(ctx, sh->Type)) {
  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_geomprog(ctx, &shared->DefaultGeometryProgram, NULL);
  317.    _mesa_reference_fragprog(ctx, &shared->DefaultFragmentProgram, NULL);
  318.  
  319.    _mesa_HashDeleteAll(shared->ATIShaders, delete_fragshader_cb, ctx);
  320.    _mesa_DeleteHashTable(shared->ATIShaders);
  321.    _mesa_delete_ati_fragment_shader(ctx, shared->DefaultFragmentShader);
  322.  
  323.    _mesa_HashDeleteAll(shared->BufferObjects, delete_bufferobj_cb, ctx);
  324.    _mesa_DeleteHashTable(shared->BufferObjects);
  325.  
  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.  
  331.    _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL);
  332.  
  333.    {
  334.       struct set_entry *entry;
  335.  
  336.       set_foreach(shared->SyncObjects, entry) {
  337.          _mesa_unref_sync_object(ctx, (struct gl_sync_object *) entry->key);
  338.       }
  339.    }
  340.    _mesa_set_destroy(shared->SyncObjects, NULL);
  341.  
  342.    _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx);
  343.    _mesa_DeleteHashTable(shared->SamplerObjects);
  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.    mtx_destroy(&shared->Mutex);
  360.    mtx_destroy(&shared->TexMutex);
  361.  
  362.    free(shared);
  363. }
  364.  
  365.  
  366. /**
  367.  * gl_shared_state objects are ref counted.
  368.  * If ptr's refcount goes to zero, free the shared state.
  369.  */
  370. void
  371. _mesa_reference_shared_state(struct gl_context *ctx,
  372.                              struct gl_shared_state **ptr,
  373.                              struct gl_shared_state *state)
  374. {
  375.    if (*ptr == state)
  376.       return;
  377.  
  378.    if (*ptr) {
  379.       /* unref old state */
  380.       struct gl_shared_state *old = *ptr;
  381.       GLboolean delete;
  382.  
  383.       mtx_lock(&old->Mutex);
  384.       assert(old->RefCount >= 1);
  385.       old->RefCount--;
  386.       delete = (old->RefCount == 0);
  387.       mtx_unlock(&old->Mutex);
  388.  
  389.       if (delete) {
  390.          free_shared_state(ctx, old);
  391.       }
  392.  
  393.       *ptr = NULL;
  394.    }
  395.  
  396.    if (state) {
  397.       /* reference new state */
  398.       mtx_lock(&state->Mutex);
  399.       state->RefCount++;
  400.       *ptr = state;
  401.       mtx_unlock(&state->Mutex);
  402.    }
  403. }
  404.