• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitializeGLContext(struct gl_context * ctx)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;
GLContextGLContext73    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    }
~GLContextGLContext79    ~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 
GLContextDctr()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
operator <ShaderKey104    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)();
~InstanceInstance113    ~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 
GGLShaderCreate(GLenum type)132 gl_shader * GGLShaderCreate(GLenum type)
133 {
134    return _mesa_new_shader(NULL, 0, type);
135 }
136 
ShaderCreate(const GGLInterface * iface,GLenum type)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 
GGLShaderSource(gl_shader_t * shader,GLsizei count,const char ** string,const int * length)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 
GGLShaderCompile(gl_shader * shader,const char * glsl,const char ** infoLog)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 
ShaderCompile(const GGLInterface * iface,gl_shader * shader,const char * glsl,const char ** infoLog)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 
GGLShaderDelete(gl_shader * shader)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 
ShaderDelete(const GGLInterface * iface,gl_shader * shader)199 static void ShaderDelete(const GGLInterface * iface, gl_shader * shader)
200 {
201    GGLShaderDelete(shader);
202 }
203 
GGLShaderProgramCreate()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 
ShaderProgramCreate(const GGLInterface * iface)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 
GGLShaderAttach(gl_shader_program * program,gl_shader * shader)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 
ShaderAttach(const GGLInterface * iface,gl_shader_program * program,gl_shader * shader)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 
GGLShaderProgramLink(gl_shader_program * program,const char ** infoLog)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 
ShaderProgramLink(gl_shader_program * program,const char ** infoLog)280 static GLboolean ShaderProgramLink(gl_shader_program * program, const char ** infoLog)
281 {
282    return GGLShaderProgramLink(program, infoLog);
283 }
284 
GetShaderKey(const GGLState * ctx,const gl_shader * shader,ShaderKey * key)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 
HexDigit(unsigned char d)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 
GetShaderKeyString(const GLenum type,const ShaderKey * key,char * buffer,const unsigned bufferSize)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 
GetScanlineKeyString(const ShaderKey * key,char * buffer,const unsigned bufferSize)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 
SymbolLookup(void * pContext,const char * name)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 
CodeGen(Instance * instance,const char * mainName,gl_shader * shader,gl_shader_program * program,const GGLState * gglCtx)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 
GGLShaderUse(void * llvmCtx,const GGLState * gglState,gl_shader_program * program)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 
ShaderUse(GGLInterface * iface,gl_shader_program * program)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 
GGLShaderDetach(gl_shader_program * program,gl_shader * shader)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 
ShaderDetach(const GGLInterface * iface,gl_shader_program * program,gl_shader * shader)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 
GGLShaderProgramDelete(gl_shader_program * program)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 
ShaderProgramDelete(GGLInterface * iface,gl_shader_program * program)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 
GGLShaderGetiv(const gl_shader_t * shader,const GLenum pname,GLint * params)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 
GGLShaderGetInfoLog(const gl_shader_t * shader,GLsizei bufsize,GLsizei * length,GLchar * infolog)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 
GGLShaderProgramGetiv(const gl_shader_program_t * program,const GLenum pname,GLint * params)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 
GGLShaderProgramGetInfoLog(const gl_shader_program_t * program,GLsizei bufsize,GLsizei * length,GLchar * infolog)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 
GGLShaderAttributeBind(const gl_shader_program * program,GLuint index,const GLchar * name)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 
GGLShaderAttributeLocation(const gl_shader_program * program,const char * name)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 
GGLShaderVaryingLocation(const gl_shader_program_t * program,const char * name,GLint * vertexOutputLocation)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 
GGLShaderUniformLocation(const gl_shader_program * program,const char * name)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 
GGLShaderUniformGetfv(gl_shader_program * program,GLint location,GLfloat * params)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 
GGLShaderUniformGetiv(gl_shader_program * program,GLint location,GLint * params)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 
GGLShaderUniformGetSamplers(const gl_shader_program_t * program,int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS])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 
GGLShaderUniform(gl_shader_program * program,GLint location,GLsizei count,const GLvoid * values,GLenum type)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 
GGLShaderUniformMatrix(gl_shader_program * program,GLint cols,GLint rows,GLint location,GLsizei count,GLboolean transpose,const GLfloat * values)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 
ShaderVerifyProcessVertex(const GGLInterface * iface,const VertexInput * input,VertexOutput * output)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 
ShaderVerifyDrawTriangle(const GGLInterface * iface,const VertexInput * v0,const VertexInput * v1,const VertexInput * v2)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 
ShaderVerifyRasterTriangle(const GGLInterface * iface,const VertexOutput * v1,const VertexOutput * v2,const VertexOutput * v3)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 
ShaderVerifyRasterTrapezoid(const GGLInterface * iface,const VertexOutput * tl,const VertexOutput * tr,const VertexOutput * bl,const VertexOutput * br)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 
ShaderVerifyScanLine(const GGLInterface * iface,const VertexOutput * v1,const VertexOutput * v2)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
SetShaderVerifyFunctions(struct GGLInterface * iface)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 
InitializeShaderFunctions(struct GGLInterface * iface)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 
DestroyShaderFunctions(GGLInterface * iface)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