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
 * 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
 * Copyright © 2010 Intel Corporation
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the "Software"),
10
 * to deal in the Software without restriction, including without limitation
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * Software is furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included
16
 * in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
 * OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
 
27
/**
28
 * \file uniforms.c
29
 * Functions related to GLSL uniform variables.
30
 * \author Brian Paul
31
 */
32
 
33
/**
34
 * XXX things to do:
35
 * 1. Check that the right error code is generated for all _mesa_error() calls.
36
 * 2. Insert FLUSH_VERTICES calls in various places
37
 */
38
 
39
#include "main/glheader.h"
40
#include "main/context.h"
41
#include "main/dispatch.h"
42
#include "main/shaderapi.h"
43
#include "main/shaderobj.h"
44
#include "main/uniforms.h"
45
#include "main/enums.h"
46
#include "ir_uniform.h"
47
#include "glsl_types.h"
48
#include "program/program.h"
49
 
50
/**
51
 * Update the vertex/fragment program's TexturesUsed array.
52
 *
53
 * This needs to be called after glUniform(set sampler var) is called.
54
 * A call to glUniform(samplerVar, value) causes a sampler to point to a
55
 * particular texture unit.  We know the sampler's texture target
56
 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
57
 * set by glUniform() calls.
58
 *
59
 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
60
 * information to update the prog->TexturesUsed[] values.
61
 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
62
 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
63
 * We'll use that info for state validation before rendering.
64
 */
65
void
66
_mesa_update_shader_textures_used(struct gl_shader_program *shProg,
67
				  struct gl_program *prog)
68
{
69
   GLuint s;
70
   struct gl_shader *shader =
71
      shProg->_LinkedShaders[_mesa_program_target_to_index(prog->Target)];
72
 
73
   assert(shader);
74
 
75
   memcpy(prog->SamplerUnits, shader->SamplerUnits, sizeof(prog->SamplerUnits));
76
   memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
77
 
78
   for (s = 0; s < MAX_SAMPLERS; s++) {
79
      if (prog->SamplersUsed & (1 << s)) {
80
         GLuint unit = shader->SamplerUnits[s];
81
         GLuint tgt = shader->SamplerTargets[s];
82
         assert(unit < Elements(prog->TexturesUsed));
83
         assert(tgt < NUM_TEXTURE_TARGETS);
84
         prog->TexturesUsed[unit] |= (1 << tgt);
85
      }
86
   }
87
}
88
 
89
/**
90
 * Connect a piece of driver storage with a part of a uniform
91
 *
92
 * \param uni            The uniform with which the storage will be associated
93
 * \param element_stride Byte-stride between array elements.
94
 *                       \sa gl_uniform_driver_storage::element_stride.
95
 * \param vector_stride  Byte-stride between vectors (in a matrix).
96
 *                       \sa gl_uniform_driver_storage::vector_stride.
97
 * \param format         Conversion from native format to driver format
98
 *                       required by the driver.
99
 * \param data           Location to dump the data.
100
 */
101
void
102
_mesa_uniform_attach_driver_storage(struct gl_uniform_storage *uni,
103
				    unsigned element_stride,
104
				    unsigned vector_stride,
105
				    enum gl_uniform_driver_format format,
106
				    void *data)
107
{
108
   uni->driver_storage =
109
      realloc(uni->driver_storage,
110
	      sizeof(struct gl_uniform_driver_storage)
111
	      * (uni->num_driver_storage + 1));
112
 
113
   uni->driver_storage[uni->num_driver_storage].element_stride = element_stride;
114
   uni->driver_storage[uni->num_driver_storage].vector_stride = vector_stride;
115
   uni->driver_storage[uni->num_driver_storage].format = (uint8_t) format;
116
   uni->driver_storage[uni->num_driver_storage].data = data;
117
 
118
   uni->num_driver_storage++;
119
}
120
 
121
/**
122
 * Sever all connections with all pieces of driver storage for all uniforms
123
 *
124
 * \warning
125
 * This function does \b not release any of the \c data pointers
126
 * previously passed in to \c _mesa_uniform_attach_driver_stoarge.
127
 */
128
void
129
_mesa_uniform_detach_all_driver_storage(struct gl_uniform_storage *uni)
130
{
131
   free(uni->driver_storage);
132
   uni->driver_storage = NULL;
133
   uni->num_driver_storage = 0;
134
}
135
 
