1b8e80941Smrg/* 2b8e80941Smrg * Mesa 3-D graphics library 3b8e80941Smrg * 4b8e80941Smrg * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 5b8e80941Smrg * 6b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 8b8e80941Smrg * to deal in the Software without restriction, including without limitation 9b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 11b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 12b8e80941Smrg * 13b8e80941Smrg * The above copyright notice and this permission notice shall be included 14b8e80941Smrg * in all copies or substantial portions of the Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20b8e80941Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21b8e80941Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22b8e80941Smrg * OTHER DEALINGS IN THE SOFTWARE. 23b8e80941Smrg * 24b8e80941Smrg */ 25b8e80941Smrg 26b8e80941Smrg#include "main/enums.h" 27b8e80941Smrg#include "main/macros.h" 28b8e80941Smrg#include "main/mtypes.h" 29b8e80941Smrg#include "main/shaderapi.h" 30b8e80941Smrg#include "main/shaderobj.h" 31b8e80941Smrg#include "main/context.h" 32b8e80941Smrg#include "program_resource.h" 33b8e80941Smrg#include "compiler/glsl/ir_uniform.h" 34b8e80941Smrg 35b8e80941Smrgstatic bool 36b8e80941Smrgsupported_interface_enum(struct gl_context *ctx, GLenum iface) 37b8e80941Smrg{ 38b8e80941Smrg switch (iface) { 39b8e80941Smrg case GL_UNIFORM: 40b8e80941Smrg case GL_UNIFORM_BLOCK: 41b8e80941Smrg case GL_PROGRAM_INPUT: 42b8e80941Smrg case GL_PROGRAM_OUTPUT: 43b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 44b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 45b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 46b8e80941Smrg case GL_BUFFER_VARIABLE: 47b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 48b8e80941Smrg return true; 49b8e80941Smrg case GL_VERTEX_SUBROUTINE: 50b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 51b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 52b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 53b8e80941Smrg return _mesa_has_ARB_shader_subroutine(ctx); 54b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 55b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 56b8e80941Smrg return _mesa_has_geometry_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx); 57b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 58b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 59b8e80941Smrg return _mesa_has_compute_shaders(ctx) && _mesa_has_ARB_shader_subroutine(ctx); 60b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 61b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 62b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 63b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 64b8e80941Smrg return _mesa_has_tessellation(ctx) && _mesa_has_ARB_shader_subroutine(ctx); 65b8e80941Smrg default: 66b8e80941Smrg return false; 67b8e80941Smrg } 68b8e80941Smrg} 69b8e80941Smrg 70b8e80941Smrgstatic struct gl_shader_program * 71b8e80941Smrglookup_linked_program(GLuint program, const char *caller) 72b8e80941Smrg{ 73b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 74b8e80941Smrg struct gl_shader_program *prog = 75b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, caller); 76b8e80941Smrg 77b8e80941Smrg if (!prog) 78b8e80941Smrg return NULL; 79b8e80941Smrg 80b8e80941Smrg if (prog->data->LinkStatus == LINKING_FAILURE) { 81b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", 82b8e80941Smrg caller); 83b8e80941Smrg return NULL; 84b8e80941Smrg } 85b8e80941Smrg return prog; 86b8e80941Smrg} 87b8e80941Smrg 88b8e80941Smrgvoid GLAPIENTRY 89b8e80941Smrg_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, 90b8e80941Smrg GLenum pname, GLint *params) 91b8e80941Smrg{ 92b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 93b8e80941Smrg 94b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 95b8e80941Smrg _mesa_debug(ctx, "glGetProgramInterfaceiv(%u, %s, %s, %p)\n", 96b8e80941Smrg program, _mesa_enum_to_string(programInterface), 97b8e80941Smrg _mesa_enum_to_string(pname), params); 98b8e80941Smrg } 99b8e80941Smrg 100b8e80941Smrg unsigned i; 101b8e80941Smrg struct gl_shader_program *shProg = 102b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, 103b8e80941Smrg "glGetProgramInterfaceiv"); 104b8e80941Smrg if (!shProg) 105b8e80941Smrg return; 106b8e80941Smrg 107b8e80941Smrg if (!params) { 108b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 109b8e80941Smrg "glGetProgramInterfaceiv(params NULL)"); 110b8e80941Smrg return; 111b8e80941Smrg } 112b8e80941Smrg 113b8e80941Smrg /* Validate interface. */ 114b8e80941Smrg if (!supported_interface_enum(ctx, programInterface)) { 115b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)", 116b8e80941Smrg _mesa_enum_to_string(programInterface)); 117b8e80941Smrg return; 118b8e80941Smrg } 119b8e80941Smrg 120b8e80941Smrg /* Validate pname against interface. */ 121b8e80941Smrg switch(pname) { 122b8e80941Smrg case GL_ACTIVE_RESOURCES: 123b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) 124b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) 125b8e80941Smrg (*params)++; 126b8e80941Smrg break; 127b8e80941Smrg case GL_MAX_NAME_LENGTH: 128b8e80941Smrg if (programInterface == GL_ATOMIC_COUNTER_BUFFER || 129b8e80941Smrg programInterface == GL_TRANSFORM_FEEDBACK_BUFFER) { 130b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 131b8e80941Smrg "glGetProgramInterfaceiv(%s pname %s)", 132b8e80941Smrg _mesa_enum_to_string(programInterface), 133b8e80941Smrg _mesa_enum_to_string(pname)); 134b8e80941Smrg return; 135b8e80941Smrg } 136b8e80941Smrg /* Name length consists of base name, 3 additional chars '[0]' if 137b8e80941Smrg * resource is an array and finally 1 char for string terminator. 138b8e80941Smrg */ 139b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 140b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type != programInterface) 141b8e80941Smrg continue; 142b8e80941Smrg unsigned len = 143b8e80941Smrg _mesa_program_resource_name_len(&shProg->data->ProgramResourceList[i]); 144b8e80941Smrg *params = MAX2(*params, len + 1); 145b8e80941Smrg } 146b8e80941Smrg break; 147b8e80941Smrg case GL_MAX_NUM_ACTIVE_VARIABLES: 148b8e80941Smrg switch (programInterface) { 149b8e80941Smrg case GL_UNIFORM_BLOCK: 150b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 151b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) { 152b8e80941Smrg struct gl_uniform_block *block = 153b8e80941Smrg (struct gl_uniform_block *) 154b8e80941Smrg shProg->data->ProgramResourceList[i].Data; 155b8e80941Smrg *params = MAX2(*params, block->NumUniforms); 156b8e80941Smrg } 157b8e80941Smrg } 158b8e80941Smrg break; 159b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 160b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 161b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) { 162b8e80941Smrg struct gl_uniform_block *block = 163b8e80941Smrg (struct gl_uniform_block *) 164b8e80941Smrg shProg->data->ProgramResourceList[i].Data; 165b8e80941Smrg GLint block_params = 0; 166b8e80941Smrg for (unsigned j = 0; j < block->NumUniforms; j++) { 167b8e80941Smrg const char *iname = block->Uniforms[j].IndexName; 168b8e80941Smrg struct gl_program_resource *uni = 169b8e80941Smrg _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE, 170b8e80941Smrg iname, NULL); 171b8e80941Smrg if (!uni) 172b8e80941Smrg continue; 173b8e80941Smrg block_params++; 174b8e80941Smrg } 175b8e80941Smrg *params = MAX2(*params, block_params); 176b8e80941Smrg } 177b8e80941Smrg } 178b8e80941Smrg break; 179b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 180b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 181b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) { 182b8e80941Smrg struct gl_active_atomic_buffer *buffer = 183b8e80941Smrg (struct gl_active_atomic_buffer *) 184b8e80941Smrg shProg->data->ProgramResourceList[i].Data; 185b8e80941Smrg *params = MAX2(*params, buffer->NumUniforms); 186b8e80941Smrg } 187b8e80941Smrg } 188b8e80941Smrg break; 189b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 190b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 191b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) { 192b8e80941Smrg struct gl_transform_feedback_buffer *buffer = 193b8e80941Smrg (struct gl_transform_feedback_buffer *) 194b8e80941Smrg shProg->data->ProgramResourceList[i].Data; 195b8e80941Smrg *params = MAX2(*params, buffer->NumVaryings); 196b8e80941Smrg } 197b8e80941Smrg } 198b8e80941Smrg break; 199b8e80941Smrg default: 200b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 201b8e80941Smrg "glGetProgramInterfaceiv(%s pname %s)", 202b8e80941Smrg _mesa_enum_to_string(programInterface), 203b8e80941Smrg _mesa_enum_to_string(pname)); 204b8e80941Smrg } 205b8e80941Smrg break; 206b8e80941Smrg case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: 207b8e80941Smrg switch (programInterface) { 208b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 209b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 210b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 211b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 212b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 213b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: { 214b8e80941Smrg for (i = 0, *params = 0; i < shProg->data->NumProgramResourceList; i++) { 215b8e80941Smrg if (shProg->data->ProgramResourceList[i].Type == programInterface) { 216b8e80941Smrg struct gl_uniform_storage *uni = 217b8e80941Smrg (struct gl_uniform_storage *) 218b8e80941Smrg shProg->data->ProgramResourceList[i].Data; 219b8e80941Smrg *params = MAX2(*params, uni->num_compatible_subroutines); 220b8e80941Smrg } 221b8e80941Smrg } 222b8e80941Smrg break; 223b8e80941Smrg } 224b8e80941Smrg 225b8e80941Smrg default: 226b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 227b8e80941Smrg "glGetProgramInterfaceiv(%s pname %s)", 228b8e80941Smrg _mesa_enum_to_string(programInterface), 229b8e80941Smrg _mesa_enum_to_string(pname)); 230b8e80941Smrg } 231b8e80941Smrg break; 232b8e80941Smrg default: 233b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 234b8e80941Smrg "glGetProgramInterfaceiv(pname %s)", 235b8e80941Smrg _mesa_enum_to_string(pname)); 236b8e80941Smrg } 237b8e80941Smrg} 238b8e80941Smrg 239b8e80941Smrgstatic bool 240b8e80941Smrgis_xfb_marker(const char *str) 241b8e80941Smrg{ 242b8e80941Smrg static const char *markers[] = { 243b8e80941Smrg "gl_NextBuffer", 244b8e80941Smrg "gl_SkipComponents1", 245b8e80941Smrg "gl_SkipComponents2", 246b8e80941Smrg "gl_SkipComponents3", 247b8e80941Smrg "gl_SkipComponents4", 248b8e80941Smrg NULL 249b8e80941Smrg }; 250b8e80941Smrg const char **m = markers; 251b8e80941Smrg 252b8e80941Smrg if (strncmp(str, "gl_", 3) != 0) 253b8e80941Smrg return false; 254b8e80941Smrg 255b8e80941Smrg for (; *m; m++) 256b8e80941Smrg if (strcmp(*m, str) == 0) 257b8e80941Smrg return true; 258b8e80941Smrg 259b8e80941Smrg return false; 260b8e80941Smrg} 261b8e80941Smrg 262b8e80941SmrgGLuint GLAPIENTRY 263b8e80941Smrg_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface, 264b8e80941Smrg const GLchar *name) 265b8e80941Smrg{ 266b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 267b8e80941Smrg 268b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 269b8e80941Smrg _mesa_debug(ctx, "glGetProgramResourceIndex(%u, %s, %s)\n", 270b8e80941Smrg program, _mesa_enum_to_string(programInterface), name); 271b8e80941Smrg } 272b8e80941Smrg 273b8e80941Smrg unsigned array_index = 0; 274b8e80941Smrg struct gl_program_resource *res; 275b8e80941Smrg struct gl_shader_program *shProg = 276b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, 277b8e80941Smrg "glGetProgramResourceIndex"); 278b8e80941Smrg if (!shProg || !name) 279b8e80941Smrg return GL_INVALID_INDEX; 280b8e80941Smrg 281b8e80941Smrg if (!supported_interface_enum(ctx, programInterface)) { 282b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", 283b8e80941Smrg _mesa_enum_to_string(programInterface)); 284b8e80941Smrg return GL_INVALID_INDEX; 285b8e80941Smrg } 286b8e80941Smrg /* 287b8e80941Smrg * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX 288b8e80941Smrg * should be returned when querying the index assigned to the special names 289b8e80941Smrg * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", 290b8e80941Smrg * "gl_SkipComponents3", and "gl_SkipComponents4". 291b8e80941Smrg */ 292b8e80941Smrg if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING && 293b8e80941Smrg is_xfb_marker(name)) 294b8e80941Smrg return GL_INVALID_INDEX; 295b8e80941Smrg 296b8e80941Smrg switch (programInterface) { 297b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE: 298b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 299b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE: 300b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 301b8e80941Smrg case GL_COMPUTE_SUBROUTINE: 302b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 303b8e80941Smrg case GL_GEOMETRY_SUBROUTINE: 304b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 305b8e80941Smrg case GL_VERTEX_SUBROUTINE: 306b8e80941Smrg case GL_FRAGMENT_SUBROUTINE: 307b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 308b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 309b8e80941Smrg case GL_PROGRAM_INPUT: 310b8e80941Smrg case GL_PROGRAM_OUTPUT: 311b8e80941Smrg case GL_UNIFORM: 312b8e80941Smrg case GL_BUFFER_VARIABLE: 313b8e80941Smrg case GL_TRANSFORM_FEEDBACK_VARYING: 314b8e80941Smrg case GL_UNIFORM_BLOCK: 315b8e80941Smrg case GL_SHADER_STORAGE_BLOCK: 316b8e80941Smrg res = _mesa_program_resource_find_name(shProg, programInterface, name, 317b8e80941Smrg &array_index); 318b8e80941Smrg if (!res || array_index > 0) 319b8e80941Smrg return GL_INVALID_INDEX; 320b8e80941Smrg 321b8e80941Smrg return _mesa_program_resource_index(shProg, res); 322b8e80941Smrg case GL_ATOMIC_COUNTER_BUFFER: 323b8e80941Smrg case GL_TRANSFORM_FEEDBACK_BUFFER: 324b8e80941Smrg default: 325b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)", 326b8e80941Smrg _mesa_enum_to_string(programInterface)); 327b8e80941Smrg } 328b8e80941Smrg 329b8e80941Smrg return GL_INVALID_INDEX; 330b8e80941Smrg} 331b8e80941Smrg 332b8e80941Smrgvoid GLAPIENTRY 333b8e80941Smrg_mesa_GetProgramResourceName(GLuint program, GLenum programInterface, 334b8e80941Smrg GLuint index, GLsizei bufSize, GLsizei *length, 335b8e80941Smrg GLchar *name) 336b8e80941Smrg{ 337b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 338b8e80941Smrg 339b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 340b8e80941Smrg _mesa_debug(ctx, "glGetProgramResourceName(%u, %s, %u, %d, %p, %p)\n", 341b8e80941Smrg program, _mesa_enum_to_string(programInterface), index, 342b8e80941Smrg bufSize, length, name); 343b8e80941Smrg } 344b8e80941Smrg 345b8e80941Smrg struct gl_shader_program *shProg = 346b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, 347b8e80941Smrg "glGetProgramResourceName"); 348b8e80941Smrg 349b8e80941Smrg if (!shProg || !name) 350b8e80941Smrg return; 351b8e80941Smrg 352b8e80941Smrg if (programInterface == GL_ATOMIC_COUNTER_BUFFER || 353b8e80941Smrg programInterface == GL_TRANSFORM_FEEDBACK_BUFFER || 354b8e80941Smrg !supported_interface_enum(ctx, programInterface)) { 355b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)", 356b8e80941Smrg _mesa_enum_to_string(programInterface)); 357b8e80941Smrg return; 358b8e80941Smrg } 359b8e80941Smrg 360b8e80941Smrg _mesa_get_program_resource_name(shProg, programInterface, index, bufSize, 361b8e80941Smrg length, name, "glGetProgramResourceName"); 362b8e80941Smrg} 363b8e80941Smrg 364b8e80941Smrgvoid GLAPIENTRY 365b8e80941Smrg_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, 366b8e80941Smrg GLuint index, GLsizei propCount, 367b8e80941Smrg const GLenum *props, GLsizei bufSize, 368b8e80941Smrg GLsizei *length, GLint *params) 369b8e80941Smrg{ 370b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 371b8e80941Smrg 372b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 373b8e80941Smrg _mesa_debug(ctx, "glGetProgramResourceiv(%u, %s, %u, %d, %p, %d, %p, %p)\n", 374b8e80941Smrg program, _mesa_enum_to_string(programInterface), index, 375b8e80941Smrg propCount, props, bufSize, length, params); 376b8e80941Smrg } 377b8e80941Smrg 378b8e80941Smrg struct gl_shader_program *shProg = 379b8e80941Smrg _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv"); 380b8e80941Smrg 381b8e80941Smrg if (!shProg || !params) 382b8e80941Smrg return; 383b8e80941Smrg 384b8e80941Smrg /* The error INVALID_VALUE is generated if <propCount> is zero. 385b8e80941Smrg * Note that we check < 0 here because it makes sense to bail early. 386b8e80941Smrg */ 387b8e80941Smrg if (propCount <= 0) { 388b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 389b8e80941Smrg "glGetProgramResourceiv(propCount <= 0)"); 390b8e80941Smrg return; 391b8e80941Smrg } 392b8e80941Smrg 393b8e80941Smrg _mesa_get_program_resourceiv(shProg, programInterface, index, 394b8e80941Smrg propCount, props, bufSize, length, params); 395b8e80941Smrg} 396b8e80941Smrg 397b8e80941SmrgGLint GLAPIENTRY 398b8e80941Smrg_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface, 399b8e80941Smrg const GLchar *name) 400b8e80941Smrg{ 401b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 402b8e80941Smrg 403b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 404b8e80941Smrg _mesa_debug(ctx, "glGetProgramResourceLocation(%u, %s, %s)\n", 405b8e80941Smrg program, _mesa_enum_to_string(programInterface), name); 406b8e80941Smrg } 407b8e80941Smrg 408b8e80941Smrg struct gl_shader_program *shProg = 409b8e80941Smrg lookup_linked_program(program, "glGetProgramResourceLocation"); 410b8e80941Smrg 411b8e80941Smrg if (!shProg || !name) 412b8e80941Smrg return -1; 413b8e80941Smrg 414b8e80941Smrg /* Validate programInterface. */ 415b8e80941Smrg switch (programInterface) { 416b8e80941Smrg case GL_UNIFORM: 417b8e80941Smrg case GL_PROGRAM_INPUT: 418b8e80941Smrg case GL_PROGRAM_OUTPUT: 419b8e80941Smrg break; 420b8e80941Smrg 421b8e80941Smrg case GL_VERTEX_SUBROUTINE_UNIFORM: 422b8e80941Smrg case GL_FRAGMENT_SUBROUTINE_UNIFORM: 423b8e80941Smrg if (!_mesa_has_ARB_shader_subroutine(ctx)) 424b8e80941Smrg goto fail; 425b8e80941Smrg break; 426b8e80941Smrg case GL_GEOMETRY_SUBROUTINE_UNIFORM: 427b8e80941Smrg if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx)) 428b8e80941Smrg goto fail; 429b8e80941Smrg break; 430b8e80941Smrg case GL_COMPUTE_SUBROUTINE_UNIFORM: 431b8e80941Smrg if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_ARB_shader_subroutine(ctx)) 432b8e80941Smrg goto fail; 433b8e80941Smrg break; 434b8e80941Smrg case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: 435b8e80941Smrg case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: 436b8e80941Smrg if (!_mesa_has_tessellation(ctx) || !_mesa_has_ARB_shader_subroutine(ctx)) 437b8e80941Smrg goto fail; 438b8e80941Smrg break; 439b8e80941Smrg default: 440b8e80941Smrg goto fail; 441b8e80941Smrg } 442b8e80941Smrg 443b8e80941Smrg return _mesa_program_resource_location(shProg, programInterface, name); 444b8e80941Smrgfail: 445b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)", 446b8e80941Smrg _mesa_enum_to_string(programInterface), name); 447b8e80941Smrg return -1; 448b8e80941Smrg} 449b8e80941Smrg 450b8e80941Smrg/** 451b8e80941Smrg * Returns output index for dual source blending. 452b8e80941Smrg */ 453b8e80941SmrgGLint GLAPIENTRY 454b8e80941Smrg_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, 455b8e80941Smrg const GLchar *name) 456b8e80941Smrg{ 457b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 458b8e80941Smrg 459b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) { 460b8e80941Smrg _mesa_debug(ctx, "glGetProgramResourceLocationIndex(%u, %s, %s)\n", 461b8e80941Smrg program, _mesa_enum_to_string(programInterface), name); 462b8e80941Smrg } 463b8e80941Smrg 464b8e80941Smrg struct gl_shader_program *shProg = 465b8e80941Smrg lookup_linked_program(program, "glGetProgramResourceLocationIndex"); 466b8e80941Smrg 467b8e80941Smrg if (!shProg || !name) 468b8e80941Smrg return -1; 469b8e80941Smrg 470b8e80941Smrg /* From the GL_ARB_program_interface_query spec: 471b8e80941Smrg * 472b8e80941Smrg * "For GetProgramResourceLocationIndex, <programInterface> must be 473b8e80941Smrg * PROGRAM_OUTPUT." 474b8e80941Smrg */ 475b8e80941Smrg if (programInterface != GL_PROGRAM_OUTPUT) { 476b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, 477b8e80941Smrg "glGetProgramResourceLocationIndex(%s)", 478b8e80941Smrg _mesa_enum_to_string(programInterface)); 479b8e80941Smrg return -1; 480b8e80941Smrg } 481b8e80941Smrg 482b8e80941Smrg return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, 483b8e80941Smrg name); 484b8e80941Smrg} 485