Home | History | Annotate | Download | only in pixelflinger2
      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 
     49 static 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 
     79 void * llvmCtx = NULL;
     80 static 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 
     98 extern "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 
    105 struct 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 
    118 struct 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 
    129 struct Executable { // codegen info
    130    std::map<ShaderKey, Instance *> instances;
    131 };
    132 
    133 bool do_mat_op_to_vec(exec_list *instructions);
    134 
    135 extern void link_shaders(const struct gl_context *ctx, struct gl_shader_program *prog);
    136 
    137 extern "C" void compile_shader(const struct gl_context *ctx, struct gl_shader *shader);
    138 
    139 gl_shader * GGLShaderCreate(GLenum type)
    140 {
    141    return _mesa_new_shader(NULL, 0, type);
    142 }
    143 
    144 static 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 
    158 void 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 
    170 GLboolean 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 
    183 static 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 
    195 void 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 
    206 static void ShaderDelete(const GGLInterface * iface, gl_shader * shader)
    207 {
    208    GGLShaderDelete(shader);
    209 }
    210 
    211 gl_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 
    229 static 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 
    238 unsigned 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 
    256 static 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 
    264 GLboolean 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 
    287 static GLboolean ShaderProgramLink(gl_shader_program * program, const char ** infoLog)
    288 {
    289    return GGLShaderProgramLink(program, infoLog);
    290 }
    291 
    292 static 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 
    317 static inline char HexDigit(unsigned char d)
    318 {
    319    return (d > 9 ? d + 'A' - 10 : d + '0');
    320 }
    321 
    322 static const unsigned SHADER_KEY_STRING_LEN = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS * 4 + 2;
    323 
    324 static 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 
    346 static const unsigned SCANLINE_KEY_STRING_LEN = 2 * sizeof(ShaderKey::ScanLineKey) + 3 + SHADER_KEY_STRING_LEN;
    347 
    348 static 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 
    366 struct SymbolLookupContext {
    367    const GGLState * gglCtx;
    368    const gl_shader_program * program;
    369    const gl_shader * shader;
    370 };
    371 
    372 static 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 
    393 static 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 
    441 void GenerateScanLine(const GGLState * gglCtx, const gl_shader_program * program, llvm::Module * mod,
    442                       const char * shaderName, const char * scanlineName);
    443 
    444 void 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 
    574 static 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 
    600 unsigned 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 
    615 static 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 
    623 void 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 
    637 static 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 
    647 void 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 
    671 void 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 
    685 void 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 
    718 void 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 
    732 void 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 
    738 GLint 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 
    746 GLint 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 
    758 GLint 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 
    767 void 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 
    775 void 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 
    787 void 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 
    806 GLint 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 
    871 void 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 
    901 static 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 
    912 static 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 
    923 static 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 
    934 static 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 
    946 static 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
    958 void 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 
    967 void 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 
    999 void 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