Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1901 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
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
/**
27
 * \file uniforms.c
28
 * Functions related to GLSL uniform variables.
29
 * \author Brian Paul
30
 */
31
 
32
/**
33
 * XXX things to do:
34
 * 1. Check that the right error code is generated for all _mesa_error() calls.
35
 * 2. Insert FLUSH_VERTICES calls in various places
36
 */
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 "program/prog_parameter.h"
46
#include "program/prog_statevars.h"
47
#include "program/prog_uniform.h"
48
#include "program/prog_instruction.h"
49
 
50
 
51
static GLenum
52
base_uniform_type(GLenum type)
53
{
54
   switch (type) {
55
#if 0 /* not needed, for now */
56
   case GL_BOOL:
57
   case GL_BOOL_VEC2:
58
   case GL_BOOL_VEC3:
59
   case GL_BOOL_VEC4:
60
      return GL_BOOL;
61
#endif
62
   case GL_FLOAT:
63
   case GL_FLOAT_VEC2:
64
   case GL_FLOAT_VEC3:
65
   case GL_FLOAT_VEC4:
66
      return GL_FLOAT;
67
   case GL_UNSIGNED_INT:
68
   case GL_UNSIGNED_INT_VEC2:
69
   case GL_UNSIGNED_INT_VEC3:
70
   case GL_UNSIGNED_INT_VEC4:
71
      return GL_UNSIGNED_INT;
72
   case GL_INT:
73
   case GL_INT_VEC2:
74
   case GL_INT_VEC3:
75
   case GL_INT_VEC4:
76
      return GL_INT;
77
   default:
78
      _mesa_problem(NULL, "Invalid type in base_uniform_type()");
79
      return GL_FLOAT;
80
   }
81
}
82
 
83
static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
84
   {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
85
   {"far", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_YYYY},
86
   {"diff", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_ZZZZ},
87
};
88
 
89
static struct gl_builtin_uniform_element gl_ClipPlane_elements[] = {
90
   {NULL, {STATE_CLIPPLANE, 0, 0}, SWIZZLE_XYZW}
91
};
92
 
