prog_hash_table: Convert to using util/hash_table.h.
[mesa.git] / src / mesa / program / program.c
index eb1f8bec220491e3a8b3428a6e024b922a2c0ebf..67672164f594fbea18ef105b2624d013262a4a19 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "main/glheader.h"
 #include "main/context.h"
+#include "main/framebuffer.h"
 #include "main/hash.h"
 #include "main/macros.h"
 #include "program.h"
@@ -175,12 +176,13 @@ _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
 /**
  * Initialize a new gl_program object.
  */
-static void
-init_program_struct(struct gl_program *prog, GLenum target, GLuint id)
+struct gl_program *
+_mesa_init_gl_program(struct gl_program *prog, GLenum target, GLuint id)
 {
    GLuint i;
 
-   assert(prog);
+   if (!prog)
+      return NULL;
 
    memset(prog, 0, sizeof(*prog));
    mtx_init(&prog->Mutex, mtx_plain);
@@ -192,102 +194,8 @@ init_program_struct(struct gl_program *prog, GLenum target, GLuint id)
    /* default mapping from samplers to texture units */
    for (i = 0; i < MAX_SAMPLERS; i++)
       prog->SamplerUnits[i] = i;
-}
-
-
-/**
- * Initialize a new fragment program object.
- */
-struct gl_program *
-_mesa_init_fragment_program(struct gl_context *ctx,
-                            struct gl_fragment_program *prog,
-                            GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
-}
-
-
-/**
- * Initialize a new vertex program object.
- */
-struct gl_program *
-_mesa_init_vertex_program(struct gl_context *ctx,
-                          struct gl_vertex_program *prog,
-                          GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
-}
-
-
-/**
- * Initialize a new compute program object.
- */
-struct gl_program *
-_mesa_init_compute_program(struct gl_context *ctx,
-                           struct gl_compute_program *prog,
-                           GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
-}
-
 
-/**
- * Initialize a new tessellation control program object.
- */
-struct gl_program *
-_mesa_init_tess_ctrl_program(struct gl_context *ctx,
-                             struct gl_tess_ctrl_program *prog,
-                             GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
-}
-
-
-/**
- * Initialize a new tessellation evaluation program object.
- */
-struct gl_program *
-_mesa_init_tess_eval_program(struct gl_context *ctx,
-                             struct gl_tess_eval_program *prog,
-                             GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
-}
-
-
-/**
- * Initialize a new geometry program object.
- */
-struct gl_program *
-_mesa_init_geometry_program(struct gl_context *ctx,
-                            struct gl_geometry_program *prog,
-                            GLenum target, GLuint id)
-{
-   if (prog) {
-      init_program_struct(&prog->Base, target, id);
-      return &prog->Base;
-   }
-   return NULL;
+   return prog;
 }
 
 
