/**************************************************************************
*
- * 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
* 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.
#include "main/macros.h"
#include "main/enums.h"
-#include "shader/prog_instruction.h"
-#include "shader/prog_parameter.h"
-#include "shader/program.h"
-#include "shader/programopt.h"
-#include "shader/prog_print.h"
+#include "program/prog_instruction.h"
+#include "program/prog_parameter.h"
+#include "program/program.h"
+#include "program/programopt.h"
+#include "program/prog_print.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
-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.
static GLuint
src_vector(struct i915_fragment_program *p,
const struct prog_src_register *source,
- const struct gl_fragment_program *program)
+ const struct gl_program *program)
{
GLuint src;
+ unsigned unit;
switch (source->File) {
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;
}
break;
+ 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:
+ src = UREG(REG_TYPE_OD, 0);
+ break;
+ default:
+ i915_program_error(p, "Bad source->Index: %d", source->Index);
+ return 0;
+ }
+ break;
+
/* 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]);
+ case PROGRAM_UNIFORM: {
+ struct gl_program_parameter_list *params = program->Parameters;
+ unsigned offset = params->ParameterValueOffset[source->Index];
+ src = i915_emit_param4fv(p, ¶ms->ParameterValues[offset].f);
break;
-
+ }
default:
i915_program_error(p, "Bad source->File: %d", source->File);
return 0;
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;
{
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;
#define EMIT_TEX( OP ) \
do { \
GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget ); \
- const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; \
- GLuint unit = program->Base.SamplerUnits[inst->TexSrcUnit]; \
+ const struct gl_program *program = &p->FragProg; \
+ GLuint unit = program->SamplerUnits[inst->TexSrcUnit]; \
GLuint sampler = i915_emit_decl(p, REG_TYPE_S, \
unit, dim); \
GLuint coord = src_vector( p, &inst->SrcReg[0], program); \
/*
* 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_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--) {
- struct prog_instruction *inst = &program->Base.Instructions[i];
+ for (i = program->arb.NumInstructions - 1; i >= 0; i--) {
+ struct prog_instruction *inst = &program->arb.Instructions[i];
int opArgs = _mesa_num_inst_src_regs(inst->Opcode);
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;
- GLuint nr = inst - program->Base.Instructions;
+ const struct gl_program *program = &p->FragProg;
+ GLuint nr = inst - program->arb.Instructions;
return p->usedRegs[nr];
}
static void
upload_program(struct i915_fragment_program *p)
{
- const struct gl_fragment_program *program =
- p->ctx->FragmentProgram._Current;
- const struct prog_instruction *inst = program->Base.Instructions;
+ const struct gl_program *program = &p->FragProg;
+ const struct prog_instruction *inst = program->arb.Instructions;
if (INTEL_DEBUG & DEBUG_WM)
- _mesa_print_program(&program->Base);
+ _mesa_print_program(program);
/* Is this a parse-failed program? Ensure a valid program is
* loaded, as the flagging of an error isn't sufficient to stop
return;
}
- if (program->Base.NumInstructions > I915_MAX_INSN) {
- i915_program_error( p, "Exceeded max instructions" );
- return;
- }
+ if (program->arb.NumInstructions > I915_MAX_INSN) {
+ i915_program_error(p, "Exceeded max instructions (%d out of %d)",
+ program->arb.NumInstructions, I915_MAX_INSN);
+ return;
+ }
/* 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;
swizzle(tmp, X, X, X, X));
break;
+ case OPCODE_DP2:
+ src0 = src_vector(p, &inst->SrcReg[0], program);
+ src1 = src_vector(p, &inst->SrcReg[1], program);
+ i915_emit_arith(p,
+ A0_DP3,
+ get_result_vector(p, inst),
+ get_result_flags(inst), 0,
+ swizzle(src0, X, Y, ZERO, ZERO),
+ swizzle(src1, X, Y, ZERO, ZERO),
+ 0);
+ break;
+
case OPCODE_DP3:
EMIT_2ARG_ARITH(A0_DP3);
break;
0, src0, T0_TEXKILL);
break;
- case OPCODE_KIL_NV:
- if (inst->DstReg.CondMask == COND_TR) {
- tmp = i915_get_utemp(p);
-
- 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 */
- T0_TEXKILL);
- } else {
- p->error = 1;
- i915_program_error(p, "Unsupported KIL_NV condition code: %d",
- inst->DstReg.CondMask);
- }
- break;
-
case OPCODE_LG2:
src0 = src_vector(p, &inst->SrcReg[0], program);
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:
EMIT_2ARG_ARITH(A0_MUL);
break;
- case OPCODE_NOISE1:
- case OPCODE_NOISE2:
- case OPCODE_NOISE3:
- case OPCODE_NOISE4:
- /* Don't implement noise because we just don't have the instructions
- * to spare. We aren't the first vendor to do so.
- */
- i915_program_error(p, "Stubbed-out noise functions");
- i915_emit_arith(p,
- A0_MOV,
- get_result_vector(p, inst),
- get_result_flags(inst), 0,
- swizzle(tmp, ZERO, ZERO, ZERO, ZERO), 0, 0);
- break;
-
case OPCODE_POW:
src0 = src_vector(p, &inst->SrcReg[0], program);
src1 = src_vector(p, &inst->SrcReg[1], program);
}
break;
- case OPCODE_SEQ:
- tmp = i915_get_utemp(p);
- flags = get_result_flags(inst);
- dst = get_result_vector(p, inst);
-
- /* dst = src1 >= src2 */
- i915_emit_arith(p,
- A0_SGE,
- dst,
- flags, 0,
- src_vector(p, &inst->SrcReg[0], program),
- src_vector(p, &inst->SrcReg[1], program),
- 0);
- /* tmp = src1 <= src2 */
- i915_emit_arith(p,
- A0_SGE,
- tmp,
- 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),
- 0);
- /* dst = tmp && dst */
- i915_emit_arith(p,
- A0_MUL,
- dst,
- flags, 0,
- dst,
- tmp,
- 0);
- break;
-
case OPCODE_SIN:
src0 = src_vector(p, &inst->SrcReg[0], program);
tmp = i915_get_utemp(p);
EMIT_2ARG_ARITH(A0_SGE);
break;
- case OPCODE_SGT:
- i915_emit_arith(p,
- A0_SLT,
- get_result_vector( p, inst ),
- get_result_flags( inst ), 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),
- 0);
- break;
-
- case OPCODE_SLE:
- i915_emit_arith(p,
- A0_SGE,
- get_result_vector( p, inst ),
- get_result_flags( inst ), 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),
- 0);
- break;
-
case OPCODE_SLT:
EMIT_2ARG_ARITH(A0_SLT);
break;
- case OPCODE_SNE:
- tmp = i915_get_utemp(p);
- flags = get_result_flags(inst);
+ case OPCODE_SSG:
dst = get_result_vector(p, inst);
+ flags = get_result_flags(inst);
+ src0 = src_vector(p, &inst->SrcReg[0], program);
+ tmp = i915_get_utemp(p);
- /* dst = src1 < src2 */
+ /* tmp = (src < 0.0) */
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,
+ swizzle(src0, ZERO, ZERO, ZERO, ZERO),
0);
- /* tmp = src1 > src2 */
+
+ /* dst = (0.0 < src) */
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),
+ swizzle(src0, ZERO, ZERO, ZERO, ZERO),
+ src0,
0);
- /* dst = tmp || dst */
+
+ /* dst = (src > 0.0) - (src < 0.0) */
i915_emit_arith(p,
A0_ADD,
dst,
- flags | A0_DEST_SATURATE, 0,
+ flags, 0,
dst,
- tmp,
+ negate(tmp, 1, 1, 1, 1),
0);
+
break;
case OPCODE_SUB:
case OPCODE_BGNLOOP:
case OPCODE_BGNSUB:
- case OPCODE_BRA:
case OPCODE_BRK:
case OPCODE_CAL:
case OPCODE_CONT:
}
}
+static void
+check_texcoord_mapping(struct i915_fragment_program *p)
+{
+ GLbitfield64 inputs = p->FragProg.info.inputs_read;
+ 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.info.inputs_read;
GLint i;
+ unsigned unit = 0;
- p->wpos_tex = -1;
+ p->wpos_tex = I915_WPOS_TEX_INVALID;
+
+ 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");
- }
}
{
struct i915_context *i915 = I915_CONTEXT(p->ctx);
+ if (INTEL_DEBUG & DEBUG_WM) {
+ printf("fp:\n");
+ _mesa_print_program(&p->FragProg);
+ printf("\n");
+ }
+
i915_init_program(i915, p);
+ check_texcoord_mapping(p);
check_wpos(p);
upload_program(p);
fixup_depth_write(p);
GLint i;
if (p->nr_params)
- _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters);
+ _mesa_load_state_parameters(p->ctx, p->FragProg.Parameters);
for (i = 0; i < p->nr_params; i++) {
GLint reg = p->param[i].reg;
p->on_hardware = 0; /* overkill */
}
-
-static void
-i915BindProgram(GLcontext * ctx, GLenum target, struct gl_program *prog)
-{
- if (target == GL_FRAGMENT_PROGRAM_ARB) {
- struct i915_context *i915 = I915_CONTEXT(ctx);
- struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
-
- if (i915->current_program == p)
- return;
-
- if (i915->current_program) {
- i915->current_program->on_hardware = 0;
- i915->current_program->params_uptodate = 0;
- }
-
- i915->current_program = p;
-
- assert(p->on_hardware == 0);
- assert(p->params_uptodate == 0);
-
- }
-}
-
static struct gl_program *
-i915NewProgram(GLcontext * ctx, GLenum target, GLuint id)
+i915NewProgram(struct gl_context * ctx, GLenum target, GLuint id,
+ bool is_arb_asm)
{
switch (target) {
- case GL_VERTEX_PROGRAM_ARB:
- return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
- target, id);
+ case GL_VERTEX_PROGRAM_ARB: {
+ struct gl_program *prog = rzalloc(NULL, struct gl_program);
+ return _mesa_init_gl_program(prog, target, id, is_arb_asm);
+ }
case GL_FRAGMENT_PROGRAM_ARB:{
struct i915_fragment_program *prog =
- CALLOC_STRUCT(i915_fragment_program);
+ rzalloc(NULL, struct i915_fragment_program);
if (prog) {
i915_init_program(I915_CONTEXT(ctx), prog);
- return _mesa_init_fragment_program(ctx, &prog->FragProg,
- target, id);
+ return _mesa_init_gl_program(&prog->FragProg, target, id,
+ is_arb_asm);
}
else
return NULL;
default:
/* Just fallback:
*/
- return _mesa_new_program(ctx, target, id);
+ return _mesa_new_program(ctx, target, id, is_arb_asm);
}
}
static void
-i915DeleteProgram(GLcontext * ctx, struct gl_program *prog)
+i915DeleteProgram(struct gl_context * ctx, struct gl_program *prog)
{
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
struct i915_context *i915 = I915_CONTEXT(ctx);
static GLboolean
-i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
+i915IsProgramNative(struct gl_context * ctx, GLenum target, struct gl_program *prog)
{
if (target == GL_FRAGMENT_PROGRAM_ARB) {
struct i915_fragment_program *p = (struct i915_fragment_program *) prog;
return !p->error;
}
else
- return GL_TRUE;
+ return true;
}
static GLboolean
-i915ProgramStringNotify(GLcontext * ctx,
+i915ProgramStringNotify(struct gl_context * ctx,
GLenum target, struct gl_program *prog)
{
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
-i915_update_program(GLcontext *ctx)
+i915_update_program(struct gl_context *ctx)
{
struct intel_context *intel = intel_context(ctx);
struct i915_context *i915 = i915_context(&intel->ctx);
void
i915ValidateFragmentProgram(struct i915_context *i915)
{
- GLcontext *ctx = &i915->intel.ctx;
+ struct gl_context *ctx = &i915->intel.ctx;
struct intel_context *intel = intel_context(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
struct i915_fragment_program *p =
(struct i915_fragment_program *) ctx->FragmentProgram._Current;
- const GLuint inputsRead = p->FragProg.Base.InputsRead;
+ const GLbitfield64 inputsRead = p->FragProg.info.inputs_read;
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
GLuint s2 = S2_TEXCOORD_NONE;
+ GLuint s3 = 0;
int i, offset = 0;
/* Important:
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) {
- 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);
- }
+ /* Always emit W to get consistent perspective
+ * correct interpolation of primary/secondary colors.
+ */
+ EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16);
- 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));
+ s3 |= S3_TEXCOORD_PERSPECTIVE_DISABLE(i);
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] ||
+ s3 != i915->state.Ctx[I915_CTXREG_LIS3] ||
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
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_LIS3] = s3;
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)
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
i915InitFragProgFuncs(struct dd_function_table *functions)
{
- functions->BindProgram = i915BindProgram;
functions->NewProgram = i915NewProgram;
functions->DeleteProgram = i915DeleteProgram;
functions->IsProgramNative = i915IsProgramNative;
functions->ProgramStringNotify = i915ProgramStringNotify;
+ functions->SamplerUniformChange = i915SamplerUniformChange;
}