136
void GLAPIENTRY
137
_mesa_Uniform1f(GLint location, GLfloat v0)
138
{
139
   GET_CURRENT_CONTEXT(ctx);
140
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
141
}
142
 
143
void GLAPIENTRY
144
_mesa_Uniform2f(GLint location, GLfloat v0, GLfloat v1)
145
{
146
   GET_CURRENT_CONTEXT(ctx);
147
   GLfloat v[2];
148
   v[0] = v0;
149
   v[1] = v1;
150
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
151
}
152
 
153
void GLAPIENTRY
154
_mesa_Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
155
{
156
   GET_CURRENT_CONTEXT(ctx);
157
   GLfloat v[3];
158
   v[0] = v0;
159
   v[1] = v1;
160
   v[2] = v2;
161
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
162
}
163
 
164
void GLAPIENTRY
165
_mesa_Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
166
                   GLfloat v3)
167
{
168
   GET_CURRENT_CONTEXT(ctx);
169
   GLfloat v[4];
170
   v[0] = v0;
171
   v[1] = v1;
172
   v[2] = v2;
173
   v[3] = v3;
174
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
175
}
176
 
177
void GLAPIENTRY
178
_mesa_Uniform1i(GLint location, GLint v0)
179
{
180
   GET_CURRENT_CONTEXT(ctx);
181
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
182
}
183
 
184
void GLAPIENTRY
185
_mesa_Uniform2i(GLint location, GLint v0, GLint v1)
186
{
187
   GET_CURRENT_CONTEXT(ctx);
188
   GLint v[2];
189
   v[0] = v0;
190
   v[1] = v1;
191
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
192
}
193
 
194
void GLAPIENTRY
195
_mesa_Uniform3i(GLint location, GLint v0, GLint v1, GLint v2)
196
{
197
   GET_CURRENT_CONTEXT(ctx);
198
   GLint v[3];
199
   v[0] = v0;
200
   v[1] = v1;
201
   v[2] = v2;
202
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
203
}
204
 
205
void GLAPIENTRY
206
_mesa_Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
207
{
208
   GET_CURRENT_CONTEXT(ctx);
209
   GLint v[4];
210
   v[0] = v0;
211
   v[1] = v1;
212
   v[2] = v2;
213
   v[3] = v3;
214
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
215
}
216
 
217
void GLAPIENTRY
218
_mesa_Uniform1fv(GLint location, GLsizei count, const GLfloat * value)
219
{
220
   GET_CURRENT_CONTEXT(ctx);
221
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
222
}
223
 
224
void GLAPIENTRY
225
_mesa_Uniform2fv(GLint location, GLsizei count, const GLfloat * value)
226
{
227
   GET_CURRENT_CONTEXT(ctx);
228
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
229
}
230
 
231
void GLAPIENTRY
232
_mesa_Uniform3fv(GLint location, GLsizei count, const GLfloat * value)
233
{
234
   GET_CURRENT_CONTEXT(ctx);
235
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
236
}
237
 
238
void GLAPIENTRY
239
_mesa_Uniform4fv(GLint location, GLsizei count, const GLfloat * value)
240
{
241
   GET_CURRENT_CONTEXT(ctx);
242
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
243
}
244
 
245
void GLAPIENTRY
246
_mesa_Uniform1iv(GLint location, GLsizei count, const GLint * value)
247
{
248
   GET_CURRENT_CONTEXT(ctx);
249
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
250
}
251
 
252
void GLAPIENTRY
253
_mesa_Uniform2iv(GLint location, GLsizei count, const GLint * value)
254
{
255
   GET_CURRENT_CONTEXT(ctx);
256
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
257
}
258
 
259
void GLAPIENTRY
260
_mesa_Uniform3iv(GLint location, GLsizei count, const GLint * value)
261
{
262
   GET_CURRENT_CONTEXT(ctx);
263
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
264
}
265
 
266
void GLAPIENTRY
267
_mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
268
{
269
   GET_CURRENT_CONTEXT(ctx);
270
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
271
}
272
 
273
 
