📄 program.c
字号:
if (deleteFlag) { ASSERT(ctx); ctx->Driver.DeleteProgram(ctx, *ptr); } *ptr = NULL; } assert(!*ptr); if (prog) { /*_glthread_LOCK_MUTEX(prog->Mutex);*/ prog->RefCount++;#if 0 printf("Program %p ID=%u Target=%s Refcount++ to %d\n", prog, prog->Id, (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"), prog->RefCount);#endif /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/ } *ptr = prog;}/** * Return a copy of a program. * XXX Problem here if the program object is actually OO-derivation * made by a device driver. */struct gl_program *_mesa_clone_program(GLcontext *ctx, const struct gl_program *prog){ struct gl_program *clone; clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id); if (!clone) return NULL; assert(clone->Target == prog->Target); assert(clone->RefCount == 1); clone->String = (GLubyte *) _mesa_strdup((char *) prog->String); clone->Format = prog->Format; clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions); if (!clone->Instructions) { _mesa_reference_program(ctx, &clone, NULL); return NULL; } _mesa_copy_instructions(clone->Instructions, prog->Instructions, prog->NumInstructions); clone->InputsRead = prog->InputsRead; clone->OutputsWritten = prog->OutputsWritten; clone->SamplersUsed = prog->SamplersUsed; clone->ShadowSamplers = prog->ShadowSamplers; memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed)); if (prog->Parameters) clone->Parameters = _mesa_clone_parameter_list(prog->Parameters); memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams)); if (prog->Varying) clone->Varying = _mesa_clone_parameter_list(prog->Varying); if (prog->Attributes) clone->Attributes = _mesa_clone_parameter_list(prog->Attributes); memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams)); clone->NumInstructions = prog->NumInstructions; clone->NumTemporaries = prog->NumTemporaries; clone->NumParameters = prog->NumParameters; clone->NumAttributes = prog->NumAttributes; clone->NumAddressRegs = prog->NumAddressRegs; clone->NumNativeInstructions = prog->NumNativeInstructions; clone->NumNativeTemporaries = prog->NumNativeTemporaries; clone->NumNativeParameters = prog->NumNativeParameters; clone->NumNativeAttributes = prog->NumNativeAttributes; clone->NumNativeAddressRegs = prog->NumNativeAddressRegs; clone->NumAluInstructions = prog->NumAluInstructions; clone->NumTexInstructions = prog->NumTexInstructions; clone->NumTexIndirections = prog->NumTexIndirections; clone->NumNativeAluInstructions = prog->NumNativeAluInstructions; clone->NumNativeTexInstructions = prog->NumNativeTexInstructions; clone->NumNativeTexIndirections = prog->NumNativeTexIndirections; switch (prog->Target) { case GL_VERTEX_PROGRAM_ARB: { const struct gl_vertex_program *vp = (const struct gl_vertex_program *) prog; struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone; vpc->IsPositionInvariant = vp->IsPositionInvariant; } break; case GL_FRAGMENT_PROGRAM_ARB: { const struct gl_fragment_program *fp = (const struct gl_fragment_program *) prog; struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone; fpc->FogOption = fp->FogOption; fpc->UsesKill = fp->UsesKill; } break; default: _mesa_problem(NULL, "Unexpected target in _mesa_clone_program"); } return clone;}/** * Insert 'count' NOP instructions at 'start' in the given program. * Adjust branch targets accordingly. */GLboolean_mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count){ const GLuint origLen = prog->NumInstructions; const GLuint newLen = origLen + count; struct prog_instruction *newInst; GLuint i; /* adjust branches */ for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { if (inst->BranchTarget >= start) { inst->BranchTarget += count; } } } /* Alloc storage for new instructions */ newInst = _mesa_alloc_instructions(newLen); if (!newInst) { return GL_FALSE; } /* Copy 'start' instructions into new instruction buffer */ _mesa_copy_instructions(newInst, prog->Instructions, start); /* init the new instructions */ _mesa_init_instructions(newInst + start, count); /* Copy the remaining/tail instructions to new inst buffer */ _mesa_copy_instructions(newInst + start + count, prog->Instructions + start, origLen - start); /* free old instructions */ _mesa_free_instructions(prog->Instructions, origLen); /* install new instructions */ prog->Instructions = newInst; prog->NumInstructions = newLen; return GL_TRUE;}/** * Delete 'count' instructions at 'start' in the given program. * Adjust branch targets accordingly. */GLboolean_mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count){ const GLuint origLen = prog->NumInstructions; const GLuint newLen = origLen - count; struct prog_instruction *newInst; GLuint i; /* adjust branches */ for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { if (inst->BranchTarget >= start) { inst->BranchTarget -= count; } } } /* Alloc storage for new instructions */ newInst = _mesa_alloc_instructions(newLen); if (!newInst) { return GL_FALSE; } /* Copy 'start' instructions into new instruction buffer */ _mesa_copy_instructions(newInst, prog->Instructions, start); /* Copy the remaining/tail instructions to new inst buffer */ _mesa_copy_instructions(newInst + start, prog->Instructions + start + count, newLen - start); /* free old instructions */ _mesa_free_instructions(prog->Instructions, origLen); /* install new instructions */ prog->Instructions = newInst; prog->NumInstructions = newLen; return GL_TRUE;}/** * Search instructions for registers that match (oldFile, oldIndex), * replacing them with (newFile, newIndex). */static voidreplace_registers(struct prog_instruction *inst, GLuint numInst, GLuint oldFile, GLuint oldIndex, GLuint newFile, GLuint newIndex){ GLuint i, j; for (i = 0; i < numInst; i++) { /* src regs */ for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) { if (inst[i].SrcReg[j].File == oldFile && inst[i].SrcReg[j].Index == oldIndex) { inst[i].SrcReg[j].File = newFile; inst[i].SrcReg[j].Index = newIndex; } } /* dst reg */ if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) { inst[i].DstReg.File = newFile; inst[i].DstReg.Index = newIndex; } }}/** * Search instructions for references to program parameters. When found, * increment the parameter index by 'offset'. * Used when combining programs. */static voidadjust_param_indexes(struct prog_instruction *inst, GLuint numInst, GLuint offset){ GLuint i, j; for (i = 0; i < numInst; i++) { for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) { GLuint f = inst[i].SrcReg[j].File; if (f == PROGRAM_CONSTANT || f == PROGRAM_UNIFORM || f == PROGRAM_STATE_VAR) { inst[i].SrcReg[j].Index += offset; } } }}/** * Combine two programs into one. Fix instructions so the outputs of * the first program go to the inputs of the second program. */struct gl_program *_mesa_combine_programs(GLcontext *ctx, const struct gl_program *progA, const struct gl_program *progB){ struct prog_instruction *newInst; struct gl_program *newProg; const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */ const GLuint lenB = progB->NumInstructions; const GLuint numParamsA = _mesa_num_parameters(progA->Parameters); const GLuint newLength = lenA + lenB; GLbitfield inputsB; GLuint i; ASSERT(progA->Target == progB->Target); newInst = _mesa_alloc_instructions(newLength); if (!newInst) return GL_FALSE; _mesa_copy_instructions(newInst, progA->Instructions, lenA); _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB); /* adjust branch / instruction addresses for B's instructions */ for (i = 0; i < lenB; i++) { newInst[lenA + i].BranchTarget += lenA; } newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0); newProg->Instructions = newInst; newProg->NumInstructions = newLength; if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { struct gl_fragment_program *fprogA, *fprogB, *newFprog; fprogA = (struct gl_fragment_program *) progA; fprogB = (struct gl_fragment_program *) progB; newFprog = (struct gl_fragment_program *) newProg; newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill; /* Connect color outputs of fprogA to color inputs of fprogB, via a * new temporary register. */ if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) && (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) { GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY); if (tempReg < 0) { _mesa_problem(ctx, "No free temp regs found in " "_mesa_combine_programs(), using 31"); tempReg = 31; } /* replace writes to result.color[0] with tempReg */ replace_registers(newInst, lenA, PROGRAM_OUTPUT, FRAG_RESULT_COLR, PROGRAM_TEMPORARY, tempReg); /* replace reads from input.color[0] with tempReg */ replace_registers(newInst + lenA, lenB, PROGRAM_INPUT, FRAG_ATTRIB_COL0, PROGRAM_TEMPORARY, tempReg); } inputsB = progB->InputsRead; if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) { inputsB &= ~(1 << FRAG_ATTRIB_COL0); } newProg->InputsRead = progA->InputsRead | inputsB; newProg->OutputsWritten = progB->OutputsWritten; newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed; } else { /* vertex program */ assert(0); /* XXX todo */ } /* * Merge parameters (uniforms, constants, etc) */ newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters, progB->Parameters); adjust_param_indexes(newInst + lenA, lenB, numParamsA); return newProg;}/** * Scan the given program to find a free register of the given type. * \param regFile - PROGRAM_INPUT, PROGRAM_OUTPUT or PROGRAM_TEMPORARY */GLint_mesa_find_free_register(const struct gl_program *prog, GLuint regFile){ GLboolean used[MAX_PROGRAM_TEMPS]; GLuint i, k; assert(regFile == PROGRAM_INPUT || regFile == PROGRAM_OUTPUT || regFile == PROGRAM_TEMPORARY); _mesa_memset(used, 0, sizeof(used)); for (i = 0; i < prog->NumInstructions; i++) { const struct prog_instruction *inst = prog->Instructions + i; const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); for (k = 0; k < n; k++) { if (inst->SrcReg[k].File == regFile) { used[inst->SrcReg[k].Index] = GL_TRUE; } } } for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { if (!used[i]) return i; } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -