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