Subversion Repositories Kolibri OS

Rev

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