274
/** OpenGL 3.0 GLuint-valued functions **/
275
void GLAPIENTRY
276
_mesa_Uniform1ui(GLint location, GLuint v0)
277
{
278
   GET_CURRENT_CONTEXT(ctx);
279
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
280
}
281
 
282
void GLAPIENTRY
283
_mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
284
{
285
   GET_CURRENT_CONTEXT(ctx);
286
   GLuint v[2];
287
   v[0] = v0;
288
   v[1] = v1;
289
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
290
}
291
 
292
void GLAPIENTRY
293
_mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
294
{
295
   GET_CURRENT_CONTEXT(ctx);
296
   GLuint v[3];
297
   v[0] = v0;
298
   v[1] = v1;
299
   v[2] = v2;
300
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
301
}
302
 
303
void GLAPIENTRY
304
_mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
305
{
306
   GET_CURRENT_CONTEXT(ctx);
307
   GLuint v[4];
308
   v[0] = v0;
309
   v[1] = v1;
310
   v[2] = v2;
311
   v[3] = v3;
312
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
313
}
314
 
315
void GLAPIENTRY
316
_mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
317
{
318
   GET_CURRENT_CONTEXT(ctx);
319
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
320
}
321
 
322
void GLAPIENTRY
323
_mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
324
{
325
   GET_CURRENT_CONTEXT(ctx);
326
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
327
}
328
 
329
void GLAPIENTRY
330
_mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
331
{
332
   GET_CURRENT_CONTEXT(ctx);
333
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
334
}
335
 
336
void GLAPIENTRY
337
_mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
338
{
339
   GET_CURRENT_CONTEXT(ctx);
340
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
341
}
342
 
343
 
344
 
345
void GLAPIENTRY
346
_mesa_UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
347
                          const GLfloat * value)
348
{
349
   GET_CURRENT_CONTEXT(ctx);
350
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
351
			2, 2, location, count, transpose, value);
352
}
353
 
354
void GLAPIENTRY
355
_mesa_UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose,
356
                          const GLfloat * value)
357
{
358
   GET_CURRENT_CONTEXT(ctx);
359
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
360
			3, 3, location, count, transpose, value);
361
}
362
 
363
void GLAPIENTRY
364
_mesa_UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
365
                          const GLfloat * value)
366
{
367
   GET_CURRENT_CONTEXT(ctx);
368
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
369
			4, 4, location, count, transpose, value);
370
}
371
 
372
 
373
/**
374
 * Non-square UniformMatrix are OpenGL 2.1
375
 */
376
void GLAPIENTRY
377
_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
378
                         const GLfloat *value)
379
{
380
   GET_CURRENT_CONTEXT(ctx);
381
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
382
			2, 3, location, count, transpose, value);
383
}
384
 
385
void GLAPIENTRY
386
_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
387
                         const GLfloat *value)
388
{
389
   GET_CURRENT_CONTEXT(ctx);
390
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
391
			3, 2, location, count, transpose, value);
392
}
393
 
394
void GLAPIENTRY
395
_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
396
                         const GLfloat *value)
397
{
398
   GET_CURRENT_CONTEXT(ctx);
399
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
400
			2, 4, location, count, transpose, value);
401
}
402
 
403
void GLAPIENTRY
404
_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
405
                         const GLfloat *value)
406
{
407
   GET_CURRENT_CONTEXT(ctx);
408
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
409
			4, 2, location, count, transpose, value);
410
}
411
 
412
void GLAPIENTRY
413
_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
414
                         const GLfloat *value)
415
{
416
   GET_CURRENT_CONTEXT(ctx);
417
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
418
			3, 4, location, count, transpose, value);
419
}
420
 
421
void GLAPIENTRY
422
_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
423
                         const GLfloat *value)
424
{
425
   GET_CURRENT_CONTEXT(ctx);
426
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
427
			4, 3, location, count, transpose, value);
428
}
429
 
430
 
431
void GLAPIENTRY
432
_mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
433
                       GLsizei bufSize, GLfloat *params)
434
{
435
   GET_CURRENT_CONTEXT(ctx);
436
   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_FLOAT, params);
437
}
438
 
439
void GLAPIENTRY
440
_mesa_GetUniformfv(GLhandleARB program, GLint location, GLfloat *params)
441
{
442
   _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
443
}
444
 
445
 
