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 <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 
     40 static 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 
     70 void * llvmCtx = NULL;
     71 static 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 
     89 extern "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 
     96 struct 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 
    109 struct 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 
    122 struct Executable { // codegen info
    123    std::map<ShaderKey, Instance *> instances;
    124 };
    125 
    126 bool do_mat_op_to_vec(exec_list *instructions);
    127 
    128 extern void link_shaders(const struct gl_context *ctx, struct gl_shader_program *prog);
    129 
    130 extern "C" void compile_shader(const struct gl_context *ctx, struct gl_shader *shader);
    131 
    132 gl_shader * GGLShaderCreate(GLenum type)
    133 {
    134    return _mesa_new_shader(NULL, 0, type);
    135 }
    136 
    137 static 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 
    151 void 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 
    163 GLboolean 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 
    176 static 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 
    188 void 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 
    199 static void ShaderDelete(const GGLInterface * iface, gl_shader * shader)
    200 {
    201    GGLShaderDelete(shader);
    202 }
    203 
    204 gl_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 
    222 static 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 
    231 unsigned 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 
    249 static 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 
    257 GLboolean 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 
    280 static GLboolean ShaderProgramLink(gl_shader_program * program, const char ** infoLog)
    281 {
    282    return GGLShaderProgramLink(program, infoLog);
    283 }
    284 
    285 static 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 
    310 static inline char HexDigit(unsigned char d)
    311 {
    312    return (d > 9 ? d + 'A' - 10 : d + '0');
    313 }
    314 
    315 static const unsigned SHADER_KEY_STRING_LEN = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS * 4 + 2;
    316 
    317 static 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 
    339 static const unsigned SCANLINE_KEY_STRING_LEN = 2 * sizeof(ShaderKey::ScanLineKey) + 3 + SHADER_KEY_STRING_LEN;
    340 
    341 static 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 
    359 struct SymbolLookupContext {
    360    const GGLState * gglCtx;
    361    const gl_shader_program * program;
    362    const gl_shader * shader;
    363 };
    364 
    365 static 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 
    386 static 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 
    420 void GenerateScanLine(const GGLState * gglCtx, const gl_shader_program * program, llvm::Module * mod,
    421                       const char * shaderName, const char * scanlineName);
    422 
    423 void 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 
    540 static 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 
    566 unsigned 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 
    581 static 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 
    589 void 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 
    603 static 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 
    613 void 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 
    637 void 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 
    651 void 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 
    684 void 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 
    698 void 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 
    704 GLint 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 
    712 GLint 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 
    724 GLint 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 
    733 void 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 
    741 void 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 
    753 void 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 
    772 GLint 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 
    837 void 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 
    867 static 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 
    878 static 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 
    889 static 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 
    900 static 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 
    912 static 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
    924 void 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 
    933 void 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 
    963 void 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