Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2015 Intel Corporation.  All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 */
25
 
26
#include "main/enums.h"
27
#include "main/macros.h"
28
#include "main/mtypes.h"
29
#include "main/shaderapi.h"
30
#include "main/shaderobj.h"
31
#include "program_resource.h"
32
 
33
static bool
34
supported_interface_enum(GLenum iface)
35
{
36
   switch (iface) {
37
   case GL_UNIFORM:
38
   case GL_UNIFORM_BLOCK:
39
   case GL_PROGRAM_INPUT:
40
   case GL_PROGRAM_OUTPUT:
41
   case GL_TRANSFORM_FEEDBACK_VARYING:
42
   case GL_ATOMIC_COUNTER_BUFFER:
43
      return true;
44
   case GL_VERTEX_SUBROUTINE:
45
   case GL_TESS_CONTROL_SUBROUTINE:
46
   case GL_TESS_EVALUATION_SUBROUTINE:
47
   case GL_GEOMETRY_SUBROUTINE:
48
   case GL_FRAGMENT_SUBROUTINE:
49
   case GL_COMPUTE_SUBROUTINE:
50
   case GL_VERTEX_SUBROUTINE_UNIFORM:
51
   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
52
   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
53
   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
54
   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
55
   case GL_COMPUTE_SUBROUTINE_UNIFORM:
56
   case GL_BUFFER_VARIABLE:
57
   case GL_SHADER_STORAGE_BLOCK:
58
   default:
59
      return false;
60
   }
61
}
62
 
63
void GLAPIENTRY
64
_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
65
                            GLenum pname, GLint *params)
66
{
67
   GET_CURRENT_CONTEXT(ctx);
68
   unsigned i;
69
   struct gl_shader_program *shProg =
70
      _mesa_lookup_shader_program_err(ctx, program,
71
                                      "glGetProgramInterfaceiv");
72
   if (!shProg)
73
      return;
74
 
75
   if (!params) {
76
      _mesa_error(ctx, GL_INVALID_OPERATION,
77
                  "glGetProgramInterfaceiv(params NULL)");
78
      return;
79
   }
80
 
81
   /* Validate interface. */
82
   if (!supported_interface_enum(programInterface)) {
83
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
84
                  _mesa_lookup_enum_by_nr(programInterface));
85
      return;
86
   }
87
 
88
   /* Validate pname against interface. */
89
   switch(pname) {
90
   case GL_ACTIVE_RESOURCES:
91
      for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++)
92
         if (shProg->ProgramResourceList[i].Type == programInterface)
93
            (*params)++;
94
      break;
95
   case GL_MAX_NAME_LENGTH:
96
      if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
97
         _mesa_error(ctx, GL_INVALID_OPERATION,
98
                     "glGetProgramInterfaceiv(%s pname %s)",
99
                     _mesa_lookup_enum_by_nr(programInterface),
100
                     _mesa_lookup_enum_by_nr(pname));
101
         return;
102
      }
103
      /* Name length consists of base name, 3 additional chars '[0]' if
104
       * resource is an array and finally 1 char for string terminator.
105
       */
106
      for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
107
         if (shProg->ProgramResourceList[i].Type != programInterface)
108
            continue;
109
         const char *name =
110
            _mesa_program_resource_name(&shProg->ProgramResourceList[i]);
111
         unsigned array_size =
112
            _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]);
113
         *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1);
114
      }
115
      break;
116
   case GL_MAX_NUM_ACTIVE_VARIABLES:
117
      switch (programInterface) {
118
      case GL_UNIFORM_BLOCK:
119
         for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
120
            if (shProg->ProgramResourceList[i].Type == programInterface) {
121
               struct gl_uniform_block *block =
122
                  (struct gl_uniform_block *)
123
                  shProg->ProgramResourceList[i].Data;
124
               *params = MAX2(*params, block->NumUniforms);
125
            }
126
         }
127
         break;
128
      case GL_ATOMIC_COUNTER_BUFFER:
129
         for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
130
            if (shProg->ProgramResourceList[i].Type == programInterface) {
131
               struct gl_active_atomic_buffer *buffer =
132
                  (struct gl_active_atomic_buffer *)
133
                  shProg->ProgramResourceList[i].Data;
134
               *params = MAX2(*params, buffer->NumUniforms);
135
            }
136
         }
137
         break;
138
      default:
139
        _mesa_error(ctx, GL_INVALID_OPERATION,
140
                    "glGetProgramInterfaceiv(%s pname %s)",
141
                    _mesa_lookup_enum_by_nr(programInterface),
142
                    _mesa_lookup_enum_by_nr(pname));
