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) 2004-2008  Brian Paul   All Rights Reserved.
  5.  * Copyright (C) 2009-2010  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.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. /**
  27.  * \file shaderobj.c
  28.  * \author Brian Paul
  29.  *
  30.  */
  31.  
  32.  
  33. #include "main/glheader.h"
  34. #include "main/context.h"
  35. #include "main/hash.h"
  36. #include "main/mtypes.h"
  37. #include "main/shaderobj.h"
  38. #include "main/uniforms.h"
  39. #include "program/program.h"
  40. #include "program/prog_parameter.h"
  41. #include "program/hash_table.h"
  42. #include "ralloc.h"
  43.  
  44. /**********************************************************************/
  45. /*** Shader object functions                                        ***/
  46. /**********************************************************************/
  47.  
  48.  
  49. /**
  50.  * Set ptr to point to sh.
  51.  * If ptr is pointing to another shader, decrement its refcount (and delete
  52.  * if refcount hits zero).
  53.  * Then set ptr to point to sh, incrementing its refcount.
  54.  */
  55. void
  56. _mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
  57.                        struct gl_shader *sh)
  58. {
  59.    assert(ptr);
  60.    if (*ptr == sh) {
  61.       /* no-op */
  62.       return;
  63.    }
  64.    if (*ptr) {
  65.       /* Unreference the old shader */
  66.       GLboolean deleteFlag = GL_FALSE;
  67.       struct gl_shader *old = *ptr;
  68.  
  69.       ASSERT(old->RefCount > 0);
  70.       old->RefCount--;
  71.       /*printf("SHADER DECR %p (%d) to %d\n",
  72.         (void*) old, old->Name, old->RefCount);*/
  73.       deleteFlag = (old->RefCount == 0);
  74.  
  75.       if (deleteFlag) {
  76.          if (old->Name != 0)
  77.             _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
  78.          ctx->Driver.DeleteShader(ctx, old);
  79.       }
  80.  
  81.       *ptr = NULL;
  82.    }
  83.    assert(!*ptr);
  84.  
  85.    if (sh) {
  86.       /* reference new */
  87.       sh->RefCount++;
  88.       /*printf("SHADER INCR %p (%d) to %d\n",
  89.         (void*) sh, sh->Name, sh->RefCount);*/
  90.       *ptr = sh;
  91.    }
  92. }
  93.  
  94. void
  95. _mesa_init_shader(struct gl_context *ctx, struct gl_shader *shader)
  96. {
  97.    shader->RefCount = 1;
  98. }
  99.  
  100. /**
  101.  * Allocate a new gl_shader object, initialize it.
  102.  * Called via ctx->Driver.NewShader()
  103.  */
  104. struct gl_shader *
  105. _mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
  106. {
  107.    struct gl_shader *shader;
  108.    assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER ||
  109.           type == GL_GEOMETRY_SHADER_ARB);
  110.    shader = rzalloc(NULL, struct gl_shader);
  111.    if (shader) {
  112.       shader->Type = type;
  113.       shader->Name = name;
  114.       _mesa_init_shader(ctx, shader);
  115.    }
  116.    return shader;
  117. }
  118.  
  119.  
  120. /**
  121.  * Delete a shader object.
  122.  * Called via ctx->Driver.DeleteShader().
  123.  */
  124. static void
  125. _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh)
  126. {
  127.    free((void *)sh->Source);
  128.    _mesa_reference_program(ctx, &sh->Program, NULL);
  129.    ralloc_free(sh);
  130. }
  131.  
  132.  
  133. /**
  134.  * Lookup a GLSL shader object.
  135.  */
  136. struct gl_shader *
  137. _mesa_lookup_shader(struct gl_context *ctx, GLuint name)
  138. {
  139.    if (name) {
  140.       struct gl_shader *sh = (struct gl_shader *)
  141.          _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  142.       /* Note that both gl_shader and gl_shader_program objects are kept
  143.        * in the same hash table.  Check the object's type to be sure it's
  144.        * what we're expecting.
  145.        */
  146.       if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
  147.          return NULL;
  148.       }
  149.       return sh;
  150.    }
  151.    return NULL;
  152. }
  153.  
  154.  
  155. /**
  156.  * As above, but record an error if shader is not found.
  157.  */
  158. struct gl_shader *
  159. _mesa_lookup_shader_err(struct gl_context *ctx, GLuint name, const char *caller)
  160. {
  161.    if (!name) {
  162.       _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  163.       return NULL;
  164.    }
  165.    else {
  166.       struct gl_shader *sh = (struct gl_shader *)
  167.          _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  168.       if (!sh) {
  169.          _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  170.          return NULL;
  171.       }
  172.       if (sh->Type == GL_SHADER_PROGRAM_MESA) {
  173.          _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
  174.          return NULL;
  175.       }
  176.       return sh;
  177.    }
  178. }
  179.  
  180.  
  181.  
  182. /**********************************************************************/
  183. /*** Shader Program object functions                                ***/
  184. /**********************************************************************/
  185.  
  186.  
  187. /**
  188.  * Set ptr to point to shProg.
  189.  * If ptr is pointing to another object, decrement its refcount (and delete
  190.  * if refcount hits zero).
  191.  * Then set ptr to point to shProg, incrementing its refcount.
  192.  */
  193. void
  194. _mesa_reference_shader_program(struct gl_context *ctx,
  195.                                struct gl_shader_program **ptr,
  196.                                struct gl_shader_program *shProg)
  197. {
  198.    assert(ptr);
  199.    if (*ptr == shProg) {
  200.       /* no-op */
  201.       return;
  202.    }
  203.    if (*ptr) {
  204.       /* Unreference the old shader program */
  205.       GLboolean deleteFlag = GL_FALSE;
  206.       struct gl_shader_program *old = *ptr;
  207.  
  208.       ASSERT(old->RefCount > 0);
  209.       old->RefCount--;
  210. #if 0
  211.       printf("ShaderProgram %p ID=%u  RefCount-- to %d\n",
  212.              (void *) old, old->Name, old->RefCount);
  213. #endif
  214.       deleteFlag = (old->RefCount == 0);
  215.  
  216.       if (deleteFlag) {
  217.          if (old->Name != 0)
  218.             _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
  219.          ctx->Driver.DeleteShaderProgram(ctx, old);
  220.       }
  221.  
  222.       *ptr = NULL;
  223.    }
  224.    assert(!*ptr);
  225.  
  226.    if (shProg) {
  227.       shProg->RefCount++;
  228. #if 0
  229.       printf("ShaderProgram %p ID=%u  RefCount++ to %d\n",
  230.              (void *) shProg, shProg->Name, shProg->RefCount);
  231. #endif
  232.       *ptr = shProg;
  233.    }
  234. }
  235.  
  236. void
  237. _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog)
  238. {
  239.    prog->Type = GL_SHADER_PROGRAM_MESA;
  240.    prog->RefCount = 1;
  241.  
  242.    prog->AttributeBindings = string_to_uint_map_ctor();
  243.    prog->FragDataBindings = string_to_uint_map_ctor();
  244.    prog->FragDataIndexBindings = string_to_uint_map_ctor();
  245.  
  246.    prog->Geom.VerticesOut = 0;
  247.    prog->Geom.InputType = GL_TRIANGLES;
  248.    prog->Geom.OutputType = GL_TRIANGLE_STRIP;
  249.  
  250.    prog->TransformFeedback.BufferMode = GL_INTERLEAVED_ATTRIBS;
  251.  
  252.    prog->InfoLog = ralloc_strdup(prog, "");
  253. }
  254.  
  255. /**
  256.  * Allocate a new gl_shader_program object, initialize it.
  257.  * Called via ctx->Driver.NewShaderProgram()
  258.  */
  259. static struct gl_shader_program *
  260. _mesa_new_shader_program(struct gl_context *ctx, GLuint name)
  261. {
  262.    struct gl_shader_program *shProg;
  263.    shProg = rzalloc(NULL, struct gl_shader_program);
  264.    if (shProg) {
  265.       shProg->Name = name;
  266.       _mesa_init_shader_program(ctx, shProg);
  267.    }
  268.    return shProg;
  269. }
  270.  
  271.  
  272. /**
  273.  * Clear (free) the shader program state that gets produced by linking.
  274.  */
  275. void
  276. _mesa_clear_shader_program_data(struct gl_context *ctx,
  277.                                 struct gl_shader_program *shProg)
  278. {
  279.    if (shProg->UniformStorage) {
  280.       unsigned i;
  281.       for (i = 0; i < shProg->NumUserUniformStorage; ++i)
  282.          _mesa_uniform_detach_all_driver_storage(&shProg->UniformStorage[i]);
  283.       ralloc_free(shProg->UniformStorage);
  284.       shProg->NumUserUniformStorage = 0;
  285.       shProg->UniformStorage = NULL;
  286.       shProg->UniformLocationBaseScale = 0;
  287.    }
  288.  
  289.    if (shProg->UniformHash) {
  290.       string_to_uint_map_dtor(shProg->UniformHash);
  291.       shProg->UniformHash = NULL;
  292.    }
  293.  
  294.    assert(shProg->InfoLog != NULL);
  295.    ralloc_free(shProg->InfoLog);
  296.    shProg->InfoLog = ralloc_strdup(shProg, "");
  297. }
  298.  
  299.  
  300. /**
  301.  * Free all the data that hangs off a shader program object, but not the
  302.  * object itself.
  303.  */
  304. void
  305. _mesa_free_shader_program_data(struct gl_context *ctx,
  306.                                struct gl_shader_program *shProg)
  307. {
  308.    GLuint i;
  309.    gl_shader_type sh;
  310.  
  311.    assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
  312.  
  313.    _mesa_clear_shader_program_data(ctx, shProg);
  314.  
  315.    if (shProg->AttributeBindings) {
  316.       string_to_uint_map_dtor(shProg->AttributeBindings);
  317.       shProg->AttributeBindings = NULL;
  318.    }
  319.  
  320.    if (shProg->FragDataBindings) {
  321.       string_to_uint_map_dtor(shProg->FragDataBindings);
  322.       shProg->FragDataBindings = NULL;
  323.    }
  324.  
  325.    if (shProg->FragDataIndexBindings) {
  326.       string_to_uint_map_dtor(shProg->FragDataIndexBindings);
  327.       shProg->FragDataIndexBindings = NULL;
  328.    }
  329.  
  330.    /* detach shaders */
  331.    for (i = 0; i < shProg->NumShaders; i++) {
  332.       _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
  333.    }
  334.    shProg->NumShaders = 0;
  335.  
  336.    free(shProg->Shaders);
  337.    shProg->Shaders = NULL;
  338.  
  339.    /* Transform feedback varying vars */
  340.    for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) {
  341.       free(shProg->TransformFeedback.VaryingNames[i]);
  342.    }
  343.    free(shProg->TransformFeedback.VaryingNames);
  344.    shProg->TransformFeedback.VaryingNames = NULL;
  345.    shProg->TransformFeedback.NumVarying = 0;
  346.  
  347.  
  348.    for (sh = 0; sh < MESA_SHADER_TYPES; sh++) {
  349.       if (shProg->_LinkedShaders[sh] != NULL) {
  350.          ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[sh]);
  351.          shProg->_LinkedShaders[sh] = NULL;
  352.       }
  353.    }
  354. }
  355.  
  356.  
  357. /**
  358.  * Free/delete a shader program object.
  359.  * Called via ctx->Driver.DeleteShaderProgram().
  360.  */
  361. static void
  362. _mesa_delete_shader_program(struct gl_context *ctx, struct gl_shader_program *shProg)
  363. {
  364.    _mesa_free_shader_program_data(ctx, shProg);
  365.  
  366.    ralloc_free(shProg);
  367. }
  368.  
  369.  
  370. /**
  371.  * Lookup a GLSL program object.
  372.  */
  373. struct gl_shader_program *
  374. _mesa_lookup_shader_program(struct gl_context *ctx, GLuint name)
  375. {
  376.    struct gl_shader_program *shProg;
  377.    if (name) {
  378.       shProg = (struct gl_shader_program *)
  379.          _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  380.       /* Note that both gl_shader and gl_shader_program objects are kept
  381.        * in the same hash table.  Check the object's type to be sure it's
  382.        * what we're expecting.
  383.        */
  384.       if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
  385.          return NULL;
  386.       }
  387.       return shProg;
  388.    }
  389.    return NULL;
  390. }
  391.  
  392.  
  393. /**
  394.  * As above, but record an error if program is not found.
  395.  */
  396. struct gl_shader_program *
  397. _mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
  398.                                 const char *caller)
  399. {
  400.    if (!name) {
  401.       _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  402.       return NULL;
  403.    }
  404.    else {
  405.       struct gl_shader_program *shProg = (struct gl_shader_program *)
  406.          _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
  407.       if (!shProg) {
  408.          _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
  409.          return NULL;
  410.       }
  411.       if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
  412.          _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
  413.          return NULL;
  414.       }
  415.       return shProg;
  416.    }
  417. }
  418.  
  419.  
  420. void
  421. _mesa_init_shader_object_functions(struct dd_function_table *driver)
  422. {
  423.    driver->NewShader = _mesa_new_shader;
  424.    driver->DeleteShader = _mesa_delete_shader;
  425.    driver->NewShaderProgram = _mesa_new_shader_program;
  426.    driver->DeleteShaderProgram = _mesa_delete_shader_program;
  427.    driver->LinkShader = _mesa_ir_link_shader;
  428. }
  429.