diff options
Diffstat (limited to 'src/mesa/shader')
27 files changed, 297 insertions, 151 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index a09be71020e..bdd26b7f3a7 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -54,10 +54,8 @@ having three separate program parameter arrays. #include "main/glheader.h" #include "main/imports.h" #include "main/context.h" -#include "main/macros.h" #include "main/mtypes.h" #include "arbprogparse.h" -#include "program.h" #include "programopt.h" #include "prog_parameter.h" #include "prog_statevars.h" @@ -123,6 +121,8 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target, case OPTION_FOG_LINEAR: program->FogOption = GL_LINEAR; break; default: program->FogOption = GL_NONE; break; } + program->OriginUpperLeft = state.option.OriginUpperLeft; + program->PixelCenterInteger = state.option.PixelCenterInteger; program->UsesKill = state.fragment.UsesKill; diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c index eb537cd1b99..7e3040a6ef4 100644 --- a/src/mesa/shader/arbprogram.c +++ b/src/mesa/shader/arbprogram.c @@ -180,23 +180,24 @@ _mesa_DeletePrograms(GLsizei n, const GLuint *ids) } else if (prog) { /* Unbind program if necessary */ - if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */ - prog->Target == GL_VERTEX_STATE_PROGRAM_NV) { + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + case GL_VERTEX_STATE_PROGRAM_NV: if (ctx->VertexProgram.Current && ctx->VertexProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } - } - else if (prog->Target == GL_FRAGMENT_PROGRAM_NV || - prog->Target == GL_FRAGMENT_PROGRAM_ARB) { + break; + case GL_FRAGMENT_PROGRAM_NV: + case GL_FRAGMENT_PROGRAM_ARB: if (ctx->FragmentProgram.Current && ctx->FragmentProgram.Current->Base.Id == ids[i]) { /* unbind this currently bound program */ _mesa_BindProgram(prog->Target, 0); } - } - else { + break; + default: _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); return; } @@ -488,8 +489,13 @@ _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, return; } - if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify) - ctx->Driver.ProgramStringNotify( ctx, target, base ); + if (ctx->Program.ErrorPos == -1) { + /* finally, give the program to the driver for translation/checking */ + if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glProgramStringARB(rejected by driver"); + } + } } @@ -561,6 +567,8 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, } } + + /** * Set a program env parameter register. * \note Called from the GL API dispatcher. @@ -569,10 +577,35 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, */ void GLAPIENTRY _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index, - const GLfloat *params) + const GLfloat *params) { - _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1], - params[2], params[3]); + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); + + if (target == GL_FRAGMENT_PROGRAM_ARB + && ctx->Extensions.ARB_fragment_program) { + if (index >= ctx->Const.FragmentProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter4fv(index)"); + return; + } + memcpy(ctx->FragmentProgram.Parameters[index], params, + 4 * sizeof(GLfloat)); + } + else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */ + && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) { + if (index >= ctx->Const.VertexProgram.MaxEnvParams) { + _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter4fv(index)"); + return; + } + memcpy(ctx->VertexProgram.Parameters[index], params, + 4 * sizeof(GLfloat)); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter4fv(target)"); + return; + } } @@ -581,7 +614,6 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params) { GET_CURRENT_CONTEXT(ctx); - GLint i; GLfloat * dest; ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -612,11 +644,7 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, return; } - for ( i = 0 ; i < count ; i++ ) { - COPY_4V(dest, params); - params += 4; - dest += 4; - } + memcpy(dest, params, count * 4 * sizeof(GLfloat)); } @@ -729,8 +757,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params) { GET_CURRENT_CONTEXT(ctx); - struct gl_program *prog; - GLint i; + GLfloat *dest; ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); @@ -745,7 +772,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)"); return; } - prog = &(ctx->FragmentProgram.Current->Base); + dest = ctx->FragmentProgram.Current->Base.LocalParams[index]; } else if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { @@ -753,18 +780,14 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)"); return; } - prog = &(ctx->VertexProgram.Current->Base); + dest = ctx->VertexProgram.Current->Base.LocalParams[index]; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)"); return; } - for (i = 0; i < count; i++) { - ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS); - COPY_4V(prog->LocalParams[index + i], params); - params += 4; - } + memcpy(dest, params, count * 4 * sizeof(GLfloat)); } diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c index e04a05b22ff..ab7b2030d19 100644 --- a/src/mesa/shader/atifragshader.c +++ b/src/mesa/shader/atifragshader.c @@ -378,8 +378,11 @@ _mesa_EndFragmentShaderATI(void) } if (ctx->ATIFragmentShader.Current->cur_pass > 1) ctx->ATIFragmentShader.Current->NumPasses = 2; - else ctx->ATIFragmentShader.Current->NumPasses = 1; - ctx->ATIFragmentShader.Current->cur_pass=0; + else + ctx->ATIFragmentShader.Current->NumPasses = 1; + + ctx->ATIFragmentShader.Current->cur_pass = 0; + #if MESA_DEBUG_ATI_FS for (j = 0; j < MAX_NUM_PASSES_ATI; j++) { for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { @@ -402,8 +405,13 @@ _mesa_EndFragmentShaderATI(void) } } #endif - if (ctx->Driver.ProgramStringNotify) - ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_SHADER_ATI, NULL ); + + if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) { + ctx->ATIFragmentShader.Current->isValid = GL_FALSE; + /* XXX is this the right error? */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEndFragmentShaderATI(driver rejected shader)"); + } } void GLAPIENTRY diff --git a/src/mesa/shader/lex.yy.c b/src/mesa/shader/lex.yy.c index 68543ae2e12..d1af35fedb6 100644 --- a/src/mesa/shader/lex.yy.c +++ b/src/mesa/shader/lex.yy.c @@ -1043,12 +1043,12 @@ static yyconst flex_int16_t yy_chk[1368] = */ #include "main/glheader.h" #include "main/imports.h" -#include "prog_instruction.h" -#include "prog_statevars.h" +#include "shader/prog_instruction.h" +#include "shader/prog_statevars.h" -#include "symbol_table.h" -#include "program_parser.h" -#include "program_parse.tab.h" +#include "shader/symbol_table.h" +#include "shader/program_parser.h" +#include "shader/program_parse.tab.h" #define require_ARB_vp (yyextra->mode == ARB_vertex) #define require_ARB_fp (yyextra->mode == ARB_fragment) diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c index fd6cbb0f409..87f295e39ae 100644 --- a/src/mesa/shader/nvprogram.c +++ b/src/mesa/shader/nvprogram.c @@ -515,7 +515,7 @@ _mesa_emit_nv_temp_initialization(GLcontext *ctx, struct gl_program *program) { struct prog_instruction *inst; - int i; + GLuint i; if (!ctx->Shader.EmitNVTempInitialization) return; @@ -559,7 +559,7 @@ _mesa_emit_nv_temp_initialization(GLcontext *ctx, void _mesa_setup_nv_temporary_count(GLcontext *ctx, struct gl_program *program) { - int i; + GLuint i; program->NumTemporaries = 0; for (i = 0; i < program->NumInstructions; i++) { diff --git a/src/mesa/shader/nvvertparse.c b/src/mesa/shader/nvvertparse.c index 8574016050c..baff7658d18 100644 --- a/src/mesa/shader/nvvertparse.c +++ b/src/mesa/shader/nvvertparse.c @@ -40,7 +40,6 @@ #include "main/glheader.h" #include "main/context.h" #include "main/imports.h" -#include "main/macros.h" #include "nvprogram.h" #include "nvvertparse.h" #include "prog_instruction.h" diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c index 7f034520cd4..7781cb3f7f1 100644 --- a/src/mesa/shader/prog_execute.c +++ b/src/mesa/shader/prog_execute.c @@ -38,7 +38,6 @@ #include "main/glheader.h" #include "main/colormac.h" #include "main/context.h" -#include "program.h" #include "prog_execute.h" #include "prog_instruction.h" #include "prog_parameter.h" @@ -352,6 +351,28 @@ fetch_vector1(const struct prog_src_register *source, } +static GLuint +fetch_vector1ui(const struct prog_src_register *source, + const struct gl_program_machine *machine) +{ + const GLuint *src = (GLuint *) get_src_register_pointer(source, machine); + GLuint result; + + ASSERT(src); + + result = src[GET_SWZ(source->Swizzle, 0)]; + + if (source->Abs) { + result = FABSF(result); + } + if (source->Negate) { + result = -result; + } + + return result; +} + + /** * Fetch texel from texture. Use partial derivatives when possible. */ @@ -680,6 +701,9 @@ _mesa_execute_program(GLcontext * ctx, GLfloat t[4]; fetch_vector4(&inst->SrcReg[0], machine, t); machine->AddressReg[0][0] = IFLOOR(t[0]); + if (DEBUG_PROG) { + printf("ARL %d\n", machine->AddressReg[0][0]); + } } break; case OPCODE_BGNLOOP: @@ -996,12 +1020,12 @@ _mesa_execute_program(GLcontext * ctx, /* XXX we could probably just use pow() here */ if (a[0] > 0.0F) { if (a[1] == 0.0 && a[3] == 0.0) - result[2] = 1.0; + result[2] = 1.0F; else result[2] = (GLfloat) _mesa_pow(a[1], a[3]); } else { - result[2] = 0.0; + result[2] = 0.0F; } result[3] = 1.0F; store_vector4(inst, machine, result); @@ -1668,13 +1692,11 @@ _mesa_execute_program(GLcontext * ctx, break; case OPCODE_UP2H: /* unpack two 16-bit floats */ { - GLfloat a[4], result[4]; - fi_type fi; - GLhalfNV hx, hy; - fetch_vector1(&inst->SrcReg[0], machine, a); - fi.f = a[0]; - hx = fi.i & 0xffff; - hy = fi.i >> 16; + const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine); + GLfloat result[4]; + GLushort hx, hy; + hx = raw & 0xffff; + hy = raw >> 16; result[0] = result[2] = _mesa_half_to_float(hx); result[1] = result[3] = _mesa_half_to_float(hy); store_vector4(inst, machine, result); @@ -1682,13 +1704,11 @@ _mesa_execute_program(GLcontext * ctx, break; case OPCODE_UP2US: /* unpack two GLushorts */ { - GLfloat a[4], result[4]; - fi_type fi; + const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine); + GLfloat result[4]; GLushort usx, usy; - fetch_vector1(&inst->SrcReg[0], machine, a); - fi.f = a[0]; - usx = fi.i & 0xffff; - usy = fi.i >> 16; + usx = raw & 0xffff; + usy = raw >> 16; result[0] = result[2] = usx * (1.0f / 65535.0f); result[1] = result[3] = usy * (1.0f / 65535.0f); store_vector4(inst, machine, result); @@ -1696,27 +1716,23 @@ _mesa_execute_program(GLcontext * ctx, break; case OPCODE_UP4B: /* unpack four GLbytes */ { - GLfloat a[4], result[4]; - fi_type fi; - fetch_vector1(&inst->SrcReg[0], machine, a); - fi.f = a[0]; - result[0] = (((fi.i >> 0) & 0xff) - 128) / 127.0F; - result[1] = (((fi.i >> 8) & 0xff) - 128) / 127.0F; - result[2] = (((fi.i >> 16) & 0xff) - 128) / 127.0F; - result[3] = (((fi.i >> 24) & 0xff) - 128) / 127.0F; + const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine); + GLfloat result[4]; + result[0] = (((raw >> 0) & 0xff) - 128) / 127.0F; + result[1] = (((raw >> 8) & 0xff) - 128) / 127.0F; + result[2] = (((raw >> 16) & 0xff) - 128) / 127.0F; + result[3] = (((raw >> 24) & 0xff) - 128) / 127.0F; store_vector4(inst, machine, result); } break; case OPCODE_UP4UB: /* unpack four GLubytes */ { - GLfloat a[4], result[4]; - fi_type fi; - fetch_vector1(&inst->SrcReg[0], machine, a); - fi.f = a[0]; - result[0] = ((fi.i >> 0) & 0xff) / 255.0F; - result[1] = ((fi.i >> 8) & 0xff) / 255.0F; - result[2] = ((fi.i >> 16) & 0xff) / 255.0F; - result[3] = ((fi.i >> 24) & 0xff) / 255.0F; + const GLuint raw = fetch_vector1ui(&inst->SrcReg[0], machine); + GLfloat result[4]; + result[0] = ((raw >> 0) & 0xff) / 255.0F; + result[1] = ((raw >> 8) & 0xff) / 255.0F; + result[2] = ((raw >> 16) & 0xff) / 255.0F; + result[3] = ((raw >> 24) & 0xff) / 255.0F; store_vector4(inst, machine, result); } break; diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index ce411731b22..e1ec52254c0 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -459,7 +459,7 @@ _mesa_remove_extra_move_use(struct gl_program *prog) */ for (j = i + 1; j < prog->NumInstructions; j++) { struct prog_instruction *inst2 = prog->Instructions + j; - int arg; + GLuint arg; if (_mesa_is_flow_control_opcode(inst2->Opcode)) break; @@ -867,7 +867,7 @@ find_live_intervals(struct gl_program *prog, _mesa_printf("Reg[%d] live [%d, %d]:", inv->Reg, inv->Start, inv->End); if (1) { - int j; + GLuint j; for (j = 0; j < inv->Start; j++) _mesa_printf(" "); for (j = inv->Start; j <= inv->End; j++) @@ -945,7 +945,7 @@ _mesa_reallocate_registers(struct gl_program *prog) */ { GLint j; - for (j = 0; j < activeIntervals.Num; j++) { + for (j = 0; j < (GLint) activeIntervals.Num; j++) { const struct interval *inv = activeIntervals.Intervals + j; if (inv->End >= live->Start) { /* Stop now. Since the activeInterval list is sorted @@ -994,7 +994,7 @@ _mesa_reallocate_registers(struct gl_program *prog) } } - if (maxTemp + 1 < liveIntervals.Num) { + if (maxTemp + 1 < (GLint) liveIntervals.Num) { /* OK, we've reduced the number of registers needed. * Scan the program and replace all the old temporary register * indexes with the new indexes. diff --git a/src/mesa/shader/prog_parameter.h b/src/mesa/shader/prog_parameter.h index 699cb0c7356..1111c859769 100644 --- a/src/mesa/shader/prog_parameter.h +++ b/src/mesa/shader/prog_parameter.h @@ -43,6 +43,7 @@ #define PROG_PARAM_BIT_INVARIANT 0x2 /**< for varying vars (GLSL 1.20) */ #define PROG_PARAM_BIT_FLAT 0x4 /**< for varying vars (GLSL 1.30) */ #define PROG_PARAM_BIT_LINEAR 0x8 /**< for varying vars (GLSL 1.30) */ +#define PROG_PARAM_BIT_CYL_WRAP 0x10 /**< XXX gallium debug */ /*@}*/ diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c index 9f9789e010c..54fd88ad4fb 100644 --- a/src/mesa/shader/prog_print.c +++ b/src/mesa/shader/prog_print.c @@ -150,6 +150,10 @@ arb_input_attrib_string(GLint index, GLenum progType) "fragment.varying[7]" }; + /* sanity checks */ + assert(strcmp(vertAttribs[VERT_ATTRIB_TEX0], "vertex.texcoord[0]") == 0); + assert(strcmp(vertAttribs[VERT_ATTRIB_GENERIC15], "vertex.attrib[15]") == 0); + if (progType == GL_VERTEX_PROGRAM_ARB) { assert(index < sizeof(vertAttribs) / sizeof(vertAttribs[0])); return vertAttribs[index]; @@ -162,6 +166,43 @@ arb_input_attrib_string(GLint index, GLenum progType) /** + * Print a vertex program's InputsRead field in human-readable format. + * For debugging. + */ +void +_mesa_print_vp_inputs(GLbitfield inputs) +{ + _mesa_printf("VP Inputs 0x%x: \n", inputs); + while (inputs) { + GLint attr = _mesa_ffs(inputs) - 1; + const char *name = arb_input_attrib_string(attr, + GL_VERTEX_PROGRAM_ARB); + _mesa_printf(" %d: %s\n", attr, name); + inputs &= ~(1 << attr); + } +} + + +/** + * Print a fragment program's InputsRead field in human-readable format. + * For debugging. + */ +void +_mesa_print_fp_inputs(GLbitfield inputs) +{ + _mesa_printf("FP Inputs 0x%x: \n", inputs); + while (inputs) { + GLint attr = _mesa_ffs(inputs) - 1; + const char *name = arb_input_attrib_string(attr, + GL_FRAGMENT_PROGRAM_ARB); + _mesa_printf(" %d: %s\n", attr, name); + inputs &= ~(1 << attr); + } +} + + + +/** * Return ARB_v/f_prog-style output attrib string. */ static const char * diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h index fc286ded540..9ab74560169 100644 --- a/src/mesa/shader/prog_print.h +++ b/src/mesa/shader/prog_print.h @@ -37,6 +37,12 @@ typedef enum { } gl_prog_print_mode; +extern void +_mesa_print_vp_inputs(GLbitfield inputs); + +extern void +_mesa_print_fp_inputs(GLbitfield inputs); + extern const char * _mesa_condcode_string(GLuint condcode); diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c index 460ecd44a84..a0be1acfcab 100644 --- a/src/mesa/shader/prog_statevars.c +++ b/src/mesa/shader/prog_statevars.c @@ -31,7 +31,6 @@ #include "main/glheader.h" #include "main/context.h" -#include "main/hash.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" @@ -303,9 +302,11 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], matrix = &ctx->_ModelProjectMatrix; } else if (mat == STATE_TEXTURE_MATRIX) { + ASSERT(index < Elements(ctx->TextureMatrixStack)); matrix = ctx->TextureMatrixStack[index].Top; } else if (mat == STATE_PROGRAM_MATRIX) { + ASSERT(index < Elements(ctx->ProgramMatrixStack)); matrix = ctx->ProgramMatrixStack[index].Top; } else if (mat == STATE_COLOR_MATRIX) { @@ -1140,7 +1141,9 @@ _mesa_load_tracked_matrices(GLcontext *ctx) mat = ctx->ProjectionMatrixStack.Top; } else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) { - mat = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top; + GLuint unit = MIN2(ctx->Texture.CurrentUnit, + Elements(ctx->TextureMatrixStack) - 1); + mat = ctx->TextureMatrixStack[unit].Top; } else if (ctx->VertexProgram.TrackMatrix[i] == GL_COLOR) { mat = ctx->ColorMatrixStack.Top; @@ -1152,7 +1155,7 @@ _mesa_load_tracked_matrices(GLcontext *ctx) else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV && ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) { GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV; - ASSERT(n < MAX_PROGRAM_MATRICES); + ASSERT(n < Elements(ctx->ProgramMatrixStack)); mat = ctx->ProgramMatrixStack[n].Top; } else { diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index 6b8d94e6614..aaf5f96e2a5 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -580,7 +580,7 @@ _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { - if (inst->BranchTarget > start) { + if (inst->BranchTarget > (GLint) start) { inst->BranchTarget -= count; } } @@ -677,6 +677,8 @@ _mesa_combine_programs(GLcontext *ctx, const GLuint lenB = progB->NumInstructions; const GLuint numParamsA = _mesa_num_parameters(progA->Parameters); const GLuint newLength = lenA + lenB; + GLboolean usedTemps[MAX_PROGRAM_TEMPS]; + GLuint firstTemp = 0; GLbitfield inputsB; GLuint i; @@ -698,6 +700,10 @@ _mesa_combine_programs(GLcontext *ctx, newProg->Instructions = newInst; newProg->NumInstructions = newLength; + /* find used temp regs (we may need new temps below) */ + _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY, + usedTemps, MAX_PROGRAM_TEMPS); + if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { struct gl_fragment_program *fprogA, *fprogB, *newFprog; GLbitfield progB_inputsRead = progB->InputsRead; @@ -741,12 +747,15 @@ _mesa_combine_programs(GLcontext *ctx, */ if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) && (progB_inputsRead & FRAG_BIT_COL0)) { - GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY); + GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS, + firstTemp); if (tempReg < 0) { _mesa_problem(ctx, "No free temp regs found in " "_mesa_combine_programs(), using 31"); tempReg = 31; } + firstTemp = tempReg + 1; + /* replace writes to result.color[0] with tempReg */ replace_registers(newInst, lenA, PROGRAM_OUTPUT, FRAG_RESULT_COLOR, @@ -784,53 +793,64 @@ _mesa_combine_programs(GLcontext *ctx, } - - /** - * Scan the given program to find a free register of the given type. - * \param regFile - PROGRAM_INPUT, PROGRAM_OUTPUT or PROGRAM_TEMPORARY + * Populate the 'used' array with flags indicating which registers (TEMPs, + * INPUTs, OUTPUTs, etc, are used by the given program. + * \param file type of register to scan for + * \param used returns true/false flags for in use / free + * \param usedSize size of the 'used' array */ -GLint -_mesa_find_free_register(const struct gl_program *prog, GLuint regFile) +void +_mesa_find_used_registers(const struct gl_program *prog, + gl_register_file file, + GLboolean used[], GLuint usedSize) { - GLboolean used[MAX_PROGRAM_TEMPS]; - GLuint i, k; - - assert(regFile == PROGRAM_INPUT || - regFile == PROGRAM_OUTPUT || - regFile == PROGRAM_TEMPORARY); + GLuint i, j; - _mesa_memset(used, 0, sizeof(used)); + _mesa_memset(used, 0, usedSize); 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); - /* check dst reg first */ - if (inst->DstReg.File == regFile) { + if (inst->DstReg.File == file) { used[inst->DstReg.Index] = GL_TRUE; } - else { - /* check src regs otherwise */ - for (k = 0; k < n; k++) { - if (inst->SrcReg[k].File == regFile) { - used[inst->SrcReg[k].Index] = GL_TRUE; - break; - } + + for (j = 0; j < n; j++) { + if (inst->SrcReg[j].File == file) { + used[inst->SrcReg[j].Index] = GL_TRUE; } } } +} - for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { + +/** + * Scan the given 'used' register flag array for the first entry + * that's >= firstReg. + * \param used vector of flags indicating registers in use (as returned + * by _mesa_find_used_registers()) + * \param usedSize size of the 'used' array + * \param firstReg first register to start searching at + * \return index of unused register, or -1 if none. + */ +GLint +_mesa_find_free_register(const GLboolean used[], + GLuint usedSize, GLuint firstReg) +{ + GLuint i; + + assert(firstReg < usedSize); + + for (i = firstReg; i < usedSize; i++) if (!used[i]) return i; - } return -1; } - /** * "Post-process" a GPU program. This is intended to be used for debugging. * Example actions include no-op'ing instructions or changing instruction diff --git a/src/mesa/shader/program.h b/src/mesa/shader/program.h index 56a4191f578..0187a2c55ff 100644 --- a/src/mesa/shader/program.h +++ b/src/mesa/shader/program.h @@ -119,8 +119,14 @@ _mesa_combine_programs(GLcontext *ctx, const struct gl_program *progA, const struct gl_program *progB); +extern void +_mesa_find_used_registers(const struct gl_program *prog, + gl_register_file file, + GLboolean used[], GLuint usedSize); + extern GLint -_mesa_find_free_register(const struct gl_program *prog, GLuint regFile); +_mesa_find_free_register(const GLboolean used[], + GLuint maxRegs, GLuint firstReg); extern void _mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog); diff --git a/src/mesa/shader/program_lexer.l b/src/mesa/shader/program_lexer.l index e2acb3c0c96..83bc5089d9e 100644 --- a/src/mesa/shader/program_lexer.l +++ b/src/mesa/shader/program_lexer.l @@ -23,12 +23,12 @@ */ #include "main/glheader.h" #include "main/imports.h" -#include "prog_instruction.h" -#include "prog_statevars.h" +#include "shader/prog_instruction.h" +#include "shader/prog_statevars.h" -#include "symbol_table.h" -#include "program_parser.h" -#include "program_parse.tab.h" +#include "shader/symbol_table.h" +#include "shader/program_parser.h" +#include "shader/program_parse.tab.h" #define require_ARB_vp (yyextra->mode == ARB_vertex) #define require_ARB_fp (yyextra->mode == ARB_fragment) diff --git a/src/mesa/shader/program_parse.tab.c b/src/mesa/shader/program_parse.tab.c index b12dcee9dfa..2adfb409739 100644 --- a/src/mesa/shader/program_parse.tab.c +++ b/src/mesa/shader/program_parse.tab.c @@ -98,14 +98,14 @@ #include "main/mtypes.h" #include "main/imports.h" -#include "program.h" -#include "prog_parameter.h" -#include "prog_parameter_layout.h" -#include "prog_statevars.h" -#include "prog_instruction.h" - -#include "symbol_table.h" -#include "program_parser.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_parameter_layout.h" +#include "shader/prog_statevars.h" +#include "shader/prog_instruction.h" + +#include "shader/symbol_table.h" +#include "shader/program_parser.h" extern void *yy_scan_string(char *); extern void yy_delete_buffer(void *); diff --git a/src/mesa/shader/program_parse.y b/src/mesa/shader/program_parse.y index 5c5d8d75908..3880d549172 100644 --- a/src/mesa/shader/program_parse.y +++ b/src/mesa/shader/program_parse.y @@ -27,14 +27,14 @@ #include "main/mtypes.h" #include "main/imports.h" -#include "program.h" -#include "prog_parameter.h" -#include "prog_parameter_layout.h" -#include "prog_statevars.h" -#include "prog_instruction.h" - -#include "symbol_table.h" -#include "program_parser.h" +#include "shader/program.h" +#include "shader/prog_parameter.h" +#include "shader/prog_parameter_layout.h" +#include "shader/prog_statevars.h" +#include "shader/prog_instruction.h" + +#include "shader/symbol_table.h" +#include "shader/program_parser.h" extern void *yy_scan_string(char *); extern void yy_delete_buffer(void *); diff --git a/src/mesa/shader/program_parse_extra.c b/src/mesa/shader/program_parse_extra.c index 0656c5eaa8e..ae98b782b70 100644 --- a/src/mesa/shader/program_parse_extra.c +++ b/src/mesa/shader/program_parse_extra.c @@ -216,6 +216,18 @@ _mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option) state->option.Shadow = 1; return 1; } + } else if (strncmp(option, "fragment_coord_", 15) == 0) { + option += 15; + if (state->ctx->Extensions.ARB_fragment_coord_conventions) { + if (strcmp(option, "origin_upper_left") == 0) { + state->option.OriginUpperLeft = 1; + return 1; + } + else if (strcmp(option, "pixel_center_integer") == 0) { + state->option.PixelCenterInteger = 1; + return 1; + } + } } } else if (strncmp(option, "NV_fragment_program", 19) == 0) { option += 19; diff --git a/src/mesa/shader/program_parser.h b/src/mesa/shader/program_parser.h index 69396ca2c0f..730466c30f5 100644 --- a/src/mesa/shader/program_parser.h +++ b/src/mesa/shader/program_parser.h @@ -209,6 +209,8 @@ struct asm_parser_state { unsigned TexRect:1; unsigned TexArray:1; unsigned NV_fragment:1; + unsigned OriginUpperLeft:1; + unsigned PixelCenterInteger:1; } option; struct { diff --git a/src/mesa/shader/programopt.c b/src/mesa/shader/programopt.c index 9514545709d..fb2ebe6338f 100644 --- a/src/mesa/shader/programopt.c +++ b/src/mesa/shader/programopt.c @@ -495,6 +495,11 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type) GLuint i; GLint outputMap[VERT_RESULT_MAX]; GLuint numVaryingReads = 0; + GLboolean usedTemps[MAX_PROGRAM_TEMPS]; + GLuint firstTemp = 0; + + _mesa_find_used_registers(prog, PROGRAM_TEMPORARY, + usedTemps, MAX_PROGRAM_TEMPS); assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT); assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING); @@ -513,8 +518,10 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type) const GLuint var = inst->SrcReg[j].Index; if (outputMap[var] == -1) { numVaryingReads++; - outputMap[var] = _mesa_find_free_register(prog, - PROGRAM_TEMPORARY); + outputMap[var] = _mesa_find_free_register(usedTemps, + MAX_PROGRAM_TEMPS, + firstTemp); + firstTemp = outputMap[var] + 1; } inst->SrcReg[j].File = PROGRAM_TEMPORARY; inst->SrcReg[j].Index = outputMap[var]; diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 453cd3964af..e8eaa9c1031 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -39,10 +39,8 @@ #include "main/glheader.h" #include "main/context.h" #include "main/hash.h" -#include "main/macros.h" #include "shader/program.h" #include "shader/prog_parameter.h" -#include "shader/prog_print.h" #include "shader/prog_statevars.h" #include "shader/prog_uniform.h" #include "shader/shader_api.h" @@ -957,7 +955,7 @@ _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, if (size) { GLint typeSize = sizeof_glsl_type(param->DataType); - if (param->Size > typeSize) { + if ((GLint) param->Size > typeSize) { /* This is an array. * Array elements are placed on vector[4] boundaries so they're * a multiple of four floats. We round typeSize up to next multiple @@ -1717,7 +1715,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, */ FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM); _mesa_update_shader_textures_used(program); - ctx->Driver.ProgramStringNotify(ctx, program->Target, program); + /* Do we need to care about the return value here? + * This should not be the first time the driver was notified of + * this program. + */ + (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program); } } else { @@ -1728,7 +1730,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, const GLint typeSize = sizeof_glsl_type(param->DataType); GLsizei k, i; - if (param->Size > typeSize) { + if ((GLint) param->Size > typeSize) { /* an array */ /* we'll ignore extra data below */ } @@ -1913,7 +1915,7 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, GLuint mat, row, col; GLuint src = 0; const struct gl_program_parameter * param = &program->Parameters->Parameters[index]; - const GLint slots = (param->Size + 3) / 4; + const GLuint slots = (param->Size + 3) / 4; const GLint typeSize = sizeof_glsl_type(param->DataType); GLint nr, nc; @@ -1925,7 +1927,7 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, return; } - if (param->Size <= typeSize) { + if ((GLint) param->Size <= typeSize) { /* non-array: count must be at most one; count == 0 is handled by the loop below */ if (count > 1) { _mesa_error(ctx, GL_INVALID_OPERATION, diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index e5809509c93..0a9f0b97fb9 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -36,7 +36,6 @@ #include "shader/prog_parameter.h" #include "shader/prog_statevars.h" #include "shader/slang/slang_ir.h" -#include "shader/slang/slang_emit.h" #include "shader/slang/slang_builtin.h" diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 372a9acdd03..83098b7350e 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -3196,7 +3196,7 @@ _slang_unroll_for_loop(slang_assemble_ctx * A, const slang_operation *oper) newOper = slang_operation_new(1); newOper->type = SLANG_OPER_LITERAL_INT; newOper->literal_size = 1; - newOper->literal[0] = iter; + newOper->literal[0] = (GLfloat) iter; /* replace instances of the loop variable with newOper */ slang_substitute(A, body, 1, &oldVar, &newOper, GL_FALSE); diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 6499cfcb2fe..63d10f45978 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -40,14 +40,11 @@ #include "slang_codegen.h" #include "slang_compile.h" #include "slang_storage.h" -#include "slang_emit.h" #include "slang_log.h" #include "slang_mem.h" #include "slang_vartable.h" #include "slang_simplify.h" -#include "slang_print.h" - /* * This is a straightforward implementation of the slang front-end * compiler. Lots of error-checking functionality is missing but diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index ce3f6ab7ea2..c9ecbd275b8 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -38,7 +38,6 @@ #include "main/imports.h" #include "main/context.h" -#include "main/macros.h" #include "shader/program.h" #include "shader/prog_instruction.h" #include "shader/prog_parameter.h" diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index ed27821a951..df524ce0787 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -31,7 +31,6 @@ #include "main/imports.h" #include "main/context.h" -#include "main/hash.h" #include "main/macros.h" #include "shader/program.h" #include "shader/prog_instruction.h" @@ -720,6 +719,7 @@ _slang_link(GLcontext *ctx, { const struct gl_vertex_program *vertProg = NULL; const struct gl_fragment_program *fragProg = NULL; + GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE; GLuint numSamplers = 0; GLuint i; @@ -872,8 +872,8 @@ _slang_link(GLcontext *ctx, _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base); /* notify driver that a new fragment program has been compiled/linked */ - ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, - &shProg->FragmentProgram->Base); + vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, + &shProg->FragmentProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { _mesa_printf("Mesa pre-link fragment program:\n"); _mesa_print_program(&fragProg->Base); @@ -890,8 +890,8 @@ _slang_link(GLcontext *ctx, _mesa_update_shader_textures_used(&shProg->VertexProgram->Base); /* notify driver that a new vertex program has been compiled/linked */ - ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, - &shProg->VertexProgram->Base); + fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, + &shProg->VertexProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { _mesa_printf("Mesa pre-link vertex program:\n"); _mesa_print_program(&vertProg->Base); @@ -919,6 +919,12 @@ _slang_link(GLcontext *ctx, } } - shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); + if (!vertNotify || !fragNotify) { + /* driver rejected one/both of the vertex/fragment programs */ + link_error(shProg, "Vertex and/or fragment program rejected by driver\n"); + } + else { + shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); + } } diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c index d7d2b4fbfd0..4f6b8541c5a 100644 --- a/src/mesa/shader/slang/slang_log.c +++ b/src/mesa/shader/slang/slang_log.c @@ -24,7 +24,6 @@ */ #include "main/imports.h" -#include "main/context.h" #include "slang_log.h" #include "slang_utility.h" |