143
      };
144
      break;
145
   case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
146
   default:
147
      _mesa_error(ctx, GL_INVALID_OPERATION,
148
                  "glGetProgramInterfaceiv(pname %s)",
149
                  _mesa_lookup_enum_by_nr(pname));
150
   }
151
}
152
 
153
static bool
154
is_xfb_marker(const char *str)
155
{
156
   static const char *markers[] = {
157
      "gl_NextBuffer",
158
      "gl_SkipComponents1",
159
      "gl_SkipComponents2",
160
      "gl_SkipComponents3",
161
      "gl_SkipComponents4",
162
      NULL
163
   };
164
   const char **m = markers;
165
 
166
   if (strncmp(str, "gl_", 3) != 0)
167
      return false;
168
 
169
   for (; *m; m++)
170
      if (strcmp(*m, str) == 0)
171
         return true;
172
 
173
   return false;
174
}
175
 
176
/**
177
 * Checks if given name index is legal for GetProgramResourceIndex,
178
 * check is written to be compatible with GL_ARB_array_of_arrays.
179
 */
180
static bool
181
valid_program_resource_index_name(const GLchar *name)
182
{
183
   const char *array = strstr(name, "[");
184
   const char *close = strrchr(name, ']');
185
 
186
   /* Not array, no need for the check. */
187
   if (!array)
188
      return true;
189
 
190
   /* Last array index has to be zero. */
191
   if (!close || *--close != '0')
192
      return false;
193
 
194
   return true;
195
}
196
 
197
GLuint GLAPIENTRY
198
_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
199
                              const GLchar *name)
200
{
201
   GET_CURRENT_CONTEXT(ctx);
202
   struct gl_program_resource *res;
203
   struct gl_shader_program *shProg =
204
      _mesa_lookup_shader_program_err(ctx, program,
205
                                      "glGetProgramResourceIndex");
206
   if (!shProg || !name)
207
      return GL_INVALID_INDEX;
208
 
209
   /*
210
    * For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
211
    * should be returned when querying the index assigned to the special names
212
    * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
213
    * "gl_SkipComponents3", and "gl_SkipComponents4".
214
    */
215
   if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING &&
216
       is_xfb_marker(name))
217
      return GL_INVALID_INDEX;
218
 
219
   switch (programInterface) {
220
   case GL_PROGRAM_INPUT:
221
   case GL_PROGRAM_OUTPUT:
222
   case GL_UNIFORM:
223
   case GL_UNIFORM_BLOCK:
224
   case GL_TRANSFORM_FEEDBACK_VARYING:
225
      /* Validate name syntax for arrays. */
226
      if (!valid_program_resource_index_name(name))
227
         return GL_INVALID_INDEX;
228
 
229
      res = _mesa_program_resource_find_name(shProg, programInterface, name);
230
      if (!res)
231
         return GL_INVALID_INDEX;
232
 
233
      return _mesa_program_resource_index(shProg, res);
234
   case GL_ATOMIC_COUNTER_BUFFER:
235
   default:
236
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
237
                  _mesa_lookup_enum_by_nr(programInterface));
238
   }
239
 
240
   return GL_INVALID_INDEX;
241
}
242
 
243
void GLAPIENTRY
244
_mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
245
                             GLuint index, GLsizei bufSize, GLsizei *length,
246
                             GLchar *name)
247
{
248
   GET_CURRENT_CONTEXT(ctx);
249
   struct gl_shader_program *shProg =
250
      _mesa_lookup_shader_program_err(ctx, program,
251
                                      "glGetProgramResourceName");
252
 
253
   /* Set user friendly return values in case of errors. */
254
   if (name)
255
      *name = '\0';
256
   if (length)
257
      *length = 0;
258
 
259
   if (!shProg || !name)
260
      return;
261
 
262
   if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
263
       !supported_interface_enum(programInterface)) {
264
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
265
                  _mesa_lookup_enum_by_nr(programInterface));
266
      return;
267
   }
268
 
269
   _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
270
                                   length, name, "glGetProgramResourceName");
271
}
272
 
273
void GLAPIENTRY
274
_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
275
                           GLuint index, GLsizei propCount,
276
                           const GLenum *props, GLsizei bufSize,
277
                           GLsizei *length, GLint *params)