93
static struct gl_builtin_uniform_element gl_Point_elements[] = {
94
   {"size", {STATE_POINT_SIZE}, SWIZZLE_XXXX},
95
   {"sizeMin", {STATE_POINT_SIZE}, SWIZZLE_YYYY},
96
   {"sizeMax", {STATE_POINT_SIZE}, SWIZZLE_ZZZZ},
97
   {"fadeThresholdSize", {STATE_POINT_SIZE}, SWIZZLE_WWWW},
98
   {"distanceConstantAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_XXXX},
99
   {"distanceLinearAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_YYYY},
100
   {"distanceQuadraticAttenuation", {STATE_POINT_ATTENUATION}, SWIZZLE_ZZZZ},
101
};
102
 
103
static struct gl_builtin_uniform_element gl_FrontMaterial_elements[] = {
104
   {"emission", {STATE_MATERIAL, 0, STATE_EMISSION}, SWIZZLE_XYZW},
105
   {"ambient", {STATE_MATERIAL, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
106
   {"diffuse", {STATE_MATERIAL, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
107
   {"specular", {STATE_MATERIAL, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
108
   {"shininess", {STATE_MATERIAL, 0, STATE_SHININESS}, SWIZZLE_XXXX},
109
};
110
 
111
static struct gl_builtin_uniform_element gl_BackMaterial_elements[] = {
112
   {"emission", {STATE_MATERIAL, 1, STATE_EMISSION}, SWIZZLE_XYZW},
113
   {"ambient", {STATE_MATERIAL, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
114
   {"diffuse", {STATE_MATERIAL, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
115
   {"specular", {STATE_MATERIAL, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
116
   {"shininess", {STATE_MATERIAL, 1, STATE_SHININESS}, SWIZZLE_XXXX},
117
};
118
 
119
static struct gl_builtin_uniform_element gl_LightSource_elements[] = {
120
   {"ambient", {STATE_LIGHT, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
121
   {"diffuse", {STATE_LIGHT, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
122
   {"specular", {STATE_LIGHT, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
123
   {"position", {STATE_LIGHT, 0, STATE_POSITION}, SWIZZLE_XYZW},
124
   {"halfVector", {STATE_LIGHT, 0, STATE_HALF_VECTOR}, SWIZZLE_XYZW},
125
   {"spotDirection", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION},
126
    MAKE_SWIZZLE4(SWIZZLE_X,
127
		  SWIZZLE_Y,
128
		  SWIZZLE_Z,
129
		  SWIZZLE_Z)},
130
   {"spotCosCutoff", {STATE_LIGHT, 0, STATE_SPOT_DIRECTION}, SWIZZLE_WWWW},
131
   {"spotCutoff", {STATE_LIGHT, 0, STATE_SPOT_CUTOFF}, SWIZZLE_XXXX},
132
   {"spotExponent", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_WWWW},
133
   {"constantAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_XXXX},
134
   {"linearAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_YYYY},
135
   {"quadraticAttenuation", {STATE_LIGHT, 0, STATE_ATTENUATION}, SWIZZLE_ZZZZ},
136
};
137
 
138
static struct gl_builtin_uniform_element gl_LightModel_elements[] = {
139
   {"ambient", {STATE_LIGHTMODEL_AMBIENT, 0}, SWIZZLE_XYZW},
140
};
141
 
142
static struct gl_builtin_uniform_element gl_FrontLightModelProduct_elements[] = {
143
   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 0}, SWIZZLE_XYZW},
144
};
145
 
146
static struct gl_builtin_uniform_element gl_BackLightModelProduct_elements[] = {
147
   {"sceneColor", {STATE_LIGHTMODEL_SCENECOLOR, 1}, SWIZZLE_XYZW},
148
};
149
 
150
static struct gl_builtin_uniform_element gl_FrontLightProduct_elements[] = {
151
   {"ambient", {STATE_LIGHTPROD, 0, 0, STATE_AMBIENT}, SWIZZLE_XYZW},
152
   {"diffuse", {STATE_LIGHTPROD, 0, 0, STATE_DIFFUSE}, SWIZZLE_XYZW},
153
   {"specular", {STATE_LIGHTPROD, 0, 0, STATE_SPECULAR}, SWIZZLE_XYZW},
154
};
155
 
156
static struct gl_builtin_uniform_element gl_BackLightProduct_elements[] = {
157
   {"ambient", {STATE_LIGHTPROD, 0, 1, STATE_AMBIENT}, SWIZZLE_XYZW},
158
   {"diffuse", {STATE_LIGHTPROD, 0, 1, STATE_DIFFUSE}, SWIZZLE_XYZW},
159
   {"specular", {STATE_LIGHTPROD, 0, 1, STATE_SPECULAR}, SWIZZLE_XYZW},
160
};
161
 
162
static struct gl_builtin_uniform_element gl_TextureEnvColor_elements[] = {
163
   {NULL, {STATE_TEXENV_COLOR, 0}, SWIZZLE_XYZW},
164
};
165
 
166
static struct gl_builtin_uniform_element gl_EyePlaneS_elements[] = {
167
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_S}, SWIZZLE_XYZW},
168
};
169
 
170
static struct gl_builtin_uniform_element gl_EyePlaneT_elements[] = {
171
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_T}, SWIZZLE_XYZW},
172
};
173
 
174
static struct gl_builtin_uniform_element gl_EyePlaneR_elements[] = {
175
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_R}, SWIZZLE_XYZW},
176
};
177
 
178
static struct gl_builtin_uniform_element gl_EyePlaneQ_elements[] = {
179
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_EYE_Q}, SWIZZLE_XYZW},
180
};
181
 
182
static struct gl_builtin_uniform_element gl_ObjectPlaneS_elements[] = {
183
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_S}, SWIZZLE_XYZW},
184
};
185
 
186
static struct gl_builtin_uniform_element gl_ObjectPlaneT_elements[] = {
187
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_T}, SWIZZLE_XYZW},
188
};
189
 
190
static struct gl_builtin_uniform_element gl_ObjectPlaneR_elements[] = {
191
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_R}, SWIZZLE_XYZW},
192
};
193
 
194
static struct gl_builtin_uniform_element gl_ObjectPlaneQ_elements[] = {
195
   {NULL, {STATE_TEXGEN, 0, STATE_TEXGEN_OBJECT_Q}, SWIZZLE_XYZW},
196
};
197
 
198
static struct gl_builtin_uniform_element gl_Fog_elements[] = {
199
   {"color", {STATE_FOG_COLOR}, SWIZZLE_XYZW},
200
   {"density", {STATE_FOG_PARAMS}, SWIZZLE_XXXX},
201
   {"start", {STATE_FOG_PARAMS}, SWIZZLE_YYYY},
202
   {"end", {STATE_FOG_PARAMS}, SWIZZLE_ZZZZ},
203
   {"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
204
};
205
 
206
static struct gl_builtin_uniform_element gl_NormalScale_elements[] = {
207
   {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
208
};
209
 
210
#define MATRIX(name, statevar, modifier)				\
211
   static struct gl_builtin_uniform_element name ## _elements[] = {	\
212
      { NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW },		\
213
      { NULL, { statevar, 0, 1, 1, modifier}, SWIZZLE_XYZW },		\
214
      { NULL, { statevar, 0, 2, 2, modifier}, SWIZZLE_XYZW },		\
215
      { NULL, { statevar, 0, 3, 3, modifier}, SWIZZLE_XYZW },		\
216
   }
217
 
218
MATRIX(gl_ModelViewMatrix,
219
       STATE_MODELVIEW_MATRIX, STATE_MATRIX_TRANSPOSE);
220
MATRIX(gl_ModelViewMatrixInverse,
221
       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVTRANS);
222
MATRIX(gl_ModelViewMatrixTranspose,
223
       STATE_MODELVIEW_MATRIX, 0);
224
MATRIX(gl_ModelViewMatrixInverseTranspose,
225
       STATE_MODELVIEW_MATRIX, STATE_MATRIX_INVERSE);
226
 
227
MATRIX(gl_ProjectionMatrix,
228
       STATE_PROJECTION_MATRIX, STATE_MATRIX_TRANSPOSE);
229
MATRIX(gl_ProjectionMatrixInverse,
230
       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVTRANS);
231
MATRIX(gl_ProjectionMatrixTranspose,
232
       STATE_PROJECTION_MATRIX, 0);
233
MATRIX(gl_ProjectionMatrixInverseTranspose,
234
       STATE_PROJECTION_MATRIX, STATE_MATRIX_INVERSE);
235
 
236
MATRIX(gl_ModelViewProjectionMatrix,
237
       STATE_MVP_MATRIX, STATE_MATRIX_TRANSPOSE);
238
MATRIX(gl_ModelViewProjectionMatrixInverse,
239
       STATE_MVP_MATRIX, STATE_MATRIX_INVTRANS);
240
MATRIX(gl_ModelViewProjectionMatrixTranspose,
241
       STATE_MVP_MATRIX, 0);
242
MATRIX(gl_ModelViewProjectionMatrixInverseTranspose,
243
       STATE_MVP_MATRIX, STATE_MATRIX_INVERSE);
244
 
245
MATRIX(gl_TextureMatrix,
246
       STATE_TEXTURE_MATRIX, STATE_MATRIX_TRANSPOSE);
247
MATRIX(gl_TextureMatrixInverse,
248
       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVTRANS);
249
MATRIX(gl_TextureMatrixTranspose,
250
       STATE_TEXTURE_MATRIX, 0);
251
MATRIX(gl_TextureMatrixInverseTranspose,
252
       STATE_TEXTURE_MATRIX, STATE_MATRIX_INVERSE);
253
 
254
static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
255
   { NULL, { STATE_MODELVIEW_MATRIX, 0, 0, 0, STATE_MATRIX_INVERSE},
256
     SWIZZLE_XYZW },
257
   { NULL, { STATE_MODELVIEW_MATRIX, 0, 1, 1, STATE_MATRIX_INVERSE},
258
     SWIZZLE_XYZW },
259
   { NULL, { STATE_MODELVIEW_MATRIX, 0, 2, 2, STATE_MATRIX_INVERSE},
260
     SWIZZLE_XYZW },
261
};
262
 
263
#undef MATRIX
264
 
265
#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
266
 
267
const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
268
   STATEVAR(gl_DepthRange),
269
   STATEVAR(gl_ClipPlane),
270
   STATEVAR(gl_Point),
271
   STATEVAR(gl_FrontMaterial),
272
   STATEVAR(gl_BackMaterial),
273
   STATEVAR(gl_LightSource),
274
   STATEVAR(gl_LightModel),
275
   STATEVAR(gl_FrontLightModelProduct),
276
   STATEVAR(gl_BackLightModelProduct),
277
   STATEVAR(gl_FrontLightProduct),
278
   STATEVAR(gl_BackLightProduct),
279
   STATEVAR(gl_TextureEnvColor),
280
   STATEVAR(gl_EyePlaneS),
281
   STATEVAR(gl_EyePlaneT),
282
   STATEVAR(gl_EyePlaneR),
283
   STATEVAR(gl_EyePlaneQ),
284
   STATEVAR(gl_ObjectPlaneS),
285
   STATEVAR(gl_ObjectPlaneT),
286
   STATEVAR(gl_ObjectPlaneR),
287
   STATEVAR(gl_ObjectPlaneQ),
288
   STATEVAR(gl_Fog),
289
 
290
   STATEVAR(gl_ModelViewMatrix),
291
   STATEVAR(gl_ModelViewMatrixInverse),
292
   STATEVAR(gl_ModelViewMatrixTranspose),
293
   STATEVAR(gl_ModelViewMatrixInverseTranspose),
294
 
295
   STATEVAR(gl_ProjectionMatrix),
296
   STATEVAR(gl_ProjectionMatrixInverse),
297
   STATEVAR(gl_ProjectionMatrixTranspose),
298
   STATEVAR(gl_ProjectionMatrixInverseTranspose),
299
 
300
   STATEVAR(gl_ModelViewProjectionMatrix),
301
   STATEVAR(gl_ModelViewProjectionMatrixInverse),
302
   STATEVAR(gl_ModelViewProjectionMatrixTranspose),
303
   STATEVAR(gl_ModelViewProjectionMatrixInverseTranspose),
304
 
305
   STATEVAR(gl_TextureMatrix),
306
   STATEVAR(gl_TextureMatrixInverse),
307
   STATEVAR(gl_TextureMatrixTranspose),
308
   STATEVAR(gl_TextureMatrixInverseTranspose),
309
 
310
   STATEVAR(gl_NormalMatrix),
311
   STATEVAR(gl_NormalScale),
312
 
313
   {NULL, NULL, 0}
314
};
315
 
316
static GLboolean
317
is_boolean_type(GLenum type)
318
{
319
   switch (type) {
320
   case GL_BOOL:
321
   case GL_BOOL_VEC2:
322
   case GL_BOOL_VEC3:
323
   case GL_BOOL_VEC4:
324
      return GL_TRUE;
325
   default:
326
      return GL_FALSE;
327
   }
328
}
329
 
330
 
331
static GLboolean
332
is_sampler_type(GLenum type)
333
{
334
   switch (type) {
335
   case GL_SAMPLER_1D:
336
   case GL_SAMPLER_2D:
337
   case GL_SAMPLER_3D:
338
   case GL_SAMPLER_CUBE:
339
   case GL_SAMPLER_1D_SHADOW:
340
   case GL_SAMPLER_2D_SHADOW:
341
   case GL_SAMPLER_2D_RECT_ARB:
342
   case GL_SAMPLER_2D_RECT_SHADOW_ARB:
343
   case GL_SAMPLER_1D_ARRAY_EXT:
344
   case GL_SAMPLER_2D_ARRAY_EXT:
345
   case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
346
   case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
347
      return GL_TRUE;
348
   default:
349
      return GL_FALSE;
350
   }
351
}
352
 
353
 
354
static struct gl_program_parameter *
355
get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
356
{
357
   const struct gl_program *prog = NULL;
358
   GLint progPos;
359
 
360
   progPos = shProg->Uniforms->Uniforms[index].VertPos;
361
   if (progPos >= 0) {
362
      prog = &shProg->VertexProgram->Base;
363
   }
364
   else {
365
      progPos = shProg->Uniforms->Uniforms[index].FragPos;
366
      if (progPos >= 0) {
367
         prog = &shProg->FragmentProgram->Base;
368
      } else {
369
         progPos = shProg->Uniforms->Uniforms[index].GeomPos;
370
         if (progPos >= 0) {
371
            prog = &shProg->GeometryProgram->Base;
372
         }
373
      }
374
   }
375
 
376
   if (!prog || progPos < 0)
377
      return NULL; /* should never happen */
378
 
379
   return &prog->Parameters->Parameters[progPos];
380
}
381
 
382
 
383
/**
384
 * Called by glGetActiveUniform().
385
 */
386
static void
387
_mesa_get_active_uniform(struct gl_context *ctx, GLuint program, GLuint index,
388
                         GLsizei maxLength, GLsizei *length, GLint *size,
389
                         GLenum *type, GLchar *nameOut)
390
{
391
   const struct gl_shader_program *shProg;
392
   const struct gl_program *prog = NULL;
393
   const struct gl_program_parameter *param;
394
   GLint progPos;
395
 
396
   shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
397
   if (!shProg)
398
      return;
399
 
400
   if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
401
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
402
      return;
403
   }
404
 
405
   progPos = shProg->Uniforms->Uniforms[index].VertPos;
406
   if (progPos >= 0) {
407
      prog = &shProg->VertexProgram->Base;
408
   }
409
   else {
410
      progPos = shProg->Uniforms->Uniforms[index].FragPos;
411
      if (progPos >= 0) {
412
         prog = &shProg->FragmentProgram->Base;
413
      } else {
414
         progPos = shProg->Uniforms->Uniforms[index].GeomPos;
415
         if (progPos >= 0) {
416
            prog = &shProg->GeometryProgram->Base;
417
         }
418
      }
419
   }
420
 
421
   if (!prog || progPos < 0)
422
      return; /* should never happen */
423
 
424
   ASSERT(progPos < prog->Parameters->NumParameters);
425
   param = &prog->Parameters->Parameters[progPos];
426
 
427
   if (nameOut) {
428
      _mesa_copy_string(nameOut, maxLength, length, param->Name);
429
   }
430
 
431
   if (size) {
432
      GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
433
      if ((GLint) param->Size > typeSize) {
434
         /* This is an array.
435
          * Array elements are placed on vector[4] boundaries so they're
436
          * a multiple of four floats.  We round typeSize up to next multiple
437
          * of four to get the right size below.
438
          */
439
         typeSize = (typeSize + 3) & ~3;
440
      }
441
      /* Note that the returned size is in units of the , not bytes */
442
      *size = param->Size / typeSize;
443
   }
444
 
445
   if (type) {
446
      *type = param->DataType;
447
   }
448
}
449
 
450
 
451
static unsigned
452
get_vector_elements(GLenum type)
453
{
454
   switch (type) {
455
   case GL_FLOAT:
456
   case GL_INT:
457
   case GL_BOOL:
458
   case GL_UNSIGNED_INT:
459
   default: /* Catch all the various sampler types. */
460
      return 1;
461
 
462
   case GL_FLOAT_VEC2:
463
   case GL_INT_VEC2:
464
   case GL_BOOL_VEC2:
465
   case GL_UNSIGNED_INT_VEC2:
466
      return 2;
467
 
468
   case GL_FLOAT_VEC3:
469
   case GL_INT_VEC3:
470
   case GL_BOOL_VEC3:
471
   case GL_UNSIGNED_INT_VEC3:
472
      return 3;
473
 
474
   case GL_FLOAT_VEC4:
475
   case GL_INT_VEC4:
476
   case GL_BOOL_VEC4:
477
   case GL_UNSIGNED_INT_VEC4:
478
      return 4;
479
   }
480
}
481
 
482
static void
483
get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
484
{
485
   switch (type) {
486
   case GL_FLOAT_MAT2:
487
      *rows = *cols = 2;
488
      break;
489
   case GL_FLOAT_MAT2x3:
490
      *rows = 3;
491
      *cols = 2;
492
      break;
493
   case GL_FLOAT_MAT2x4:
494
      *rows = 4;
495
      *cols = 2;
496
      break;
497
   case GL_FLOAT_MAT3:
498
      *rows = 3;
499
      *cols = 3;
500
      break;
501
   case GL_FLOAT_MAT3x2:
502
      *rows = 2;
503
      *cols = 3;
504
      break;
505
   case GL_FLOAT_MAT3x4:
506
      *rows = 4;
507
      *cols = 3;
508
      break;
509
   case GL_FLOAT_MAT4:
510
      *rows = 4;
511
      *cols = 4;
512
      break;
513
   case GL_FLOAT_MAT4x2:
514
      *rows = 2;
515
      *cols = 4;
516
      break;
517
   case GL_FLOAT_MAT4x3:
518
      *rows = 3;
519
      *cols = 4;
520
      break;
521
   default:
522
      *rows = *cols = 0;
523
   }
524
}
525
 
526
 
527
/**
528
 * Determine the number of rows and columns occupied by a uniform
529
 * according to its datatype.  For non-matrix types (such as GL_FLOAT_VEC4),
530
 * the number of rows = 1 and cols = number of elements in the vector.
531
 */
532
static void
533
get_uniform_rows_cols(const struct gl_program_parameter *p,
534
                      GLint *rows, GLint *cols)
535
{
536
   get_matrix_dims(p->DataType, rows, cols);
537
   if (*rows == 0 && *cols == 0) {
538
      /* not a matrix type, probably a float or vector */
539
      *rows = 1;
540
      *cols = get_vector_elements(p->DataType);
541
   }
542
}
543
 
544
 
545
/**
546
 * Helper for get_uniform[fi]v() functions.
547
 * Given a shader program name and uniform location, return a pointer
548
 * to the shader program and return the program parameter position.
549
 */
550
static void
551
lookup_uniform_parameter(struct gl_context *ctx, GLuint program, GLint location,
552
                         struct gl_program **progOut, GLint *paramPosOut)
553
{
554
   struct gl_shader_program *shProg
555
      = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
556
   struct gl_program *prog = NULL;
557
   GLint progPos = -1;
558
 
559
   /* if shProg is NULL, we'll have already recorded an error */
560
 
561
   if (shProg) {
562
      if (!shProg->Uniforms ||
563
          location < 0 ||
564
          location >= (GLint) shProg->Uniforms->NumUniforms) {
565
         _mesa_error(ctx, GL_INVALID_OPERATION,  "glGetUniformfv(location)");
566
      }
567
      else {
568
         /* OK, find the gl_program and program parameter location */
569
         progPos = shProg->Uniforms->Uniforms[location].VertPos;
570
         if (progPos >= 0) {
571
            prog = &shProg->VertexProgram->Base;
572
         }
573
         else {
574
            progPos = shProg->Uniforms->Uniforms[location].FragPos;
575
            if (progPos >= 0) {
576
               prog = &shProg->FragmentProgram->Base;
577
            } else {
578
               progPos = shProg->Uniforms->Uniforms[location].GeomPos;
579
               if (progPos >= 0) {
580
                  prog = &shProg->GeometryProgram->Base;
581
               }
582
            }
583
         }
584
      }
585
   }
586
 
587
   *progOut = prog;
588
   *paramPosOut = progPos;
589
}
590
 
591
 
592
/**
593
 * GLGL uniform arrays and structs require special handling.
594
 *
595
 * The GL_ARB_shader_objects spec says that if you use
596
 * glGetUniformLocation to get the location of an array, you CANNOT
597
 * access other elements of the array by adding an offset to the
598
 * returned location.  For example, you must call
599
 * glGetUniformLocation("foo[16]") if you want to set the 16th element
600
 * of the array with glUniform().
601
 *
602
 * HOWEVER, some other OpenGL drivers allow accessing array elements
603
 * by adding an offset to the returned array location.  And some apps
604
 * seem to depend on that behaviour.
605
 *
606
 * Mesa's gl_uniform_list doesn't directly support this since each
607
 * entry in the list describes one uniform variable, not one uniform
608
 * element.  We could insert dummy entries in the list for each array
609
 * element after [0] but that causes complications elsewhere.
610
 *
611
 * We solve this problem by encoding two values in the location that's
612
 * returned by glGetUniformLocation():
613
 *  a) index into gl_uniform_list::Uniforms[] for the uniform
614
 *  b) an array/field offset (0 for simple types)
615
 *
616
 * These two values are encoded in the high and low halves of a GLint.
617
 * By putting the uniform number in the high part and the offset in the
618
 * low part, we can support the unofficial ability to index into arrays
619
 * by adding offsets to the location value.
620
 */
621
static void
622
merge_location_offset(GLint *location, GLint offset)
623
{
624
   *location = (*location << 16) | offset;
625
}
626
 
627
 
628
/**
629
 * Separate the uniform location and parameter offset.  See above.
630
 */
631
static void
632
split_location_offset(GLint *location, GLint *offset)
633
{
634
   *offset = *location & 0xffff;
635
   *location = *location >> 16;
636
}
637
 
638
 
639
 
640
/**
641
 * Called via glGetUniformfv().
642
 */
643
static void
644
_mesa_get_uniformfv(struct gl_context *ctx, GLuint program, GLint location,
645
                    GLfloat *params)
646
{
647
   struct gl_program *prog;
648
   GLint paramPos;
649
   GLint offset;
650
 
651
   split_location_offset(&location, &offset);
652
 
653
   lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos);
654
 
655
   if (prog) {
656
      const struct gl_program_parameter *p =
657
         &prog->Parameters->Parameters[paramPos];
658
      GLint rows, cols, i, j, k;
659
 
660
      get_uniform_rows_cols(p, &rows, &cols);
661
 
662
      k = 0;
663
      for (i = 0; i < rows; i++) {
664
	 const int base = paramPos + offset + i;
665
 
666
         for (j = 0; j < cols; j++ ) {
667
            params[k++] = prog->Parameters->ParameterValues[base][j];
668
         }
669
      }
670
   }
671
}
672
 
673
 
674
/**
675
 * Called via glGetUniformiv().
676
 * \sa _mesa_get_uniformfv, only difference is a cast.
677
 */
678
static void
679
_mesa_get_uniformiv(struct gl_context *ctx, GLuint program, GLint location,
680
                    GLint *params)
681
{
682
   struct gl_program *prog;
683
   GLint paramPos;
684
   GLint offset;
685
 
686
   split_location_offset(&location, &offset);
687
 
688
   lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos);
689
 
690
   if (prog) {
691
      const struct gl_program_parameter *p =
692
         &prog->Parameters->Parameters[paramPos];
693
      GLint rows, cols, i, j, k;
694
 
695
      get_uniform_rows_cols(p, &rows, &cols);
696
 
697
      k = 0;
698
      for (i = 0; i < rows; i++) {
699
	 const int base = paramPos + offset + i;
700
 
701
         for (j = 0; j < cols; j++ ) {
702
            params[k++] = (GLint) prog->Parameters->ParameterValues[base][j];
703
         }
704
      }
705
   }
706
}
707
 
708
 
709
/**
710
 * Called via glGetUniformuiv().
711
 * New in GL_EXT_gpu_shader4, OpenGL 3.0
712
 * \sa _mesa_get_uniformfv, only difference is a cast.
713
 */
714
static void
715
_mesa_get_uniformuiv(struct gl_context *ctx, GLuint program, GLint location,
716
                     GLuint *params)
717
{
718
   struct gl_program *prog;
719
   GLint paramPos;
720
   GLint offset;
721
 
722
   split_location_offset(&location, &offset);
723
 
724
   lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos);
725
 
726
   if (prog) {
727
      const struct gl_program_parameter *p =
728
         &prog->Parameters->Parameters[paramPos];
729
      GLint rows, cols, i, j, k;
730
 
731
      get_uniform_rows_cols(p, &rows, &cols);
732
 
733
      k = 0;
734
      for (i = 0; i < rows; i++) {
735
	 const int base = paramPos + offset + i;
736
 
737
         for (j = 0; j < cols; j++ ) {
738
            params[k++] = (GLuint) prog->Parameters->ParameterValues[base][j];
739
         }
740
      }
741
   }
742
}
743
 
