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