Subversion Repositories Kolibri OS

Rev

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