744
 
745
/**
746
 * Called via glGetUniformLocation().
747
 *
748
 * The return value will encode two values, the uniform location and an
749
 * offset (used for arrays, structs).
750
 */
751
GLint
752
_mesa_get_uniform_location(struct gl_context *ctx, struct gl_shader_program *shProg,
753
			   const GLchar *name)
754
{
755
   GLint offset = 0, location = -1;
756
 
757
   if (shProg->LinkStatus == GL_FALSE) {
758
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
759
      return -1;
760
   }
761
 
762
   /* XXX we should return -1 if the uniform was declared, but not
763
    * actually used.
764
    */
765
 
766
   /* XXX we need to be able to parse uniform names for structs and arrays
767
    * such as:
768
    *   mymatrix[1]
769
    *   mystruct.field1
770
    */
771
 
772
   {
773
      /* handle 1-dimension arrays here... */
774
      char *c = strchr(name, '[');
775
      if (c) {
776
         /* truncate name at [ */
777
         const GLint len = c - name;
778
         GLchar *newName = malloc(len + 1);
779
         if (!newName)
780
            return -1; /* out of mem */
781
         memcpy(newName, name, len);
782
         newName[len] = 0;
783
 
784
         location = _mesa_lookup_uniform(shProg->Uniforms, newName);
785
         if (location >= 0) {
786
            const GLint element = atoi(c + 1);
787
            if (element > 0) {
788
               /* get type of the uniform array element */
789
               struct gl_program_parameter *p;
790
               p = get_uniform_parameter(shProg, location);
791
               if (p) {
792
                  GLint rows, cols;
793
                  get_matrix_dims(p->DataType, &rows, &cols);
794
                  if (rows < 1)
795
                     rows = 1;
796
                  offset = element * rows;
797
               }
798
            }
799
         }
800
 
801
         free(newName);
802
      }
803
   }
804
 
805
   if (location < 0) {
806
      location = _mesa_lookup_uniform(shProg->Uniforms, name);
807
   }
808
 
809
   if (location >= 0) {
810
      merge_location_offset(&location, offset);
811
   }
812
 
813
   return location;
814
}
815
 
816
 
817
 
818
/**
819
 * Update the vertex/fragment program's TexturesUsed array.
820
 *
821
 * This needs to be called after glUniform(set sampler var) is called.
822
 * A call to glUniform(samplerVar, value) causes a sampler to point to a
823
 * particular texture unit.  We know the sampler's texture target
824
 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
825
 * set by glUniform() calls.
826
 *
827
 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
828
 * information to update the prog->TexturesUsed[] values.
829
 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
830
 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
831
 * We'll use that info for state validation before rendering.
832
 */
833
void
834
_mesa_update_shader_textures_used(struct gl_program *prog)
835
{
836
   GLuint s;
837
 
838
   memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
839
 
840
   for (s = 0; s < MAX_SAMPLERS; s++) {
841
      if (prog->SamplersUsed & (1 << s)) {
842
         GLuint unit = prog->SamplerUnits[s];
843
         GLuint tgt = prog->SamplerTargets[s];
844
         assert(unit < MAX_TEXTURE_IMAGE_UNITS);
845
         assert(tgt < NUM_TEXTURE_TARGETS);
846
         prog->TexturesUsed[unit] |= (1 << tgt);
847
      }
848
   }
849
}
850
 
851
 
852
/**
853
 * Check if the type given by userType is allowed to set a uniform of the
854
 * target type.  Generally, equivalence is required, but setting Boolean
855
 * uniforms can be done with glUniformiv or glUniformfv.
856
 */
857
static GLboolean
858
compatible_types(GLenum userType, GLenum targetType)
859
{
860
   if (userType == targetType)
861
      return GL_TRUE;
862
 
863
   if (targetType == GL_BOOL && (userType == GL_FLOAT ||
864
                                 userType == GL_UNSIGNED_INT ||
865
                                 userType == GL_INT))
866
      return GL_TRUE;
867
 
868
   if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
869
                                      userType == GL_UNSIGNED_INT_VEC2 ||
870
                                      userType == GL_INT_VEC2))
871
      return GL_TRUE;
872
 
873
   if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
874
                                      userType == GL_UNSIGNED_INT_VEC3 ||
875
                                      userType == GL_INT_VEC3))
876
      return GL_TRUE;
877
 
878
   if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
879
                                      userType == GL_UNSIGNED_INT_VEC4 ||
880
                                      userType == GL_INT_VEC4))
881
      return GL_TRUE;
882
 
883
   if (is_sampler_type(targetType) && userType == GL_INT)
884
      return GL_TRUE;
885
 
886
   return GL_FALSE;
887
}
888
 
889
 
890
/**
891
 * Set the value of a program's uniform variable.
892
 * \param program  the program whose uniform to update
893
 * \param index  the index of the program parameter for the uniform
894
 * \param offset  additional parameter slot offset (for arrays)
895
 * \param type  the incoming datatype of 'values'
896
 * \param count  the number of uniforms to set
897
 * \param elems  number of elements per uniform (1, 2, 3 or 4)
898
 * \param values  the new values, of datatype 'type'
899
 */
900
static void
901
set_program_uniform(struct gl_context *ctx, struct gl_program *program,
902
                    GLint index, GLint offset,
903
                    GLenum type, GLsizei count, GLint elems,
904
                    const void *values)
