Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2011 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. /**
  25.  * \file shader_query.cpp
  26.  * C-to-C++ bridge functions to query GLSL shader data
  27.  *
  28.  * \author Ian Romanick <ian.d.romanick@intel.com>
  29.  */
  30.  
  31. #include "main/core.h"
  32. #include "glsl_symbol_table.h"
  33. #include "ir.h"
  34. #include "shaderobj.h"
  35. #include "program/hash_table.h"
  36. #include "../glsl/program.h"
  37.  
  38. extern "C" {
  39. #include "shaderapi.h"
  40. }
  41.  
  42. void GLAPIENTRY
  43. _mesa_BindAttribLocation(GLhandleARB program, GLuint index,
  44.                             const GLcharARB *name)
  45. {
  46.    GET_CURRENT_CONTEXT(ctx);
  47.  
  48.    struct gl_shader_program *const shProg =
  49.       _mesa_lookup_shader_program_err(ctx, program, "glBindAttribLocation");
  50.    if (!shProg)
  51.       return;
  52.  
  53.    if (!name)
  54.       return;
  55.  
  56.    if (strncmp(name, "gl_", 3) == 0) {
  57.       _mesa_error(ctx, GL_INVALID_OPERATION,
  58.                   "glBindAttribLocation(illegal name)");
  59.       return;
  60.    }
  61.  
  62.    if (index >= ctx->Const.VertexProgram.MaxAttribs) {
  63.       _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
  64.       return;
  65.    }
  66.  
  67.    /* Replace the current value if it's already in the list.  Add
  68.     * VERT_ATTRIB_GENERIC0 because that's how the linker differentiates
  69.     * between built-in attributes and user-defined attributes.
  70.     */
  71.    shProg->AttributeBindings->put(index + VERT_ATTRIB_GENERIC0, name);
  72.  
  73.    /*
  74.     * Note that this attribute binding won't go into effect until
  75.     * glLinkProgram is called again.
  76.     */
  77. }
  78.  
  79. void GLAPIENTRY
  80. _mesa_GetActiveAttrib(GLhandleARB program, GLuint desired_index,
  81.                          GLsizei maxLength, GLsizei * length, GLint * size,
  82.                          GLenum * type, GLcharARB * name)
  83. {
  84.    GET_CURRENT_CONTEXT(ctx);
  85.    struct gl_shader_program *shProg;
  86.  
  87.    shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
  88.    if (!shProg)
  89.       return;
  90.  
  91.    if (!shProg->LinkStatus) {
  92.       _mesa_error(ctx, GL_INVALID_VALUE,
  93.                   "glGetActiveAttrib(program not linked)");
  94.       return;
  95.    }
  96.  
  97.    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  98.       _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(no vertex shader)");
  99.       return;
  100.    }
  101.  
  102.    exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  103.    unsigned current_index = 0;
  104.  
  105.    foreach_list(node, ir) {
  106.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  107.  
  108.       if (var == NULL
  109.           || var->mode != ir_var_shader_in
  110.           || var->location == -1)
  111.          continue;
  112.  
  113.       if (current_index == desired_index) {
  114.          _mesa_copy_string(name, maxLength, length, var->name);
  115.  
  116.          if (size)
  117.             *size = (var->type->is_array()) ? var->type->length : 1;
  118.  
  119.          if (type)
  120.             *type = var->type->gl_type;
  121.  
  122.          return;
  123.       }
  124.  
  125.       current_index++;
  126.    }
  127.  
  128.    /* If the loop did not return early, the caller must have asked for
  129.     * an index that did not exit.  Set an error.
  130.     */
  131.    _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
  132. }
  133.  
  134. GLint GLAPIENTRY
  135. _mesa_GetAttribLocation(GLhandleARB program, const GLcharARB * name)
  136. {
  137.    GET_CURRENT_CONTEXT(ctx);
  138.    struct gl_shader_program *const shProg =
  139.       _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
  140.  
  141.    if (!shProg) {
  142.       return -1;
  143.    }
  144.  
  145.    if (!shProg->LinkStatus) {
  146.       _mesa_error(ctx, GL_INVALID_OPERATION,
  147.                   "glGetAttribLocation(program not linked)");
  148.       return -1;
  149.    }
  150.  
  151.    if (!name)
  152.       return -1;
  153.  
  154.    /* Not having a vertex shader is not an error.
  155.     */
  156.    if (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)
  157.       return -1;
  158.  
  159.    exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  160.    foreach_list(node, ir) {
  161.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  162.  
  163.       /* The extra check against VERT_ATTRIB_GENERIC0 is because
  164.        * glGetAttribLocation cannot be used on "conventional" attributes.
  165.        *
  166.        * From page 95 of the OpenGL 3.0 spec:
  167.        *
  168.        *     "If name is not an active attribute, if name is a conventional
  169.        *     attribute, or if an error occurs, -1 will be returned."
  170.        */
  171.       if (var == NULL
  172.           || var->mode != ir_var_shader_in
  173.           || var->location == -1
  174.           || var->location < VERT_ATTRIB_GENERIC0)
  175.          continue;
  176.  
  177.       if (strcmp(var->name, name) == 0)
  178.          return var->location - VERT_ATTRIB_GENERIC0;
  179.    }
  180.  
  181.    return -1;
  182. }
  183.  
  184.  
  185. unsigned
  186. _mesa_count_active_attribs(struct gl_shader_program *shProg)
  187. {
  188.    if (!shProg->LinkStatus
  189.        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  190.       return 0;
  191.    }
  192.  
  193.    exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  194.    unsigned i = 0;
  195.  
  196.    foreach_list(node, ir) {
  197.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  198.  
  199.       if (var == NULL
  200.           || var->mode != ir_var_shader_in
  201.           || var->location == -1)
  202.          continue;
  203.  
  204.       i++;
  205.    }
  206.  
  207.    return i;
  208. }
  209.  
  210.  
  211. size_t
  212. _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
  213. {
  214.    if (!shProg->LinkStatus
  215.        || shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
  216.       return 0;
  217.    }
  218.  
  219.    exec_list *const ir = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->ir;
  220.    size_t longest = 0;
  221.  
  222.    foreach_list(node, ir) {
  223.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  224.  
  225.       if (var == NULL
  226.           || var->mode != ir_var_shader_in
  227.           || var->location == -1)
  228.          continue;
  229.  
  230.       const size_t len = strlen(var->name);
  231.       if (len >= longest)
  232.          longest = len + 1;
  233.    }
  234.  
  235.    return longest;
  236. }
  237.  
  238. void GLAPIENTRY
  239. _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
  240.                            const GLchar *name)
  241. {
  242.    _mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
  243. }
  244.  
  245. void GLAPIENTRY
  246. _mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
  247.                                   GLuint index, const GLchar *name)
  248. {
  249.    GET_CURRENT_CONTEXT(ctx);
  250.  
  251.    struct gl_shader_program *const shProg =
  252.       _mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
  253.    if (!shProg)
  254.       return;
  255.  
  256.    if (!name)
  257.       return;
  258.  
  259.    if (strncmp(name, "gl_", 3) == 0) {
  260.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
  261.       return;
  262.    }
  263.  
  264.    if (index > 1) {
  265.       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
  266.       return;
  267.    }
  268.  
  269.    if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
  270.       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
  271.       return;
  272.    }
  273.  
  274.    if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
  275.       _mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
  276.       return;
  277.    }
  278.  
  279.    /* Replace the current value if it's already in the list.  Add
  280.     * FRAG_RESULT_DATA0 because that's how the linker differentiates
  281.     * between built-in attributes and user-defined attributes.
  282.     */
  283.    shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
  284.    shProg->FragDataIndexBindings->put(index, name);
  285.    /*
  286.     * Note that this binding won't go into effect until
  287.     * glLinkProgram is called again.
  288.     */
  289.  
  290. }
  291.  
  292. GLint GLAPIENTRY
  293. _mesa_GetFragDataIndex(GLuint program, const GLchar *name)
  294. {
  295.    GET_CURRENT_CONTEXT(ctx);
  296.    struct gl_shader_program *const shProg =
  297.       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
  298.  
  299.    if (!shProg) {
  300.       return -1;
  301.    }
  302.  
  303.    if (!shProg->LinkStatus) {
  304.       _mesa_error(ctx, GL_INVALID_OPERATION,
  305.                   "glGetFragDataIndex(program not linked)");
  306.       return -1;
  307.    }
  308.  
  309.    if (!name)
  310.       return -1;
  311.  
  312.    if (strncmp(name, "gl_", 3) == 0) {
  313.       _mesa_error(ctx, GL_INVALID_OPERATION,
  314.                   "glGetFragDataIndex(illegal name)");
  315.       return -1;
  316.    }
  317.  
  318.    /* Not having a fragment shader is not an error.
  319.     */
  320.    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
  321.       return -1;
  322.  
  323.    exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
  324.    foreach_list(node, ir) {
  325.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  326.  
  327.       /* The extra check against FRAG_RESULT_DATA0 is because
  328.        * glGetFragDataLocation cannot be used on "conventional" attributes.
  329.        *
  330.        * From page 95 of the OpenGL 3.0 spec:
  331.        *
  332.        *     "If name is not an active attribute, if name is a conventional
  333.        *     attribute, or if an error occurs, -1 will be returned."
  334.        */
  335.       if (var == NULL
  336.           || var->mode != ir_var_shader_out
  337.           || var->location == -1
  338.           || var->location < FRAG_RESULT_DATA0)
  339.          continue;
  340.  
  341.       if (strcmp(var->name, name) == 0)
  342.          return var->index;
  343.    }
  344.  
  345.    return -1;
  346. }
  347.  
  348. GLint GLAPIENTRY
  349. _mesa_GetFragDataLocation(GLuint program, const GLchar *name)
  350. {
  351.    GET_CURRENT_CONTEXT(ctx);
  352.    struct gl_shader_program *const shProg =
  353.       _mesa_lookup_shader_program_err(ctx, program, "glGetFragDataLocation");
  354.  
  355.    if (!shProg) {
  356.       return -1;
  357.    }
  358.  
  359.    if (!shProg->LinkStatus) {
  360.       _mesa_error(ctx, GL_INVALID_OPERATION,
  361.                   "glGetFragDataLocation(program not linked)");
  362.       return -1;
  363.    }
  364.  
  365.    if (!name)
  366.       return -1;
  367.  
  368.    if (strncmp(name, "gl_", 3) == 0) {
  369.       _mesa_error(ctx, GL_INVALID_OPERATION,
  370.                   "glGetFragDataLocation(illegal name)");
  371.       return -1;
  372.    }
  373.  
  374.    /* Not having a fragment shader is not an error.
  375.     */
  376.    if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
  377.       return -1;
  378.  
  379.    exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
  380.    foreach_list(node, ir) {
  381.       const ir_variable *const var = ((ir_instruction *) node)->as_variable();
  382.  
  383.       /* The extra check against FRAG_RESULT_DATA0 is because
  384.        * glGetFragDataLocation cannot be used on "conventional" attributes.
  385.        *
  386.        * From page 95 of the OpenGL 3.0 spec:
  387.        *
  388.        *     "If name is not an active attribute, if name is a conventional
  389.        *     attribute, or if an error occurs, -1 will be returned."
  390.        */
  391.       if (var == NULL
  392.           || var->mode != ir_var_shader_out
  393.           || var->location == -1
  394.           || var->location < FRAG_RESULT_DATA0)
  395.          continue;
  396.  
  397.       if (strcmp(var->name, name) == 0)
  398.          return var->location - FRAG_RESULT_DATA0;
  399.    }
  400.  
  401.    return -1;
  402. }
  403.