#include "main/glheader.h"
#include "main/context.h"
+#include "main/framebuffer.h"
#include "main/hash.h"
#include "main/macros.h"
#include "program.h"
/**
* 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);
/* 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;
}
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;
}
}
-/**
- * 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.
}
-
-/**
- * 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.
* 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;
}