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