905
{
906
   const struct gl_program_parameter *param =
907
      &program->Parameters->Parameters[index];
908
 
909
   assert(offset >= 0);
910
   assert(elems >= 1);
911
   assert(elems <= 4);
912
 
913
   if (!compatible_types(type, param->DataType)) {
914
      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
915
      return;
916
   }
917
 
918
   if (index + offset > (GLint) program->Parameters->Size) {
919
      /* out of bounds! */
920
      return;
921
   }
922
 
923
   if (param->Type == PROGRAM_SAMPLER) {
924
      /* This controls which texture unit which is used by a sampler */
925
      GLboolean changed = GL_FALSE;
926
      GLint i;
927
 
928
      /* this should have been caught by the compatible_types() check */
929
      ASSERT(type == GL_INT);
930
 
931
      /* loop over number of samplers to change */
932
      for (i = 0; i < count; i++) {
933
         GLuint sampler =
934
            (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
935
         GLuint texUnit = ((GLuint *) values)[i];
936
 
937
         /* check that the sampler (tex unit index) is legal */
938
         if (texUnit >= ctx->Const.MaxTextureImageUnits) {
939
            _mesa_error(ctx, GL_INVALID_VALUE,
940
                        "glUniform1(invalid sampler/tex unit index for '%s')",
941
                        param->Name);
942
            return;
943
         }
944
 
945
         /* This maps a sampler to a texture unit: */
946
         if (sampler < MAX_SAMPLERS) {
947
#if 0
948
            printf("Set program %p sampler %d '%s' to unit %u\n",
949
		   program, sampler, param->Name, texUnit);
950
#endif
951
            if (program->SamplerUnits[sampler] != texUnit) {
952
               program->SamplerUnits[sampler] = texUnit;
953
               changed = GL_TRUE;
954
            }
955
         }
956
      }
957
 
958
      if (changed) {
959
         /* When a sampler's value changes it usually requires rewriting
960
          * a GPU program's TEX instructions since there may not be a
961
          * sampler->texture lookup table.  We signal this with the
962
          * ProgramStringNotify() callback.
963
          */
964
         FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
965
         _mesa_update_shader_textures_used(program);
966
         /* Do we need to care about the return value here?
967
          * This should not be the first time the driver was notified of
968
          * this program.
969
          */
970
         (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
971
      }
972
   }
973
   else {
974
      /* ordinary uniform variable */
975
      const GLboolean isUniformBool = is_boolean_type(param->DataType);
976
      const GLenum basicType = base_uniform_type(type);
977
      const GLint slots = (param->Size + 3) / 4;
978
      const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
979
      GLsizei k, i;
980
 
981
      if ((GLint) param->Size > typeSize) {
982
         /* an array */
983
         /* we'll ignore extra data below */
984
      }
985
      else {
986
         /* non-array: count must be at most one; count == 0 is handled by the loop below */
987
         if (count > 1) {
988
            _mesa_error(ctx, GL_INVALID_OPERATION,
989
                        "glUniform(uniform '%s' is not an array)",
990
                        param->Name);
991
            return;
992
         }
993
      }
994
 
995
      /* loop over number of array elements */
996
      for (k = 0; k < count; k++) {
997
         GLfloat *uniformVal;
998
 
999
         if (offset + k >= slots) {
1000
            /* Extra array data is ignored */
1001
            break;
1002
         }
1003
 
1004
         /* uniformVal (the destination) is always float[4] */
1005
         uniformVal = program->Parameters->ParameterValues[index + offset + k];
1006
 
1007
         if (basicType == GL_INT) {
1008
            /* convert user's ints to floats */
1009
            const GLint *iValues = ((const GLint *) values) + k * elems;
1010
            for (i = 0; i < elems; i++) {
1011
               uniformVal[i] = (GLfloat) iValues[i];
1012
            }
1013
         }
1014
         else if (basicType == GL_UNSIGNED_INT) {
1015
            /* convert user's uints to floats */
1016
            const GLuint *iValues = ((const GLuint *) values) + k * elems;
1017
            for (i = 0; i < elems; i++) {
1018
               uniformVal[i] = (GLfloat) iValues[i];
1019
            }
1020
         }
1021
         else {
1022
            const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1023
            assert(basicType == GL_FLOAT);
1024
            for (i = 0; i < elems; i++) {
1025
               uniformVal[i] = fValues[i];
1026
            }
1027
         }
1028
 
1029
         /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
1030
         if (isUniformBool) {
1031
            for (i = 0; i < elems; i++) {
1032
               uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
1033
            }
1034
         }
1035
      }
1036
   }
1037
}
1038
 
1039
 
1040
/**
1041
 * Called via glUniform*() functions.
1042
 */
1043
void
1044
_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
1045
	      GLint location, GLsizei count,
1046
              const GLvoid *values, GLenum type)
1047
{
1048
   struct gl_uniform *uniform;
1049
   GLint elems, offset;
1050
 
1051
   if (!shProg || !shProg->LinkStatus) {
1052
      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
1053
      return;
1054
   }
1055
 
1056
   if (location == -1)
1057
      return;   /* The standard specifies this as a no-op */
1058
 
1059
   if (location < -1) {
1060
      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)",
1061
                  location);
1062
      return;
1063
   }
1064
 
1065
   split_location_offset(&location, &offset);
1066
 
1067
   if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1068
      _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location);
1069
      return;
1070
   }
1071
 
1072
   if (count < 0) {
1073
      _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1074
      return;
1075
   }
1076
 
1077
   elems = _mesa_sizeof_glsl_type(type);
1078
 
1079
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1080
 
1081
   uniform = &shProg->Uniforms->Uniforms[location];
1082
 
1083
   if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1084
      const GLenum basicType = base_uniform_type(type);
1085
      GLint i;
1086
      printf("Mesa: set program %u uniform %s (loc %d) to: ",
1087
	     shProg->Name, uniform->Name, location);
1088
      if (basicType == GL_INT) {
1089
         const GLint *v = (const GLint *) values;
1090
         for (i = 0; i < count * elems; i++) {
1091
            printf("%d ", v[i]);
1092
         }
1093
      }
1094
      else if (basicType == GL_UNSIGNED_INT) {
1095
         const GLuint *v = (const GLuint *) values;
1096
         for (i = 0; i < count * elems; i++) {
1097
            printf("%u ", v[i]);
1098
         }
1099
      }
1100
      else {
1101
         const GLfloat *v = (const GLfloat *) values;
1102
         assert(basicType == GL_FLOAT);
1103
         for (i = 0; i < count * elems; i++) {
1104
            printf("%g ", v[i]);
1105
         }
1106
      }
1107
      printf("\n");
1108
   }
1109
 
1110
   /* A uniform var may be used by both a vertex shader and a fragment
1111
    * shader.  We may need to update one or both shader's uniform here:
1112
    */
1113
   if (shProg->VertexProgram) {
1114
      /* convert uniform location to program parameter index */
1115
      GLint index = uniform->VertPos;
1116
      if (index >= 0) {
1117
         set_program_uniform(ctx, &shProg->VertexProgram->Base,
1118
                             index, offset, type, count, elems, values);
1119
      }
1120
   }
1121
 
1122
   if (shProg->FragmentProgram) {
1123
      /* convert uniform location to program parameter index */
1124
      GLint index = uniform->FragPos;
1125
      if (index >= 0) {
1126
         set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1127
                             index, offset, type, count, elems, values);
1128
      }
1129
   }
1130
 
1131
   if (shProg->GeometryProgram) {
1132
      /* convert uniform location to program parameter index */
1133
      GLint index = uniform->GeomPos;
1134
      if (index >= 0) {
1135
         set_program_uniform(ctx, &shProg->GeometryProgram->Base,
1136
                             index, offset, type, count, elems, values);
1137
      }
1138
   }
1139
 
1140
   uniform->Initialized = GL_TRUE;
1141
}
1142
 
1143
 
1144
/**
1145
 * Set a matrix-valued program parameter.
1146
 */
1147
static void
1148
set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program,
1149
                           GLuint index, GLuint offset,
1150
                           GLuint count, GLuint rows, GLuint cols,
1151
                           GLboolean transpose, const GLfloat *values)
1152
{
1153
   GLuint mat, row, col;
1154
   GLuint src = 0;
1155
   const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
1156
   const GLuint slots = (param->Size + 3) / 4;
1157
   const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType);
1158
   GLint nr, nc;
1159
 
1160
   /* check that the number of rows, columns is correct */
1161
   get_matrix_dims(param->DataType, &nr, &nc);
1162
   if (rows != nr || cols != nc) {
1163
      _mesa_error(ctx, GL_INVALID_OPERATION,
1164
                  "glUniformMatrix(matrix size mismatch)");
1165
      return;
1166
   }
1167
 
1168
   if ((GLint) param->Size <= typeSize) {
1169
      /* non-array: count must be at most one; count == 0 is handled by the loop below */
1170
      if (count > 1) {
1171
         _mesa_error(ctx, GL_INVALID_OPERATION,
1172
                     "glUniformMatrix(uniform is not an array)");
1173
         return;
1174
      }
1175
   }
1176
 
1177
   /*
1178
    * Note: the _columns_ of a matrix are stored in program registers, not
1179
    * the rows.  So, the loops below look a little funny.
1180
    * XXX could optimize this a bit...
1181
    */
1182
 
1183
   /* loop over matrices */
1184
   for (mat = 0; mat < count; mat++) {
1185
 
1186
      /* each matrix: */
1187
      for (col = 0; col < cols; col++) {
1188
         GLfloat *v;
1189
         if (offset >= slots) {
1190
            /* Ignore writes beyond the end of (the used part of) an array */
1191
            return;
1192
         }
1193
         v = program->Parameters->ParameterValues[index + offset];
1194
         for (row = 0; row < rows; row++) {
1195
            if (transpose) {
1196
               v[row] = values[src + row * cols + col];
1197
            }
1198
            else {
1199
               v[row] = values[src + col * rows + row];
1200
            }
1201
         }
1202
 
1203
         offset++;
1204
      }
1205
 
1206
      src += rows * cols;  /* next matrix */
1207
   }
1208
}
1209
 
1210
 
1211
/**
1212
 * Called by glUniformMatrix*() functions.
1213
 * Note: cols=2, rows=4  ==>  array[2] of vec4
1214
 */
1215
void
1216
_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg,
1217
		     GLint cols, GLint rows,
1218
                     GLint location, GLsizei count,
1219
                     GLboolean transpose, const GLfloat *values)
1220
{
1221
   struct gl_uniform *uniform;
1222
   GLint offset;
1223
 
1224
   if (!shProg || !shProg->LinkStatus) {
1225
      _mesa_error(ctx, GL_INVALID_OPERATION,
1226
         "glUniformMatrix(program not linked)");
1227
      return;
1228
   }
1229
 
1230
   if (location == -1)
1231
      return;   /* The standard specifies this as a no-op */
1232
 
1233
   if (location < -1) {
1234
      _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1235
      return;
1236
   }
1237
 
1238
   split_location_offset(&location, &offset);
1239
 
1240
   if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1241
      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1242
      return;
1243
   }
1244
   if (values == NULL) {
1245
      _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
1246
      return;
1247
   }
1248
 
1249
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
1250
 
1251
   uniform = &shProg->Uniforms->Uniforms[location];
1252
 
1253
   if (shProg->VertexProgram) {
1254
      /* convert uniform location to program parameter index */
1255
      GLint index = uniform->VertPos;
1256
      if (index >= 0) {
1257
         set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1258
                                    index, offset,
1259
                                    count, rows, cols, transpose, values);
1260
      }
1261
   }
1262
 
1263
   if (shProg->FragmentProgram) {
1264
      /* convert uniform location to program parameter index */
1265
      GLint index = uniform->FragPos;
1266
      if (index >= 0) {
1267
         set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1268
                                    index, offset,
1269
                                    count, rows, cols, transpose, values);
1270
      }
1271
   }
1272
 
1273
   if (shProg->GeometryProgram) {
1274
      /* convert uniform location to program parameter index */
1275
      GLint index = uniform->GeomPos;
1276
      if (index >= 0) {
1277
         set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base,
1278
                                    index, offset,
1279
                                    count, rows, cols, transpose, values);
1280
      }
1281
   }
1282
 
1283
   uniform->Initialized = GL_TRUE;
1284
}
1285
 
1286
 
1287
void GLAPIENTRY
1288
_mesa_Uniform1fARB(GLint location, GLfloat v0)
1289
{
1290
   GET_CURRENT_CONTEXT(ctx);
1291
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
1292
}
1293
 
1294
void GLAPIENTRY
1295
_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
1296
{
1297
   GET_CURRENT_CONTEXT(ctx);
1298
   GLfloat v[2];
1299
   v[0] = v0;
1300
   v[1] = v1;
1301
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC2);
1302
}
1303
 
1304
void GLAPIENTRY
1305
_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
1306
{
1307
   GET_CURRENT_CONTEXT(ctx);
1308
   GLfloat v[3];
1309
   v[0] = v0;
1310
   v[1] = v1;
1311
   v[2] = v2;
1312
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC3);
1313
}
1314
 
1315
void GLAPIENTRY
1316
_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
1317
                   GLfloat v3)
1318
{
1319
   GET_CURRENT_CONTEXT(ctx);
1320
   GLfloat v[4];
1321
   v[0] = v0;
1322
   v[1] = v1;
1323
   v[2] = v2;
1324
   v[3] = v3;
1325
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_FLOAT_VEC4);
1326
}
1327
 
1328
void GLAPIENTRY
1329
_mesa_Uniform1iARB(GLint location, GLint v0)
1330
{
1331
   GET_CURRENT_CONTEXT(ctx);
1332
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
1333
}
1334
 
1335
void GLAPIENTRY
1336
_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
1337
{
1338
   GET_CURRENT_CONTEXT(ctx);
1339
   GLint v[2];
1340
   v[0] = v0;
1341
   v[1] = v1;
1342
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC2);
1343
}
1344
 
1345
void GLAPIENTRY
1346
_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
1347
{
1348
   GET_CURRENT_CONTEXT(ctx);
1349
   GLint v[3];
1350
   v[0] = v0;
1351
   v[1] = v1;
1352
   v[2] = v2;
1353
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC3);
1354
}
1355
 
1356
void GLAPIENTRY
1357
_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
1358
{
1359
   GET_CURRENT_CONTEXT(ctx);
1360
   GLint v[4];
1361
   v[0] = v0;
1362
   v[1] = v1;
1363
   v[2] = v2;
1364
   v[3] = v3;
1365
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_INT_VEC4);
1366
}
1367
 
1368
void GLAPIENTRY
1369
_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
1370
{
1371
   GET_CURRENT_CONTEXT(ctx);
1372
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
1373
}
1374
 
1375
void GLAPIENTRY
1376
_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
1377
{
1378
   GET_CURRENT_CONTEXT(ctx);
1379
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
1380
}
1381
 
1382
void GLAPIENTRY
1383
_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
1384
{
1385
   GET_CURRENT_CONTEXT(ctx);
1386
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
1387
}
1388
 
1389
void GLAPIENTRY
1390
_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
1391
{
1392
   GET_CURRENT_CONTEXT(ctx);
1393
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
1394
}
1395
 
1396
void GLAPIENTRY
1397
_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
1398
{
1399
   GET_CURRENT_CONTEXT(ctx);
1400
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
1401
}
1402
 
1403
void GLAPIENTRY
1404
_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
1405
{
1406
   GET_CURRENT_CONTEXT(ctx);
1407
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
1408
}
1409
 
1410
void GLAPIENTRY
1411
_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
1412
{
1413
   GET_CURRENT_CONTEXT(ctx);
1414
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
1415
}
1416
 