446
void GLAPIENTRY
447
_mesa_GetnUniformivARB(GLhandleARB program, GLint location,
448
                       GLsizei bufSize, GLint *params)
449
{
450
   GET_CURRENT_CONTEXT(ctx);
451
   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_INT, params);
452
}
453
 
454
void GLAPIENTRY
455
_mesa_GetUniformiv(GLhandleARB program, GLint location, GLint *params)
456
{
457
   _mesa_GetnUniformivARB(program, location, INT_MAX, params);
458
}
459
 
460
 
461
/* GL3 */
462
void GLAPIENTRY
463
_mesa_GetnUniformuivARB(GLhandleARB program, GLint location,
464
                        GLsizei bufSize, GLuint *params)
465
{
466
   GET_CURRENT_CONTEXT(ctx);
467
   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_UINT, params);
468
}
469
 
470
void GLAPIENTRY
471
_mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
472
{
473
   _mesa_GetnUniformuivARB(program, location, INT_MAX, params);
474
}
475
 
476
 
477
/* GL4 */
478
void GLAPIENTRY
479
_mesa_GetnUniformdvARB(GLhandleARB program, GLint location,
480
                        GLsizei bufSize, GLdouble *params)
481
{
482
   GET_CURRENT_CONTEXT(ctx);
483
 
484
   (void) program;
485
   (void) location;
486
   (void) bufSize;
487
   (void) params;
488
 
489
   /*
490
   _mesa_get_uniform(ctx, program, location, bufSize, GLSL_TYPE_DOUBLE, params);
491
   */
492
   _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformdvARB"
493
               "(GL_ARB_gpu_shader_fp64 not implemented)");
494
}
495
 
496
void GLAPIENTRY
497
_mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
498
{
499
   _mesa_GetnUniformdvARB(program, location, INT_MAX, params);
500
}
501
 
502
 
503
GLint GLAPIENTRY
504
_mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name)
505
{
506
   struct gl_shader_program *shProg;
507
   GLuint index, offset;
508
 
509
   GET_CURRENT_CONTEXT(ctx);
510
 
511
   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
512
					    "glGetUniformLocation");
513
   if (!shProg)
514
      return -1;
515
 
516
   /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says:
517
    *
518
    *     "If program has not been successfully linked, the error
519
    *     INVALID_OPERATION is generated."
520
    */
521
   if (shProg->LinkStatus == GL_FALSE) {
522
      _mesa_error(ctx, GL_INVALID_OPERATION,
523
		  "glGetUniformLocation(program not linked)");
524
      return -1;
525
   }
526
 
527
   index = _mesa_get_uniform_location(ctx, shProg, name, &offset);
528
   if (index == GL_INVALID_INDEX)
529
      return -1;
530
 
531
   /* From the GL_ARB_uniform_buffer_object spec:
532
    *
533
    *     "The value -1 will be returned if  does not correspond to an
534
    *      active uniform variable name in , if  is associated
535
    *      with a named uniform block, or if  starts with the reserved
536
    *      prefix "gl_"."
537
    */
538
   if (shProg->UniformStorage[index].block_index != -1)
539
      return -1;
540
 
541
   return _mesa_uniform_merge_location_offset(shProg, index, offset);
542
}
543
 
544
GLuint GLAPIENTRY
545
_mesa_GetUniformBlockIndex(GLuint program,
546
			   const GLchar *uniformBlockName)
547
{
548
   GET_CURRENT_CONTEXT(ctx);
549
   GLuint i;
550
   struct gl_shader_program *shProg;
551
 
552
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
553
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformBlockIndex");
554
      return GL_INVALID_INDEX;
555
   }
556
 
557
   shProg = _mesa_lookup_shader_program_err(ctx, program,
558
					    "glGetUniformBlockIndex");
559
   if (!shProg)
560
      return GL_INVALID_INDEX;
561
 
562
   for (i = 0; i < shProg->NumUniformBlocks; i++) {
563
      if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
564
	 return i;
565
   }
566
 
567
   return GL_INVALID_INDEX;
568
}
569
 
570
void GLAPIENTRY
571
_mesa_GetUniformIndices(GLuint program,
572
			GLsizei uniformCount,
573
			const GLchar * const *uniformNames,
574
			GLuint *uniformIndices)
