shader.cpp revision 8e399777f3d6c0e02a31af9e231e7547d3fdbb7d
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "src/pixelflinger2/pixelflinger2.h"
17
18#include <assert.h>
19#include <stdio.h>
20#include <string.h>
21#include <map>
22
23#include <llvm/LLVMContext.h>
24#include <llvm/Module.h>
25#include <bcc/bcc.h>
26#include <dlfcn.h>
27
28
29#include "src/talloc/hieralloc.h"
30#include "src/mesa/main/shaderobj.h"
31#include "src/mesa/program/prog_parameter.h"
32#include "src/mesa/program/prog_uniform.h"
33#include "src/glsl/glsl_types.h"
34#include "src/glsl/ir_to_llvm.h"
35
36static void InitializeGLContext(struct gl_context *ctx)
37{
38   memset(ctx, 0, sizeof(*ctx));
39   ctx->API = API_OPENGLES2;
40   ctx->Extensions.ARB_draw_buffers = GL_TRUE;
41   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
42   ctx->Extensions.EXT_texture_array = GL_TRUE;
43   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
44
45   /* 1.10 minimums. */
46   ctx->Const.MaxLights = 8;
47   ctx->Const.MaxClipPlanes = 8;
48   ctx->Const.MaxTextureUnits = 2;
49
50   /* More than the 1.10 minimum to appease parser tests taken from
51    * apps that (hopefully) already checked the number of coords.
52    */
53   ctx->Const.MaxTextureCoordUnits = 4;
54
55   ctx->Const.VertexProgram.MaxAttribs = 16;
56   ctx->Const.VertexProgram.MaxUniformComponents = 512;
57   ctx->Const.MaxVarying = 8;
58   ctx->Const.MaxVertexTextureImageUnits = 0;
59   ctx->Const.MaxCombinedTextureImageUnits = 2;
60   ctx->Const.MaxTextureImageUnits = 2;
61   ctx->Const.FragmentProgram.MaxUniformComponents = 64;
62
63   ctx->Const.MaxDrawBuffers = 2;
64}
65
66void * llvmCtx = NULL;
67static const struct GLContext {
68   const gl_context * ctx;
69   GLContext() {
70      ctx = hieralloc_zero(NULL, gl_context);
71//      ctx = (const gl_context*)calloc(1,sizeof(gl_context));
72      InitializeGLContext(const_cast<gl_context *>(ctx));
73      llvmCtx = new llvm::LLVMContext();
74   }
75   ~GLContext() {
76      _mesa_glsl_release_types(); // TODO: find when to release to minize memory
77      _mesa_glsl_release_functions(); // the IR has pointers to types
78      hieralloc_free(const_cast<gl_context *>(ctx));
79//      free(const_cast<gl_context *>(ctx));
80      ctx = NULL;
81      delete (llvm::LLVMContext *)llvmCtx;
82   }
83} glContext;
84
85extern "C" void GLContextDctr()
86{
87   _mesa_glsl_release_types(); // TODO: find when to release to minize memory
88   _mesa_glsl_release_functions();
89   //glContext.~GLContext();
90}
91
92struct ShaderKey {
93   struct ScanLineKey {
94      GGLStencilState frontStencil, backStencil;
95      GGLBufferState bufferState;
96      GGLBlendState blendState;
97   } scanLineKey;
98   GGLPixelFormat textureFormats[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS];
99   unsigned char textureParameters[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; // wrap and filter
100   bool operator <(const ShaderKey & rhs) const {
101      return memcmp(this, &rhs, sizeof(*this)) < 0;
102   }
103};
104
105struct Instance {
106   llvm::Module * module;
107   struct BCCOpaqueScript * script;
108   void (* function)();
109   ~Instance() {
110      // TODO: check bccDisposeScript, which seems to dispose llvm::Module
111      if (script)
112         bccDisposeScript(script);
113      else if (module)
114         delete module;
115   }
116};
117
118struct Executable { // codegen info
119   std::map<ShaderKey, Instance *> instances;
120};
121
122bool do_mat_op_to_vec(exec_list *instructions);
123
124extern void link_shaders(const struct gl_context *ctx, struct gl_shader_program *prog);
125
126extern "C" void compile_shader(const struct gl_context *ctx, struct gl_shader *shader);
127
128gl_shader * GGLShaderCreate(GLenum type)
129{
130   return _mesa_new_shader(NULL, 0, type);
131}
132
133static gl_shader * ShaderCreate(const GGLInterface * iface, GLenum type)
134{
135   GGL_GET_CONST_CONTEXT(ctx, iface);
136   if (GL_VERTEX_SHADER != type && GL_FRAGMENT_SHADER != type) {
137      gglError(GL_INVALID_ENUM);
138      return NULL;
139   }
140   gl_shader * shader = _mesa_new_shader(NULL, 0, type);
141   if (!shader)
142      gglError(GL_OUT_OF_MEMORY);
143   assert(1 == shader->RefCount);
144   return shader;
145}
146
147void GGLShaderSource(gl_shader_t * shader, GLsizei count, const char ** string, const int * length)
148{
149   hieralloc_free(const_cast<GLchar *>(shader->Source));
150   for (unsigned i = 0; i < count; i++)
151   {
152      int len = strlen(string[i]);
153      if (length && length[i] >= 0)
154         len = length[i];
155      shader->Source = hieralloc_strndup_append(const_cast<GLchar *>(shader->Source), string[i], len);
156   }
157   printf("pf2: GGLShaderSource: \n '%s' \n", shader->Source);
158}
159
160GLboolean GGLShaderCompile(gl_shader * shader, const char * glsl, const char ** infoLog)
161{
162   if (glsl)
163      shader->Source = glsl;
164   assert(shader->Source);
165   compile_shader(glContext.ctx, shader);
166   shader->Source = NULL;
167   if (infoLog)
168      *infoLog = shader->InfoLog;
169   return shader->CompileStatus;
170}
171
172static GLboolean ShaderCompile(const GGLInterface * iface, gl_shader * shader,
173                               const char * glsl, const char ** infoLog)
174{
175   GGL_GET_CONST_CONTEXT(ctx, iface);
176   if (!glsl && !shader->Source) {
177      gglError(GL_INVALID_VALUE);
178      assert(0);
179      return GL_FALSE;
180   }
181   return GGLShaderCompile(shader, glsl, infoLog);
182}
183
184void GGLShaderDelete(gl_shader * shader)
185{
186   if (shader && shader->executable) {
187      for (std::map<ShaderKey, Instance *>::iterator it=shader->executable->instances.begin();
188            it != shader->executable->instances.end(); it++)
189         (*it).second->~Instance();
190      shader->executable->instances.~map();
191   }
192   _mesa_delete_shader(NULL, shader);
193}
194
195static void ShaderDelete(const GGLInterface * iface, gl_shader * shader)
196{
197   GGLShaderDelete(shader);
198}
199
200gl_shader_program * GGLShaderProgramCreate()
201{
202   gl_shader_program * program = hieralloc_zero(NULL, struct gl_shader_program);
203   if (!program)
204      return NULL;
205   program->Attributes = hieralloc_zero(program, gl_program_parameter_list);
206   if (!program->Attributes) {
207      hieralloc_free(program);
208      return NULL;
209   }
210   program->Varying = hieralloc_zero(program, gl_program_parameter_list);
211   if (!program->Varying) {
212      hieralloc_free(program);
213      return NULL;
214   }
215   return program;
216}
217
218static gl_shader_program * ShaderProgramCreate(const GGLInterface * iface)
219{
220   GGL_GET_CONST_CONTEXT(ctx, iface);
221   gl_shader_program * program = GGLShaderProgramCreate();
222   if (!program)
223      gglError(GL_OUT_OF_MEMORY);
224   return program;
225}
226
227unsigned GGLShaderAttach(gl_shader_program * program, gl_shader * shader)
228{
229   for (unsigned i = 0; i < program->NumShaders; i++)
230      if (program->Shaders[i]->Type == shader->Type || program->Shaders[i] == shader)
231         return GL_INVALID_OPERATION;
232
233   program->Shaders = (gl_shader **)hieralloc_realloc
234                      (program, program->Shaders, gl_shader *, program->NumShaders + 1);
235   if (!program->Shaders) {
236      assert(0);
237      return GL_OUT_OF_MEMORY;
238   }
239   program->Shaders[program->NumShaders] = shader;
240   program->NumShaders++;
241   shader->RefCount++;
242   return GL_NO_ERROR;
243}
244
245static void ShaderAttach(const GGLInterface * iface, gl_shader_program * program,
246                         gl_shader * shader)
247{
248   unsigned error = GGLShaderAttach(program, shader);
249   if (GL_NO_ERROR != error)
250      gglError(error);
251}
252
253GLboolean GGLShaderProgramLink(gl_shader_program * program, const char ** infoLog)
254{
255   link_shaders(glContext.ctx, program);
256   if (infoLog)
257      *infoLog = program->InfoLog;
258   if (!program->LinkStatus)
259      return program->LinkStatus;
260   printf("slots: attribute=%d varying=%d uniforms=%d \n", program->AttributeSlots, program->VaryingSlots, program->Uniforms->Slots);
261   for (unsigned i = 0; i < program->Attributes->NumParameters; i++) {
262      const gl_program_parameter & attribute = program->Attributes->Parameters[i];
263      printf("attribute '%s': location=%d slots=%d \n", attribute.Name, attribute.Location, attribute.Slots);
264   }
265   for (unsigned i = 0; i < program->Varying->NumParameters; i++) {
266      const gl_program_parameter & varying = program->Varying->Parameters[i];
267      printf("varying '%s': vs_location=%d fs_location=%d \n", varying.Name, varying.BindLocation, varying.Location);
268   }
269   for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++) {
270      const gl_uniform & uniform = program->Uniforms->Uniforms[i];
271      printf("uniform '%s': location=%d type=%s \n", uniform.Name, uniform.Pos, uniform.Type->name);
272   }
273   return program->LinkStatus;
274}
275
276static GLboolean ShaderProgramLink(gl_shader_program * program, const char ** infoLog)
277{
278   return GGLShaderProgramLink(program, infoLog);
279}
280
281static void GetShaderKey(const GGLState * ctx, const gl_shader * shader, ShaderKey * key)
282{
283   memset(key, 0, sizeof(*key));
284   if (GL_FRAGMENT_SHADER == shader->Type) {
285      key->scanLineKey.frontStencil = ctx->frontStencil;
286      key->scanLineKey.backStencil = ctx->backStencil;
287      key->scanLineKey.bufferState = ctx->bufferState;
288      key->scanLineKey.blendState = ctx->blendState;
289   }
290
291   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
292      if (shader->SamplersUsed & (1 << i)) {
293         const GGLTexture & texture = ctx->textureState.textures[i];
294         key->textureFormats[i] = texture.format;
295         assert((1 << 2) > texture.wrapS);
296         key->textureParameters[i] |= texture.wrapS;
297         assert((1 << 2) > texture.wrapT);
298         key->textureParameters[i] |= texture.wrapT << 2;
299         assert((1 << 3) > texture.minFilter);
300         key->textureParameters[i] |= texture.minFilter << (2 + 2);
301         assert((1 << 1) > texture.magFilter);
302         key->textureParameters[i] |= texture.magFilter << (2 + 2 + 3);
303      }
304}
305
306static inline char HexDigit(unsigned char d)
307{
308   return (d > 9 ? d + 'A' - 10 : d + '0');
309}
310
311static const unsigned SHADER_KEY_STRING_LEN = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS * 4 + 2;
312
313static void GetShaderKeyString(const GLenum type, const ShaderKey * key,
314                               char * buffer, const unsigned bufferSize)
315{
316   assert(1 == sizeof(char));
317   assert(0xff >= GGL_PIXEL_FORMAT_COUNT);
318   assert(SHADER_KEY_STRING_LEN <= bufferSize);
319   char * str = buffer;
320   if (GL_VERTEX_SHADER == type)
321      *str++ = 'v';
322   else if (GL_FRAGMENT_SHADER == type)
323      *str++ = 'f';
324   else
325      assert(0);
326   for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) {
327      *str++ = HexDigit(key->textureFormats[i] / 16);
328      *str++ = HexDigit(key->textureFormats[i] % 16);
329      *str++ = HexDigit(key->textureParameters[i] / 16);
330      *str++ = HexDigit(key->textureParameters[i] % 16);
331   }
332   *str++ = '\0';
333}
334
335static const unsigned SCANLINE_KEY_STRING_LEN = 2 * sizeof(ShaderKey::scanLineKey) + 3 + SHADER_KEY_STRING_LEN;
336
337static char * GetScanlineKeyString(const ShaderKey * key, char * buffer,
338                                   const unsigned bufferSize)
339{
340   assert(1 == sizeof(char));
341   assert(0xff >= GGL_PIXEL_FORMAT_COUNT);
342   assert(SCANLINE_KEY_STRING_LEN <= bufferSize);
343   char * str = buffer;
344   *str++ = 's';
345   const unsigned char * start = (const unsigned char *)&key->scanLineKey;
346   const unsigned char * const end = start + sizeof(key->scanLineKey);
347   for (; start < end; start++) {
348      *str++ = HexDigit(*start / 16);
349      *str++ = HexDigit(*start % 16);
350   }
351   GetShaderKeyString(GL_FRAGMENT_SHADER, key, str, bufferSize - (str - buffer));
352   return buffer;
353}
354
355struct SymbolLookupContext {
356   const GGLState * gglCtx;
357   const gl_shader_program * program;
358   const gl_shader * shader;
359};
360
361static void* SymbolLookup(void* pContext, const char* name)
362{
363   SymbolLookupContext * ctx = (SymbolLookupContext *)pContext;
364//   const gl_shader * shader = ctx->shader;
365//   const gl_shader_program * program = ctx->program;
366   const GGLState * gglCtx = ctx->gglCtx;
367   const void * symbol = (void*)dlsym(RTLD_DEFAULT, name);
368   if (NULL == symbol) {
369      if (!strcmp(_PF2_TEXTURE_DATA_NAME_, name))
370         symbol = (void *)gglCtx->textureState.textureData;
371      else if (!strcmp(_PF2_TEXTURE_DIMENSIONS_NAME_, name))
372         symbol = (void *)gglCtx->textureState.textureDimensions;
373      else // attributes, varyings and uniforms are mapped to locations in pointers
374         assert(0);
375   }
376   printf("symbolLookup '%s'=%p \n", name, symbol);
377   assert(symbol);
378   return (void *)symbol;
379}
380
381static void CodeGen(Instance * instance, const char * mainName, gl_shader * shader,
382                    gl_shader_program * program, const GGLState * gglCtx)
383{
384   SymbolLookupContext ctx = {gglCtx, program, shader};
385   int result = 0;
386
387   BCCScriptRef & script = instance->script;
388   script = bccCreateScript();
389   result = bccReadModule(script, "glsl", (LLVMModuleRef)instance->module, 0);
390   assert(0 == result);
391   result = bccRegisterSymbolCallback(script, SymbolLookup, &ctx);
392   assert(0 == result);
393   result = bccPrepareExecutable(script, NULL, 0);
394
395   result = bccGetError(script);
396   if (result != 0) {
397      puts("failed bcc_compile");
398      assert(0);
399      return;
400   }
401
402   instance->function = (void (*)())bccGetFuncAddr(script, mainName);
403   assert(instance->function);
404   result = bccGetError(script);
405   if (result != BCC_NO_ERROR)
406      fprintf(stderr, "Could not find '%s': %d\n", "main", result);
407   else
408      printf("bcc_compile %s=%p \n", mainName, instance->function);
409}
410
411void GenerateScanLine(const GGLState * gglCtx, const gl_shader_program * program, llvm::Module * mod,
412                      const char * shaderName, const char * scanlineName);
413
414void GGLShaderUse(void * llvmCtx, const GGLState * gglState, gl_shader_program * program)
415{
416   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
417      if (!program->_LinkedShaders[i])
418         continue;
419      gl_shader * shader = program->_LinkedShaders[i];
420      shader->function = NULL;
421      if (!shader->executable) {
422         shader->executable = hieralloc_zero(shader, Executable);
423         shader->executable->instances = std::map<ShaderKey, Instance *>();
424      }
425
426      ShaderKey shaderKey;
427      GetShaderKey(gglState, shader, &shaderKey);
428      Instance * instance = shader->executable->instances[shaderKey];
429      if (!instance) {
430         puts("begin jit new shader");
431         instance = hieralloc_zero(shader->executable, Instance);
432         instance->module = new llvm::Module("glsl", *(llvm::LLVMContext *)llvmCtx);
433
434         char shaderName [SHADER_KEY_STRING_LEN] = {0};
435         GetShaderKeyString(shader->Type, &shaderKey, shaderName, sizeof shaderName / sizeof *shaderName);
436
437         char mainName [SHADER_KEY_STRING_LEN + 6] = {"main"};
438         strcat(mainName, shaderName);
439
440         do_mat_op_to_vec(shader->ir); // TODO: move these passes to link?
441
442         llvm::Module * module = glsl_ir_to_llvm_module(shader->ir, instance->module, gglState, shaderName);
443         if (!module)
444            assert(0);
445#if USE_LLVM_SCANLINE
446         if (GL_FRAGMENT_SHADER == shader->Type) {
447            char scanlineName [SCANLINE_KEY_STRING_LEN] = {0};
448            GetScanlineKeyString(&shaderKey, scanlineName, sizeof scanlineName / sizeof *scanlineName);
449            GenerateScanLine(gglState, program, module, mainName, scanlineName);
450            CodeGen(instance, scanlineName, shader, program, gglState);
451         } else
452#endif
453            CodeGen(instance, mainName, shader, program, gglState);
454         shader->executable->instances[shaderKey] = instance;
455         debug_printf("jit new shader '%s'(%p) \n", mainName, instance->function);
456      } else
457//         debug_printf("use cached shader %p \n", instance->function);
458         ;
459
460      shader->function  = instance->function;
461   }
462   puts("pf2: GGLShaderUse end");
463}
464
465static void ShaderUse(GGLInterface * iface, gl_shader_program * program)
466{
467   GGL_GET_CONTEXT(ctx, iface);
468   // so drawing calls will do nothing until ShaderUse with a program
469   SetShaderVerifyFunctions(iface);
470   if (!program) {
471      ctx->CurrentProgram = NULL;
472      return;
473   }
474
475   GGLShaderUse(ctx->llvmCtx, &ctx->state, program);
476   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
477      if (!program->_LinkedShaders[i])
478         continue;
479      if (!program->_LinkedShaders[i]->function)
480         continue;
481      if (GL_VERTEX_SHADER == program->_LinkedShaders[i]->Type)
482         ctx->PickRaster(iface);
483      else if (GL_FRAGMENT_SHADER == program->_LinkedShaders[i]->Type)
484         ctx->PickScanLine(iface);
485      else
486         assert(0);
487   }
488   ctx->CurrentProgram = program;
489}
490
491unsigned GGLShaderDetach(gl_shader_program * program, gl_shader * shader)
492{
493   for (unsigned i = 0; i < program->NumShaders; i++)
494      if (program->Shaders[i] == shader) {
495         program->NumShaders--;
496         // just swap end to deleted shader
497         program->Shaders[i] = program->Shaders[program->NumShaders];
498         shader->RefCount--;
499         if (1 == shader->RefCount && shader->DeletePending)
500            GGLShaderDelete(shader);
501         return GL_NO_ERROR;
502      }
503   return (GL_INVALID_OPERATION);
504}
505
506static void ShaderDetach(const GGLInterface * iface, gl_shader_program * program,
507                         gl_shader * shader)
508{
509   unsigned error = GGLShaderDetach(program, shader);
510   if (GL_NO_ERROR != error)
511      gglError(error);
512}
513
514void GGLShaderProgramDelete(gl_shader_program * program)
515{
516   for (unsigned i = 0; i < program->NumShaders; i++) {
517      GGLShaderDelete(program->Shaders[i]); // actually just mark for delete
518      GGLShaderDetach(program, program->Shaders[i]); // detach will delete if ref == 1
519      i--; // GGLShaderDetach just swaps end to detached shader
520   }
521
522   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
523      GGLShaderDelete(program->_LinkedShaders[i]);
524
525   hieralloc_free(program);
526}
527
528static void ShaderProgramDelete(GGLInterface * iface, gl_shader_program * program)
529{
530   GGL_GET_CONTEXT(ctx, iface);
531   if (ctx->CurrentProgram == program) {
532      ctx->CurrentProgram = NULL;
533      SetShaderVerifyFunctions(iface);
534   }
535   GGLShaderProgramDelete(program);
536}
537
538void GGLShaderGetiv(gl_shader_t * shader, const GLenum pname, GLint * params)
539{
540   switch (pname) {
541   case GL_SHADER_TYPE:
542      *params = shader->Type;
543      break;
544   case GL_DELETE_STATUS:
545      *params = shader->DeletePending;
546      break;
547   case GL_COMPILE_STATUS:
548      *params = shader->CompileStatus;
549      break;
550   case GL_INFO_LOG_LENGTH:
551      *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
552      break;
553   case GL_SHADER_SOURCE_LENGTH:
554      *params = shader->Source ? strlen(shader->Source) + 1 : 0;
555      break;
556   default:
557      assert(0);
558      break;
559   }
560}
561
562void GGLShaderProgramGetiv(gl_shader_program_t * program, const GLenum pname, GLint * params)
563{
564   switch (pname) {
565   case GL_DELETE_STATUS:
566      *params = program->DeletePending;
567      break;
568   case GL_LINK_STATUS:
569      *params = program->LinkStatus;
570      break;
571   case GL_VALIDATE_STATUS:
572      *params = program->LinkStatus;
573      break;
574   case GL_INFO_LOG_LENGTH:
575      *params = program->InfoLog ? strlen(program->InfoLog) + 1 : 0;
576      break;
577   case GL_ATTACHED_SHADERS:
578      *params = program->NumShaders;
579      break;
580   case GL_ACTIVE_ATTRIBUTES:
581      *params = program->AttributeSlots;
582      break;
583   case GL_ACTIVE_UNIFORMS:
584      *params = program->Uniforms->Slots;
585      break;
586   case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
587   case GL_ACTIVE_UNIFORM_MAX_LENGTH:
588      printf("pf2:GGLShaderProgramGetiv not implemented: %d \n", pname);
589   default:
590      assert(0);
591      break;
592   }
593}
594
595void GGLShaderAttributeBind(const gl_shader_program * program, GLuint index, const GLchar * name)
596{
597   int i = _mesa_add_parameter(program->Attributes, name);
598   program->Attributes->Parameters[i].BindLocation = index;
599}
600
601GLint GGLShaderAttributeLocation(const gl_shader_program * program, const char * name)
602{
603   int i = _mesa_get_parameter(program->Attributes, name);
604   if (i >= 0)
605      return program->Attributes->Parameters[i].Location;
606   return -1;
607}
608
609GLint GGLShaderVaryingLocation(const gl_shader_program_t * program,
610                               const char * name, GLint * vertexOutputLocation)
611{
612   for (unsigned int i = 0; i < program->Varying->NumParameters; i++)
613      if (!strcmp(program->Varying->Parameters[i].Name, name)) {
614         if (vertexOutputLocation)
615            *vertexOutputLocation = program->Varying->Parameters[i].BindLocation;
616         return program->Varying->Parameters[i].Location;
617      }
618   return -1;
619}
620
621GLint GGLShaderUniformLocation(const gl_shader_program * program,
622                               const char * name)
623{
624   for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++)
625      if (!strcmp(program->Uniforms->Uniforms[i].Name, name))
626         return i;
627   return -1;
628}
629
630void GGLShaderUniformGetfv(gl_shader_program * program, GLint location, GLfloat * params)
631{
632   assert(0 <= location && program->Uniforms->NumUniforms > location);
633   int index = program->Uniforms->Uniforms[location].Pos;
634   assert(0 <= index && program->Uniforms->Slots > index);
635   memcpy(params, program->ValuesUniform + index, sizeof(*program->ValuesUniform));
636}
637
638void GGLShaderUniformGetiv(gl_shader_program * program, GLint location, GLint * params)
639{
640   assert(0 <= location && program->Uniforms->NumUniforms > location);
641   int index = program->Uniforms->Uniforms[location].Pos;
642   assert(0 <= index && program->Uniforms->Slots > index);
643   const float * uniform = program->ValuesUniform[index];
644   params[0] = uniform[0];
645   params[1] = uniform[1];
646   params[2] = uniform[2];
647   params[3] = uniform[3];
648}
649
650void GGLShaderUniformGetSamplers(const gl_shader_program_t * program,
651      int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS])
652{
653   memset(sampler2tmu, 0xff, sizeof sampler2tmu);
654   for (unsigned i = 0; i < program->Uniforms->NumUniforms; i++)
655   {
656      const gl_uniform & uniform = program->Uniforms->Uniforms[i];
657      if (uniform.Type->is_sampler())
658         sampler2tmu[uniform.Pos] = program->ValuesUniform[i][0];
659      else if (uniform.Type->is_array() && uniform.Type->fields.array->is_sampler())
660         assert(0);
661   }
662}
663
664GLint GGLShaderUniform(gl_shader_program * program, GLint location, GLsizei count,
665                       const GLvoid *values, GLenum type)
666{
667   // TODO: sampler uniform and type checking
668   if (!program) {
669      //gglError(GL_INVALID_OPERATION);
670      return -2;
671   }
672   assert(0 <= location && program->Uniforms->NumUniforms > location);
673   const gl_uniform & unifrom = program->Uniforms->Uniforms[location];
674   int start = unifrom.Pos;
675   int slots = 0, elems = 0;
676   switch (type) {
677   case GL_INT:
678   case GL_FLOAT:
679   case  GL_BOOL:
680      slots = count;
681      elems = 1;
682      break;
683   case GL_FLOAT_VEC2: // fall through
684   case  GL_INT_VEC2: // fall through
685   case  GL_BOOL_VEC2:
686      slots = count;
687      elems = 2;
688      break;
689   case  GL_INT_VEC3: // fall through
690   case  GL_BOOL_VEC3: // fall through
691   case  GL_FLOAT_VEC3: // fall through
692      slots = count;
693      elems = 3;
694      break;
695   case  GL_INT_VEC4: // fall through
696   case  GL_FLOAT_VEC4: // fall through
697   case  GL_BOOL_VEC4: // fall through
698      slots = count;
699      elems = 4;
700      break;
701   default:
702      assert(0);
703   }
704   if (0 < start)
705      return -2;
706   if (start + slots > program->Uniforms->Slots)
707      return -2;
708   for (int i = 0; i < slots; i++)
709      memcpy(program->ValuesUniform + start + i, values, elems * sizeof(float));
710   if (unifrom.Type->is_sampler())
711      return program->ValuesUniform[start][0];
712   else if (unifrom.Type->is_array() && unifrom.Type->fields.array->is_sampler())
713      assert(0);
714   return -2;
715}
716
717void GGLShaderUniformMatrix(gl_shader_program * program, GLint cols, GLint rows,
718                            GLint location, GLsizei count, GLboolean transpose, const GLfloat *values)
719{
720   if (location == -1)
721      return;
722   assert(cols == rows);
723   assert(0 <= location && program->Uniforms->NumUniforms > location);
724   int start = program->Uniforms->Uniforms[location].Pos;
725   unsigned slots = cols * count;
726   if (start < 0 || start + slots > program->Uniforms->Slots)
727      return gglError(GL_INVALID_OPERATION);
728   for (unsigned i = 0; i < slots; i++) {
729      float * column = program->ValuesUniform[start + i];
730      for (unsigned j = 0; j < rows; j++)
731         column[j] = *(values++);
732   }
733}
734
735static void ShaderVerifyProcessVertex(const GGLInterface * iface, const VertexInput * input,
736                                      VertexOutput * output)
737{
738   GGL_GET_CONST_CONTEXT(ctx, iface);
739   if (ctx->CurrentProgram) {
740      ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram);
741      if (ShaderVerifyProcessVertex != iface->ProcessVertex)
742         iface->ProcessVertex(iface, input, output);
743   }
744}
745
746static void ShaderVerifyDrawTriangle(const GGLInterface * iface, const VertexInput * v0,
747                                     const VertexInput * v1, const VertexInput * v2)
748{
749   GGL_GET_CONST_CONTEXT(ctx, iface);
750   if (ctx->CurrentProgram) {
751      ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram);
752      if (ShaderVerifyDrawTriangle != iface->DrawTriangle)
753         iface->DrawTriangle(iface, v0, v1, v2);
754   }
755}
756
757static void ShaderVerifyRasterTriangle(const GGLInterface * iface, const VertexOutput * v1,
758                                       const VertexOutput * v2, const VertexOutput * v3)
759{
760   GGL_GET_CONST_CONTEXT(ctx, iface);
761   if (ctx->CurrentProgram) {
762      ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram);
763      if (ShaderVerifyRasterTriangle != iface->RasterTriangle)
764         iface->RasterTriangle(iface, v1, v2, v3);
765   }
766}
767
768static void ShaderVerifyRasterTrapezoid(const GGLInterface * iface, const VertexOutput * tl,
769                                        const VertexOutput * tr, const VertexOutput * bl,
770                                        const VertexOutput * br)
771{
772   GGL_GET_CONST_CONTEXT(ctx, iface);
773   if (ctx->CurrentProgram) {
774      ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram);
775      if (ShaderVerifyRasterTrapezoid != iface->RasterTrapezoid)
776         iface->RasterTrapezoid(iface, tl, tr, bl, br);
777   }
778}
779
780static void ShaderVerifyScanLine(const GGLInterface * iface, const VertexOutput * v1,
781                                 const VertexOutput * v2)
782{
783   GGL_GET_CONST_CONTEXT(ctx, iface);
784   if (ctx->CurrentProgram) {
785      ShaderUse(const_cast<GGLInterface *>(iface), ctx->CurrentProgram);
786      if (ShaderVerifyScanLine != iface->ScanLine)
787         iface->ScanLine(iface, v1, v2);
788   }
789}
790
791// called after state changes so that drawing calls will trigger JIT
792void SetShaderVerifyFunctions(struct GGLInterface * iface)
793{
794   iface->ProcessVertex = ShaderVerifyProcessVertex;
795   iface->DrawTriangle = ShaderVerifyDrawTriangle;
796   iface->RasterTriangle = ShaderVerifyRasterTriangle;
797   iface->RasterTrapezoid = ShaderVerifyRasterTrapezoid;
798   iface->ScanLine = ShaderVerifyScanLine;
799}
800
801void InitializeShaderFunctions(struct GGLInterface * iface)
802{
803   GGL_GET_CONTEXT(ctx, iface);
804   ctx->llvmCtx = new llvm::LLVMContext();
805
806   iface->ShaderCreate = ShaderCreate;
807   iface->ShaderSource = GGLShaderSource;
808   iface->ShaderCompile = ShaderCompile;
809   iface->ShaderDelete = ShaderDelete;
810   iface->ShaderProgramCreate = ShaderProgramCreate;
811   iface->ShaderAttach = ShaderAttach;
812   iface->ShaderDetach = ShaderDetach;
813   iface->ShaderProgramLink = ShaderProgramLink;
814   iface->ShaderUse = ShaderUse;
815   iface->ShaderProgramDelete = ShaderProgramDelete;
816   iface->ShaderGetiv = GGLShaderGetiv;
817   iface->ShaderProgramGetiv = GGLShaderProgramGetiv;
818   iface->ShaderAttributeBind = GGLShaderAttributeBind;
819   iface->ShaderAttributeLocation = GGLShaderAttributeLocation;
820   iface->ShaderVaryingLocation = GGLShaderVaryingLocation;
821   iface->ShaderUniformLocation = GGLShaderUniformLocation;
822   iface->ShaderUniformGetfv = GGLShaderUniformGetfv;
823   iface->ShaderUniformGetiv = GGLShaderUniformGetiv;
824   iface->ShaderUniformGetSamplers = GGLShaderUniformGetSamplers;
825   iface->ShaderUniform = GGLShaderUniform;
826   iface->ShaderUniformMatrix = GGLShaderUniformMatrix;
827}
828
829void DestroyShaderFunctions(GGLInterface * iface)
830{
831   GGL_GET_CONTEXT(ctx, iface);
832   _mesa_glsl_release_types();
833   _mesa_glsl_release_functions();
834   delete ctx->llvmCtx;
835   ctx->llvmCtx = NULL;
836}
837