1417
void GLAPIENTRY
1418
_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
1419
{
1420
   GET_CURRENT_CONTEXT(ctx);
1421
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
1422
}
1423
 
1424
 
1425
/** OpenGL 3.0 GLuint-valued functions **/
1426
void GLAPIENTRY
1427
_mesa_Uniform1ui(GLint location, GLuint v0)
1428
{
1429
   GET_CURRENT_CONTEXT(ctx);
1430
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_UNSIGNED_INT);
1431
}
1432
 
1433
void GLAPIENTRY
1434
_mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
1435
{
1436
   GET_CURRENT_CONTEXT(ctx);
1437
   GLuint v[2];
1438
   v[0] = v0;
1439
   v[1] = v1;
1440
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
1441
}
1442
 
1443
void GLAPIENTRY
1444
_mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1445
{
1446
   GET_CURRENT_CONTEXT(ctx);
1447
   GLuint v[3];
1448
   v[0] = v0;
1449
   v[1] = v1;
1450
   v[2] = v2;
1451
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
1452
}
1453
 
1454
void GLAPIENTRY
1455
_mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1456
{
1457
   GET_CURRENT_CONTEXT(ctx);
1458
   GLuint v[4];
1459
   v[0] = v0;
1460
   v[1] = v1;
1461
   v[2] = v2;
1462
   v[3] = v3;
1463
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
1464
}
1465
 
1466
void GLAPIENTRY
1467
_mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
1468
{
1469
   GET_CURRENT_CONTEXT(ctx);
1470
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT);
1471
}
1472
 
1473
void GLAPIENTRY
1474
_mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
1475
{
1476
   GET_CURRENT_CONTEXT(ctx);
1477
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
1478
}
1479
 
1480
void GLAPIENTRY
1481
_mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
1482
{
1483
   GET_CURRENT_CONTEXT(ctx);
1484
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
1485
}
1486
 
1487
void GLAPIENTRY
1488
_mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
1489
{
1490
   GET_CURRENT_CONTEXT(ctx);
1491
   _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
1492
}
1493
 
1494
 
1495
 
1496
void GLAPIENTRY
1497
_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
1498
                          const GLfloat * value)
1499
{
1500
   GET_CURRENT_CONTEXT(ctx);
1501
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1502
			2, 2, location, count, transpose, value);
1503
}
1504
 
1505
void GLAPIENTRY
1506
_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
1507
                          const GLfloat * value)
1508
{
1509
   GET_CURRENT_CONTEXT(ctx);
1510
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1511
			3, 3, location, count, transpose, value);
1512
}
1513
 
1514
void GLAPIENTRY
1515
_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
1516
                          const GLfloat * value)
1517
{
1518
   GET_CURRENT_CONTEXT(ctx);
1519
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1520
			4, 4, location, count, transpose, value);
1521
}
1522
 
1523
 
1524
/**
1525
 * Non-square UniformMatrix are OpenGL 2.1
1526
 */
1527
void GLAPIENTRY
1528
_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
1529
                         const GLfloat *value)
1530
{
1531
   GET_CURRENT_CONTEXT(ctx);
1532
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1533
			2, 3, location, count, transpose, value);
1534
}
1535
 
1536
void GLAPIENTRY
1537
_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
1538
                         const GLfloat *value)
1539
{
1540
   GET_CURRENT_CONTEXT(ctx);
1541
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1542
			3, 2, location, count, transpose, value);
1543
}
1544
 
1545
void GLAPIENTRY
1546
_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
1547
                         const GLfloat *value)
1548
{
1549
   GET_CURRENT_CONTEXT(ctx);
1550
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1551
			2, 4, location, count, transpose, value);
1552
}
1553
 
1554
void GLAPIENTRY
1555
_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
1556
                         const GLfloat *value)
1557
{
1558
   GET_CURRENT_CONTEXT(ctx);
1559
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1560
			4, 2, location, count, transpose, value);
1561
}
1562
 
1563
void GLAPIENTRY
1564
_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
1565
                         const GLfloat *value)
1566
{
1567
   GET_CURRENT_CONTEXT(ctx);
1568
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1569
			3, 4, location, count, transpose, value);
1570
}
1571
 
1572
void GLAPIENTRY
1573
_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
1574
                         const GLfloat *value)
1575
{
1576
   GET_CURRENT_CONTEXT(ctx);
1577
   _mesa_uniform_matrix(ctx, ctx->Shader.ActiveProgram,
1578
			4, 3, location, count, transpose, value);
1579
}
1580
 
1581
 
1582
void GLAPIENTRY
1583
_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
1584
{
1585
   GET_CURRENT_CONTEXT(ctx);
1586
   _mesa_get_uniformfv(ctx, program, location, params);
1587
}
1588
 
1589
 
1590
void GLAPIENTRY
1591
_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
1592
{
1593
   GET_CURRENT_CONTEXT(ctx);
1594
   _mesa_get_uniformiv(ctx, program, location, params);
1595
}
1596
 
1597
 
1598
/* GL3 */
1599
void GLAPIENTRY
1600
_mesa_GetUniformuiv(GLhandleARB program, GLint location, GLuint *params)
1601
{
1602
   GET_CURRENT_CONTEXT(ctx);
1603
   _mesa_get_uniformuiv(ctx, program, location, params);
1604
}
1605
 
1606
 
1607
 
1608
GLint GLAPIENTRY
1609
_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
1610
{
1611
   struct gl_shader_program *shProg;
1612
 
1613
   GET_CURRENT_CONTEXT(ctx);
1614
 
1615
   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
1616
					    "glGetUniformLocation");
1617
   if (!shProg)
1618
      return -1;
1619
 
1620
   return _mesa_get_uniform_location(ctx, shProg, name);
1621
}
1622
 
1623
 
1624
void GLAPIENTRY
1625
_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
1626
                          GLsizei maxLength, GLsizei * length, GLint * size,
1627
                          GLenum * type, GLcharARB * name)
1628
{
1629
   GET_CURRENT_CONTEXT(ctx);
1630
   _mesa_get_active_uniform(ctx, program, index, maxLength, length, size,
1631
                            type, name);
1632
}
1633
 
1634
 
1635
/**
1636
 * Plug in shader uniform-related functions into API dispatch table.
1637
 */
1638
void
1639
_mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
1640
{
1641
#if FEATURE_GL
1642
   SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
1643
   SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
1644
   SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
1645
   SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
1646
   SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
1647
   SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
1648
   SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
1649
   SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
1650
   SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
1651
   SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
1652
   SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
1653
   SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
1654
   SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
1655
   SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
1656
   SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
1657
   SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
1658
   SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
1659
   SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
1660
   SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
1661
 
1662
   SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
1663
   SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
1664
   SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
1665
   SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
1666
 
1667
   /* OpenGL 2.1 */
1668
   SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
1669
   SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
1670
   SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
1671
   SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
1672
   SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
1673
   SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
1674
 
1675
   /* OpenGL 3.0 */
1676
   /* XXX finish dispatch */
1677
   SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
1678
   SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
1679
   SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
1680
   SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
1681
   SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
1682
   SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
1683
   SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
1684
   SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
1685
   SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
1686
 
1687
 
1688
#endif /* FEATURE_GL */
1689
}