Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 Serge 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 
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
}