@@ -306,43 +214,35 @@ _mesa_init_geometry_program(struct gl_context *ctx,
 struct gl_program *
 _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
 {
-   struct gl_program *prog;
    switch (target) {
-   case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
-      prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
-                                       target, id );
-      break;
-   case GL_FRAGMENT_PROGRAM_NV:
-   case GL_FRAGMENT_PROGRAM_ARB:
-      prog =_mesa_init_fragment_program(ctx,
-                                         CALLOC_STRUCT(gl_fragment_program),
-                                         target, id );
-      break;
-   case GL_GEOMETRY_PROGRAM_NV:
-      prog = _mesa_init_geometry_program(ctx,
-                                         CALLOC_STRUCT(gl_geometry_program),
-                                         target, id);
-      break;
-   case GL_TESS_CONTROL_PROGRAM_NV:
-      prog = _mesa_init_tess_ctrl_program(ctx,
-                                          CALLOC_STRUCT(gl_tess_ctrl_program),
-                                          target, id);
-      break;
-   case GL_TESS_EVALUATION_PROGRAM_NV:
-      prog = _mesa_init_tess_eval_program(ctx,
-                                         CALLOC_STRUCT(gl_tess_eval_program),
-                                         target, id);
-      break;
-   case GL_COMPUTE_PROGRAM_NV:
-      prog = _mesa_init_compute_program(ctx,
-                                        CALLOC_STRUCT(gl_compute_program),
-                                        target, id);
-      break;
+   case GL_VERTEX_PROGRAM_ARB: { /* == GL_VERTEX_PROGRAM_NV */
+      struct gl_vertex_program *prog = CALLOC_STRUCT(gl_vertex_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
+   case GL_FRAGMENT_PROGRAM_ARB: {
+      struct gl_fragment_program *prog = CALLOC_STRUCT(gl_fragment_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
+   case GL_GEOMETRY_PROGRAM_NV: {
+      struct gl_geometry_program *prog = CALLOC_STRUCT(gl_geometry_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
+   case GL_TESS_CONTROL_PROGRAM_NV: {
+      struct gl_tess_ctrl_program *prog = CALLOC_STRUCT(gl_tess_ctrl_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
+   case GL_TESS_EVALUATION_PROGRAM_NV: {
+      struct gl_tess_eval_program *prog = CALLOC_STRUCT(gl_tess_eval_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
+   case GL_COMPUTE_PROGRAM_NV: {
+      struct gl_compute_program *prog = CALLOC_STRUCT(gl_compute_program);
+      return _mesa_init_gl_program(&prog->Base, target, id);
+   }
    default:
       _mesa_problem(ctx, "bad target in _mesa_new_program");
-      prog = NULL;
+      return NULL;
    }
-   return prog;
 }
 
 
@@ -546,57 +446,6 @@ _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
 }
 
 
-/**
- * Search instructions for registers that match (oldFile, oldIndex),
- * replacing them with (newFile, newIndex).
- */
-static void
-replace_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[i].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 void
-adjust_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[i].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;
-         }
-      }
-   }
-}
-
-
 /**
  * Populate the 'used' array with flags indicating which registers (TEMPs,
  * INPUTs, OUTPUTs, etc, are used by the given program.
@@ -659,140 +508,6 @@ _mesa_find_free_register(const GLboolean used[],
 }
 
 
-
-/**
- * Check if the given register index is valid (doesn't exceed implementation-
- * dependent limits).
- * \return GL_TRUE if OK, GL_FALSE if bad index
- */
-GLboolean
-_mesa_valid_register_index(const struct gl_context *ctx,
-                           gl_shader_stage shaderType,
-                           gl_register_file file, GLint index)
-{
-   const struct gl_program_constants *c;
-
-   assert(0 <= shaderType && shaderType < MESA_SHADER_STAGES);
-   c = &ctx->Const.Program[shaderType];
-
-   switch (file) {
-   case PROGRAM_UNDEFINED:
-      return GL_TRUE;  /* XXX or maybe false? */
-
-   case PROGRAM_TEMPORARY:
-      return index >= 0 && index < (GLint) c->MaxTemps;
-
-   case PROGRAM_UNIFORM:
-   case PROGRAM_STATE_VAR:
-      /* aka constant buffer */
-      return index >= 0 && index < (GLint) c->MaxUniformComponents / 4;
-
-   case PROGRAM_CONSTANT:
-      /* constant buffer w/ possible relative negative addressing */
-      return (index > (int) c->MaxUniformComponents / -4 &&
-              index < (int) c->MaxUniformComponents / 4);
-
-   case PROGRAM_INPUT:
-      if (index < 0)
-         return GL_FALSE;
-
-      switch (shaderType) {
-      case MESA_SHADER_VERTEX:
-         return index < VERT_ATTRIB_GENERIC0 + (GLint) c->MaxAttribs;
-      case MESA_SHADER_FRAGMENT:
-         return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying;
-      case MESA_SHADER_GEOMETRY:
-         return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying;
-      default:
-         return GL_FALSE;
-      }
-
-   case PROGRAM_OUTPUT:
-      if (index < 0)
-         return GL_FALSE;
-
-      switch (shaderType) {
-      case MESA_SHADER_VERTEX:
-         return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying;
-      case MESA_SHADER_FRAGMENT:
-         return index < FRAG_RESULT_DATA0 + (GLint) ctx->Const.MaxDrawBuffers;
-      case MESA_SHADER_GEOMETRY:
-         return index < VARYING_SLOT_VAR0 + (GLint) ctx->Const.MaxVarying;
-      default:
-         return GL_FALSE;
-      }
-
-   case PROGRAM_ADDRESS:
-      return index >= 0 && index < (GLint) c->MaxAddressRegs;
-
-   default:
-      _mesa_problem(ctx,
-                    "unexpected register file in _mesa_valid_register_index()");
-      return GL_FALSE;
-   }
-}
-
-
-
-/**
- * "Post-process" a GPU program.  This is intended to be used for debugging.
- * Example actions include no-op'ing instructions or changing instruction
- * behaviour.
- */
-void
-_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
-{
-   static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
-   GLuint i;
-   GLuint whiteSwizzle;
-   GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
-                                                 (gl_constant_value *) white,
-                                                 4, &whiteSwizzle);
-
-   (void) whiteIndex;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
-
-      (void) n;
-
-      if (_mesa_is_tex_instruction(inst->Opcode)) {
-#if 0
-         /* replace TEX/TXP/TXB with MOV */
-         inst->Opcode = OPCODE_MOV;
-         inst->DstReg.WriteMask = WRITEMASK_XYZW;
-         inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
-         inst->SrcReg[0].Negate = NEGATE_NONE;
-#endif
-
-#if 0
-         /* disable shadow texture mode */
-         inst->TexShadow = 0;
-#endif
-      }
-
-      if (inst->Opcode == OPCODE_TXP) {
-#if 0
-         inst->Opcode = OPCODE_MOV;
-         inst->DstReg.WriteMask = WRITEMASK_XYZW;
-         inst->SrcReg[0].File = PROGRAM_CONSTANT;
-         inst->SrcReg[0].Index = whiteIndex;
-         inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
-         inst->SrcReg[0].Negate = NEGATE_NONE;
-#endif
-#if 0
-         inst->TexShadow = 0;
-#endif
-#if 0
-         inst->Opcode = OPCODE_TEX;
-         inst->TexShadow = 0;
-#endif
-      }
-
-   }
-}
-
 /* Gets the minimum number of shader invocations per fragment.
  * This function is useful to determine if we need to do per
  * sample shading or per fragment shading.
@@ -819,14 +534,14 @@ _mesa_get_min_invocations_per_fragment(struct gl_context *ctx,
        *  forces per-sample shading"
        */
       if (prog->IsSample && !ignore_sample_qualifier)
-         return MAX2(ctx->DrawBuffer->Visual.samples, 1);
+         return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1);
 
       if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID |
                                          SYSTEM_BIT_SAMPLE_POS))
-         return MAX2(ctx->DrawBuffer->Visual.samples, 1);
+         return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1);
       else if (ctx->Multisample.SampleShading)
          return MAX2(ceil(ctx->Multisample.MinSampleShadingValue *
-                          ctx->DrawBuffer->Visual.samples), 1);
+                          _mesa_geometric_samples(ctx->DrawBuffer)), 1);
       else
          return 1;
    }