⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 program.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
      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 + -