575
{
576
   GET_CURRENT_CONTEXT(ctx);
577
   GLsizei i;
578
   struct gl_shader_program *shProg;
579
 
580
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
581
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformIndices");
582
      return;
583
   }
584
 
585
   shProg = _mesa_lookup_shader_program_err(ctx, program,
586
					    "glGetUniformIndices");
587
   if (!shProg)
588
      return;
589
 
590
   if (uniformCount < 0) {
591
      _mesa_error(ctx, GL_INVALID_VALUE,
592
		  "glGetUniformIndices(uniformCount < 0)");
593
      return;
594
   }
595
 
596
   for (i = 0; i < uniformCount; i++) {
597
      unsigned offset;
598
      uniformIndices[i] = _mesa_get_uniform_location(ctx, shProg,
599
						     uniformNames[i], &offset);
600
   }
601
}
602
 
603
void GLAPIENTRY
604
_mesa_UniformBlockBinding(GLuint program,
605
			  GLuint uniformBlockIndex,
606
			  GLuint uniformBlockBinding)
607
{
608
   GET_CURRENT_CONTEXT(ctx);
609
   struct gl_shader_program *shProg;
610
 
611
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
612
      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformBlockBinding");
613
      return;
614
   }
615
 
616
   shProg = _mesa_lookup_shader_program_err(ctx, program,
617
					    "glUniformBlockBinding");
618
   if (!shProg)
619
      return;
620
 
621
   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
622
      _mesa_error(ctx, GL_INVALID_VALUE,
623
		  "glUniformBlockBinding(block index %u >= %u)",
624
		  uniformBlockIndex, shProg->NumUniformBlocks);
625
      return;
626
   }
627
 
628
   if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) {
629
      _mesa_error(ctx, GL_INVALID_VALUE,
630
		  "glUniformBlockBinding(block binding %u >= %u)",
631
		  uniformBlockBinding, ctx->Const.MaxUniformBufferBindings);
632
      return;
633
   }
634
 
635
   if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
636
       uniformBlockBinding) {
637
      int i;
638
 
639
      FLUSH_VERTICES(ctx, 0);
640
      ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
641
 
642
      shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
643
 
644
      for (i = 0; i < MESA_SHADER_TYPES; i++) {
645
	 int stage_index = shProg->UniformBlockStageIndex[i][uniformBlockIndex];
646
 
647
	 if (stage_index != -1) {
648
	    struct gl_shader *sh = shProg->_LinkedShaders[i];
649
	    sh->UniformBlocks[stage_index].Binding = uniformBlockBinding;
650
	 }
651
      }
652
   }
653
}
654
 
655
void GLAPIENTRY
656
_mesa_GetActiveUniformBlockiv(GLuint program,
657
			      GLuint uniformBlockIndex,
658
			      GLenum pname,
659
			      GLint *params)
660
{
661
   GET_CURRENT_CONTEXT(ctx);
662
   struct gl_shader_program *shProg;
663
   struct gl_uniform_block *block;
664
   unsigned i;
665
 
666
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
667
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
668
      return;
669
   }
670
 
671
   shProg = _mesa_lookup_shader_program_err(ctx, program,
672
					    "glGetActiveUniformBlockiv");
673
   if (!shProg)
674
      return;
675
 
676
   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
677
      _mesa_error(ctx, GL_INVALID_VALUE,
678
		  "glGetActiveUniformBlockiv(block index %u >= %u)",
679
		  uniformBlockIndex, shProg->NumUniformBlocks);
680
      return;
681
   }
682
 
683
   block = &shProg->UniformBlocks[uniformBlockIndex];
684
 
685
   switch (pname) {
686
   case GL_UNIFORM_BLOCK_BINDING:
687
      params[0] = block->Binding;
688
      return;
689
 
690
   case GL_UNIFORM_BLOCK_DATA_SIZE:
691
      params[0] = block->UniformBufferSize;
692
      return;
693
 
694
   case GL_UNIFORM_BLOCK_NAME_LENGTH:
695
      params[0] = strlen(block->Name) + 1;
696
      return;
697
 
698
   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
699
      params[0] = block->NumUniforms;
700
      return;
701
 
702
   case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
703
      for (i = 0; i < block->NumUniforms; i++) {
704
	 unsigned offset;
705
	 params[i] = _mesa_get_uniform_location(ctx, shProg,
706
						block->Uniforms[i].IndexName,
707
						&offset);
708
      }
709
      return;
710
 
711
   case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
712
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
713
      return;
714
 
715
   case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
716
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
717
      return;
718
 
719
   case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
720
      params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
721
      return;
722
 
723
   default:
724
      _mesa_error(ctx, GL_INVALID_ENUM,
725
		  "glGetActiveUniformBlockiv(pname 0x%x (%s))",
726
		  pname, _mesa_lookup_enum_by_nr(pname));
727
      return;
728
   }
