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