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