729
}
730
 
731
void GLAPIENTRY
732
_mesa_GetActiveUniformBlockName(GLuint program,
733
				GLuint uniformBlockIndex,
734
				GLsizei bufSize,
735
				GLsizei *length,
736
				GLchar *uniformBlockName)
737
{
738
   GET_CURRENT_CONTEXT(ctx);
739
   struct gl_shader_program *shProg;
740
   struct gl_uniform_block *block;
741
 
742
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
743
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
744
      return;
745
   }
746
 
747
   if (bufSize < 0) {
748
      _mesa_error(ctx, GL_INVALID_VALUE,
749
		  "glGetActiveUniformBlockName(bufSize %d < 0)",
750
		  bufSize);
751
      return;
752
   }
753
 
754
   shProg = _mesa_lookup_shader_program_err(ctx, program,
755
					    "glGetActiveUniformBlockiv");
756
   if (!shProg)
757
      return;
758
 
759
   if (uniformBlockIndex >= shProg->NumUniformBlocks) {
760
      _mesa_error(ctx, GL_INVALID_VALUE,
761
		  "glGetActiveUniformBlockiv(block index %u >= %u)",
762
		  uniformBlockIndex, shProg->NumUniformBlocks);
763
      return;
764
   }
765
 
766
   block = &shProg->UniformBlocks[uniformBlockIndex];
767
 
768
   if (uniformBlockName) {
769
      _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
770
   }
771
}
772
 
773
void GLAPIENTRY
774
_mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
775
			   GLsizei bufSize, GLsizei *length,
776
			   GLchar *uniformName)
777
{
778
   GET_CURRENT_CONTEXT(ctx);
779
   struct gl_shader_program *shProg;
780
 
781
   if (!ctx->Extensions.ARB_uniform_buffer_object) {
782
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
783
      return;
784
   }
785
 
786
   if (bufSize < 0) {
787
      _mesa_error(ctx, GL_INVALID_VALUE,
788
		  "glGetActiveUniformName(bufSize %d < 0)",
789
		  bufSize);
790
      return;
791
   }
792
 
793
   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniformName");
794
 
795
   if (!shProg)
796
      return;
797
 
798
   if (uniformIndex >= shProg->NumUserUniformStorage) {
799
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
800
      return;
801
   }
802
 
803
   if (uniformName) {
804
      _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex],
805
                             bufSize, length, uniformName);
806
   }
807
}
808
 
809
void
810
_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
811
                       GLsizei maxLength, GLsizei *length,
812
                       GLchar *nameOut)
813
{
814
   GLsizei localLength;
815
 
816
   if (length == NULL)
817
      length = &localLength;
818
 
819
   _mesa_copy_string(nameOut, maxLength, length, uni->name);
820
 
821
   /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
822
    * spec says:
823
    *
824
    *     "If the active uniform is an array, the uniform name returned in
825
    *     name will always be the name of the uniform array appended with
826
    *     "[0]"."
827
    *
828
    * The same text also appears in the OpenGL 4.2 spec.  It does not,
829
    * however, appear in any previous spec.  Previous specifications are
830
    * ambiguous in this regard.  However, either name can later be passed
831
    * to glGetUniformLocation (and related APIs), so there shouldn't be any
832
    * harm in always appending "[0]" to uniform array names.
833
    */
834
   if (uni->array_elements != 0) {
835
      int i;
836
 
837
      /* The comparison is strange because *length does *NOT* include the
838
       * terminating NUL, but maxLength does.
839
       */
840
      for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++)
841
         nameOut[*length + i] = "[0]"[i];
842
 
843
      nameOut[*length + i] = '\0';
844
      *length += i;
845
   }
846
}