diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2007-03-14 09:28:41 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2007-03-14 09:28:41 +0000 |
commit | 7d35d981653dd6c6cf51cd5e862b1afb5ae4c8e0 (patch) | |
tree | d3c3d5c8b0e5b63241d98c393648b49cb06b5618 | |
parent | a764f168139b22ef2f8944fc8fe554e0b67d5ce6 (diff) |
Missing files
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_fpc.c | 171 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_fpc_debug.c | 336 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_fpc_emit.c | 376 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_fpc_translate.c | 781 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_state_fallback.c | 114 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/i915_state_invarient.c | 140 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_debug.h | 58 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_metaops.c | 546 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_metaops.h | 86 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_program.c | 269 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_state.h | 46 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_state_callbacks.c | 113 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_state_inlines.h | 165 |
13 files changed, 3201 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i915tex/i915_fpc.c b/src/mesa/drivers/dri/i915tex/i915_fpc.c new file mode 100644 index 0000000000..30420f05ef --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fpc.c @@ -0,0 +1,171 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 <strings.h> + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "i915_fpc.h" + + + +void +i915_program_error(struct i915_fp_compile *p, const char *msg) +{ + _mesa_problem(NULL, "i915_program_error: %s", msg); + p->fp->error = 1; +} + + +static struct i915_fp_compile * +i915_init_compile(struct i915_context *i915, struct i915_fragment_program *fp) +{ + struct i915_fp_compile *p = CALLOC_STRUCT(i915_fp_compile); + + p->fp = fp; + p->env_param = i915->intel.ctx.FragmentProgram.Parameters; + + p->nr_tex_indirect = 1; /* correct? */ + p->nr_tex_insn = 0; + p->nr_alu_insn = 0; + p->nr_decl_insn = 0; + + memset(p->constant_flags, 0, sizeof(p->constant_flags)); + + p->csr = p->program; + p->decl = p->declarations; + p->decl_s = 0; + p->decl_t = 0; + p->temp_flag = 0xffff000; + p->utemp_flag = ~0x7; + + p->fp->translated = 0; + p->fp->error = 0; + p->fp->nr_constants = 0; + p->fp->wpos_tex = -1; + p->fp->nr_params = 0; + + *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM; + + return p; +} + +/* Copy compile results to the fragment program struct and destroy the + * compilation context. + */ +static void +i915_fini_compile(struct i915_fp_compile *p) +{ + GLuint program_size = p->csr - p->program; + GLuint decl_size = p->decl - p->declarations; + + if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT) + i915_program_error(p, "Exceeded max nr indirect texture lookups"); + + if (p->nr_tex_insn > I915_MAX_TEX_INSN) + i915_program_error(p, "Exceeded max TEX instructions"); + + if (p->nr_alu_insn > I915_MAX_ALU_INSN) + i915_program_error(p, "Exceeded max ALU instructions"); + + if (p->nr_decl_insn > I915_MAX_DECL_INSN) + i915_program_error(p, "Exceeded max DECL instructions"); + + if (p->fp->error) { + p->fp->Base.Base.NumNativeInstructions = 0; + p->fp->Base.NumNativeAluInstructions = 0; + p->fp->Base.NumNativeTexInstructions = 0; + p->fp->Base.NumNativeTexIndirections = 0; + return; + } + else { + p->fp->Base.Base.NumNativeInstructions = (p->nr_alu_insn + + p->nr_tex_insn + + p->nr_decl_insn); + p->fp->Base.NumNativeAluInstructions = p->nr_alu_insn; + p->fp->Base.NumNativeTexInstructions = p->nr_tex_insn; + p->fp->Base.NumNativeTexIndirections = p->nr_tex_indirect; + } + + p->declarations[0] |= program_size + decl_size - 2; + + /* Copy compilation results to fragment program struct: + */ + memcpy(p->fp->program, + p->declarations, + decl_size * sizeof(GLuint)); + + memcpy(p->fp->program + decl_size, + p->program, + program_size * sizeof(GLuint)); + + p->fp->program_size = program_size + decl_size; + + /* Release the compilation struct: + */ + FREE(p); +} + + + +static void +check_wpos(struct i915_fp_compile *p) +{ + GLuint inputs = p->fp->Base.Base.InputsRead; + GLint i; + + p->fp->wpos_tex = -1; + + if (inputs & FRAG_BIT_WPOS) { + for (i = 0; i < I915_TEX_UNITS; i++) { + if ((inputs & (FRAG_BIT_TEX0 << i)) == 0) { + p->fp->wpos_tex = i; + return; + } + } + + i915_program_error(p, "No free texcoord for wpos value"); + } +} + + + +void i915_compile_fragment_program( struct i915_context *i915, + struct i915_fragment_program *fp ) +{ + struct i915_fp_compile *p = i915_init_compile(i915, fp); + + check_wpos(p); + + i915_translate_program(p); + i915_fixup_depth_write(p); + + i915_fini_compile(p); + fp->translated = 1; +} diff --git a/src/mesa/drivers/dri/i915tex/i915_fpc_debug.c b/src/mesa/drivers/dri/i915tex/i915_fpc_debug.c new file mode 100644 index 0000000000..22a9342b64 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fpc_debug.c @@ -0,0 +1,336 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 <stdio.h> + +#include "i915_reg.h" +#include "i915_fpc.h" +#include "shader/program.h" +#include "shader/program_instruction.h" + +static const char *opcodes[0x20] = { + "NOP", + "ADD", + "MOV", + "MUL", + "MAD", + "DP2ADD", + "DP3", + "DP4", + "FRC", + "RCP", + "RSQ", + "EXP", + "LOG", + "CMP", + "MIN", + "MAX", + "FLR", + "MOD", + "TRC", + "SGE", + "SLT", + "TEXLD", + "TEXLDP", + "TEXLDB", + "TEXKILL", + "DCL", + "0x1a", + "0x1b", + "0x1c", + "0x1d", + "0x1e", + "0x1f", +}; + + +static const int args[0x20] = { + 0, /* 0 nop */ + 2, /* 1 add */ + 1, /* 2 mov */ + 2, /* 3 m ul */ + 3, /* 4 mad */ + 3, /* 5 dp2add */ + 2, /* 6 dp3 */ + 2, /* 7 dp4 */ + 1, /* 8 frc */ + 1, /* 9 rcp */ + 1, /* a rsq */ + 1, /* b exp */ + 1, /* c log */ + 3, /* d cmp */ + 2, /* e min */ + 2, /* f max */ + 1, /* 10 flr */ + 1, /* 11 mod */ + 1, /* 12 trc */ + 2, /* 13 sge */ + 2, /* 14 slt */ + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + + +static const char *regname[0x8] = { + "R", + "T", + "CONST", + "S", + "OC", + "OD", + "U", + "UNKNOWN", +}; + +static void +print_reg_type_nr(GLuint type, GLuint nr) +{ + switch (type) { + case REG_TYPE_T: + switch (nr) { + case T_DIFFUSE: + fprintf(stderr, "T_DIFFUSE"); + return; + case T_SPECULAR: + fprintf(stderr, "T_SPECULAR"); + return; + case T_FOG_W: + fprintf(stderr, "T_FOG_W"); + return; + default: + fprintf(stderr, "T_TEX%d", nr); + return; + } + case REG_TYPE_OC: + if (nr == 0) { + fprintf(stderr, "oC"); + return; + } + break; + case REG_TYPE_OD: + if (nr == 0) { + fprintf(stderr, "oD"); + return; + } + break; + default: + break; + } + + fprintf(stderr, "%s[%d]", regname[type], nr); +} + +#define REG_SWIZZLE_MASK 0x7777 +#define REG_NEGATE_MASK 0x8888 + +#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ + (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ + (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ + (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) + + +static void +print_reg_neg_swizzle(GLuint reg) +{ + int i; + + if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && + (reg & REG_NEGATE_MASK) == 0) + return; + + fprintf(stderr, "."); + + for (i = 3; i >= 0; i--) { + if (reg & (1 << ((i * 4) + 3))) + fprintf(stderr, "-"); + + switch ((reg >> (i * 4)) & 0x7) { + case 0: + fprintf(stderr, "x"); + break; + case 1: + fprintf(stderr, "y"); + break; + case 2: + fprintf(stderr, "z"); + break; + case 3: + fprintf(stderr, "w"); + break; + case 4: + fprintf(stderr, "0"); + break; + case 5: + fprintf(stderr, "1"); + break; + default: + fprintf(stderr, "?"); + break; + } + } +} + + +static void +print_src_reg(GLuint dword) +{ + GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; + GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; + print_reg_type_nr(type, nr); + print_reg_neg_swizzle(dword); +} + + +static void +print_dest_reg(GLuint dword) +{ + GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; + GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; + print_reg_type_nr(type, nr); + if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) + return; + fprintf(stderr, "."); + if (dword & A0_DEST_CHANNEL_X) + fprintf(stderr, "x"); + if (dword & A0_DEST_CHANNEL_Y) + fprintf(stderr, "y"); + if (dword & A0_DEST_CHANNEL_Z) + fprintf(stderr, "z"); + if (dword & A0_DEST_CHANNEL_W) + fprintf(stderr, "w"); +} + + +#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) +#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) +#define GET_SRC2_REG(r) (r) + + +static void +print_arith_op(GLuint opcode, const GLuint * program) +{ + if (opcode != A0_NOP) { + print_dest_reg(program[0]); + if (program[0] & A0_DEST_SATURATE) + fprintf(stderr, " = SATURATE "); + else + fprintf(stderr, " = "); + } + + fprintf(stderr, "%s ", opcodes[opcode]); + + print_src_reg(GET_SRC0_REG(program[0], program[1])); + if (args[opcode] == 1) { + fprintf(stderr, "\n"); + return; + } + + fprintf(stderr, ", "); + print_src_reg(GET_SRC1_REG(program[1], program[2])); + if (args[opcode] == 2) { + fprintf(stderr, "\n"); + return; + } + + fprintf(stderr, ", "); + print_src_reg(GET_SRC2_REG(program[2])); + fprintf(stderr, "\n"); + return; +} + + +static void +print_tex_op(GLuint opcode, const GLuint * program) +{ + print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); + fprintf(stderr, " = "); + + fprintf(stderr, "%s ", opcodes[opcode]); + + fprintf(stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK); + + print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & + REG_TYPE_MASK, + (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); + fprintf(stderr, "\n"); +} + +static void +print_dcl_op(GLuint opcode, const GLuint * program) +{ + fprintf(stderr, "%s ", opcodes[opcode]); + print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); + fprintf(stderr, "\n"); +} + + +void +i915_disassemble_program(const GLuint * program, GLuint sz) +{ + GLuint size = program[0] & 0x1ff; + GLint i; + + fprintf(stderr, "BEGIN\n"); + + assert(size + 2 == sz); + + program++; + for (i = 1; i < sz; i += 3, program += 3) { + GLuint opcode = program[0] & (0x1f << 24); + + if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT) + print_arith_op(opcode >> 24, program); + else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) + print_tex_op(opcode >> 24, program); + else if (opcode == D0_DCL) + print_dcl_op(opcode >> 24, program); + else + fprintf(stderr, "Unknown opcode 0x%x\n", opcode); + } + + fprintf(stderr, "END\n\n"); +} + + +void i915_print_mesa_instructions( const struct prog_instruction *insn, + GLuint nr ) +{ + GLuint i; + for (i = 0; i < nr; i++, insn++) { + _mesa_printf("%3d: ", i); + _mesa_print_instruction(insn); + } +} diff --git a/src/mesa/drivers/dri/i915tex/i915_fpc_emit.c b/src/mesa/drivers/dri/i915tex/i915_fpc_emit.c new file mode 100644 index 0000000000..dd9d612321 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fpc_emit.c @@ -0,0 +1,376 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 <strings.h> + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "i915_reg.h" +#include "i915_context.h" +#include "i915_fpc.h" + + +#define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) +#define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) +#define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) +#define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT) +#define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT) +#define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT) +#define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT) +#define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT) + +/* These are special, and don't have swizzle/negate bits. + */ +#define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT) +#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \ + (GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT)) + + +/* Macros for translating UREG's into the various register fields used + * by the I915 programmable unit. + */ +#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT) +#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT) +#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT) +#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) +#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT) + +#define UREG_MASK 0xffffff00 +#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \ + (REG_NR_MASK << UREG_NR_SHIFT)) + + +#define I915_CONSTFLAG_PARAM 0x1f + +GLuint +i915_get_temp(struct i915_fp_compile *p) +{ + int bit = ffs(~p->temp_flag); + if (!bit) { + i915_program_error(p, "i915_get_temp: out of temporaries\n"); + return 0; + } + + p->temp_flag |= 1 << (bit - 1); + return UREG(REG_TYPE_R, (bit - 1)); +} + + +GLuint +i915_get_utemp(struct i915_fp_compile * p) +{ + int bit = ffs(~p->utemp_flag); + if (!bit) { + i915_program_error(p, "i915_get_utemp: out of temporaries\n"); + return 0; + } + + p->utemp_flag |= 1 << (bit - 1); + return UREG(REG_TYPE_U, (bit - 1)); +} + +void +i915_release_utemps(struct i915_fp_compile *p) +{ + p->utemp_flag = ~0x7; +} + + +GLuint +i915_emit_decl(struct i915_fp_compile *p, + GLuint type, GLuint nr, GLuint d0_flags) +{ + GLuint reg = UREG(type, nr); + + if (type == REG_TYPE_T) { + if (p->decl_t & (1 << nr)) + return reg; + + p->decl_t |= (1 << nr); + } + else if (type == REG_TYPE_S) { + if (p->decl_s & (1 << nr)) + return reg; + + p->decl_s |= (1 << nr); + } + else + return reg; + + *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags); + *(p->decl++) = D1_MBZ; + *(p->decl++) = D2_MBZ; + + p->nr_decl_insn++; + return reg; +} + +GLuint +i915_emit_arith(struct i915_fp_compile * p, + GLuint op, + GLuint dest, + GLuint mask, + GLuint saturate, GLuint src0, GLuint src1, GLuint src2) +{ + GLuint c[3]; + GLuint nr_const = 0; + + assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); + dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); + assert(dest); + + if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) + c[nr_const++] = 0; + if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) + c[nr_const++] = 1; + if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) + c[nr_const++] = 2; + + /* Recursively call this function to MOV additional const values + * into temporary registers. Use utemp registers for this - + * currently shouldn't be possible to run out, but keep an eye on + * this. + */ + if (nr_const > 1) { + GLuint s[3], first, i, old_utemp_flag; + + s[0] = src0; + s[1] = src1; + s[2] = src2; + old_utemp_flag = p->utemp_flag; + + first = GET_UREG_NR(s[c[0]]); + for (i = 1; i < nr_const; i++) { + if (GET_UREG_NR(s[c[i]]) != first) { + GLuint tmp = i915_get_utemp(p); + + i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0, + s[c[i]], 0, 0); + s[c[i]] = tmp; + } + } + + src0 = s[0]; + src1 = s[1]; + src2 = s[2]; + p->utemp_flag = old_utemp_flag; /* restore */ + } + + *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); + *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); + *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); + + p->nr_alu_insn++; + return dest; +} + +GLuint i915_emit_texld( struct i915_fp_compile *p, + GLuint dest, + GLuint destmask, + GLuint sampler, + GLuint coord, + GLuint op ) +{ + if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) { + /* No real way to work around this in the general case - need to + * allocate and declare a new temporary register (a utemp won't + * do). Will fallback for now. + */ + i915_program_error(p, "Can't (yet) swizzle TEX arguments"); + return 0; + } + + /* Don't worry about saturate as we only support + */ + if (destmask != A0_DEST_CHANNEL_ALL) { + GLuint tmp = i915_get_utemp(p); + i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op ); + i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 ); + return dest; + } + else { + assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); + assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); + + if (GET_UREG_TYPE(coord) != REG_TYPE_T) { + p->nr_tex_indirect++; + } + + *(p->csr++) = (op | + T0_DEST( dest ) | + T0_SAMPLER( sampler )); + + *(p->csr++) = T1_ADDRESS_REG( coord ); + *(p->csr++) = T2_MBZ; + + p->nr_tex_insn++; + return dest; + } +} + + +GLuint +i915_emit_const1f(struct i915_fp_compile * p, GLfloat c0) +{ + GLint reg, idx; + + if (c0 == 0.0) + return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO); + if (c0 == 1.0) + return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE); + + for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { + if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM) + continue; + for (idx = 0; idx < 4; idx++) { + if (!(p->constant_flags[reg] & (1 << idx)) || + p->fp->constant[reg][idx] == c0) { + p->fp->constant[reg][idx] = c0; + p->constant_flags[reg] |= 1 << idx; + if (reg + 1 > p->fp->nr_constants) + p->fp->nr_constants = reg + 1; + return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE); + } + } + } + + i915_program_error(p, "i915_emit_const1f: out of constants\n"); + return 0; +} + +GLuint +i915_emit_const2f(struct i915_fp_compile * p, GLfloat c0, GLfloat c1) +{ + GLint reg, idx; + + if (c0 == 0.0) + return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W); + if (c0 == 1.0) + return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W); + + if (c1 == 0.0) + return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W); + if (c1 == 1.0) + return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W); + + for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { + if (p->constant_flags[reg] == 0xf || + p->constant_flags[reg] == I915_CONSTFLAG_PARAM) + continue; + for (idx = 0; idx < 3; idx++) { + if (!(p->constant_flags[reg] & (3 << idx))) { + p->fp->constant[reg][idx] = c0; + p->fp->constant[reg][idx + 1] = c1; + p->constant_flags[reg] |= 3 << idx; + if (reg + 1 > p->fp->nr_constants) + p->fp->nr_constants = reg + 1; + return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, + ONE); + } + } + } + + i915_program_error(p, "i915_emit_const2f: out of constants\n"); + return 0; +} + + + +GLuint +i915_emit_const4f(struct i915_fp_compile * p, + GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3) +{ + GLint reg; + + for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { + if (p->constant_flags[reg] == 0xf && + p->fp->constant[reg][0] == c0 && + p->fp->constant[reg][1] == c1 && + p->fp->constant[reg][2] == c2 && + p->fp->constant[reg][3] == c3) { + return UREG(REG_TYPE_CONST, reg); + } + else if (p->constant_flags[reg] == 0) { + p->fp->constant[reg][0] = c0; + p->fp->constant[reg][1] = c1; + p->fp->constant[reg][2] = c2; + p->fp->constant[reg][3] = c3; + p->constant_flags[reg] = 0xf; + if (reg + 1 > p->fp->nr_constants) + p->fp->nr_constants = reg + 1; + return UREG(REG_TYPE_CONST, reg); + } + } + + i915_program_error(p, "i915_emit_const4f: out of constants\n"); + return 0; +} + + +GLuint +i915_emit_const4fv(struct i915_fp_compile * p, const GLfloat * c) +{ + return i915_emit_const4f(p, c[0], c[1], c[2], c[3]); +} + +/* Reserve a slot in the constant file for a Mesa state parameter. + * These will later need to be tracked on statechanges, but that is + * done elsewhere. + */ +GLuint +i915_emit_param4fv(struct i915_fp_compile * p, const GLfloat * values) +{ + struct i915_fragment_program *fp = p->fp; + GLint i; + + for (i = 0; i < fp->nr_params; i++) { + if (fp->param[i].values == values) + return UREG(REG_TYPE_CONST, fp->param[i].reg); + } + + if (fp->nr_constants == I915_MAX_CONSTANT || + fp->nr_params == I915_MAX_CONSTANT) { + i915_program_error(p, "i915_emit_param4fv: out of constants\n"); + return 0; + } + + { + GLint reg = fp->nr_constants++; + GLint i = fp->nr_params++; + + assert (p->constant_flags[reg] == 0); + p->constant_flags[reg] = I915_CONSTFLAG_PARAM; + + fp->param[i].values = values; + fp->param[i].reg = reg; + + return UREG(REG_TYPE_CONST, reg); + } +} diff --git a/src/mesa/drivers/dri/i915tex/i915_fpc_translate.c b/src/mesa/drivers/dri/i915tex/i915_fpc_translate.c new file mode 100644 index 0000000000..26c3894978 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fpc_translate.c @@ -0,0 +1,781 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "intel_batchbuffer.h" + +#include "i915_reg.h" +#include "i915_context.h" +#include "i915_fpc.h" + +#include "program_instruction.h" +#include "program.h" +#include "programopt.h" + + + +/* 1, -1/3!, 1/5!, -1/7! */ +static const GLfloat sin_constants[4] = { 1.0, + -1.0 / (3 * 2 * 1), + 1.0 / (5 * 4 * 3 * 2 * 1), + -1.0 / (7 * 6 * 5 * 4 * 3 * 2 * 1) +}; + +/* 1, -1/2!, 1/4!, -1/6! */ +static const GLfloat cos_constants[4] = { 1.0, + -1.0 / (2 * 1), + 1.0 / (4 * 3 * 2 * 1), + -1.0 / (6 * 5 * 4 * 3 * 2 * 1) +}; + +/** + * Retrieve a ureg for the given source register. Will emit + * constants, apply swizzling and negation as needed. + */ +static GLuint +src_vector(struct i915_fp_compile *p, + const struct prog_src_register *source, + const struct gl_fragment_program *program) +{ + GLuint src; + + switch (source->File) { + + /* Registers: + */ + case PROGRAM_TEMPORARY: + if (source->Index >= I915_MAX_TEMPORARY) { + i915_program_error(p, "Exceeded max temporary reg"); + return 0; + } + src = UREG(REG_TYPE_R, source->Index); + break; + case PROGRAM_INPUT: + /* XXX: Packing COL1, FOGC into a single attribute works for + * texenv programs, but will fail for real fragment programs + * that use these attributes and expect them to be a full 4 + * components wide. Could use a texcoord to pass these + * attributes if necessary, but that won't work in the general + * case. + * + * We also use a texture coordinate to pass wpos when possible. + */ + switch (source->Index) { + case FRAG_ATTRIB_WPOS: + src = i915_emit_decl(p, REG_TYPE_T, p->fp->wpos_tex, D0_CHANNEL_ALL); + break; + case FRAG_ATTRIB_COL0: + src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); + break; + case FRAG_ATTRIB_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: + src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W); + src = swizzle(src, W, W, W, W); + 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: + src = i915_emit_decl(p, REG_TYPE_T, + T_TEX0 + (source->Index - FRAG_ATTRIB_TEX0), + D0_CHANNEL_ALL); + break; + + default: + i915_program_error(p, "Bad 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->env_param[source->Index]); + break; + + case PROGRAM_CONSTANT: + case PROGRAM_STATE_VAR: + case PROGRAM_NAMED_PARAM: + src = i915_emit_param4fv( + p, program->Base.Parameters->ParameterValues[source->Index]); + break; + + default: + i915_program_error(p, "Bad source->File"); + return 0; + } + + src = swizzle(src, + GET_SWZ(source->Swizzle, 0), + GET_SWZ(source->Swizzle, 1), + GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3)); + + if (source->NegateBase) + src = negate(src, + GET_BIT(source->NegateBase, 0), + GET_BIT(source->NegateBase, 1), + GET_BIT(source->NegateBase, 2), + GET_BIT(source->NegateBase, 3)); + + return src; +} + + +static GLuint +get_result_vector(struct i915_fp_compile *p, + const struct prog_instruction *inst) +{ + switch (inst->DstReg.File) { + case PROGRAM_OUTPUT: + switch (inst->DstReg.Index) { + case FRAG_RESULT_COLR: + return UREG(REG_TYPE_OC, 0); + case FRAG_RESULT_DEPR: + return UREG(REG_TYPE_OD, 0); + default: + i915_program_error(p, "Bad inst->DstReg.Index"); + return 0; + } + case PROGRAM_TEMPORARY: + return UREG(REG_TYPE_R, inst->DstReg.Index); + default: + i915_program_error(p, "Bad inst->DstReg.File"); + return 0; + } +} + +static GLuint +get_result_flags(const struct prog_instruction *inst) +{ + GLuint flags = 0; + + if (inst->SaturateMode == SATURATE_ZERO_ONE) + flags |= A0_DEST_SATURATE; + if (inst->DstReg.WriteMask & WRITEMASK_X) + flags |= A0_DEST_CHANNEL_X; + if (inst->DstReg.WriteMask & WRITEMASK_Y) + flags |= A0_DEST_CHANNEL_Y; + if (inst->DstReg.WriteMask & WRITEMASK_Z) + flags |= A0_DEST_CHANNEL_Z; + if (inst->DstReg.WriteMask & WRITEMASK_W) + flags |= A0_DEST_CHANNEL_W; + + return flags; +} + +static GLuint +translate_tex_src_target(struct i915_fp_compile *p, GLubyte bit) +{ + switch (bit) { + case TEXTURE_1D_INDEX: + return D0_SAMPLE_TYPE_2D; + case TEXTURE_2D_INDEX: + return D0_SAMPLE_TYPE_2D; + case TEXTURE_RECT_INDEX: + return D0_SAMPLE_TYPE_2D; + case TEXTURE_3D_INDEX: + return D0_SAMPLE_TYPE_VOLUME; + case TEXTURE_CUBE_INDEX: + return D0_SAMPLE_TYPE_CUBE; + default: + i915_program_error(p, "TexSrcBit"); + return 0; + } +} + +#define EMIT_TEX( OP ) \ +do { \ + GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget ); \ + GLuint sampler = i915_emit_decl(p, REG_TYPE_S, \ + inst->TexSrcUnit, dim); \ + GLuint coord = src_vector( p, &inst->SrcReg[0], program); \ + /* Texel lookup */ \ + \ + i915_emit_texld( p, \ + get_result_vector( p, inst ), \ + get_result_flags( inst ), \ + sampler, \ + coord, \ + OP); \ +} while (0) + +#define EMIT_ARITH( OP, N ) \ +do { \ + i915_emit_arith( p, \ + OP, \ + get_result_vector( p, inst ), \ + get_result_flags( inst ), 0, \ + (N<1)?0:src_vector( p, &inst->SrcReg[0], program), \ + (N<2)?0:src_vector( p, &inst->SrcReg[1], program), \ + (N<3)?0:src_vector( p, &inst->SrcReg[2], program)); \ +} while (0) + +#define EMIT_1ARG_ARITH( OP ) EMIT_ARITH( OP, 1 ) +#define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 ) +#define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 ) + + +/* Possible concerns: + * + * SIN, COS -- could use another taylor step? + * LIT -- results seem a little different to sw mesa + * LOG -- different to mesa on negative numbers, but this is conformant. + * + * Parse failures -- Mesa doesn't currently give a good indication + * internally whether a particular program string parsed or not. This + * can lead to confusion -- hopefully we cope with it ok now. + * + */ +void +i915_translate_program(struct i915_fp_compile *p) +{ + const struct gl_fragment_program *program = &p->fp->Base; + const struct prog_instruction *inst = program->Base.Instructions; + + if (1) + i915_print_mesa_instructions(inst, program->Base.NumInstructions); + + /* Is this a parse-failed program? Ensure a valid program is + * loaded, as the flagging of an error isn't sufficient to stop + * this being uploaded to hardware. + */ + if (inst[0].Opcode == OPCODE_END) { + GLuint tmp = i915_get_utemp(p); + i915_emit_arith(p, + A0_MOV, + UREG(REG_TYPE_OC, 0), + A0_DEST_CHANNEL_ALL, 0, + swizzle(tmp, ONE, ZERO, ONE, ONE), 0, 0); + return; + } + + while (1) { + GLuint src0, src1, src2, flags; + GLuint tmp = 0; + + switch (inst->Opcode) { + case OPCODE_ABS: + src0 = src_vector(p, &inst->SrcReg[0], program); + i915_emit_arith(p, + A0_MAX, + get_result_vector(p, inst), + get_result_flags(inst), 0, + src0, negate(src0, 1, 1, 1, 1), 0); + break; + + case OPCODE_ADD: + EMIT_2ARG_ARITH(A0_ADD); + break; + + case OPCODE_CMP: + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + src2 = src_vector(p, &inst->SrcReg[2], program); + i915_emit_arith(p, A0_CMP, + get_result_vector(p, inst), get_result_flags(inst), + 0, src0, src2, src1); /* NOTE: order of src2, src1 */ + break; + + case OPCODE_COS: + src0 = src_vector(p, &inst->SrcReg[0], program); + tmp = i915_get_utemp(p); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_X, 0, + src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0); + + i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); + + /* By choosing different taylor constants, could get rid of this mul: + */ + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_X, 0, + tmp, i915_emit_const1f(p, (M_PI * 2)), 0); + + /* + * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 + * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, 1 + * t0 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1 + * result = DP4 t0, cos_constants + */ + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XY, 0, + swizzle(tmp, X, X, ONE, ONE), + swizzle(tmp, X, ONE, ONE, ONE), 0); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XYZ, 0, + swizzle(tmp, X, Y, X, ONE), + swizzle(tmp, X, X, ONE, ONE), 0); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XYZ, 0, + swizzle(tmp, X, X, Z, ONE), + swizzle(tmp, Z, ONE, ONE, ONE), 0); + + i915_emit_arith(p, + A0_DP4, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(tmp, ONE, Z, Y, X), + i915_emit_const4fv(p, cos_constants), 0); + + break; + + case OPCODE_DP3: + EMIT_2ARG_ARITH(A0_DP3); + break; + + case OPCODE_DP4: + EMIT_2ARG_ARITH(A0_DP4); + break; + + case OPCODE_DPH: + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + + i915_emit_arith(p, + A0_DP4, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, X, Y, Z, ONE), src1, 0); + break; + + case OPCODE_DST: + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + + /* result[0] = 1 * 1; + * result[1] = a[1] * b[1]; + * result[2] = a[2] * 1; + * result[3] = 1 * b[3]; + */ + i915_emit_arith(p, + A0_MUL, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, ONE, Y, Z, ONE), + swizzle(src1, ONE, Y, ONE, W), 0); + break; + + case OPCODE_EX2: + src0 = src_vector(p, &inst->SrcReg[0], program); + + i915_emit_arith(p, + A0_EXP, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, X, X, X, X), 0, 0); + break; + + case OPCODE_FLR: + EMIT_1ARG_ARITH(A0_FLR); + break; + + case OPCODE_FRC: + EMIT_1ARG_ARITH(A0_FRC); + break; + + case OPCODE_KIL: + src0 = src_vector(p, &inst->SrcReg[0], program); + tmp = i915_get_utemp(p); + + i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */ + 0, src0, T0_TEXKILL); + break; + + case OPCODE_LG2: + src0 = src_vector(p, &inst->SrcReg[0], program); + + i915_emit_arith(p, + A0_LOG, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, X, X, X, X), 0, 0); + break; + + case OPCODE_LIT: + src0 = src_vector(p, &inst->SrcReg[0], program); + tmp = i915_get_utemp(p); + + /* tmp = max( a.xyzw, a.00zw ) + * XXX: Clamp tmp.w to -128..128 + * tmp.y = log(tmp.y) + * tmp.y = tmp.w * tmp.y + * tmp.y = exp(tmp.y) + * result = cmp (a.11-x1, a.1x01, a.1xy1 ) + */ + i915_emit_arith(p, A0_MAX, tmp, A0_DEST_CHANNEL_ALL, 0, + src0, swizzle(src0, ZERO, ZERO, Z, W), 0); + + i915_emit_arith(p, A0_LOG, tmp, A0_DEST_CHANNEL_Y, 0, + swizzle(tmp, Y, Y, Y, Y), 0, 0); + + i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_Y, 0, + swizzle(tmp, ZERO, Y, ZERO, ZERO), + swizzle(tmp, ZERO, W, ZERO, ZERO), 0); + + i915_emit_arith(p, A0_EXP, tmp, A0_DEST_CHANNEL_Y, 0, + swizzle(tmp, Y, Y, Y, Y), 0, 0); + + i915_emit_arith(p, A0_CMP, + get_result_vector(p, inst), + get_result_flags(inst), 0, + negate(swizzle(tmp, ONE, ONE, X, ONE), 0, 0, 1, 0), + swizzle(tmp, ONE, X, ZERO, ONE), + swizzle(tmp, ONE, X, Y, ONE)); + + break; + + case OPCODE_LRP: + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + src2 = src_vector(p, &inst->SrcReg[2], program); + flags = get_result_flags(inst); + tmp = i915_get_utemp(p); + + /* b*a + c*(1-a) + * + * b*a + c - ca + * + * tmp = b*a + c, + * result = (-c)*a + tmp + */ + i915_emit_arith(p, A0_MAD, tmp, + flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2); + + i915_emit_arith(p, A0_MAD, + get_result_vector(p, inst), + flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp); + break; + + case OPCODE_MAD: + EMIT_3ARG_ARITH(A0_MAD); + break; + + case OPCODE_MAX: + EMIT_2ARG_ARITH(A0_MAX); + 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); + break; + + case OPCODE_MOV: + EMIT_1ARG_ARITH(A0_MOV); + break; + + case OPCODE_MUL: + EMIT_2ARG_ARITH(A0_MUL); + break; + + case OPCODE_POW: + 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); + + /* XXX: masking on intermediate values, here and elsewhere. + */ + i915_emit_arith(p, + A0_LOG, + tmp, A0_DEST_CHANNEL_X, 0, + swizzle(src0, X, X, X, X), 0, 0); + + i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0); + + + i915_emit_arith(p, + A0_EXP, + get_result_vector(p, inst), + flags, 0, swizzle(tmp, X, X, X, X), 0, 0); + + break; + + case OPCODE_RCP: + src0 = src_vector(p, &inst->SrcReg[0], program); + + i915_emit_arith(p, + A0_RCP, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, X, X, X, X), 0, 0); + break; + + case OPCODE_RSQ: + + src0 = src_vector(p, &inst->SrcReg[0], program); + + i915_emit_arith(p, + A0_RSQ, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, X, X, X, X), 0, 0); + break; + + case OPCODE_SCS: + src0 = src_vector(p, &inst->SrcReg[0], program); + tmp = i915_get_utemp(p); + + /* + * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 + * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x + * t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x + * scs.x = DP4 t1, sin_constants + * t1 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1 + * scs.y = DP4 t1, cos_constants + */ + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XY, 0, + swizzle(src0, X, X, ONE, ONE), + swizzle(src0, X, ONE, ONE, ONE), 0); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_ALL, 0, + swizzle(tmp, X, Y, X, Y), + swizzle(tmp, X, X, ONE, ONE), 0); + + if (inst->DstReg.WriteMask & WRITEMASK_Y) { + GLuint tmp1; + + if (inst->DstReg.WriteMask & WRITEMASK_X) + tmp1 = i915_get_utemp(p); + else + tmp1 = tmp; + + i915_emit_arith(p, + A0_MUL, + tmp1, A0_DEST_CHANNEL_ALL, 0, + swizzle(tmp, X, Y, Y, W), + swizzle(tmp, X, Z, ONE, ONE), 0); + + i915_emit_arith(p, + A0_DP4, + get_result_vector(p, inst), + A0_DEST_CHANNEL_Y, 0, + swizzle(tmp1, W, Z, Y, X), + i915_emit_const4fv(p, sin_constants), 0); + } + + if (inst->DstReg.WriteMask & WRITEMASK_X) { + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XYZ, 0, + swizzle(tmp, X, X, Z, ONE), + swizzle(tmp, Z, ONE, ONE, ONE), 0); + + i915_emit_arith(p, + A0_DP4, + get_result_vector(p, inst), + A0_DEST_CHANNEL_X, 0, + swizzle(tmp, ONE, Z, Y, X), + i915_emit_const4fv(p, cos_constants), 0); + } + break; + + case OPCODE_SGE: + EMIT_2ARG_ARITH(A0_SGE); + break; + + case OPCODE_SIN: + src0 = src_vector(p, &inst->SrcReg[0], program); + tmp = i915_get_utemp(p); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_X, 0, + src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0); + + i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); + + /* By choosing different taylor constants, could get rid of this mul: + */ + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_X, 0, + tmp, i915_emit_const1f(p, (M_PI * 2)), 0); + + /* + * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 + * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x + * t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x + * result = DP4 t1.wzyx, sin_constants + */ + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_XY, 0, + swizzle(tmp, X, X, ONE, ONE), + swizzle(tmp, X, ONE, ONE, ONE), 0); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_ALL, 0, + swizzle(tmp, X, Y, X, Y), + swizzle(tmp, X, X, ONE, ONE), 0); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_ALL, 0, + swizzle(tmp, X, Y, Y, W), + swizzle(tmp, X, Z, ONE, ONE), 0); + + i915_emit_arith(p, + A0_DP4, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(tmp, W, Z, Y, X), + i915_emit_const4fv(p, sin_constants), 0); + break; + + case OPCODE_SLT: + EMIT_2ARG_ARITH(A0_SLT); + break; + + case OPCODE_SUB: + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + + i915_emit_arith(p, + A0_ADD, + get_result_vector(p, inst), + get_result_flags(inst), 0, + src0, negate(src1, 1, 1, 1, 1), 0); + break; + + case OPCODE_SWZ: + EMIT_1ARG_ARITH(A0_MOV); /* extended swizzle handled natively */ + break; + + case OPCODE_TEX: + EMIT_TEX(T0_TEXLD); + break; + + case OPCODE_TXB: + EMIT_TEX(T0_TEXLDB); + break; + + case OPCODE_TXP: + EMIT_TEX(T0_TEXLDP); + break; + + case OPCODE_XPD: + /* Cross product: + * result.x = src0.y * src1.z - src0.z * src1.y; + * result.y = src0.z * src1.x - src0.x * src1.z; + * result.z = src0.x * src1.y - src0.y * src1.x; + * result.w = undef; + */ + src0 = src_vector(p, &inst->SrcReg[0], program); + src1 = src_vector(p, &inst->SrcReg[1], program); + tmp = i915_get_utemp(p); + + i915_emit_arith(p, + A0_MUL, + tmp, A0_DEST_CHANNEL_ALL, 0, + swizzle(src0, Z, X, Y, ONE), + swizzle(src1, Y, Z, X, ONE), 0); + + i915_emit_arith(p, + A0_MAD, + get_result_vector(p, inst), + get_result_flags(inst), 0, + swizzle(src0, Y, Z, X, ONE), + swizzle(src1, Z, X, Y, ONE), + negate(tmp, 1, 1, 1, 0)); + break; + + case OPCODE_END: + return; + + default: + i915_program_error(p, "bad opcode"); + return; + } + + inst++; + i915_release_utemps(p); + } +} + +/* Rather than trying to intercept and jiggle depth writes during + * emit, just move the value into its correct position at the end of + * the program: + */ +void +i915_fixup_depth_write(struct i915_fp_compile *p) +{ + if (p->fp->Base.Base.OutputsWritten & (1<<FRAG_RESULT_DEPR)) { + GLuint depth = UREG(REG_TYPE_OD, 0); + + i915_emit_arith(p, + A0_MOV, + depth, A0_DEST_CHANNEL_W, 0, + swizzle(depth, X, Y, Z, Z), 0, 0); + } +} + + + + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fallback.c b/src/mesa/drivers/dri/i915tex/i915_state_fallback.c new file mode 100644 index 0000000000..c327e19c44 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_fallback.c @@ -0,0 +1,114 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + 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 NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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. + + **********************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + + +#include "intel_batchbuffer.h" +#include "intel_regions.h" +#include "intel_context.h" +#include "intel_tex.h" +#include "intel_fbo.h" +#include "i915_context.h" + +/* A place to check fallbacks that aren't calculated on the fly or in + * callback functions. + */ +static GLboolean do_check_fallback(struct intel_context *intel) +{ + GLuint i; + + /* INTEL_NEW_METAOPS + */ + if (intel->metaops.active) + return GL_FALSE; + + /* _NEW_BUFFERS + */ + if (intel->state._ColorDrawBufferMask0 != BUFFER_BIT_FRONT_LEFT && + intel->state._ColorDrawBufferMask0 != BUFFER_BIT_BACK_LEFT) + return GL_TRUE; + + /* _NEW_RENDERMODE + * + * XXX: need to save/restore RenderMode in metaops state, or + * somehow move to a new attribs pointer: + */ + if (intel->state.RenderMode != GL_RENDER) + return GL_TRUE; + + /* _NEW_TEXTURE: + */ + for (i = 0; i < I915_TEX_UNITS; i++) { + struct gl_texture_unit *texUnit = &intel->state.Texture->Unit[i]; + if (texUnit->_ReallyEnabled) { + struct intel_texture_object *intelObj = intel_texture_object(texUnit->_Current); + struct gl_texture_image *texImage = intelObj->base.Image[0][intelObj->firstLevel]; + if (texImage->Border) + return GL_TRUE; + } + } + + /* _NEW_STENCIL, _NEW_BUFFERS + */ + if (intel->state.Stencil->Enabled) { + struct intel_renderbuffer *irbStencil = + (intel->state.DrawBuffer + ? intel_get_renderbuffer(intel->state.DrawBuffer, BUFFER_STENCIL) + : NULL); + + intel->hw_stencil = irbStencil && irbStencil->region; + + if (!intel->hw_stencil) + return GL_TRUE; + } + + + return GL_FALSE; +} + +static void check_fallback( struct intel_context *intel ) +{ + GLboolean flag = do_check_fallback( intel ); + + /* May raise INTEL_NEW_FALLBACK + */ + FALLBACK(intel, INTEL_FALLBACK_OTHER, flag ); +} + +const struct intel_tracked_state i915_check_fallback = { + .dirty = { + .mesa = _NEW_BUFFERS | _NEW_RENDERMODE | _NEW_TEXTURE | _NEW_STENCIL, + .intel = INTEL_NEW_METAOPS, + .extra = 0 + }, + .update = check_fallback +}; + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_invarient.c b/src/mesa/drivers/dri/i915tex/i915_state_invarient.c new file mode 100644 index 0000000000..befc12b76e --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_invarient.c @@ -0,0 +1,140 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 "glheader.h" +#include "macros.h" +#include "enums.h" +#include "program.h" + +#include "intel_batchbuffer.h" +#include "i915_context.h" +#include "i915_reg.h" + + + + +/*********************************************************************** + * Misc invarient state packets + */ + +static void upload_invarient_state( struct intel_context *intel ) +{ + static GLuint invarient_state[] = { + + (_3DSTATE_AA_CMD | + AA_LINE_ECAAR_WIDTH_ENABLE | + AA_LINE_ECAAR_WIDTH_1_0 | + AA_LINE_REGION_WIDTH_ENABLE | + AA_LINE_REGION_WIDTH_1_0), + + /* Could use these to reduce the size of vertices when the incoming + * array is constant. + */ + (_3DSTATE_DFLT_DIFFUSE_CMD), + (0), + + (_3DSTATE_DFLT_SPEC_CMD), + (0), + + (_3DSTATE_DFLT_Z_CMD), + (0), + + /* We support texture crossbar via the fragment shader, rather than + * with this mechanism. + */ + (_3DSTATE_COORD_SET_BINDINGS | + CSB_TCB(0, 0) | + CSB_TCB(1, 1) | + CSB_TCB(2, 2) | + CSB_TCB(3, 3) | + CSB_TCB(4, 4) | + CSB_TCB(5, 5) | + CSB_TCB(6, 6) | + CSB_TCB(7, 7)), + + /* Setup OpenGL rasterization state: + */ + (_3DSTATE_RASTER_RULES_CMD | + ENABLE_POINT_RASTER_RULE | + OGL_POINT_RASTER_RULE | + ENABLE_LINE_STRIP_PROVOKE_VRTX | + ENABLE_TRI_FAN_PROVOKE_VRTX | + LINE_STRIP_PROVOKE_VRTX(1) | + TRI_FAN_PROVOKE_VRTX(2) | + ENABLE_TEXKILL_3D_4D | + TEXKILL_4D), + + /* Need to initialize this to zero. + */ + (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(3) | + (1)), + (0), + + (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT), + (_3DSTATE_SCISSOR_RECT_0_CMD), + (0), + (0), + + + /* For private depth buffers but shared color buffers, eg + * front-buffer rendering with a private depthbuffer. We don't do + * this. + */ + (_3DSTATE_DEPTH_SUBRECT_DISABLE), + + /* Disable indirect state for now. + */ + (_3DSTATE_LOAD_INDIRECT | 0), + (0), + + (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0) + }; + + { + GLuint i; + + BEGIN_BATCH(sizeof(invarient_state)/4, 0); + + for (i = 0; i < sizeof(invarient_state)/4; i++) + OUT_BATCH( invarient_state[i] ); + + ADVANCE_BATCH(); + } +} + +const struct intel_tracked_state i915_invarient_state = { + .dirty = { + .mesa = 0, + .intel = INTEL_NEW_CONTEXT, /* or less frequently? */ + .extra = 0 + }, + .update = upload_invarient_state +}; + + + diff --git a/src/mesa/drivers/dri/i915tex/intel_debug.h b/src/mesa/drivers/dri/i915tex/intel_debug.h new file mode 100644 index 0000000000..90d654ea1d --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_debug.h @@ -0,0 +1,58 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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. + * + **************************************************************************/ + +#ifndef INTEL_DEBUG_H +#define INTEL_DEBUG_H + +#include "imports.h" + +#if defined(DEBUG) +#define DO_DEBUG 1 +extern int INTEL_DEBUG; +#else +#define INTEL_DEBUG 0 +#endif + +#define DEBUG_TEXTURE 0x1 +#define DEBUG_STATE 0x2 +#define DEBUG_IOCTL 0x4 +#define DEBUG_BLIT 0x8 +#define DEBUG_MIPTREE 0x10 +#define DEBUG_FALLBACKS 0x20 +#define DEBUG_VERBOSE 0x40 +#define DEBUG_BATCH 0x80 +#define DEBUG_PIXEL 0x100 +#define DEBUG_BUFMGR 0x200 +#define DEBUG_REGION 0x400 +#define DEBUG_FBO 0x800 +#define DEBUG_LOCK 0x1000 +#define DEBUG_IDX 0x2000 +#define DEBUG_TRI 0x4000 + +#define DBG(...) do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0) + +#endif diff --git a/src/mesa/drivers/dri/i915tex/intel_metaops.c b/src/mesa/drivers/dri/i915tex/intel_metaops.c new file mode 100644 index 0000000000..e78423947f --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_metaops.c @@ -0,0 +1,546 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + 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 NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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. + + **********************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * frame buffer texture by Gary Wong <gtw@gnu.org> + */ + +/* TODO: push this type of operation into core mesa. + */ + + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" + +#include "shader/arbprogparse.h" + +#include "intel_screen.h" +#include "intel_batchbuffer.h" +#include "intel_regions.h" +#include "intel_context.h" +#include "intel_metaops.h" +#include "intel_reg.h" + + +#define DUP(i915, STRUCT, ATTRIB) \ +do { \ + intel->metaops.state.ATTRIB = MALLOC_STRUCT(STRUCT); \ + memcpy(intel->metaops.state.ATTRIB, \ + intel->state.ATTRIB, \ + sizeof(struct STRUCT)); \ +} while (0) + + +#define INSTALL(intel, ATTRIB, STATE) \ +do { \ + intel->state.ATTRIB = intel->metaops.state.ATTRIB; \ + intel->state.dirty.mesa |= STATE; \ +} while (0) + +#define RESTORE(intel, ATTRIB, STATE) \ +do { \ + intel->state.ATTRIB = &intel->ctx.ATTRIB; \ + intel->state.dirty.mesa |= STATE; \ +} while (0) + +static void init_state( struct intel_context *intel ) +{ + DUP(intel, gl_colorbuffer_attrib, Color); + DUP(intel, gl_depthbuffer_attrib, Depth); + DUP(intel, gl_fog_attrib, Fog); + DUP(intel, gl_hint_attrib, Hint); + DUP(intel, gl_light_attrib, Light); + DUP(intel, gl_line_attrib, Line); + DUP(intel, gl_point_attrib, Point); + DUP(intel, gl_polygon_attrib, Polygon); + DUP(intel, gl_scissor_attrib, Scissor); + DUP(intel, gl_stencil_attrib, Stencil); + DUP(intel, gl_texture_attrib, Texture); + DUP(intel, gl_transform_attrib, Transform); + DUP(intel, gl_viewport_attrib, Viewport); + DUP(intel, gl_vertex_program_state, VertexProgram); + DUP(intel, gl_fragment_program_state, FragmentProgram); +} + +static void install_state( struct intel_context *intel ) +{ + INSTALL(intel, Color, _NEW_COLOR); + INSTALL(intel, Depth, _NEW_DEPTH); + INSTALL(intel, Fog, _NEW_FOG); + INSTALL(intel, Hint, _NEW_HINT); + INSTALL(intel, Light, _NEW_LIGHT); + INSTALL(intel, Line, _NEW_LINE); + INSTALL(intel, Point, _NEW_POINT); + INSTALL(intel, Polygon, _NEW_POLYGON); + INSTALL(intel, Scissor, _NEW_SCISSOR); + INSTALL(intel, Stencil, _NEW_STENCIL); + INSTALL(intel, Texture, _NEW_TEXTURE); + INSTALL(intel, Transform, _NEW_TRANSFORM); + INSTALL(intel, Viewport, _NEW_VIEWPORT); + INSTALL(intel, VertexProgram, _NEW_PROGRAM); + INSTALL(intel, FragmentProgram, _NEW_PROGRAM); +} + +static void restore_state( struct intel_context *intel ) +{ + RESTORE(intel, Color, _NEW_COLOR); + RESTORE(intel, Depth, _NEW_DEPTH); + RESTORE(intel, Fog, _NEW_FOG); + RESTORE(intel, Hint, _NEW_HINT); + RESTORE(intel, Light, _NEW_LIGHT); + RESTORE(intel, Line, _NEW_LINE); + RESTORE(intel, Point, _NEW_POINT); + RESTORE(intel, Polygon, _NEW_POLYGON); + RESTORE(intel, Scissor, _NEW_SCISSOR); + RESTORE(intel, Stencil, _NEW_STENCIL); + RESTORE(intel, Texture, _NEW_TEXTURE); + RESTORE(intel, Transform, _NEW_TRANSFORM); + RESTORE(intel, Viewport, _NEW_VIEWPORT); + RESTORE(intel, VertexProgram, _NEW_PROGRAM); + RESTORE(intel, FragmentProgram, _NEW_PROGRAM); +} + +/* It would certainly be preferably to skip the vertex program step + * and go straight to post-transform draw. We can probably do that + * with the indexed-render code and after noting that fallbacks are + * never active during metaops. + */ +static const char *vp_prog_tex = + "!!ARBvp1.0\n" + "MOV result.texcoord[0], vertex.texcoord[0];\n" + "MOV result.color, vertex.color;\n" + "MOV result.position, vertex.position;\n" + "END\n"; + + +/* Because the texenv program is calculated from ctx derived state, + * and bypasses our intel->state attribute pointer mechanism, it won't + * be correctly calculated in metaops. So, we have to supply our own + * fragment programs to do the right thing: + */ +static const char *fp_prog = + "!!ARBfp1.0\n" + "MOV result.color, fragment.color;\n" + "END\n"; + +static const char *fp_tex_prog = + "!!ARBfp1.0\n" + "TEX result.color, fragment.texcoord[0], texture[0], 2D;\n" + "END\n"; + + +void intel_meta_flat_shade( struct intel_context *intel ) +{ + intel->metaops.state.Light->ShadeModel = GL_FLAT; + intel->state.dirty.mesa |= _NEW_LIGHT; +} + + +void intel_meta_no_stencil_write( struct intel_context *intel ) +{ + intel->metaops.state.Stencil->Enabled = GL_FALSE; + intel->metaops.state.Stencil->WriteMask[0] = GL_FALSE; + intel->state.dirty.mesa |= _NEW_STENCIL; +} + +void intel_meta_no_depth_write( struct intel_context *intel ) +{ + intel->metaops.state.Depth->Test = GL_FALSE; + intel->metaops.state.Depth->Mask = GL_FALSE; + intel->state.dirty.mesa |= _NEW_DEPTH; +} + + +void intel_meta_depth_replace( struct intel_context *intel ) +{ + /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE ) + * ctx->Driver.DepthMask( ctx, GL_TRUE ) + */ + intel->metaops.state.Depth->Test = GL_TRUE; + intel->metaops.state.Depth->Mask = GL_TRUE; + intel->state.dirty.mesa |= _NEW_DEPTH; + + /* ctx->Driver.DepthFunc( ctx, GL_ALWAYS ) + */ + intel->metaops.state.Depth->Func = GL_ALWAYS; + + intel->state.dirty.mesa |= _NEW_DEPTH; +} + + +void intel_meta_stencil_replace( struct intel_context *intel, + GLuint s_mask, + GLuint s_clear) +{ + intel->metaops.state.Stencil->Enabled = GL_TRUE; + intel->metaops.state.Stencil->WriteMask[0] = s_mask; + intel->metaops.state.Stencil->ValueMask[0] = 0xff; + intel->metaops.state.Stencil->Ref[0] = s_clear; + intel->metaops.state.Stencil->Function[0] = GL_ALWAYS; + intel->metaops.state.Stencil->FailFunc[0] = GL_REPLACE; + intel->metaops.state.Stencil->ZPassFunc[0] = GL_REPLACE; + intel->metaops.state.Stencil->ZFailFunc[0] = GL_REPLACE; + intel->state.dirty.mesa |= _NEW_STENCIL; +} + + +void intel_meta_color_mask( struct intel_context *intel, GLboolean state ) +{ + if (state) + COPY_4V(intel->metaops.state.Color->ColorMask, + intel->ctx.Color.ColorMask); + else + ASSIGN_4V(intel->metaops.state.Color->ColorMask, 0, 0, 0, 0); + + intel->state.dirty.mesa |= _NEW_COLOR; +} + +void intel_meta_no_texture( struct intel_context *intel ) +{ + intel->metaops.state.Texture->CurrentUnit = 0; + intel->metaops.state.Texture->_EnabledUnits = 0; + intel->metaops.state.Texture->_EnabledCoordUnits = 0; + intel->metaops.state.Texture->Unit[ 0 ].Enabled = 0; + intel->metaops.state.Texture->Unit[ 0 ]._ReallyEnabled = 0; + + intel->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM; +} + +void intel_meta_texture_blend_replace(struct intel_context *intel) +{ + intel->metaops.state.Texture->CurrentUnit = 0; + intel->metaops.state.Texture->_EnabledUnits = 1; + intel->metaops.state.Texture->_EnabledCoordUnits = 1; + intel->metaops.state.Texture->Unit[ 0 ].Enabled = TEXTURE_2D_BIT; + intel->metaops.state.Texture->Unit[ 0 ]._ReallyEnabled = TEXTURE_2D_BIT; +/* intel->metaops.state.Texture->Unit[ 0 ].Current2D = */ +/* intel->frame_buffer_texobj; */ +/* intel->metaops.state.Texture->Unit[ 0 ]._Current = */ +/* intel->frame_buffer_texobj; */ + + intel->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM; +} + +void intel_meta_import_pixel_state(struct intel_context *intel) +{ + RESTORE(intel, Color, _NEW_COLOR); + RESTORE(intel, Depth, _NEW_DEPTH); + RESTORE(intel, Fog, _NEW_FOG); + RESTORE(intel, Scissor, _NEW_SCISSOR); + RESTORE(intel, Stencil, _NEW_STENCIL); + RESTORE(intel, Texture, _NEW_TEXTURE); + RESTORE(intel, FragmentProgram, _NEW_PROGRAM); +} + + + +/* Set up an arbitary piece of memory as a rectangular texture + * (including the front or back buffer). + */ +GLboolean intel_meta_tex_rect_source(struct intel_context *intel, + struct _DriBufferObject *buffer, + GLuint offset, + GLuint pitch, GLuint height, + GLenum format, GLenum type) +{ + assert(0); +#if 0 + GLuint unit = 0; + GLint numLevels = 1; + GLuint *state = intel->meta.Tex[0]; + GLuint textureFormat; + GLuint cpp; + + /* A full implementation of this would do the upload through + * glTexImage2d, and get all the conversion operations at that + * point. We are restricted, but still at least have access to the + * fragment program swizzle. + */ + switch (format) { + case GL_BGRA: + switch (type) { + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_BYTE: + textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); + cpp = 4; + break; + default: + return GL_FALSE; + } + break; + case GL_RGBA: + switch (type) { + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_BYTE: + textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888); + cpp = 4; + break; + default: + return GL_FALSE; + } + break; + case GL_BGR: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5_REV: + textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); + cpp = 2; + break; + default: + return GL_FALSE; + } + break; + case GL_RGB: + switch (type) { + case GL_UNSIGNED_SHORT_5_6_5: + textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); + cpp = 2; + break; + default: + return GL_FALSE; + } + break; + + default: + return GL_FALSE; + } + + + if ((pitch * cpp) & 3) { + _mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__); + return GL_FALSE; + } + +/* intel_region_release(&intel->meta.tex_region[0]); */ +/* intel_region_reference(&intel->meta.tex_region[0], region); */ + intel->meta.tex_buffer[0] = buffer; + intel->meta.tex_offset[0] = offset; +#endif + + /* Don't do this, fill in the state objects as appropriate instead. + */ +#if 0 + state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) | + ((pitch - 1) << MS3_WIDTH_SHIFT) | + textureFormat | MS3_USE_FENCE_REGS); + + state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) | + MS4_CUBE_FACE_ENA_MASK | + ((((numLevels - 1) * 4)) << MS4_MAX_LOD_SHIFT)); + + state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) | + (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | + (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); + + state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | + (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | + (unit << SS3_TEXTUREMAP_INDEX_SHIFT)); + + state[I915_TEXREG_SS4] = 0; + + i915->meta.emitted &= ~I915_UPLOAD_TEX(0); +#endif + + return GL_TRUE; +} + + + +void intel_meta_draw_region( struct intel_context *intel, + struct intel_region *draw_region, + struct intel_region *depth_region ) +{ +#if 0 + if (!intel->metaops.saved_draw_region) { + intel->metaops.saved_draw_region = intel->state.draw_region; + intel->metaops.saved_depth_region = intel->state.depth_region; + } + + intel->state.draw_region = draw_region; + intel->state.depth_region = depth_region; + + intel->state.dirty.mesa |= _NEW_BUFFERS; +#endif +} + + +/* Big problem is that tnl doesn't know about our internal + * state-swaping mechanism so wouldn't respect it if we passed this + * here. That *should* get fixed by pushing the state mechanism + * higher into mesa, but I haven't got there yet. In the meantime, + */ +void +intel_meta_draw_poly(struct intel_context *intel, + GLuint n, + GLfloat xy[][2], + GLfloat z, GLuint color, GLfloat tex[][2]) +{ + GLint sz; + GLint i; + + intel_emit_state( intel ); + + sz = intel->vertex_size; + + /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS, + * otherwise the drawing origin (DR4) might not be set correctly. + */ + BEGIN_BATCH(2+n*sz, INTEL_BATCH_CLIPRECTS); + + OUT_BATCH( _3DPRIMITIVE | + PRIM3D_TRIFAN | + (n * intel->vertex_size - 1 )); + + + for (i = 0; i < n; i++) { + OUT_BATCH_F( xy[i][0] ); + OUT_BATCH_F( xy[i][1] ); + OUT_BATCH_F( z ); + OUT_BATCH( color ); + if (intel->vertex_size == 6) { + OUT_BATCH_F( tex[i][0] ); + OUT_BATCH_F( tex[i][1] ); + } + else { + assert(intel->vertex_size == 4); + } + } + ADVANCE_BATCH(); +} + +void +intel_meta_draw_quad(struct intel_context *intel, + GLfloat x0, GLfloat x1, + GLfloat y0, GLfloat y1, + GLfloat z, + GLuint color, + GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1) +{ + GLfloat xy[4][2]; + GLfloat tex[4][2]; + + xy[0][0] = x0; + xy[0][1] = y0; + xy[1][0] = x1; + xy[1][1] = y0; + xy[2][0] = x1; + xy[2][1] = y1; + xy[3][0] = x0; + xy[3][1] = y1; + + tex[0][0] = s0; + tex[0][1] = t0; + tex[1][0] = s1; + tex[1][1] = t0; + tex[2][0] = s1; + tex[2][1] = t1; + tex[3][0] = s0; + tex[3][1] = t1; + + intel_meta_draw_poly(intel, 4, xy, z, color, tex); +} + + +void intel_install_meta_state( struct intel_context *intel ) +{ + assert(0); + + install_state(intel); + + intel_meta_no_texture(intel); + intel_meta_flat_shade(intel); + +/* intel->metaops.restore_draw_mask = ctx->DrawBuffer->_ColorDrawBufferMask[0]; */ +/* intel->metaops.restore_fp = ctx->FragmentProgram.Current; */ + + /* This works without adjusting refcounts. Fix later? + */ +/* intel->metaops.saved_draw_region = intel->state.draw_region; */ +/* intel->metaops.saved_depth_region = intel->state.depth_region; */ + intel->metaops.active = 1; + + intel->state.dirty.intel |= INTEL_NEW_METAOPS; +} + +void intel_leave_meta_state( struct intel_context *intel ) +{ + restore_state(intel); + +/* ctx->DrawBuffer->_ColorDrawBufferMask[0] = intel->metaops.restore_draw_mask; */ +/* ctx->FragmentProgram.Current = intel->metaops.restore_fp; */ + +/* intel->state.draw_region = intel->metaops.saved_draw_region; */ +/* intel->state.depth_region = intel->metaops.saved_depth_region; */ +/* intel->metaops.saved_draw_region = NULL; */ +/* intel->metaops.saved_depth_region = NULL; */ + intel->metaops.active = 0; + + intel->state.dirty.mesa |= _NEW_BUFFERS; + intel->state.dirty.intel |= INTEL_NEW_METAOPS; +} + + + +void intel_metaops_init( struct intel_context *intel ) +{ +/* GLcontext *ctx = &intel->ctx; */ + + init_state(intel); + +#if 0 + intel->metaops.fp = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 ); + + intel->metaops.fp_tex = (struct gl_fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 ); + + _mesa_parse_arb_fragment_program(ctx, GL_FRAGMENT_PROGRAM_ARB, + fp_prog, strlen(fp_prog), + intel->metaops.fp); + + _mesa_parse_arb_fragment_program(ctx, GL_FRAGMENT_PROGRAM_ARB, + fp_tex_prog, strlen(fp_tex_prog), + intel->metaops.fp_tex); +#endif + +/* intel->metaops.state.VertexProgram->Current = intel->metaops.vp; */ +/* intel->metaops.state.VertexProgram->_Enabled = GL_TRUE; */ +} + +void intel_metaops_destroy( struct intel_context *intel ) +{ + GLcontext *ctx = &intel->ctx; + + if (intel->metaops.vbo) + ctx->Driver.DeleteBuffer( ctx, intel->metaops.vbo ); + +/* ctx->Driver.DeleteProgram( ctx, intel->metaops.vp ); */ +} diff --git a/src/mesa/drivers/dri/i915tex/intel_metaops.h b/src/mesa/drivers/dri/i915tex/intel_metaops.h new file mode 100644 index 0000000000..0a4f0969ac --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_metaops.h @@ -0,0 +1,86 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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. + * + **************************************************************************/ + +#ifndef INTEL_METAOPS_H +#define INTEL_METAOPS_H + +#include "glheader.h" + +struct intel_context; +struct intel_region; +struct _DriBufferObject; + +void intel_meta_draw_poly(struct intel_context *intel, + GLuint n, + GLfloat xy[][2], + GLfloat z, GLuint color, GLfloat tex[][2]); + +void intel_meta_draw_quad(struct intel_context *intel, + GLfloat x0, GLfloat x1, + GLfloat y0, GLfloat y1, + GLfloat z, + GLuint color, + GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1); + +void intel_meta_draw_region( struct intel_context *intel, + struct intel_region *draw_region, + struct intel_region *depth_region ); + +GLboolean intel_meta_tex_rect_source(struct intel_context *intel, + struct _DriBufferObject *buffer, + GLuint offset, + GLuint pitch, GLuint height, + GLenum format, GLenum type); + +void intel_meta_import_pixel_state(struct intel_context *intel); + +void intel_meta_texture_blend_replace(struct intel_context *intel); + +void intel_meta_no_texture( struct intel_context *intel ); + +void intel_meta_color_mask( struct intel_context *intel, GLboolean state ); + +void intel_meta_stencil_replace( struct intel_context *intel, + GLuint s_mask, + GLuint s_clear); + +void intel_meta_depth_replace( struct intel_context *intel ); + +void intel_meta_no_depth_write( struct intel_context *intel ); + +void intel_meta_no_stencil_write( struct intel_context *intel ); + +void intel_meta_flat_shade( struct intel_context *intel ); + +void intel_install_meta_state( struct intel_context *intel ); +void intel_leave_meta_state( struct intel_context *intel ); + +void intel_metaops_init( struct intel_context *intel ); +void intel_metaops_destroy( struct intel_context *intel ); + + +#endif diff --git a/src/mesa/drivers/dri/i915tex/intel_program.c b/src/mesa/drivers/dri/i915tex/intel_program.c new file mode 100644 index 0000000000..e54b600667 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_program.c @@ -0,0 +1,269 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "intel_batchbuffer.h" + +#include "i915_reg.h" +#include "i915_context.h" +#include "i915_fp.h" + +#include "program_instruction.h" +#include "program.h" +#include "programopt.h" + + +static void brwBindProgram( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + struct brw_context *brw = brw_context(ctx); + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; + break; + case GL_FRAGMENT_PROGRAM_ARB: + brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; + break; + } +} + +static struct gl_program *brwNewProgram( GLcontext *ctx, + GLenum target, + GLuint id ) +{ + struct brw_context *brw = brw_context(ctx); + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: { + struct brw_vertex_program *prog = CALLOC_STRUCT(brw_vertex_program); + if (prog) { + prog->id = brw->program_id++; + + return _mesa_init_vertex_program( ctx, &prog->program, + target, id ); + } + else + return NULL; + } + + case GL_FRAGMENT_PROGRAM_ARB: { + struct brw_fragment_program *prog = CALLOC_STRUCT(brw_fragment_program); + if (prog) { + prog->id = brw->program_id++; + + return _mesa_init_fragment_program( ctx, &prog->program, + target, id ); + } + else + return NULL; + } + + default: + return _mesa_new_program(ctx, target, id); + } +} + +static void brwDeleteProgram( GLcontext *ctx, + struct gl_program *prog ) +{ + + _mesa_delete_program( ctx, prog ); +} + + +static GLboolean brwIsProgramNative( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + return GL_TRUE; +} + +static void brwProgramStringNotify( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + if (target == GL_FRAGMENT_PROGRAM_ARB) { + struct brw_context *brw = brw_context(ctx); + struct brw_fragment_program *p = (struct brw_fragment_program *)prog; + struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program; + if (p == fp) + brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; + p->id = brw->program_id++; + p->param_state = brw_parameter_list_state_flags(p->program.Base.Parameters); + } + else if (target == GL_VERTEX_PROGRAM_ARB) { + struct brw_context *brw = brw_context(ctx); + struct brw_vertex_program *p = (struct brw_vertex_program *)prog; + struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; + if (p == vp) + brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; + p->id = brw->program_id++; + p->param_state = brw_parameter_list_state_flags(p->program.Base.Parameters); + + /* Also tell tnl about it: + */ + _tnl_program_string(ctx, target, prog); + } +} + +void brwInitFragProgFuncs( struct dd_function_table *functions ) +{ + assert(functions->ProgramStringNotify == _tnl_program_string); + + functions->BindProgram = brwBindProgram; + functions->NewProgram = brwNewProgram; + functions->DeleteProgram = brwDeleteProgram; + functions->IsProgramNative = brwIsProgramNative; + functions->ProgramStringNotify = brwProgramStringNotify; +} + + + + +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; + + i915->current_program = p; + + assert(p->on_hardware == 0); + assert(p->params_uptodate == 0); + + /* Hack: make sure fog is correctly enabled according to this + * fragment program's fog options. + */ + ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB, + ctx->FragmentProgram.Enabled); + } +} + +static struct gl_program * +i915NewProgram(GLcontext * ctx, GLenum target, GLuint id) +{ + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), + target, id); + + case GL_FRAGMENT_PROGRAM_ARB:{ + struct i915_fragment_program *prog = + CALLOC_STRUCT(i915_fragment_program); + if (prog) { + i915_init_program(I915_CONTEXT(ctx), prog); + + return _mesa_init_fragment_program(ctx, &prog->FragProg, + target, id); + } + else + return NULL; + } + + default: + /* Just fallback: + */ + return _mesa_new_program(ctx, target, id); + } +} + +static void +i915DeleteProgram(GLcontext * ctx, struct gl_program *prog) +{ + if (prog->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) + i915->current_program = 0; + } + + _mesa_delete_program(ctx, prog); +} + + +static GLboolean +i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) +{ + if (target == GL_FRAGMENT_PROGRAM_ARB) { + struct i915_fragment_program *p = (struct i915_fragment_program *) prog; + + if (!p->translated) + translate_program(p); + + return !p->error; + } + else + return GL_TRUE; +} + +static void +i915ProgramStringNotify(GLcontext * 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. + */ + ctx->Driver.Enable(ctx, GL_FRAGMENT_PROGRAM_ARB, + ctx->FragmentProgram.Enabled); + + 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; + } + } + + _tnl_program_string(ctx, target, prog); +} + + + +void +i915InitFragProgFuncs(struct dd_function_table *functions) +{ + functions->BindProgram = i915BindProgram; + functions->NewProgram = i915NewProgram; + functions->DeleteProgram = i915DeleteProgram; + functions->IsProgramNative = i915IsProgramNative; + functions->ProgramStringNotify = i915ProgramStringNotify; +} diff --git a/src/mesa/drivers/dri/i915tex/intel_state.h b/src/mesa/drivers/dri/i915tex/intel_state.h new file mode 100644 index 0000000000..1f71454334 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_state.h @@ -0,0 +1,46 @@ +/* + Copyright (C) Intel Corp. 2006. All Rights Reserved. + Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + develop this 3D driver. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial + portions of the Software. + + 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 NONINFRINGEMENT. + IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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. + + **********************************************************************/ + /* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + + +#ifndef INTEL_STATE_H +#define INTEL_STATE_H + +struct intel_context; +struct intel_tracked_state; + +void intel_state_init( struct intel_context *intel ); +void intel_emit_state( struct intel_context *intel ); + + +const struct intel_tracked_state intel_update_viewport; +const struct intel_tracked_state intel_update_render_index; + +#endif diff --git a/src/mesa/drivers/dri/i915tex/intel_state_callbacks.c b/src/mesa/drivers/dri/i915tex/intel_state_callbacks.c new file mode 100644 index 0000000000..86b89fcdaf --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_state_callbacks.c @@ -0,0 +1,113 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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 "context.h" +#include "colormac.h" +#include "intel_context.h" +#include "intel_fbo.h" + + + + +/** + * Update the viewport transformation matrix. Depends on: + * - viewport pos/size + * - depthrange + * - window pos/size or FBO size + */ +static void update_viewport( struct intel_context *intel ) +{ + GLfloat yScale, yBias; + const GLframebuffer *DrawBuffer = intel->state.DrawBuffer; + + /* _NEW_BUFFERS + */ + if (DrawBuffer->Name) { + /* User created FBO */ + struct intel_renderbuffer *irb + = intel_renderbuffer(DrawBuffer->_ColorDrawBuffers[0][0]); + if (irb && !irb->RenderToTexture) { + /* y=0=top */ + yScale = -1.0; + yBias = irb->Base.Height; + } + else { + /* y=0=bottom */ + yScale = 1.0; + yBias = 0.0; + } + } + else { + /* window buffer, y=0=top */ + yScale = -1.0; + + /* INTEL_NEW_WINDOW_DIMENSIONS + * + * XXX: Note: this is only really valid while the lock is held. + * However, it is only invalidated when the window size changes, + * and when that happens we don't improve matters by noticing + * and adjusting the viewport halfway through a frame - it would + * actually be preferable to finish the frame with the same + * viewport origin as it started with. As it stands this does + * no real harm. + */ + yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F; + } + + { + /* _NEW_VIEWPORT + */ + const GLfloat *v = intel->state.Viewport->_WindowMap.m; + const GLfloat depthScale = 1.0F / DrawBuffer->_DepthMaxF; + GLfloat *m = intel->ViewportMatrix.m; + + _mesa_printf("depth scale %f\n", depthScale); + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X; + + m[MAT_SY] = v[MAT_SY] * yScale; + m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y; + + m[MAT_SZ] = v[MAT_SZ] * depthScale; + m[MAT_TZ] = v[MAT_TZ] * depthScale; + + /* Raise a flag like INTEL_NEW_VIEWPORT? + */ + } +} + + +const struct intel_tracked_state intel_update_viewport = { + .dirty = { + .mesa = _NEW_BUFFERS | _NEW_VIEWPORT, + .intel = INTEL_NEW_WINDOW_DIMENSIONS, + .extra = 0 + }, + .update = update_viewport +}; diff --git a/src/mesa/drivers/dri/i915tex/intel_state_inlines.h b/src/mesa/drivers/dri/i915tex/intel_state_inlines.h new file mode 100644 index 0000000000..c19d9645b8 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/intel_state_inlines.h @@ -0,0 +1,165 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * 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 + * 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. + * + **************************************************************************/ + +#ifndef INTEL_STATE_INLINES_H +#define INTEL_STATE_INLINES_H + +#include "glheader.h" +#include "intel_reg.h" + + +static INLINE int +intel_translate_compare_func(GLenum func) +{ + switch (func) { + case GL_NEVER: + return COMPAREFUNC_NEVER; + case GL_LESS: + return COMPAREFUNC_LESS; + case GL_LEQUAL: + return COMPAREFUNC_LEQUAL; + case GL_GREATER: + return COMPAREFUNC_GREATER; + case GL_GEQUAL: + return COMPAREFUNC_GEQUAL; + case GL_NOTEQUAL: + return COMPAREFUNC_NOTEQUAL; + case GL_EQUAL: + return COMPAREFUNC_EQUAL; + case GL_ALWAYS: + return COMPAREFUNC_ALWAYS; + default: + return COMPAREFUNC_ALWAYS; + } +} + +static INLINE int +intel_translate_stencil_op(GLenum op) +{ + switch (op) { + case GL_KEEP: + return STENCILOP_KEEP; + case GL_ZERO: + return STENCILOP_ZERO; + case GL_REPLACE: + return STENCILOP_REPLACE; + case GL_INCR: + return STENCILOP_INCRSAT; + case GL_DECR: + return STENCILOP_DECRSAT; + case GL_INCR_WRAP: + return STENCILOP_INCR; + case GL_DECR_WRAP: + return STENCILOP_DECR; + case GL_INVERT: + return STENCILOP_INVERT; + default: + return STENCILOP_ZERO; + } +} + +static INLINE int +intel_translate_blend_factor(GLenum factor) +{ + switch (factor) { + case GL_ZERO: + return BLENDFACT_ZERO; + case GL_SRC_ALPHA: + return BLENDFACT_SRC_ALPHA; + case GL_ONE: + return BLENDFACT_ONE; + case GL_SRC_COLOR: + return BLENDFACT_SRC_COLR; + case GL_ONE_MINUS_SRC_COLOR: + return BLENDFACT_INV_SRC_COLR; + case GL_DST_COLOR: + return BLENDFACT_DST_COLR; + case GL_ONE_MINUS_DST_COLOR: + return BLENDFACT_INV_DST_COLR; + case GL_ONE_MINUS_SRC_ALPHA: + return BLENDFACT_INV_SRC_ALPHA; + case GL_DST_ALPHA: + return BLENDFACT_DST_ALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return BLENDFACT_INV_DST_ALPHA; + case GL_SRC_ALPHA_SATURATE: + return BLENDFACT_SRC_ALPHA_SATURATE; + case GL_CONSTANT_COLOR: + return BLENDFACT_CONST_COLOR; + case GL_ONE_MINUS_CONSTANT_COLOR: + return BLENDFACT_INV_CONST_COLOR; + case GL_CONSTANT_ALPHA: + return BLENDFACT_CONST_ALPHA; + case GL_ONE_MINUS_CONSTANT_ALPHA: + return BLENDFACT_INV_CONST_ALPHA; + default: + return BLENDFACT_ZERO; + } +} + +static INLINE int +intel_translate_logic_op(GLenum opcode) +{ + switch (opcode) { + case GL_CLEAR: + return LOGICOP_CLEAR; + case GL_AND: + return LOGICOP_AND; + case GL_AND_REVERSE: + return LOGICOP_AND_RVRSE; + case GL_COPY: + return LOGICOP_COPY; + case GL_COPY_INVERTED: + return LOGICOP_COPY_INV; + case GL_AND_INVERTED: + return LOGICOP_AND_INV; + case GL_NOOP: + return LOGICOP_NOOP; + case GL_XOR: + return LOGICOP_XOR; + case GL_OR: + return LOGICOP_OR; + case GL_OR_INVERTED: + return LOGICOP_OR_INV; + case GL_NOR: + return LOGICOP_NOR; + case GL_EQUIV: + return LOGICOP_EQUIV; + case GL_INVERT: + return LOGICOP_INV; + case GL_OR_REVERSE: + return LOGICOP_OR_RVRSE; + case GL_NAND: + return LOGICOP_NAND; + case GL_SET: + return LOGICOP_SET; + default: + return LOGICOP_SET; + } +} + +#endif |