Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprogram.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5.3 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00032 #include "main/glheader.h" 00033 #include "main/context.h" 00034 #include "main/hash.h" 00035 #include "program.h" 00036 #include "prog_cache.h" 00037 #include "prog_parameter.h" 00038 #include "prog_instruction.h" 00039 00040 00045 struct gl_program _mesa_DummyProgram; 00046 00047 00051 void 00052 _mesa_init_program(GLcontext *ctx) 00053 { 00054 GLuint i; 00055 00056 /* 00057 * If this assertion fails, we need to increase the field 00058 * size for register indexes. 00059 */ 00060 ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4 00061 <= (1 << INST_INDEX_BITS)); 00062 ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4 00063 <= (1 << INST_INDEX_BITS)); 00064 00065 ctx->Program.ErrorPos = -1; 00066 ctx->Program.ErrorString = _mesa_strdup(""); 00067 00068 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program 00069 ctx->VertexProgram.Enabled = GL_FALSE; 00070 #if FEATURE_es2_glsl 00071 ctx->VertexProgram.PointSizeEnabled = GL_TRUE; 00072 #else 00073 ctx->VertexProgram.PointSizeEnabled = GL_FALSE; 00074 #endif 00075 ctx->VertexProgram.TwoSideEnabled = GL_FALSE; 00076 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 00077 ctx->Shared->DefaultVertexProgram); 00078 assert(ctx->VertexProgram.Current); 00079 for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) { 00080 ctx->VertexProgram.TrackMatrix[i] = GL_NONE; 00081 ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV; 00082 } 00083 ctx->VertexProgram.Cache = _mesa_new_program_cache(); 00084 #endif 00085 00086 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program 00087 ctx->FragmentProgram.Enabled = GL_FALSE; 00088 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 00089 ctx->Shared->DefaultFragmentProgram); 00090 assert(ctx->FragmentProgram.Current); 00091 ctx->FragmentProgram.Cache = _mesa_new_program_cache(); 00092 #endif 00093 00094 00095 /* XXX probably move this stuff */ 00096 #if FEATURE_ATI_fragment_shader 00097 ctx->ATIFragmentShader.Enabled = GL_FALSE; 00098 ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader; 00099 assert(ctx->ATIFragmentShader.Current); 00100 ctx->ATIFragmentShader.Current->RefCount++; 00101 #endif 00102 } 00103 00104 00108 void 00109 _mesa_free_program_data(GLcontext *ctx) 00110 { 00111 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program 00112 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); 00113 _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); 00114 #endif 00115 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program 00116 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); 00117 _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache); 00118 #endif 00119 /* XXX probably move this stuff */ 00120 #if FEATURE_ATI_fragment_shader 00121 if (ctx->ATIFragmentShader.Current) { 00122 ctx->ATIFragmentShader.Current->RefCount--; 00123 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 00124 _mesa_free(ctx->ATIFragmentShader.Current); 00125 } 00126 } 00127 #endif 00128 _mesa_free((void *) ctx->Program.ErrorString); 00129 } 00130 00131 00137 void 00138 _mesa_update_default_objects_program(GLcontext *ctx) 00139 { 00140 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program 00141 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 00142 (struct gl_vertex_program *) 00143 ctx->Shared->DefaultVertexProgram); 00144 assert(ctx->VertexProgram.Current); 00145 #endif 00146 00147 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program 00148 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 00149 (struct gl_fragment_program *) 00150 ctx->Shared->DefaultFragmentProgram); 00151 assert(ctx->FragmentProgram.Current); 00152 #endif 00153 00154 /* XXX probably move this stuff */ 00155 #if FEATURE_ATI_fragment_shader 00156 if (ctx->ATIFragmentShader.Current) { 00157 ctx->ATIFragmentShader.Current->RefCount--; 00158 if (ctx->ATIFragmentShader.Current->RefCount <= 0) { 00159 _mesa_free(ctx->ATIFragmentShader.Current); 00160 } 00161 } 00162 ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader; 00163 assert(ctx->ATIFragmentShader.Current); 00164 ctx->ATIFragmentShader.Current->RefCount++; 00165 #endif 00166 } 00167 00168 00173 void 00174 _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string) 00175 { 00176 ctx->Program.ErrorPos = pos; 00177 _mesa_free((void *) ctx->Program.ErrorString); 00178 if (!string) 00179 string = ""; 00180 ctx->Program.ErrorString = _mesa_strdup(string); 00181 } 00182 00183 00194 const GLubyte * 00195 _mesa_find_line_column(const GLubyte *string, const GLubyte *pos, 00196 GLint *line, GLint *col) 00197 { 00198 const GLubyte *lineStart = string; 00199 const GLubyte *p = string; 00200 GLubyte *s; 00201 int len; 00202 00203 *line = 1; 00204 00205 while (p != pos) { 00206 if (*p == (GLubyte) '\n') { 00207 (*line)++; 00208 lineStart = p + 1; 00209 } 00210 p++; 00211 } 00212 00213 *col = (pos - lineStart) + 1; 00214 00215 /* return copy of this line */ 00216 while (*p != 0 && *p != '\n') 00217 p++; 00218 len = p - lineStart; 00219 s = (GLubyte *) _mesa_malloc(len + 1); 00220 _mesa_memcpy(s, lineStart, len); 00221 s[len] = 0; 00222 00223 return s; 00224 } 00225 00226 00230 static struct gl_program * 00231 _mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog, 00232 GLenum target, GLuint id) 00233 { 00234 (void) ctx; 00235 if (prog) { 00236 GLuint i; 00237 _mesa_bzero(prog, sizeof(*prog)); 00238 prog->Id = id; 00239 prog->Target = target; 00240 prog->Resident = GL_TRUE; 00241 prog->RefCount = 1; 00242 prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB; 00243 00244 /* default mapping from samplers to texture units */ 00245 for (i = 0; i < MAX_SAMPLERS; i++) 00246 prog->SamplerUnits[i] = i; 00247 } 00248 00249 return prog; 00250 } 00251 00252 00256 struct gl_program * 00257 _mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog, 00258 GLenum target, GLuint id) 00259 { 00260 if (prog) 00261 return _mesa_init_program_struct( ctx, &prog->Base, target, id ); 00262 else 00263 return NULL; 00264 } 00265 00266 00270 struct gl_program * 00271 _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog, 00272 GLenum target, GLuint id) 00273 { 00274 if (prog) 00275 return _mesa_init_program_struct( ctx, &prog->Base, target, id ); 00276 else 00277 return NULL; 00278 } 00279 00280 00293 struct gl_program * 00294 _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) 00295 { 00296 struct gl_program *prog; 00297 switch (target) { 00298 case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ 00299 prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), 00300 target, id ); 00301 break; 00302 case GL_FRAGMENT_PROGRAM_NV: 00303 case GL_FRAGMENT_PROGRAM_ARB: 00304 prog =_mesa_init_fragment_program(ctx, 00305 CALLOC_STRUCT(gl_fragment_program), 00306 target, id ); 00307 break; 00308 default: 00309 _mesa_problem(ctx, "bad target in _mesa_new_program"); 00310 prog = NULL; 00311 } 00312 return prog; 00313 } 00314 00315 00322 void 00323 _mesa_delete_program(GLcontext *ctx, struct gl_program *prog) 00324 { 00325 (void) ctx; 00326 ASSERT(prog); 00327 ASSERT(prog->RefCount==0); 00328 00329 if (prog == &_mesa_DummyProgram) 00330 return; 00331 00332 if (prog->String) 00333 _mesa_free(prog->String); 00334 00335 _mesa_free_instructions(prog->Instructions, prog->NumInstructions); 00336 00337 if (prog->Parameters) { 00338 _mesa_free_parameter_list(prog->Parameters); 00339 } 00340 if (prog->Varying) { 00341 _mesa_free_parameter_list(prog->Varying); 00342 } 00343 if (prog->Attributes) { 00344 _mesa_free_parameter_list(prog->Attributes); 00345 } 00346 00347 /* XXX this is a little ugly */ 00348 if (prog->Target == GL_VERTEX_PROGRAM_ARB) { 00349 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; 00350 if (vprog->TnlData) 00351 _mesa_free(vprog->TnlData); 00352 } 00353 00354 _mesa_free(prog); 00355 } 00356 00357 00363 struct gl_program * 00364 _mesa_lookup_program(GLcontext *ctx, GLuint id) 00365 { 00366 if (id) 00367 return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id); 00368 else 00369 return NULL; 00370 } 00371 00372 00376 void 00377 _mesa_reference_program(GLcontext *ctx, 00378 struct gl_program **ptr, 00379 struct gl_program *prog) 00380 { 00381 assert(ptr); 00382 if (*ptr && prog) { 00383 /* sanity check */ 00384 if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) 00385 ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB); 00386 else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) 00387 ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB || 00388 prog->Target == GL_FRAGMENT_PROGRAM_NV); 00389 } 00390 if (*ptr == prog) { 00391 return; /* no change */ 00392 } 00393 if (*ptr) { 00394 GLboolean deleteFlag; 00395 00396 /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/ 00397 #if 0 00398 printf("Program %p ID=%u Target=%s Refcount-- to %d\n", 00399 *ptr, (*ptr)->Id, 00400 ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"), 00401 (*ptr)->RefCount - 1); 00402 #endif 00403 ASSERT((*ptr)->RefCount > 0); 00404 (*ptr)->RefCount--; 00405 00406 deleteFlag = ((*ptr)->RefCount == 0); 00407 /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/ 00408 00409 if (deleteFlag) { 00410 ASSERT(ctx); 00411 ctx->Driver.DeleteProgram(ctx, *ptr); 00412 } 00413 00414 *ptr = NULL; 00415 } 00416 00417 assert(!*ptr); 00418 if (prog) { 00419 /*_glthread_LOCK_MUTEX(prog->Mutex);*/ 00420 prog->RefCount++; 00421 #if 0 00422 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", 00423 prog, prog->Id, 00424 (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"), 00425 prog->RefCount); 00426 #endif 00427 /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/ 00428 } 00429 00430 *ptr = prog; 00431 } 00432 00433 00439 struct gl_program * 00440 _mesa_clone_program(GLcontext *ctx, const struct gl_program *prog) 00441 { 00442 struct gl_program *clone; 00443 00444 clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id); 00445 if (!clone) 00446 return NULL; 00447 00448 assert(clone->Target == prog->Target); 00449 assert(clone->RefCount == 1); 00450 00451 clone->String = (GLubyte *) _mesa_strdup((char *) prog->String); 00452 clone->Format = prog->Format; 00453 clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions); 00454 if (!clone->Instructions) { 00455 _mesa_reference_program(ctx, &clone, NULL); 00456 return NULL; 00457 } 00458 _mesa_copy_instructions(clone->Instructions, prog->Instructions, 00459 prog->NumInstructions); 00460 clone->InputsRead = prog->InputsRead; 00461 clone->OutputsWritten = prog->OutputsWritten; 00462 clone->SamplersUsed = prog->SamplersUsed; 00463 clone->ShadowSamplers = prog->ShadowSamplers; 00464 memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed)); 00465 00466 if (prog->Parameters) 00467 clone->Parameters = _mesa_clone_parameter_list(prog->Parameters); 00468 memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams)); 00469 if (prog->Varying) 00470 clone->Varying = _mesa_clone_parameter_list(prog->Varying); 00471 if (prog->Attributes) 00472 clone->Attributes = _mesa_clone_parameter_list(prog->Attributes); 00473 memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams)); 00474 clone->NumInstructions = prog->NumInstructions; 00475 clone->NumTemporaries = prog->NumTemporaries; 00476 clone->NumParameters = prog->NumParameters; 00477 clone->NumAttributes = prog->NumAttributes; 00478 clone->NumAddressRegs = prog->NumAddressRegs; 00479 clone->NumNativeInstructions = prog->NumNativeInstructions; 00480 clone->NumNativeTemporaries = prog->NumNativeTemporaries; 00481 clone->NumNativeParameters = prog->NumNativeParameters; 00482 clone->NumNativeAttributes = prog->NumNativeAttributes; 00483 clone->NumNativeAddressRegs = prog->NumNativeAddressRegs; 00484 clone->NumAluInstructions = prog->NumAluInstructions; 00485 clone->NumTexInstructions = prog->NumTexInstructions; 00486 clone->NumTexIndirections = prog->NumTexIndirections; 00487 clone->NumNativeAluInstructions = prog->NumNativeAluInstructions; 00488 clone->NumNativeTexInstructions = prog->NumNativeTexInstructions; 00489 clone->NumNativeTexIndirections = prog->NumNativeTexIndirections; 00490 00491 switch (prog->Target) { 00492 case GL_VERTEX_PROGRAM_ARB: 00493 { 00494 const struct gl_vertex_program *vp 00495 = (const struct gl_vertex_program *) prog; 00496 struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone; 00497 vpc->IsPositionInvariant = vp->IsPositionInvariant; 00498 } 00499 break; 00500 case GL_FRAGMENT_PROGRAM_ARB: 00501 { 00502 const struct gl_fragment_program *fp 00503 = (const struct gl_fragment_program *) prog; 00504 struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone; 00505 fpc->FogOption = fp->FogOption; 00506 fpc->UsesKill = fp->UsesKill; 00507 } 00508 break; 00509 default: 00510 _mesa_problem(NULL, "Unexpected target in _mesa_clone_program"); 00511 } 00512 00513 return clone; 00514 } 00515 00516 00521 GLboolean 00522 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) 00523 { 00524 const GLuint origLen = prog->NumInstructions; 00525 const GLuint newLen = origLen + count; 00526 struct prog_instruction *newInst; 00527 GLuint i; 00528 00529 /* adjust branches */ 00530 for (i = 0; i < prog->NumInstructions; i++) { 00531 struct prog_instruction *inst = prog->Instructions + i; 00532 if (inst->BranchTarget > 0) { 00533 if ((GLuint)inst->BranchTarget >= start) { 00534 inst->BranchTarget += count; 00535 } 00536 } 00537 } 00538 00539 /* Alloc storage for new instructions */ 00540 newInst = _mesa_alloc_instructions(newLen); 00541 if (!newInst) { 00542 return GL_FALSE; 00543 } 00544 00545 /* Copy 'start' instructions into new instruction buffer */ 00546 _mesa_copy_instructions(newInst, prog->Instructions, start); 00547 00548 /* init the new instructions */ 00549 _mesa_init_instructions(newInst + start, count); 00550 00551 /* Copy the remaining/tail instructions to new inst buffer */ 00552 _mesa_copy_instructions(newInst + start + count, 00553 prog->Instructions + start, 00554 origLen - start); 00555 00556 /* free old instructions */ 00557 _mesa_free_instructions(prog->Instructions, origLen); 00558 00559 /* install new instructions */ 00560 prog->Instructions = newInst; 00561 prog->NumInstructions = newLen; 00562 00563 return GL_TRUE; 00564 } 00565 00566 00571 GLboolean 00572 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) 00573 { 00574 const GLuint origLen = prog->NumInstructions; 00575 const GLuint newLen = origLen - count; 00576 struct prog_instruction *newInst; 00577 GLuint i; 00578 00579 /* adjust branches */ 00580 for (i = 0; i < prog->NumInstructions; i++) { 00581 struct prog_instruction *inst = prog->Instructions + i; 00582 if (inst->BranchTarget > 0) { 00583 if (inst->BranchTarget > start) { 00584 inst->BranchTarget -= count; 00585 } 00586 } 00587 } 00588 00589 /* Alloc storage for new instructions */ 00590 newInst = _mesa_alloc_instructions(newLen); 00591 if (!newInst) { 00592 return GL_FALSE; 00593 } 00594 00595 /* Copy 'start' instructions into new instruction buffer */ 00596 _mesa_copy_instructions(newInst, prog->Instructions, start); 00597 00598 /* Copy the remaining/tail instructions to new inst buffer */ 00599 _mesa_copy_instructions(newInst + start, 00600 prog->Instructions + start + count, 00601 newLen - start); 00602 00603 /* free old instructions */ 00604 _mesa_free_instructions(prog->Instructions, origLen); 00605 00606 /* install new instructions */ 00607 prog->Instructions = newInst; 00608 prog->NumInstructions = newLen; 00609 00610 return GL_TRUE; 00611 } 00612 00613 00618 static void 00619 replace_registers(struct prog_instruction *inst, GLuint numInst, 00620 GLuint oldFile, GLuint oldIndex, 00621 GLuint newFile, GLuint newIndex) 00622 { 00623 GLuint i, j; 00624 for (i = 0; i < numInst; i++) { 00625 /* src regs */ 00626 for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) { 00627 if (inst[i].SrcReg[j].File == oldFile && 00628 inst[i].SrcReg[j].Index == oldIndex) { 00629 inst[i].SrcReg[j].File = newFile; 00630 inst[i].SrcReg[j].Index = newIndex; 00631 } 00632 } 00633 /* dst reg */ 00634 if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) { 00635 inst[i].DstReg.File = newFile; 00636 inst[i].DstReg.Index = newIndex; 00637 } 00638 } 00639 } 00640 00641 00647 static void 00648 adjust_param_indexes(struct prog_instruction *inst, GLuint numInst, 00649 GLuint offset) 00650 { 00651 GLuint i, j; 00652 for (i = 0; i < numInst; i++) { 00653 for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) { 00654 GLuint f = inst[i].SrcReg[j].File; 00655 if (f == PROGRAM_CONSTANT || 00656 f == PROGRAM_UNIFORM || 00657 f == PROGRAM_STATE_VAR) { 00658 inst[i].SrcReg[j].Index += offset; 00659 } 00660 } 00661 } 00662 } 00663 00664 00669 struct gl_program * 00670 _mesa_combine_programs(GLcontext *ctx, 00671 const struct gl_program *progA, 00672 const struct gl_program *progB) 00673 { 00674 struct prog_instruction *newInst; 00675 struct gl_program *newProg; 00676 const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */ 00677 const GLuint lenB = progB->NumInstructions; 00678 const GLuint numParamsA = _mesa_num_parameters(progA->Parameters); 00679 const GLuint newLength = lenA + lenB; 00680 GLbitfield inputsB; 00681 GLuint i; 00682 00683 ASSERT(progA->Target == progB->Target); 00684 00685 newInst = _mesa_alloc_instructions(newLength); 00686 if (!newInst) 00687 return GL_FALSE; 00688 00689 _mesa_copy_instructions(newInst, progA->Instructions, lenA); 00690 _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB); 00691 00692 /* adjust branch / instruction addresses for B's instructions */ 00693 for (i = 0; i < lenB; i++) { 00694 newInst[lenA + i].BranchTarget += lenA; 00695 } 00696 00697 newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0); 00698 newProg->Instructions = newInst; 00699 newProg->NumInstructions = newLength; 00700 00701 if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { 00702 struct gl_fragment_program *fprogA, *fprogB, *newFprog; 00703 fprogA = (struct gl_fragment_program *) progA; 00704 fprogB = (struct gl_fragment_program *) progB; 00705 newFprog = (struct gl_fragment_program *) newProg; 00706 00707 newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill; 00708 00709 /* Connect color outputs of fprogA to color inputs of fprogB, via a 00710 * new temporary register. 00711 */ 00712 if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) && 00713 (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) { 00714 GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY); 00715 if (tempReg < 0) { 00716 _mesa_problem(ctx, "No free temp regs found in " 00717 "_mesa_combine_programs(), using 31"); 00718 tempReg = 31; 00719 } 00720 /* replace writes to result.color[0] with tempReg */ 00721 replace_registers(newInst, lenA, 00722 PROGRAM_OUTPUT, FRAG_RESULT_COLR, 00723 PROGRAM_TEMPORARY, tempReg); 00724 /* replace reads from input.color[0] with tempReg */ 00725 replace_registers(newInst + lenA, lenB, 00726 PROGRAM_INPUT, FRAG_ATTRIB_COL0, 00727 PROGRAM_TEMPORARY, tempReg); 00728 } 00729 00730 inputsB = progB->InputsRead; 00731 if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) { 00732 inputsB &= ~(1 << FRAG_ATTRIB_COL0); 00733 } 00734 newProg->InputsRead = progA->InputsRead | inputsB; 00735 newProg->OutputsWritten = progB->OutputsWritten; 00736 newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed; 00737 } 00738 else { 00739 /* vertex program */ 00740 assert(0); /* XXX todo */ 00741 } 00742 00743 /* 00744 * Merge parameters (uniforms, constants, etc) 00745 */ 00746 newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters, 00747 progB->Parameters); 00748 00749 adjust_param_indexes(newInst + lenA, lenB, numParamsA); 00750 00751 00752 return newProg; 00753 } 00754 00755 00756 00757 00762 GLint 00763 _mesa_find_free_register(const struct gl_program *prog, GLuint regFile) 00764 { 00765 GLboolean used[MAX_PROGRAM_TEMPS]; 00766 GLuint i, k; 00767 00768 assert(regFile == PROGRAM_INPUT || 00769 regFile == PROGRAM_OUTPUT || 00770 regFile == PROGRAM_TEMPORARY); 00771 00772 _mesa_memset(used, 0, sizeof(used)); 00773 00774 for (i = 0; i < prog->NumInstructions; i++) { 00775 const struct prog_instruction *inst = prog->Instructions + i; 00776 const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); 00777 00778 for (k = 0; k < n; k++) { 00779 if (inst->SrcReg[k].File == regFile) { 00780 used[inst->SrcReg[k].Index] = GL_TRUE; 00781 } 00782 } 00783 } 00784 00785 for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { 00786 if (!used[i]) 00787 return i; 00788 } 00789 00790 return -1; 00791 } Generated on Sat May 26 2012 04:19:22 for ReactOS by
1.7.6.1
|