X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi915%2Fi915_fragprog.c;h=1a5943c87fba4dc5ae64f62db266934d3638b944;hb=0febd0ecfd1e2a36381ab7793811b9c7891ed82f;hp=c00ee415b6b19336335843db3e25f98310080aec;hpb=dbf3a15313eed930a3d8fdde12e457259c43651b;p=mesa.git diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c index c00ee415b6b..1a5943c87fb 100644 --- a/src/mesa/drivers/dri/i915/i915_fragprog.c +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -72,6 +72,22 @@ static const GLfloat cos_constants[4] = { 1.0, -1.0 / (6 * 5 * 4 * 3 * 2 * 1) }; +/* texcoord_mapping[unit] = index | TEXCOORD_{TEX,VAR} */ +#define TEXCOORD_TEX (0<<7) +#define TEXCOORD_VAR (1<<7) + +static unsigned +get_texcoord_mapping(struct i915_fragment_program *p, uint8_t texcoord) +{ + for (unsigned i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { + if (p->texcoord_mapping[i] == texcoord) + return i; + } + + /* blah */ + return p->ctx->Const.MaxTextureCoordUnits - 1; +} + /** * Retrieve a ureg for the given source register. Will emit * constants, apply swizzling and negation as needed. @@ -82,6 +98,7 @@ src_vector(struct i915_fragment_program *p, const struct gl_fragment_program *program) { GLuint src; + unsigned unit; switch (source->File) { @@ -97,43 +114,47 @@ src_vector(struct i915_fragment_program *p, break; case PROGRAM_INPUT: switch (source->Index) { - case FRAG_ATTRIB_WPOS: + case VARYING_SLOT_POS: src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL); break; - case FRAG_ATTRIB_COL0: + case VARYING_SLOT_COL0: src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); break; - case FRAG_ATTRIB_COL1: + case VARYING_SLOT_COL1: src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ); src = swizzle(src, X, Y, Z, ONE); break; - case FRAG_ATTRIB_FOGC: + case VARYING_SLOT_FOGC: src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W); src = swizzle(src, W, ZERO, ZERO, ONE); break; - case FRAG_ATTRIB_TEX0: - case FRAG_ATTRIB_TEX1: - case FRAG_ATTRIB_TEX2: - case FRAG_ATTRIB_TEX3: - case FRAG_ATTRIB_TEX4: - case FRAG_ATTRIB_TEX5: - case FRAG_ATTRIB_TEX6: - case FRAG_ATTRIB_TEX7: + case VARYING_SLOT_TEX0: + case VARYING_SLOT_TEX1: + case VARYING_SLOT_TEX2: + case VARYING_SLOT_TEX3: + case VARYING_SLOT_TEX4: + case VARYING_SLOT_TEX5: + case VARYING_SLOT_TEX6: + case VARYING_SLOT_TEX7: + unit = get_texcoord_mapping(p, (source->Index - + VARYING_SLOT_TEX0) | TEXCOORD_TEX); src = i915_emit_decl(p, REG_TYPE_T, - T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0), + T_TEX0 + unit, D0_CHANNEL_ALL); break; - case FRAG_ATTRIB_VAR0: - case FRAG_ATTRIB_VAR0 + 1: - case FRAG_ATTRIB_VAR0 + 2: - case FRAG_ATTRIB_VAR0 + 3: - case FRAG_ATTRIB_VAR0 + 4: - case FRAG_ATTRIB_VAR0 + 5: - case FRAG_ATTRIB_VAR0 + 6: - case FRAG_ATTRIB_VAR0 + 7: + case VARYING_SLOT_VAR0: + case VARYING_SLOT_VAR0 + 1: + case VARYING_SLOT_VAR0 + 2: + case VARYING_SLOT_VAR0 + 3: + case VARYING_SLOT_VAR0 + 4: + case VARYING_SLOT_VAR0 + 5: + case VARYING_SLOT_VAR0 + 6: + case VARYING_SLOT_VAR0 + 7: + unit = get_texcoord_mapping(p, (source->Index - + VARYING_SLOT_VAR0) | TEXCOORD_VAR); src = i915_emit_decl(p, REG_TYPE_T, - T_TEX0 + (source->Index - FRAG_ATTRIB_VAR0), + T_TEX0 + unit, D0_CHANNEL_ALL); break; @@ -146,6 +167,7 @@ src_vector(struct i915_fragment_program *p, case PROGRAM_OUTPUT: switch (source->Index) { case FRAG_RESULT_COLOR: + case FRAG_RESULT_DATA0: src = UREG(REG_TYPE_OC, 0); break; case FRAG_RESULT_DEPTH: @@ -160,25 +182,11 @@ src_vector(struct i915_fragment_program *p, /* Various paramters and env values. All emitted to * hardware as program constants. */ - case PROGRAM_LOCAL_PARAM: - src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]); - break; - - case PROGRAM_ENV_PARAM: - src = - i915_emit_param4fv(p, - p->ctx->FragmentProgram.Parameters[source-> - Index]); - break; - case PROGRAM_CONSTANT: case PROGRAM_STATE_VAR: - case PROGRAM_NAMED_PARAM: case PROGRAM_UNIFORM: - src = - i915_emit_param4fv(p, - program->Base.Parameters->ParameterValues[source-> - Index]); + src = i915_emit_param4fv(p, + &program->Base.Parameters->ParameterValues[source->Index][0].f); break; default: @@ -210,6 +218,7 @@ get_result_vector(struct i915_fragment_program *p, case PROGRAM_OUTPUT: switch (inst->DstReg.Index) { case FRAG_RESULT_COLOR: + case FRAG_RESULT_DATA0: return UREG(REG_TYPE_OC, 0); case FRAG_RESULT_DEPTH: p->depth_written = 1; @@ -232,7 +241,7 @@ get_result_flags(const struct prog_instruction *inst) { GLuint flags = 0; - if (inst->SaturateMode == SATURATE_ZERO_ONE) + if (inst->Saturate) flags |= A0_DEST_SATURATE; if (inst->DstReg.WriteMask & WRITEMASK_X) flags |= A0_DEST_CHANNEL_X; @@ -269,7 +278,7 @@ translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit) #define EMIT_TEX( OP ) \ do { \ GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget ); \ - const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; \ + const struct gl_fragment_program *program = &p->FragProg; \ GLuint unit = program->Base.SamplerUnits[inst->TexSrcUnit]; \ GLuint sampler = i915_emit_decl(p, REG_TYPE_S, \ unit, dim); \ @@ -302,10 +311,11 @@ do { \ /* * TODO: consider moving this into core */ -static void calc_live_regs( struct i915_fragment_program *p ) +static bool calc_live_regs( struct i915_fragment_program *p ) { - const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; - GLuint regsUsed = 0xffff0000; + const struct gl_fragment_program *program = &p->FragProg; + GLuint regsUsed = ~((1 << I915_MAX_TEMPORARY) - 1); + uint8_t live_components[I915_MAX_TEMPORARY] = { 0, }; GLint i; for (i = program->Base.NumInstructions - 1; i >= 0; i--) { @@ -314,23 +324,44 @@ static void calc_live_regs( struct i915_fragment_program *p ) int a; /* Register is written to: unmark as live for this and preceeding ops */ - if (inst->DstReg.File == PROGRAM_TEMPORARY) - regsUsed &= ~(1 << inst->DstReg.Index); + if (inst->DstReg.File == PROGRAM_TEMPORARY) { + if (inst->DstReg.Index >= I915_MAX_TEMPORARY) + return false; + + live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask; + if (live_components[inst->DstReg.Index] == 0) + regsUsed &= ~(1 << inst->DstReg.Index); + } for (a = 0; a < opArgs; a++) { /* Register is read from: mark as live for this and preceeding ops */ - if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) + if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) { + unsigned c; + + if (inst->SrcReg[a].Index >= I915_MAX_TEMPORARY) + return false; + regsUsed |= 1 << inst->SrcReg[a].Index; + + for (c = 0; c < 4; c++) { + const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c); + + if (field <= SWIZZLE_W) + live_components[inst->SrcReg[a].Index] |= (1U << field); + } + } } p->usedRegs[i] = regsUsed; } + + return true; } static GLuint get_live_regs( struct i915_fragment_program *p, const struct prog_instruction *inst ) { - const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; + const struct gl_fragment_program *program = &p->FragProg; GLuint nr = inst - program->Base.Instructions; return p->usedRegs[nr]; @@ -351,8 +382,7 @@ static GLuint get_live_regs( struct i915_fragment_program *p, static void upload_program(struct i915_fragment_program *p) { - const struct gl_fragment_program *program = - p->ctx->FragmentProgram._Current; + const struct gl_fragment_program *program = &p->FragProg; const struct prog_instruction *inst = program->Base.Instructions; if (INTEL_DEBUG & DEBUG_WM) @@ -380,7 +410,10 @@ upload_program(struct i915_fragment_program *p) /* Not always needed: */ - calc_live_regs(p); + if (!calc_live_regs(p)) { + i915_program_error(p, "Could not allocate registers"); + return; + } while (1) { GLuint src0, src1, src2, flags; @@ -569,10 +602,14 @@ upload_program(struct i915_fragment_program *p) if (inst->DstReg.CondMask == COND_TR) { tmp = i915_get_utemp(p); + /* The KIL instruction discards the fragment if any component of + * the source is < 0. Emit an immediate operand of {-1}.xywz. + */ i915_emit_texld(p, get_live_regs(p, inst), tmp, A0_DEST_CHANNEL_ALL, 0, /* use a dummy dest reg */ - swizzle(tmp, ONE, ONE, ONE, ONE), /* always */ + negate(swizzle(tmp, ONE, ONE, ONE, ONE), + 1, 1, 1, 1), T0_TEXKILL); } else { p->error = 1; @@ -655,21 +692,7 @@ upload_program(struct i915_fragment_program *p) break; case OPCODE_MIN: - src0 = src_vector(p, &inst->SrcReg[0], program); - src1 = src_vector(p, &inst->SrcReg[1], program); - tmp = i915_get_utemp(p); - flags = get_result_flags(inst); - - i915_emit_arith(p, - A0_MAX, - tmp, flags & A0_DEST_CHANNEL_ALL, 0, - negate(src0, 1, 1, 1, 1), - negate(src1, 1, 1, 1, 1), 0); - - i915_emit_arith(p, - A0_MOV, - get_result_vector(p, inst), - flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0); + EMIT_2ARG_ARITH(A0_MIN); break; case OPCODE_MOV: @@ -791,23 +814,52 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 >= src2 */ + /* If both operands are uniforms or constants, we get 5 instructions + * like: + * + * U[1] = MOV CONST[1] + * U[0].xyz = SGE CONST[0].xxxx, U[1] + * U[1] = MOV CONST[1].-x-y-z-w + * R[0].xyz = SGE CONST[0].-x-x-x-x, U[1] + * R[0].xyz = MUL R[0], U[0] + * + * This code is stupid. Instead of having the individual calls to + * i915_emit_arith generate the moves to utemps, do it in the caller. + * This results in code like: + * + * U[1] = MOV CONST[1] + * U[0].xyz = SGE CONST[0].xxxx, U[1] + * R[0].xyz = SGE CONST[0].-x-x-x-x, U[1].-x-y-z-w + * R[0].xyz = MUL R[0], U[0] + */ + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + + if (GET_UREG_TYPE(src0) == REG_TYPE_CONST + && GET_UREG_TYPE(src1) == REG_TYPE_CONST) { + unsigned tmp = i915_get_utemp(p); + + i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0, + src1, 0, 0); + + src1 = tmp; + } + + /* tmp = src1 >= src2 */ i915_emit_arith(p, A0_SGE, - dst, + tmp, flags, 0, - src_vector(p, &inst->SrcReg[0], program), - src_vector(p, &inst->SrcReg[1], program), + src0, + src1, 0); - /* tmp = src1 <= src2 */ + /* dst = src1 <= src2 */ i915_emit_arith(p, A0_SGE, - tmp, + dst, flags, 0, - negate(src_vector(p, &inst->SrcReg[0], program), - 1, 1, 1, 1), - negate(src_vector(p, &inst->SrcReg[1], program), - 1, 1, 1, 1), + negate(src0, 1, 1, 1, 1), + negate(src1, 1, 1, 1, 1), 0); /* dst = tmp && dst */ i915_emit_arith(p, @@ -940,23 +992,52 @@ upload_program(struct i915_fragment_program *p) flags = get_result_flags(inst); dst = get_result_vector(p, inst); - /* dst = src1 < src2 */ + /* If both operands are uniforms or constants, we get 5 instructions + * like: + * + * U[1] = MOV CONST[1] + * U[0].xyz = SLT CONST[0].xxxx, U[1] + * U[1] = MOV CONST[1].-x-y-z-w + * R[0].xyz = SLT CONST[0].-x-x-x-x, U[1] + * R[0].xyz = MUL R[0], U[0] + * + * This code is stupid. Instead of having the individual calls to + * i915_emit_arith generate the moves to utemps, do it in the caller. + * This results in code like: + * + * U[1] = MOV CONST[1] + * U[0].xyz = SLT CONST[0].xxxx, U[1] + * R[0].xyz = SLT CONST[0].-x-x-x-x, U[1].-x-y-z-w + * R[0].xyz = MUL R[0], U[0] + */ + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + + if (GET_UREG_TYPE(src0) == REG_TYPE_CONST + && GET_UREG_TYPE(src1) == REG_TYPE_CONST) { + unsigned tmp = i915_get_utemp(p); + + i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0, + src1, 0, 0); + + src1 = tmp; + } + + /* tmp = src1 < src2 */ i915_emit_arith(p, A0_SLT, - dst, + tmp, flags, 0, - src_vector(p, &inst->SrcReg[0], program), - src_vector(p, &inst->SrcReg[1], program), + src0, + src1, 0); - /* tmp = src1 > src2 */ + /* dst = src1 > src2 */ i915_emit_arith(p, A0_SLT, - tmp, + dst, flags, 0, - negate(src_vector(p, &inst->SrcReg[0], program), - 1, 1, 1, 1), - negate(src_vector(p, &inst->SrcReg[1], program), - 1, 1, 1, 1), + negate(src0, 1, 1, 1, 1), + negate(src1, 1, 1, 1, 1), 0); /* dst = tmp || dst */ i915_emit_arith(p, @@ -1061,7 +1142,6 @@ upload_program(struct i915_fragment_program *p) case OPCODE_BGNLOOP: case OPCODE_BGNSUB: - case OPCODE_BRA: case OPCODE_BRK: case OPCODE_CAL: case OPCODE_CONT: @@ -1117,27 +1197,54 @@ fixup_depth_write(struct i915_fragment_program *p) } } +static void +check_texcoord_mapping(struct i915_fragment_program *p) +{ + GLbitfield64 inputs = p->FragProg.Base.InputsRead; + unsigned unit = 0; + + for (unsigned i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { + if (inputs & VARYING_BIT_TEX(i)) { + if (unit >= p->ctx->Const.MaxTextureCoordUnits) { + unit++; + break; + } + p->texcoord_mapping[unit++] = i | TEXCOORD_TEX; + } + if (inputs & VARYING_BIT_VAR(i)) { + if (unit >= p->ctx->Const.MaxTextureCoordUnits) { + unit++; + break; + } + p->texcoord_mapping[unit++] = i | TEXCOORD_VAR; + } + } + + if (unit > p->ctx->Const.MaxTextureCoordUnits) + i915_program_error(p, "Too many texcoord units"); +} static void check_wpos(struct i915_fragment_program *p) { - GLuint inputs = p->FragProg.Base.InputsRead; + GLbitfield64 inputs = p->FragProg.Base.InputsRead; GLint i; + unsigned unit = 0; p->wpos_tex = -1; + if ((inputs & VARYING_BIT_POS) == 0) + return; + for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { - if (inputs & (FRAG_BIT_TEX(i) | FRAG_BIT_VAR(i))) - continue; - else if (inputs & FRAG_BIT_WPOS) { - p->wpos_tex = i; - inputs &= ~FRAG_BIT_WPOS; - } + unit += !!(inputs & VARYING_BIT_TEX(i)); + unit += !!(inputs & VARYING_BIT_VAR(i)); } - if (inputs & FRAG_BIT_WPOS) { + if (unit < p->ctx->Const.MaxTextureCoordUnits) + p->wpos_tex = unit; + else i915_program_error(p, "No free texcoord for wpos value"); - } } @@ -1148,21 +1255,17 @@ translate_program(struct i915_fragment_program *p) if (INTEL_DEBUG & DEBUG_WM) { printf("fp:\n"); - _mesa_print_program(&p->ctx->FragmentProgram._Current->Base); + _mesa_print_program(&p->FragProg.Base); printf("\n"); } i915_init_program(i915, p); + check_texcoord_mapping(p); check_wpos(p); upload_program(p); fixup_depth_write(p); i915_fini_program(p); - if (INTEL_DEBUG & DEBUG_WM) { - printf("i915:\n"); - i915_disassemble_program(i915->state.Program, i915->state.ProgramSize); - } - p->translated = 1; } @@ -1263,7 +1366,7 @@ i915IsProgramNative(struct gl_context * ctx, GLenum target, struct gl_program *p return !p->error; } else - return GL_TRUE; + return true; } static GLboolean @@ -1273,21 +1376,19 @@ i915ProgramStringNotify(struct gl_context * ctx, if (target == GL_FRAGMENT_PROGRAM_ARB) { struct i915_fragment_program *p = (struct i915_fragment_program *) prog; p->translated = 0; - - /* Hack: make sure fog is correctly enabled according to this - * fragment program's fog options. - */ - if (p->FragProg.FogOption) { - /* add extra instructions to do fog, then turn off FogOption field */ - _mesa_append_fog_code(ctx, &p->FragProg); - p->FragProg.FogOption = GL_NONE; - } } (void) _tnl_program_string(ctx, target, prog); /* XXX check if program is legal, within limits */ - return GL_TRUE; + return true; +} + +static void +i915SamplerUniformChange(struct gl_context *ctx, + GLenum target, struct gl_program *prog) +{ + i915ProgramStringNotify(ctx, target, prog); } void @@ -1324,7 +1425,7 @@ i915ValidateFragmentProgram(struct i915_context *i915) struct i915_fragment_program *p = (struct i915_fragment_program *) ctx->FragmentProgram._Current; - const GLuint inputsRead = p->FragProg.Base.InputsRead; + const GLbitfield64 inputsRead = p->FragProg.Base.InputsRead; GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; GLuint s2 = S2_TEXCOORD_NONE; int i, offset = 0; @@ -1338,67 +1439,68 @@ i915ValidateFragmentProgram(struct i915_context *i915) intel->vertex_attr_count = 0; intel->wpos_offset = 0; - intel->wpos_size = 0; intel->coloroffset = 0; intel->specoffset = 0; - if (inputsRead & FRAG_BITS_TEX_ANY) { + if (inputsRead & VARYING_BITS_TEX_ANY || p->wpos_tex != -1) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16); } else { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12); } - if (inputsRead & FRAG_BIT_COL0) { + /* Handle gl_PointSize builtin var here */ + if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) + EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4); + + if (inputsRead & VARYING_BIT_COL0) { intel->coloroffset = offset / 4; EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4); } - if (inputsRead & FRAG_BIT_COL1) { + if (inputsRead & VARYING_BIT_COL1) { intel->specoffset = offset / 4; EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_4UB_4F_BGRA, S4_VFMT_SPEC_FOG, 4); } - if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) { + if ((inputsRead & VARYING_BIT_FOGC)) { EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4); } for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { - if (inputsRead & FRAG_BIT_TEX(i)) { + if (inputsRead & VARYING_BIT_TEX(i)) { + int unit = get_texcoord_mapping(p, i | TEXCOORD_TEX); int sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; - s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); - s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); + s2 &= ~S2_TEXCOORD_FMT(unit, S2_TEXCOORD_FMT0_MASK); + s2 |= S2_TEXCOORD_FMT(unit, SZ_TO_HW(sz)); EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4); } - else if (inputsRead & FRAG_BIT_VAR(i)) { + if (inputsRead & VARYING_BIT_VAR(i)) { + int unit = get_texcoord_mapping(p, i | TEXCOORD_VAR); int sz = VB->AttribPtr[_TNL_ATTRIB_GENERIC0 + i]->size; - s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); - s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); + s2 &= ~S2_TEXCOORD_FMT(unit, S2_TEXCOORD_FMT0_MASK); + s2 |= S2_TEXCOORD_FMT(unit, SZ_TO_HW(sz)); EMIT_ATTR(_TNL_ATTRIB_GENERIC0 + i, EMIT_SZ(sz), 0, sz * 4); } - else if (i == p->wpos_tex) { - + if (i == p->wpos_tex) { + int wpos_size = 4 * sizeof(float); /* If WPOS is required, duplicate the XYZ position data in an * unused texture coordinate: */ s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); - s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(3)); + s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(wpos_size)); intel->wpos_offset = offset; - intel->wpos_size = 3 * sizeof(GLuint); - - EMIT_PAD(intel->wpos_size); + EMIT_PAD(wpos_size); } } if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { - int k; - I915_STATECHANGE(i915, I915_UPLOAD_CTX); /* Must do this *after* statechange, so as not to affect @@ -1409,13 +1511,16 @@ i915ValidateFragmentProgram(struct i915_context *i915) intel->vertex_attr_count, intel->ViewportMatrix.m, 0); + assert(intel->prim.current_offset == intel->prim.start_offset); + intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size; + intel->prim.current_offset = intel->prim.start_offset; + intel->vertex_size >>= 2; i915->state.Ctx[I915_CTXREG_LIS2] = s2; i915->state.Ctx[I915_CTXREG_LIS4] = s4; - k = intel->vtbl.check_vertex_size(intel, intel->vertex_size); - assert(k); + assert(intel->vtbl.check_vertex_size(intel, intel->vertex_size)); } if (!p->params_uptodate) @@ -1423,6 +1528,11 @@ i915ValidateFragmentProgram(struct i915_context *i915) if (!p->on_hardware) i915_upload_program(i915, p); + + if (INTEL_DEBUG & DEBUG_WM) { + printf("i915:\n"); + i915_disassemble_program(i915->state.Program, i915->state.ProgramSize); + } } void @@ -1433,4 +1543,5 @@ i915InitFragProgFuncs(struct dd_function_table *functions) functions->DeleteProgram = i915DeleteProgram; functions->IsProgramNative = i915IsProgramNative; functions->ProgramStringNotify = i915ProgramStringNotify; + functions->SamplerUniformChange = i915SamplerUniformChange; }