278
{
279
   GET_CURRENT_CONTEXT(ctx);
280
   struct gl_shader_program *shProg =
281
      _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
282
 
283
   if (!shProg || !params)
284
      return;
285
 
286
   /* The error INVALID_VALUE is generated if  is zero.
287
    * Note that we check < 0 here because it makes sense to bail early.
288
    */
289
   if (propCount <= 0) {
290
      _mesa_error(ctx, GL_INVALID_VALUE,
291
                  "glGetProgramResourceiv(propCount <= 0)");
292
      return;
293
   }
294
 
295
   /* No need to write any properties, user requested none. */
296
   if (bufSize == 0)
297
      return;
298
 
299
   _mesa_get_program_resourceiv(shProg, programInterface, index,
300
                                propCount, props, bufSize, length, params);
301
}
302
 
303
/**
304
 * Function verifies syntax of given name for GetProgramResourceLocation
305
 * and GetProgramResourceLocationIndex for the following cases:
306
 *
307
 * "array element portion of a string passed to GetProgramResourceLocation
308
 * or GetProgramResourceLocationIndex must not have, a "+" sign, extra
309
 * leading zeroes, or whitespace".
310
 *
311
 * Check is written to be compatible with GL_ARB_array_of_arrays.
312
 */
313
static bool
314
invalid_array_element_syntax(const GLchar *name)
315
{
316
   char *first = strchr(name, '[');
317
   char *last = strrchr(name, '[');
318
 
319
   if (!first)
320
      return false;
321
 
322
   /* No '+' or ' ' allowed anywhere. */
323
   if (strchr(first, '+') || strchr(first, ' '))
324
      return true;
325
 
326
   /* Check that last array index is 0. */
327
   if (last[1] == '0' && last[2] != ']')
328
      return true;
329
 
330
   return false;
331
}
332
 
333
static struct gl_shader_program *
334
lookup_linked_program(GLuint program, const char *caller)
335
{
336
   GET_CURRENT_CONTEXT(ctx);
337
   struct gl_shader_program *prog =
338
      _mesa_lookup_shader_program_err(ctx, program, caller);
339
 
340
   if (!prog)
341
      return NULL;
342
 
343
   if (prog->LinkStatus == GL_FALSE) {
344
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
345
                  caller);
346
      return NULL;
347
   }
348
   return prog;
349
}
350
 
351
GLint GLAPIENTRY
352
_mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
353
                                 const GLchar *name)
354
{
355
   GET_CURRENT_CONTEXT(ctx);
356
   struct gl_shader_program *shProg =
357
      lookup_linked_program(program, "glGetProgramResourceLocation");
358
 
359
   if (!shProg || !name || invalid_array_element_syntax(name))
360
      return -1;
361
 
362
   /* Validate programInterface. */
363
   switch (programInterface) {
364
   case GL_UNIFORM:
365
   case GL_PROGRAM_INPUT:
366
   case GL_PROGRAM_OUTPUT:
367
      break;
368
 
369
   /* For reference valid cases requiring additional extension support:
370
    * GL_ARB_shader_subroutine
371
    * GL_ARB_tessellation_shader
372
    * GL_ARB_compute_shader
373
    */
374
   case GL_VERTEX_SUBROUTINE_UNIFORM:
375
   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
376
   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
377
   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
378
   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
379
   case GL_COMPUTE_SUBROUTINE_UNIFORM:
380
 
381
   default:
382
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
383
                  _mesa_lookup_enum_by_nr(programInterface), name);
384
   }
385
 
386
   return _mesa_program_resource_location(shProg, programInterface, name);
387
}
388
 
389
/**
390
 * Returns output index for dual source blending.
391
 */
392
GLint GLAPIENTRY
393
_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
394
                                      const GLchar *name)
395
{
396
   GET_CURRENT_CONTEXT(ctx);
397
   struct gl_shader_program *shProg =
398
      lookup_linked_program(program, "glGetProgramResourceLocationIndex");
399
 
400
   if (!shProg || !name || invalid_array_element_syntax(name))
401
      return -1;
402
 
403
   /* From the GL_ARB_program_interface_query spec:
404
    *
405
    * "For GetProgramResourceLocationIndex,  must be
406
    * PROGRAM_OUTPUT."
407
    */
408
   if (programInterface != GL_PROGRAM_OUTPUT) {
409
      _mesa_error(ctx, GL_INVALID_ENUM,
410
                  "glGetProgramResourceLocationIndex(%s)",
411
                  _mesa_lookup_enum_by_nr(programInterface));
412
      return -1;
413
   }
414
 
415
   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
416
                                                name);
417
}