From c11f0148aca6bb8c03b8715c58eb2d4d2da8cc6c Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 8 Mar 2007 10:40:47 +0000 Subject: Beginnings of i915 state rework. Won't compile. --- src/mesa/drivers/dri/i915tex/Makefile | 26 +- src/mesa/drivers/dri/i915tex/i830_vtbl.c | 1 - src/mesa/drivers/dri/i915tex/i915_context.c | 22 +- src/mesa/drivers/dri/i915tex/i915_context.h | 69 +- src/mesa/drivers/dri/i915tex/i915_debug.c | 334 ------ src/mesa/drivers/dri/i915tex/i915_fp.c | 295 ++++++ src/mesa/drivers/dri/i915tex/i915_fp.h | 44 + src/mesa/drivers/dri/i915tex/i915_fp_debug.c | 334 ++++++ src/mesa/drivers/dri/i915tex/i915_fp_emit.c | 487 +++++++++ src/mesa/drivers/dri/i915tex/i915_fp_emit.h | 160 +++ src/mesa/drivers/dri/i915tex/i915_fp_translate.c | 802 +++++++++++++++ src/mesa/drivers/dri/i915tex/i915_fragprog.c | 1083 ------------------- src/mesa/drivers/dri/i915tex/i915_program.c | 590 ++--------- src/mesa/drivers/dri/i915tex/i915_program.h | 160 --- src/mesa/drivers/dri/i915tex/i915_state.c | 1086 ++++---------------- src/mesa/drivers/dri/i915tex/i915_state.h | 25 + .../drivers/dri/i915tex/i915_state_constants.c | 136 +++ src/mesa/drivers/dri/i915tex/i915_state_fp.c | 92 ++ .../drivers/dri/i915tex/i915_state_fp_inputs.c | 150 +++ .../drivers/dri/i915tex/i915_state_immediate.c | 315 ++++++ src/mesa/drivers/dri/i915tex/i915_state_indirect.c | 61 ++ src/mesa/drivers/dri/i915tex/i915_state_map.c | 201 ++++ src/mesa/drivers/dri/i915tex/i915_state_misc.c | 560 ++++++++++ src/mesa/drivers/dri/i915tex/i915_state_sampler.c | 324 ++++++ src/mesa/drivers/dri/i915tex/i915_tex.c | 78 -- src/mesa/drivers/dri/i915tex/i915_texstate.c | 338 ------ src/mesa/drivers/dri/i915tex/i915_vtbl.c | 388 +------ src/mesa/drivers/dri/i915tex/intel_context.h | 5 +- src/mesa/drivers/dri/i915tex/intel_idx_render.c | 91 +- 29 files changed, 4344 insertions(+), 3913 deletions(-) delete mode 100644 src/mesa/drivers/dri/i915tex/i915_debug.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp.h create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp_debug.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp_emit.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp_emit.h create mode 100644 src/mesa/drivers/dri/i915tex/i915_fp_translate.c delete mode 100644 src/mesa/drivers/dri/i915tex/i915_fragprog.c delete mode 100644 src/mesa/drivers/dri/i915tex/i915_program.h create mode 100644 src/mesa/drivers/dri/i915tex/i915_state.h create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_constants.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_fp.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_immediate.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_indirect.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_map.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_misc.c create mode 100644 src/mesa/drivers/dri/i915tex/i915_state_sampler.c delete mode 100644 src/mesa/drivers/dri/i915tex/i915_tex.c delete mode 100644 src/mesa/drivers/dri/i915tex/i915_texstate.c diff --git a/src/mesa/drivers/dri/i915tex/Makefile b/src/mesa/drivers/dri/i915tex/Makefile index 9bd1d33507..89fd30de82 100644 --- a/src/mesa/drivers/dri/i915tex/Makefile +++ b/src/mesa/drivers/dri/i915tex/Makefile @@ -7,6 +7,22 @@ LIBNAME = i915tex_dri.so MINIGLX_SOURCES = server/intel_dri.c DRIVER_SOURCES = \ + i915_context.c \ + i915_fp.c \ + i915_fp_debug.c \ + i915_fp_emit.c \ + i915_fp_state.c \ + i915_fp_translate.c \ + i915_metaops.c \ + i915_program.c \ + i915_state.c \ + i915_state_immediate.c \ + i915_state_indirect.c \ + i915_state_misc.c \ + i915_tex.c \ + i915_tex_layout.c \ + i915_tex_state.c \ + i915_vtbl.c \ i830_context.c \ i830_metaops.c \ i830_state.c \ @@ -20,7 +36,6 @@ DRIVER_SOURCES = \ intel_buffer_objects.c \ intel_batchbuffer.c \ intel_mipmap_tree.c \ - i915_tex_layout.c \ intel_tex_layout.c \ intel_tex_image.c \ intel_tex_subimage.c \ @@ -34,15 +49,6 @@ DRIVER_SOURCES = \ intel_pixel_draw.c \ intel_buffers.c \ intel_blit.c \ - i915_tex.c \ - i915_texstate.c \ - i915_context.c \ - i915_debug.c \ - i915_fragprog.c \ - i915_metaops.c \ - i915_program.c \ - i915_state.c \ - i915_vtbl.c \ intel_context.c \ intel_ioctl.c \ intel_rotate.c \ diff --git a/src/mesa/drivers/dri/i915tex/i830_vtbl.c b/src/mesa/drivers/dri/i915tex/i830_vtbl.c index dd0670dec3..5f1363caef 100644 --- a/src/mesa/drivers/dri/i915tex/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i830_vtbl.c @@ -646,7 +646,6 @@ i830_assert_not_dirty( struct intel_context *intel ) void i830InitVtbl(struct i830_context *i830) { - i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; i830->intel.vtbl.destroy = i830_destroy_context; i830->intel.vtbl.emit_state = i830_emit_state; i830->intel.vtbl.lost_hardware = i830_lost_hardware; diff --git a/src/mesa/drivers/dri/i915tex/i915_context.c b/src/mesa/drivers/dri/i915tex/i915_context.c index 9b4d72eab3..fd2943e4e1 100644 --- a/src/mesa/drivers/dri/i915tex/i915_context.c +++ b/src/mesa/drivers/dri/i915tex/i915_context.c @@ -52,6 +52,7 @@ static const struct dri_extension i915_extensions[] = { {"GL_ARB_fragment_program", NULL}, {"GL_ARB_shadow", NULL}, {"GL_ARB_texture_env_crossbar", NULL}, + {"GL_EXT_stencil_two_side", NULL}, {"GL_ARB_texture_non_power_of_two", NULL}, {"GL_EXT_shadow_funcs", NULL}, /* ARB extn won't work if not enabled */ @@ -70,20 +71,6 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state) _tnl_InvalidateState(ctx, new_state); _tnl_invalidate_vertex_state(ctx, new_state); intel_context(ctx)->NewGLState |= new_state; - - /* Todo: gather state values under which tracked parameters become - * invalidated, add callbacks for things like - * ProgramLocalParameters, etc. - */ - { - struct i915_fragment_program *p = - (struct i915_fragment_program *) ctx->FragmentProgram._Current; - if (p && p->nr_params) - p->params_uptodate = 0; - } - - if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM)) - i915_update_fog(ctx); } @@ -91,8 +78,6 @@ static void i915InitDriverFunctions(struct dd_function_table *functions) { intelInitDriverFunctions(functions); - i915InitStateFunctions(functions); - i915InitTextureFuncs(functions); i915InitFragProgFuncs(functions); functions->UpdateState = i915InvalidateState; } @@ -162,6 +147,11 @@ i915CreateContext(const __GLcontextModes * mesaVis, driInitExtensions(ctx, i915_extensions, GL_FALSE); + /* always enbale pixel fog. vertex fog uses precaculted fog coord + * will conflict with appended fog program + */ + _tnl_allow_vertex_fog( ctx, 0 ); + _tnl_allow_pixel_fog( ctx, 1 ); _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12, 36 * sizeof(GLfloat)); diff --git a/src/mesa/drivers/dri/i915tex/i915_context.h b/src/mesa/drivers/dri/i915tex/i915_context.h index d2713e88f9..3dc0f9d81c 100644 --- a/src/mesa/drivers/dri/i915tex/i915_context.h +++ b/src/mesa/drivers/dri/i915tex/i915_context.h @@ -119,8 +119,6 @@ struct i915_fragment_program struct gl_fragment_program FragProg; GLboolean translated; - GLboolean params_uptodate; - GLboolean on_hardware; GLboolean error; /* If program is malformed for any reason. */ GLuint nr_tex_indirect; @@ -129,43 +127,15 @@ struct i915_fragment_program GLuint nr_decl_insn; - - - /* TODO: split between the stored representation of a program and - * the state used to build that representation. - */ - GLcontext *ctx; - - GLuint declarations[I915_PROGRAM_SIZE]; - GLuint program[I915_PROGRAM_SIZE]; - GLfloat constant[I915_MAX_CONSTANT][4]; GLuint constant_flags[I915_MAX_CONSTANT]; GLuint nr_constants; - GLuint *csr; /* Cursor, points into program. - */ - - GLuint *decl; /* Cursor, points into declarations. - */ - - GLuint decl_s; /* flags for which s regs need to be decl'd */ - GLuint decl_t; /* flags for which t regs need to be decl'd */ - - GLuint temp_flag; /* Tracks temporary regs which are in - * use. - */ - - GLuint utemp_flag; /* Tracks TYPE_U temporary regs which are in - * use. - */ - /* Helpers for i915_fragprog.c: */ GLuint wpos_tex; - GLboolean depth_written; struct { @@ -174,20 +144,6 @@ struct i915_fragment_program } param[I915_MAX_CONSTANT]; GLuint nr_params; - - /* Helpers for i915_texprog.c: - */ - GLuint src_texture; /* Reg containing sampled texture color, - * else UREG_BAD. - */ - - GLuint src_previous; /* Reg containing color from previous - * stage. May need to be decl'd. - */ - - GLuint last_tex_stage; /* Number of last enabled texture unit */ - - struct vertex_buffer *VB; }; @@ -216,7 +172,6 @@ struct i915_hw_state */ struct intel_region *draw_region; struct intel_region *depth_region; -/* struct intel_region *tex_region[I915_TEX_UNITS]; */ /* Regions aren't actually that appropriate here as the memory may * be from a PBO or FBO. Just use the buffer id. Will have to do @@ -230,40 +185,18 @@ struct i915_hw_state GLuint emitted; /* I915_UPLOAD_* */ }; -#define I915_FOG_PIXEL 2 -#define I915_FOG_VERTEX 1 -#define I915_FOG_NONE 0 + struct i915_context { struct intel_context intel; - GLuint last_ReallyEnabled; - GLuint vertex_fog; - GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; - - struct i915_fragment_program *current_program; struct i915_hw_state meta, initial, state, *current; }; -#define I915_STATECHANGE(i915, flag) \ -do { \ - INTEL_FIREVERTICES( &(i915)->intel ); \ - (i915)->state.emitted &= ~(flag); \ -} while (0) - -#define I915_ACTIVESTATE(i915, flag, mode) \ -do { \ - INTEL_FIREVERTICES( &(i915)->intel ); \ - if (mode) \ - (i915)->state.active |= (flag); \ - else \ - (i915)->state.active &= ~(flag); \ -} while (0) - /*====================================================================== * i915_vtbl.c diff --git a/src/mesa/drivers/dri/i915tex/i915_debug.c b/src/mesa/drivers/dri/i915tex/i915_debug.c deleted file mode 100644 index 974527e14c..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_debug.c +++ /dev/null @@ -1,334 +0,0 @@ -/************************************************************************** - * - * 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 "i915_reg.h" -#include "i915_context.h" -#include - - -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); -} - -void -i915_print_ureg(const char *msg, GLuint ureg) -{ - fprintf(stderr, "%s: ", msg); - print_src_reg(ureg >> 8); - fprintf(stderr, "\n"); -} - -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"); - - if (size + 2 != sz) { - fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__, - size + 2, sz); - exit(1); - } - - 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"); -} diff --git a/src/mesa/drivers/dri/i915tex/i915_fp.c b/src/mesa/drivers/dri/i915tex/i915_fp.c new file mode 100644 index 0000000000..5b2ccda191 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp.c @@ -0,0 +1,295 @@ +/************************************************************************** + * + * 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_program.h" + +#include "program_instruction.h" +#include "program.h" +#include "programopt.h" + + + +static void +track_params(struct i915_fragment_program *p) +{ + GLint i; + + if (p->nr_params) + _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters); + + for (i = 0; i < p->nr_params; i++) { + GLint reg = p->param[i].reg; + COPY_4V(p->constant[reg], p->param[i].values); + } +} + + +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 +i915ValidateFragmentProgram(struct i915_context *i915) +{ + GLcontext *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; + GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; + GLuint s2 = S2_TEXCOORD_NONE; + int i, offset = 0; + + if (i915->current_program != p) { + i915->current_program = p; + } + + + /* Important: + */ + VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; + + if (!p->translated) + translate_program(p); + + 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); + } + + if (inputsRead & FRAG_BIT_COL0) { + intel->coloroffset = offset / 4; + EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4); + } + + if ((inputsRead & (FRAG_BIT_COL1 | FRAG_BIT_FOGC)) || + i915->vertex_fog != I915_FOG_NONE) { + + if (inputsRead & FRAG_BIT_COL1) { + intel->specoffset = offset / 4; + EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3); + } + else + EMIT_PAD(3); + + if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) + EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1); + else + EMIT_PAD(1); + } + + /* XXX this was disabled, but enabling this code helped fix the Glean + * tfragprog1 fog tests. + */ + if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) { + 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)) { + int sz = VB->TexCoordPtr[i]->size; + + s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); + s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); + + EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4); + } + else if (i == p->wpos_tex) { + + /* 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)); + + intel->wpos_offset = offset; + intel->wpos_size = 3 * sizeof(GLuint); + + EMIT_PAD(intel->wpos_size); + } + } + + if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || + s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { + int k; + + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + + /* Must do this *after* statechange, so as not to affect + * buffered vertices reliant on the old state: + */ + intel->vertex_size = _tnl_install_attrs(&intel->ctx, + intel->vertex_attrs, + intel->vertex_attr_count, + intel->ViewportMatrix.m, 0); + + intel->vertex_size >>= 2; + + i915->state.Ctx[I915_CTXREG_LIS2] = s2; + i915->state.Ctx[I915_CTXREG_LIS4] = s4; + } + + if (!p->params_uptodate) + track_params(p); + + + i915_upload_program(i915, p); +} + +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/i915_fp.h b/src/mesa/drivers/dri/i915tex/i915_fp.h new file mode 100644 index 0000000000..8af92c82be --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp.h @@ -0,0 +1,44 @@ + +struct i915_fp_compile { + GLcontext *ctx; + + struct i915_fragment_program *fp; + + GLuint declarations[I915_PROGRAM_SIZE]; + GLuint program[I915_PROGRAM_SIZE]; + + GLfloat constant[I915_MAX_CONSTANT][4]; + GLuint constant_flags[I915_MAX_CONSTANT]; + GLuint nr_constants; + + GLuint *csr; /* Cursor, points into program. + */ + + GLuint *decl; /* Cursor, points into declarations. + */ + + GLuint decl_s; /* flags for which s regs need to be decl'd */ + GLuint decl_t; /* flags for which t regs need to be decl'd */ + + GLuint temp_flag; /* Tracks temporary regs which are in + * use. + */ + + GLuint utemp_flag; /* Tracks TYPE_U temporary regs which are in + * use. + */ + + + + /* Helpers for i915_fragprog.c: + */ + GLuint wpos_tex; + + struct + { + GLuint reg; /* Hardware constant idx */ + const GLfloat *values; /* Pointer to tracked values */ + } param[I915_MAX_CONSTANT]; + GLuint nr_params; + +}; diff --git a/src/mesa/drivers/dri/i915tex/i915_fp_debug.c b/src/mesa/drivers/dri/i915tex/i915_fp_debug.c new file mode 100644 index 0000000000..974527e14c --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp_debug.c @@ -0,0 +1,334 @@ +/************************************************************************** + * + * 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 "i915_reg.h" +#include "i915_context.h" +#include + + +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); +} + +void +i915_print_ureg(const char *msg, GLuint ureg) +{ + fprintf(stderr, "%s: ", msg); + print_src_reg(ureg >> 8); + fprintf(stderr, "\n"); +} + +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"); + + if (size + 2 != sz) { + fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__, + size + 2, sz); + exit(1); + } + + 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"); +} diff --git a/src/mesa/drivers/dri/i915tex/i915_fp_emit.c b/src/mesa/drivers/dri/i915tex/i915_fp_emit.c new file mode 100644 index 0000000000..9e4d598942 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp_emit.c @@ -0,0 +1,487 @@ +/************************************************************************** + * + * 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 + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "tnl/t_context.h" +#include "intel_batchbuffer.h" + +#include "i915_reg.h" +#include "i915_context.h" +#include "i915_program.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_SRC1_SHIFT_LEFT) +#define A2_SRC1( 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)<temp_flag); + if (!bit) { + fprintf(stderr, "%s: out of temporaries\n", __FILE__); + exit(1); + } + + p->temp_flag |= 1 << (bit - 1); + return UREG(REG_TYPE_R, (bit - 1)); +} + + +GLuint +i915_get_utemp(struct i915_fragment_program * p) +{ + int bit = ffs(~p->utemp_flag); + if (!bit) { + fprintf(stderr, "%s: out of temporaries\n", __FILE__); + exit(1); + } + + p->utemp_flag |= 1 << (bit - 1); + return UREG(REG_TYPE_U, (bit - 1)); +} + +void +i915_release_utemps(struct i915_fragment_program *p) +{ + p->utemp_flag = ~0x7; +} + + +GLuint +i915_emit_decl(struct i915_fragment_program *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_fragment_program * 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_fragment_program *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_fragment_program * 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->constant[reg][idx] == c0) { + p->constant[reg][idx] = c0; + p->constant_flags[reg] |= 1 << idx; + if (reg + 1 > p->nr_constants) + p->nr_constants = reg + 1; + return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE); + } + } + } + + fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + p->error = 1; + return 0; +} + +GLuint +i915_emit_const2f(struct i915_fragment_program * 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->constant[reg][idx] = c0; + p->constant[reg][idx + 1] = c1; + p->constant_flags[reg] |= 3 << idx; + if (reg + 1 > p->nr_constants) + p->nr_constants = reg + 1; + return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, + ONE); + } + } + } + + fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + p->error = 1; + return 0; +} + + + +GLuint +i915_emit_const4f(struct i915_fragment_program * 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->constant[reg][0] == c0 && + p->constant[reg][1] == c1 && + p->constant[reg][2] == c2 && p->constant[reg][3] == c3) { + return UREG(REG_TYPE_CONST, reg); + } + else if (p->constant_flags[reg] == 0) { + p->constant[reg][0] = c0; + p->constant[reg][1] = c1; + p->constant[reg][2] = c2; + p->constant[reg][3] = c3; + p->constant_flags[reg] = 0xf; + if (reg + 1 > p->nr_constants) + p->nr_constants = reg + 1; + return UREG(REG_TYPE_CONST, reg); + } + } + + fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + p->error = 1; + return 0; +} + + +GLuint +i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c) +{ + return i915_emit_const4f(p, c[0], c[1], c[2], c[3]); +} + + +GLuint +i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values) +{ + GLint reg, i; + + for (i = 0; i < p->nr_params; i++) { + if (p->param[i].values == values) + return UREG(REG_TYPE_CONST, p->param[i].reg); + } + + + for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { + if (p->constant_flags[reg] == 0) { + p->constant_flags[reg] = I915_CONSTFLAG_PARAM; + i = p->nr_params++; + + p->param[i].values = values; + p->param[i].reg = reg; + p->params_uptodate = 0; + + if (reg + 1 > p->nr_constants) + p->nr_constants = reg + 1; + return UREG(REG_TYPE_CONST, reg); + } + } + + fprintf(stderr, "%s: out of constants\n", __FUNCTION__); + p->error = 1; + return 0; +} + + + +void +i915_program_error(struct i915_fragment_program *p, const char *msg) +{ + _mesa_problem(NULL, "i915_program_error: %s", msg); + p->error = 1; +} + + +void +i915_init_program(struct i915_context *i915, struct i915_fragment_program *p) +{ + GLcontext *ctx = &i915->intel.ctx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + + p->translated = 0; + p->params_uptodate = 0; + p->error = 0; + + p->nr_tex_indirect = 1; /* correct? */ + p->nr_tex_insn = 0; + p->nr_alu_insn = 0; + p->nr_decl_insn = 0; + + p->ctx = ctx; + memset(p->constant_flags, 0, sizeof(p->constant_flags)); + + p->nr_constants = 0; + 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->wpos_tex = -1; + p->nr_params = 0; + + p->src_texture = UREG_BAD; + p->src_previous = UREG(REG_TYPE_T, T_DIFFUSE); + p->last_tex_stage = 0; + p->VB = &tnl->vb; + + *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM; +} + + +void +i915_fini_program(struct i915_fragment_program *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->error) { + p->FragProg.Base.NumNativeInstructions = 0; + p->FragProg.NumNativeAluInstructions = 0; + p->FragProg.NumNativeTexInstructions = 0; + p->FragProg.NumNativeTexIndirections = 0; + } + else { + p->FragProg.Base.NumNativeInstructions = (p->nr_alu_insn + + p->nr_tex_insn + + p->nr_decl_insn); + p->FragProg.NumNativeAluInstructions = p->nr_alu_insn; + p->FragProg.NumNativeTexInstructions = p->nr_tex_insn; + p->FragProg.NumNativeTexIndirections = p->nr_tex_indirect; + } + + p->declarations[0] |= program_size + decl_size - 2; +} + +void +i915_upload_program(struct i915_context *i915, + struct i915_fragment_program *p) +{ + GLuint program_size = p->csr - p->program; + GLuint decl_size = p->decl - p->declarations; + + FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, p->error); + + /* Could just go straight to the batchbuffer from here: + */ + if (i915->state.ProgramSize != (program_size + decl_size) || + memcmp(i915->state.Program + decl_size, p->program, + program_size * sizeof(int)) != 0) { + I915_STATECHANGE(i915, I915_UPLOAD_PROGRAM); + memcpy(i915->state.Program, p->declarations, decl_size * sizeof(int)); + memcpy(i915->state.Program + decl_size, p->program, + program_size * sizeof(int)); + i915->state.ProgramSize = decl_size + program_size; + } + + + /* Set dependent state variables + */ +} diff --git a/src/mesa/drivers/dri/i915tex/i915_fp_emit.h b/src/mesa/drivers/dri/i915tex/i915_fp_emit.h new file mode 100644 index 0000000000..3c12b34f16 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp_emit.h @@ -0,0 +1,160 @@ +/************************************************************************** + * + * 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 I915_PROGRAM_H +#define I915_PROGRAM_H + +#include "i915_context.h" +#include "i915_reg.h" + + + +/* Having zero and one in here makes the definition of swizzle a lot + * easier. + */ +#define UREG_TYPE_SHIFT 29 +#define UREG_NR_SHIFT 24 +#define UREG_CHANNEL_X_NEGATE_SHIFT 23 +#define UREG_CHANNEL_X_SHIFT 20 +#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 +#define UREG_CHANNEL_Y_SHIFT 16 +#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 +#define UREG_CHANNEL_Z_SHIFT 12 +#define UREG_CHANNEL_W_NEGATE_SHIFT 11 +#define UREG_CHANNEL_W_SHIFT 8 +#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 +#define UREG_CHANNEL_ZERO_SHIFT 4 +#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 +#define UREG_CHANNEL_ONE_SHIFT 0 + +#define UREG_BAD 0xffffffff /* not a valid ureg */ + +#define X SRC_X +#define Y SRC_Y +#define Z SRC_Z +#define W SRC_W +#define ZERO SRC_ZERO +#define ONE SRC_ONE + +/* Construct a ureg: + */ +#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \ + ((nr) << UREG_NR_SHIFT) | \ + (X << UREG_CHANNEL_X_SHIFT) | \ + (Y << UREG_CHANNEL_Y_SHIFT) | \ + (Z << UREG_CHANNEL_Z_SHIFT) | \ + (W << UREG_CHANNEL_W_SHIFT) | \ + (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ + (ONE << UREG_CHANNEL_ONE_SHIFT)) + +#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) +#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) + +#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)®_TYPE_MASK) +#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)®_NR_MASK) + + + +#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 + +/* One neat thing about the UREG representation: + */ +static INLINE int +swizzle(int reg, int x, int y, int z, int w) +{ + return ((reg & ~UREG_XYZW_CHANNEL_MASK) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) | + CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3)); +} + +/* Another neat thing about the UREG representation: + */ +static INLINE int +negate(int reg, int x, int y, int z, int w) +{ + return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) | + ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) | + ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) | + ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT)); +} + + +extern GLuint i915_get_temp(struct i915_fragment_program *p); +extern GLuint i915_get_utemp(struct i915_fragment_program *p); +extern void i915_release_utemps(struct i915_fragment_program *p); + + +extern GLuint i915_emit_texld(struct i915_fragment_program *p, + GLuint dest, + GLuint destmask, + GLuint sampler, GLuint coord, GLuint op); + +extern GLuint i915_emit_arith(struct i915_fragment_program *p, + GLuint op, + GLuint dest, + GLuint mask, + GLuint saturate, + GLuint src0, GLuint src1, GLuint src2); + +extern GLuint i915_emit_decl(struct i915_fragment_program *p, + GLuint type, GLuint nr, GLuint d0_flags); + + +extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0); + +extern GLuint i915_emit_const2f(struct i915_fragment_program *p, + GLfloat c0, GLfloat c1); + +extern GLuint i915_emit_const4fv(struct i915_fragment_program *p, + const GLfloat * c); + +extern GLuint i915_emit_const4f(struct i915_fragment_program *p, + GLfloat c0, GLfloat c1, + GLfloat c2, GLfloat c3); + + +extern GLuint i915_emit_param4fv(struct i915_fragment_program *p, + const GLfloat * values); + +extern void i915_program_error(struct i915_fragment_program *p, + const char *msg); + +extern void i915_init_program(struct i915_context *i915, + struct i915_fragment_program *p); + +extern void i915_upload_program(struct i915_context *i915, + struct i915_fragment_program *p); + +extern void i915_fini_program(struct i915_fragment_program *p); + + + + +#endif diff --git a/src/mesa/drivers/dri/i915tex/i915_fp_translate.c b/src/mesa/drivers/dri/i915tex/i915_fp_translate.c new file mode 100644 index 0000000000..bbcca2ef37 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_fp_translate.c @@ -0,0 +1,802 @@ +/************************************************************************** + * + * 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_program.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_fragment_program *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->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->ctx->FragmentProgram.Parameters[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_fragment_program *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_fragment_program *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. + * + */ +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; + +/* _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */ + + /* 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: + */ +static void +fixup_depth_write(struct i915_fragment_program *p) +{ + if (p->fp->Base.OutputsWritten & (1<intel.ctx; + struct intel_context *intel = intel_context(ctx); + struct i915_fragment_program *p = + (struct i915_fragment_program *) ctx->FragmentProgram._Current; + + if (!p->translated) { + i915_init_program(i915, p); + check_wpos(p); + upload_program(p); + fixup_depth_write(p); + i915_fini_program(p); + + p->translated = 1; + } +} + diff --git a/src/mesa/drivers/dri/i915tex/i915_fragprog.c b/src/mesa/drivers/dri/i915tex/i915_fragprog.c deleted file mode 100644 index 8772e70230..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_fragprog.c +++ /dev/null @@ -1,1083 +0,0 @@ -/************************************************************************** - * - * 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_program.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_fragment_program *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: - switch (source->Index) { - case FRAG_ATTRIB_WPOS: - src = i915_emit_decl(p, REG_TYPE_T, p->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->ctx->FragmentProgram.Parameters[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_fragment_program *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: - p->depth_written = 1; - 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_fragment_program *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. - * - */ -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; - -/* _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */ - - /* 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: - */ -static void -fixup_depth_write(struct i915_fragment_program *p) -{ - if (p->depth_written) { - 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); - } -} - - -#define FRAG_BIT_TEX(n) (FRAG_BIT_TEX0 << (n)) - - -static void -check_wpos(struct i915_fragment_program *p) -{ - GLuint inputs = p->FragProg.Base.InputsRead; - GLint i; - - p->wpos_tex = -1; - - for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { - if (inputs & FRAG_BIT_TEX(i)) - continue; - else if (inputs & FRAG_BIT_WPOS) { - p->wpos_tex = i; - inputs &= ~FRAG_BIT_WPOS; - } - } - - if (inputs & FRAG_BIT_WPOS) { - i915_program_error(p, "No free texcoord for wpos value"); - } -} - - -static void -translate_program(struct i915_fragment_program *p) -{ - struct i915_context *i915 = I915_CONTEXT(p->ctx); - - i915_init_program(i915, p); - check_wpos(p); - upload_program(p); - fixup_depth_write(p); - i915_fini_program(p); - - p->translated = 1; -} - - -static void -track_params(struct i915_fragment_program *p) -{ - GLint i; - - if (p->nr_params) - _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters); - - for (i = 0; i < p->nr_params; i++) { - GLint reg = p->param[i].reg; - COPY_4V(p->constant[reg], p->param[i].values); - } - - p->params_uptodate = 1; - 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); - - /* 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 -i915ValidateFragmentProgram(struct i915_context *i915) -{ - GLcontext *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; - GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; - GLuint s2 = S2_TEXCOORD_NONE; - int i, offset = 0; - - if (i915->current_program != p) { - if (i915->current_program) { - i915->current_program->on_hardware = 0; - i915->current_program->params_uptodate = 0; - } - - i915->current_program = p; - } - - - /* Important: - */ - VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; - - if (!p->translated) - translate_program(p); - - 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); - } - - if (inputsRead & FRAG_BIT_COL0) { - intel->coloroffset = offset / 4; - EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4); - } - - if ((inputsRead & (FRAG_BIT_COL1 | FRAG_BIT_FOGC)) || - i915->vertex_fog != I915_FOG_NONE) { - - if (inputsRead & FRAG_BIT_COL1) { - intel->specoffset = offset / 4; - EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3); - } - else - EMIT_PAD(3); - - if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) - EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1); - else - EMIT_PAD(1); - } - - /* XXX this was disabled, but enabling this code helped fix the Glean - * tfragprog1 fog tests. - */ -#if 1 - if ((inputsRead & FRAG_BIT_FOGC) || i915->vertex_fog != I915_FOG_NONE) { - EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4); - } -#endif - - for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { - if (inputsRead & FRAG_BIT_TEX(i)) { - int sz = VB->TexCoordPtr[i]->size; - - s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); - s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); - - EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4); - } - else if (i == p->wpos_tex) { - - /* 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)); - - intel->wpos_offset = offset; - intel->wpos_size = 3 * sizeof(GLuint); - - EMIT_PAD(intel->wpos_size); - } - } - - if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || - s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { - int k; - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - - /* Must do this *after* statechange, so as not to affect - * buffered vertices reliant on the old state: - */ - intel->vertex_size = _tnl_install_attrs(&intel->ctx, - intel->vertex_attrs, - intel->vertex_attr_count, - intel->ViewportMatrix.m, 0); - - intel->vertex_size >>= 2; - - i915->state.Ctx[I915_CTXREG_LIS2] = s2; - i915->state.Ctx[I915_CTXREG_LIS4] = s4; - - k = intel->vtbl.check_vertex_size(intel, intel->vertex_size); - assert(k); - } - - if (!p->params_uptodate) - track_params(p); - - if (!p->on_hardware) - i915_upload_program(i915, p); -} - -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/i915_program.c b/src/mesa/drivers/dri/i915tex/i915_program.c index 0be89d3320..1ae065b10d 100644 --- a/src/mesa/drivers/dri/i915tex/i915_program.c +++ b/src/mesa/drivers/dri/i915tex/i915_program.c @@ -1,515 +1,147 @@ -/************************************************************************** - * - * 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 - -#include "glheader.h" -#include "macros.h" +/* + 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 + */ + + +#include "brw_context.h" +#include "brw_aub.h" +#include "brw_util.h" +#include "program.h" +#include "imports.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_program.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_SRC1_SHIFT_LEFT) -#define A2_SRC1( 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)<temp_flag); - if (!bit) { - fprintf(stderr, "%s: out of temporaries\n", __FILE__); - exit(1); - } - - p->temp_flag |= 1 << (bit - 1); - return UREG(REG_TYPE_R, (bit - 1)); -} - + struct brw_context *brw = brw_context(ctx); -GLuint -i915_get_utemp(struct i915_fragment_program * p) -{ - int bit = ffs(~p->utemp_flag); - if (!bit) { - fprintf(stderr, "%s: out of temporaries\n", __FILE__); - exit(1); + 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; } - - p->utemp_flag |= 1 << (bit - 1); - return UREG(REG_TYPE_U, (bit - 1)); -} - -void -i915_release_utemps(struct i915_fragment_program *p) -{ - p->utemp_flag = ~0x7; } - -GLuint -i915_emit_decl(struct i915_fragment_program *p, - GLuint type, GLuint nr, GLuint d0_flags) +static struct gl_program *brwNewProgram( GLcontext *ctx, + GLenum target, + GLuint id ) { - GLuint reg = UREG(type, nr); + struct brw_context *brw = brw_context(ctx); - 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_fragment_program * p, - GLuint op, - GLuint dest, - GLuint mask, - GLuint saturate, GLuint src0, GLuint src1, GLuint src2) -{ - GLuint c[3]; - GLuint nr_const = 0; + switch (target) { + case GL_VERTEX_PROGRAM_ARB: { + struct brw_vertex_program *prog = CALLOC_STRUCT(brw_vertex_program); + if (prog) { + prog->id = brw->program_id++; - 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; - } + return _mesa_init_vertex_program( ctx, &prog->program, + target, id ); } - - src0 = s[0]; - src1 = s[1]; - src2 = s[2]; - p->utemp_flag = old_utemp_flag; /* restore */ + else + return NULL; } - *(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; -} + case GL_FRAGMENT_PROGRAM_ARB: { + struct brw_fragment_program *prog = CALLOC_STRUCT(brw_fragment_program); + if (prog) { + prog->id = brw->program_id++; -GLuint i915_emit_texld( struct i915_fragment_program *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++; + return _mesa_init_fragment_program( ctx, &prog->program, + target, id ); } - - *(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; + else + return NULL; } -} - - -GLuint -i915_emit_const1f(struct i915_fragment_program * 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->constant[reg][idx] == c0) { - p->constant[reg][idx] = c0; - p->constant_flags[reg] |= 1 << idx; - if (reg + 1 > p->nr_constants) - p->nr_constants = reg + 1; - return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE); - } - } + default: + return _mesa_new_program(ctx, target, id); } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return 0; } -GLuint -i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1) +static void brwDeleteProgram( GLcontext *ctx, + struct gl_program *prog ) { - 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->constant[reg][idx] = c0; - p->constant[reg][idx + 1] = c1; - p->constant_flags[reg] |= 3 << idx; - if (reg + 1 > p->nr_constants) - p->nr_constants = reg + 1; - return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, - ONE); - } - } - } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return 0; + + _mesa_delete_program( ctx, prog ); } - -GLuint -i915_emit_const4f(struct i915_fragment_program * p, - GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3) +static GLboolean brwIsProgramNative( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) { - GLint reg; - - for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { - if (p->constant_flags[reg] == 0xf && - p->constant[reg][0] == c0 && - p->constant[reg][1] == c1 && - p->constant[reg][2] == c2 && p->constant[reg][3] == c3) { - return UREG(REG_TYPE_CONST, reg); - } - else if (p->constant_flags[reg] == 0) { - p->constant[reg][0] = c0; - p->constant[reg][1] = c1; - p->constant[reg][2] = c2; - p->constant[reg][3] = c3; - p->constant_flags[reg] = 0xf; - if (reg + 1 > p->nr_constants) - p->nr_constants = reg + 1; - return UREG(REG_TYPE_CONST, reg); - } - } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return 0; + return GL_TRUE; } - -GLuint -i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c) +static void brwProgramStringNotify( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) { - return i915_emit_const4f(p, c[0], c[1], c[2], c[3]); -} - - -GLuint -i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values) -{ - GLint reg, i; - - for (i = 0; i < p->nr_params; i++) { - if (p->param[i].values == values) - return UREG(REG_TYPE_CONST, p->param[i].reg); - } - - - for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { - if (p->constant_flags[reg] == 0) { - p->constant_flags[reg] = I915_CONSTFLAG_PARAM; - i = p->nr_params++; - - p->param[i].values = values; - p->param[i].reg = reg; - p->params_uptodate = 0; - - if (reg + 1 > p->nr_constants) - p->nr_constants = reg + 1; - return UREG(REG_TYPE_CONST, reg); - } + 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); } - - fprintf(stderr, "%s: out of constants\n", __FUNCTION__); - p->error = 1; - return 0; -} - - - -void -i915_program_error(struct i915_fragment_program *p, const char *msg) -{ - _mesa_problem(NULL, "i915_program_error: %s", msg); - p->error = 1; -} - - -void -i915_init_program(struct i915_context *i915, struct i915_fragment_program *p) -{ - GLcontext *ctx = &i915->intel.ctx; - TNLcontext *tnl = TNL_CONTEXT(ctx); - - p->translated = 0; - p->params_uptodate = 0; - p->on_hardware = 0; - p->error = 0; - - p->nr_tex_indirect = 1; /* correct? */ - p->nr_tex_insn = 0; - p->nr_alu_insn = 0; - p->nr_decl_insn = 0; - - p->ctx = ctx; - memset(p->constant_flags, 0, sizeof(p->constant_flags)); - - p->nr_constants = 0; - 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->wpos_tex = -1; - p->depth_written = 0; - p->nr_params = 0; - - p->src_texture = UREG_BAD; - p->src_previous = UREG(REG_TYPE_T, T_DIFFUSE); - p->last_tex_stage = 0; - p->VB = &tnl->vb; - - *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM; } - -void -i915_fini_program(struct i915_fragment_program *p) +void brwInitFragProgFuncs( struct dd_function_table *functions ) { - 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->error) { - p->FragProg.Base.NumNativeInstructions = 0; - p->FragProg.NumNativeAluInstructions = 0; - p->FragProg.NumNativeTexInstructions = 0; - p->FragProg.NumNativeTexIndirections = 0; - } - else { - p->FragProg.Base.NumNativeInstructions = (p->nr_alu_insn + - p->nr_tex_insn + - p->nr_decl_insn); - p->FragProg.NumNativeAluInstructions = p->nr_alu_insn; - p->FragProg.NumNativeTexInstructions = p->nr_tex_insn; - p->FragProg.NumNativeTexIndirections = p->nr_tex_indirect; - } + assert(functions->ProgramStringNotify == _tnl_program_string); - p->declarations[0] |= program_size + decl_size - 2; + functions->BindProgram = brwBindProgram; + functions->NewProgram = brwNewProgram; + functions->DeleteProgram = brwDeleteProgram; + functions->IsProgramNative = brwIsProgramNative; + functions->ProgramStringNotify = brwProgramStringNotify; } -void -i915_upload_program(struct i915_context *i915, - struct i915_fragment_program *p) -{ - GLuint program_size = p->csr - p->program; - GLuint decl_size = p->decl - p->declarations; - - FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, p->error); - - /* Could just go straight to the batchbuffer from here: - */ - if (i915->state.ProgramSize != (program_size + decl_size) || - memcmp(i915->state.Program + decl_size, p->program, - program_size * sizeof(int)) != 0) { - I915_STATECHANGE(i915, I915_UPLOAD_PROGRAM); - memcpy(i915->state.Program, p->declarations, decl_size * sizeof(int)); - memcpy(i915->state.Program + decl_size, p->program, - program_size * sizeof(int)); - i915->state.ProgramSize = decl_size + program_size; - } - - /* Always seemed to get a failure if I used memcmp() to - * shortcircuit this state upload. Needs further investigation? - */ - if (p->nr_constants) { - GLuint nr = p->nr_constants; - - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); - I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); - - i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4); - i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1); - - memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr)); - i915->state.ConstantSize = 2 + (nr) * 4; - - if (0) { - GLuint i; - for (i = 0; i < nr; i++) { - fprintf(stderr, "const[%d]: %f %f %f %f\n", i, - p->constant[i][0], - p->constant[i][1], p->constant[i][2], p->constant[i][3]); - } - } - } - else { - I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); - } - - p->on_hardware = 1; -} diff --git a/src/mesa/drivers/dri/i915tex/i915_program.h b/src/mesa/drivers/dri/i915tex/i915_program.h deleted file mode 100644 index 3c12b34f16..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_program.h +++ /dev/null @@ -1,160 +0,0 @@ -/************************************************************************** - * - * 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 I915_PROGRAM_H -#define I915_PROGRAM_H - -#include "i915_context.h" -#include "i915_reg.h" - - - -/* Having zero and one in here makes the definition of swizzle a lot - * easier. - */ -#define UREG_TYPE_SHIFT 29 -#define UREG_NR_SHIFT 24 -#define UREG_CHANNEL_X_NEGATE_SHIFT 23 -#define UREG_CHANNEL_X_SHIFT 20 -#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 -#define UREG_CHANNEL_Y_SHIFT 16 -#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 -#define UREG_CHANNEL_Z_SHIFT 12 -#define UREG_CHANNEL_W_NEGATE_SHIFT 11 -#define UREG_CHANNEL_W_SHIFT 8 -#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 -#define UREG_CHANNEL_ZERO_SHIFT 4 -#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 -#define UREG_CHANNEL_ONE_SHIFT 0 - -#define UREG_BAD 0xffffffff /* not a valid ureg */ - -#define X SRC_X -#define Y SRC_Y -#define Z SRC_Z -#define W SRC_W -#define ZERO SRC_ZERO -#define ONE SRC_ONE - -/* Construct a ureg: - */ -#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \ - ((nr) << UREG_NR_SHIFT) | \ - (X << UREG_CHANNEL_X_SHIFT) | \ - (Y << UREG_CHANNEL_Y_SHIFT) | \ - (Z << UREG_CHANNEL_Z_SHIFT) | \ - (W << UREG_CHANNEL_W_SHIFT) | \ - (ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ - (ONE << UREG_CHANNEL_ONE_SHIFT)) - -#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) -#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) - -#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)®_TYPE_MASK) -#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)®_NR_MASK) - - - -#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 - -/* One neat thing about the UREG representation: - */ -static INLINE int -swizzle(int reg, int x, int y, int z, int w) -{ - return ((reg & ~UREG_XYZW_CHANNEL_MASK) | - CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) | - CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) | - CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) | - CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3)); -} - -/* Another neat thing about the UREG representation: - */ -static INLINE int -negate(int reg, int x, int y, int z, int w) -{ - return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) | - ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) | - ((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) | - ((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT)); -} - - -extern GLuint i915_get_temp(struct i915_fragment_program *p); -extern GLuint i915_get_utemp(struct i915_fragment_program *p); -extern void i915_release_utemps(struct i915_fragment_program *p); - - -extern GLuint i915_emit_texld(struct i915_fragment_program *p, - GLuint dest, - GLuint destmask, - GLuint sampler, GLuint coord, GLuint op); - -extern GLuint i915_emit_arith(struct i915_fragment_program *p, - GLuint op, - GLuint dest, - GLuint mask, - GLuint saturate, - GLuint src0, GLuint src1, GLuint src2); - -extern GLuint i915_emit_decl(struct i915_fragment_program *p, - GLuint type, GLuint nr, GLuint d0_flags); - - -extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0); - -extern GLuint i915_emit_const2f(struct i915_fragment_program *p, - GLfloat c0, GLfloat c1); - -extern GLuint i915_emit_const4fv(struct i915_fragment_program *p, - const GLfloat * c); - -extern GLuint i915_emit_const4f(struct i915_fragment_program *p, - GLfloat c0, GLfloat c1, - GLfloat c2, GLfloat c3); - - -extern GLuint i915_emit_param4fv(struct i915_fragment_program *p, - const GLfloat * values); - -extern void i915_program_error(struct i915_fragment_program *p, - const char *msg); - -extern void i915_init_program(struct i915_context *i915, - struct i915_fragment_program *p); - -extern void i915_upload_program(struct i915_context *i915, - struct i915_fragment_program *p); - -extern void i915_fini_program(struct i915_fragment_program *p); - - - - -#endif diff --git a/src/mesa/drivers/dri/i915tex/i915_state.c b/src/mesa/drivers/dri/i915tex/i915_state.c index 78ae4bdb5f..93e41245b3 100644 --- a/src/mesa/drivers/dri/i915tex/i915_state.c +++ b/src/mesa/drivers/dri/i915tex/i915_state.c @@ -45,965 +45,263 @@ #define FILE_DEBUG_FLAG DEBUG_STATE -static void -i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, - GLuint mask) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int test = intel_translate_compare_func(func); - - mask = mask & 0xff; - - DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(func), ref, mask); - - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; - i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | - STENCIL_TEST_MASK(mask)); - - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK | - S5_STENCIL_TEST_FUNC_MASK); - i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) | - (test << - S5_STENCIL_TEST_FUNC_SHIFT)); -} - -static void -i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - - DBG("%s : mask 0x%x\n", __FUNCTION__, mask); - - mask = mask & 0xff; - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; - i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | - STENCIL_WRITE_MASK(mask)); -} - - -static void -i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, - GLenum zpass) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int fop = intel_translate_stencil_op(fail); - int dfop = intel_translate_stencil_op(zfail); - int dpop = intel_translate_stencil_op(zpass); - - - DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(fail), - _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass)); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | - S5_STENCIL_PASS_Z_FAIL_MASK | - S5_STENCIL_PASS_Z_PASS_MASK); - - i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) | - (dfop << - S5_STENCIL_PASS_Z_FAIL_SHIFT) | - (dpop << - S5_STENCIL_PASS_Z_PASS_SHIFT)); -} - -static void -i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int test = intel_translate_compare_func(func); - GLubyte refByte; - - UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK | - S6_ALPHA_REF_MASK); - i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | - (((GLuint) refByte) << - S6_ALPHA_REF_SHIFT)); -} +/* + 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 + */ + + + +#include "brw_context.h" +#include "brw_state.h" +#include "bufmgr.h" +#include "intel_batchbuffer.h" -/* This function makes sure that the proper enables are - * set for LogicOp, Independant Alpha Blend, and Blending. - * It needs to be called from numerous places where we - * could change the LogicOp or Independant Alpha Blend without subsequent - * calls to glEnable. +/* This is used to initialize brw->state.atoms[]. We could use this + * list directly except for a single atom, brw_constant_buffer, which + * has a .dirty value which changes according to the parameters of the + * current fragment and vertex programs, and so cannot be a static + * value. */ -static void -i915EvalLogicOpBlendState(GLcontext * ctx) +const struct brw_tracked_state *atoms[] = { - struct i915_context *i915 = I915_CONTEXT(ctx); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - - if (RGBA_LOGICOP_ENABLED(ctx)) { - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; - } - else { - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE; - - if (ctx->Color.BlendEnabled) { - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; - } - else { - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; - } - } -} - -static void -i915BlendColor(GLcontext * ctx, const GLfloat color[4]) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - GLubyte r, g, b, a; - - DBG("%s\n", __FUNCTION__); - - UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = - (a << 24) | (r << 16) | (g << 8) | b; -} - - -#define DST_BLND_FACT(f) ((f)<state.Ctx[I915_CTXREG_IAB] & - ~(IAB_SRC_FACTOR_MASK | - IAB_DST_FACTOR_MASK | - (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); - - GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] & - ~(S6_CBUF_SRC_BLEND_FACT_MASK | - S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK)); - - GLuint eqRGB = ctx->Color.BlendEquationRGB; - GLuint eqA = ctx->Color.BlendEquationA; - GLuint srcRGB = ctx->Color.BlendSrcRGB; - GLuint dstRGB = ctx->Color.BlendDstRGB; - GLuint srcA = ctx->Color.BlendSrcA; - GLuint dstA = ctx->Color.BlendDstA; - - if (eqRGB == GL_MIN || eqRGB == GL_MAX) { - srcRGB = dstRGB = GL_ONE; - } + /* Emit compiled version of the fragment program. + */ + &i915_upload_fp, - if (eqA == GL_MIN || eqA == GL_MAX) { - srcA = dstA = GL_ONE; - } + /* Immediate state. Don't make any effort to combine packets yet. + */ + &i915_upload_S0S1, + &i915_upload_S2, + &i915_upload_S4, + &i915_upload_S5, + &i915_upload_S6, + + /* Other state. This will eventually be able to emit itself either + * to the batchbuffer directly, or as indirect state. Indirect + * state will be subject to caching so that we get something like + * constant state objects from the i965 driver. + */ + &i915_upload_maps, /* must do before samplers */ + &i915_upload_samplers, - lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB)); - lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB)); - lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT; + &i915_upload_MODES4, + &i915_upload_BFO, + &i915_upload_BLENDCOLOR, + &i915_upload_IAB, - iab |= SRC_ABLND_FACT(intel_translate_blend_factor(srcA)); - iab |= DST_ABLND_FACT(intel_translate_blend_factor(dstA)); - iab |= translate_blend_equation(eqA) << IAB_FUNC_SHIFT; + &i915_upload_colorbuffer, + &i915_upload_depthbuffer, - if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) - iab |= IAB_ENABLE; + /* Note this packet has a dependency on the current primitive: + */ + &i915_upload_polygon_stipple, - if (iab != i915->state.Ctx[I915_CTXREG_IAB] || - lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_IAB] = iab; - i915->state.Ctx[I915_CTXREG_LIS6] = lis6; - } + &i915_upload_scissor, - /* This will catch a logicop blend equation */ - i915EvalLogicOpBlendState(ctx); -} + NULL, /* i915_constant_buffer */ +}; -static void -i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB, - GLenum dstRGB, GLenum srcA, GLenum dstA) +void i915_init_state( struct i915_context *i915 ) { - i915UpdateBlendState(ctx); -} + GLuint i; + i915_init_pools(i915); + i915_init_caches(i915); -static void -i915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA) -{ - i915UpdateBlendState(ctx); -} + i915->state.atoms = _mesa_malloc(sizeof(atoms)); + i915->state.nr_atoms = sizeof(atoms)/sizeof(*atoms); + _mesa_memcpy(i915->state.atoms, atoms, sizeof(atoms)); + /* Patch in a pointer to the dynamic state atom: + */ + for (i = 0; i < i915->state.nr_atoms; i++) + if (i915->state.atoms[i] == NULL) + i915->state.atoms[i] = &i915->curbe.tracked_state; -static void -i915DepthFunc(GLcontext * ctx, GLenum func) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int test = intel_translate_compare_func(func); - - DBG("%s\n", __FUNCTION__); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; - i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT; + _mesa_memcpy(&i915->curbe.tracked_state, + &i915_constant_buffer, + sizeof(i915_constant_buffer)); } -static void -i915DepthMask(GLcontext * ctx, GLboolean flag) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - - DBG("%s flag (%d)\n", __FUNCTION__, flag); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (flag && ctx->Depth.Test) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE; -} - -/* ============================================================= - * Polygon stipple - * - * The i915 supports a 4x4 stipple natively, GL wants 32x32. - * Fortunately stipple is usually a repeating pattern. - */ -static void -i915PolygonStipple(GLcontext * ctx, const GLubyte * mask) +void i915_destroy_state( struct i915_context *i915 ) { - struct i915_context *i915 = I915_CONTEXT(ctx); - const GLubyte *m = mask; - GLubyte p[4]; - int i, j, k; - int active = (ctx->Polygon.StippleFlag && - i915->intel.reduced_primitive == GL_TRIANGLES); - GLuint newMask; - - if (active) { - I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); - i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; + if (i915->state.atoms) { + _mesa_free(i915->state.atoms); + i915->state.atoms = NULL; } - p[0] = mask[12] & 0xf; - p[0] |= p[0] << 4; - p[1] = mask[8] & 0xf; - p[1] |= p[1] << 4; - p[2] = mask[4] & 0xf; - p[2] |= p[2] << 4; - p[3] = mask[0] & 0xf; - p[3] |= p[3] << 4; - - for (k = 0; k < 8; k++) - for (j = 3; j >= 0; j--) - for (i = 0; i < 4; i++, m++) - if (*m != p[j]) { - i915->intel.hw_stipple = 0; - return; - } - - newMask = (((p[0] & 0xf) << 0) | - ((p[1] & 0xf) << 4) | - ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); - - - if (newMask == 0xffff || newMask == 0x0) { - /* this is needed to make conform pass */ - i915->intel.hw_stipple = 0; - return; - } - - i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff; - i915->state.Stipple[I915_STPREG_ST1] |= newMask; - i915->intel.hw_stipple = 1; - - if (active) - i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; + i915_destroy_caches(i915); + i915_destroy_batch_cache(i915); + i915_destroy_pools(i915); } - -/* ============================================================= - * Hardware clipping +/*********************************************************************** */ -static void -i915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int x1, y1, x2, y2; - - if (!ctx->DrawBuffer) - return; - - DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); - - if (ctx->DrawBuffer->Name == 0) { - x1 = x; - y1 = ctx->DrawBuffer->Height - (y + h); - x2 = x + w - 1; - y2 = y1 + h - 1; - DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2); - } - else { - /* FBO - not inverted - */ - x1 = x; - y1 = y; - x2 = x + w - 1; - y2 = y + h - 1; - DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2); - } - - x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); - y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); - x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); - y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); - - DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2); - - I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); - i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); - i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); -} -static void -i915LogicOp(GLcontext * ctx, GLenum opcode) +static GLboolean check_state( const struct i915_state_flags *a, + const struct i915_state_flags *b ) { - struct i915_context *i915 = I915_CONTEXT(ctx); - int tmp = intel_translate_logic_op(opcode); - - DBG("%s\n", __FUNCTION__); - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK; - i915->state.Ctx[I915_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp); + return ((a->mesa & b->mesa) || + (a->i915 & b->i915) || + (a->cache & b->cache)); } - - -static void -i915CullFaceFrontFace(GLcontext * ctx, GLenum unused) +static void accumulate_state( struct i915_state_flags *a, + const struct i915_state_flags *b ) { - struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint mode; - - DBG("%s %d\n", __FUNCTION__, - ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); - - if (!ctx->Polygon.CullFlag) { - mode = S4_CULLMODE_NONE; - } - else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { - mode = S4_CULLMODE_CW; - - if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) - mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); - if (ctx->Polygon.CullFaceMode == GL_FRONT) - mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); - if (ctx->Polygon.FrontFace != GL_CCW) - mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); - } - else { - mode = S4_CULLMODE_BOTH; - } - - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK; - i915->state.Ctx[I915_CTXREG_LIS4] |= mode; + a->mesa |= b->mesa; + a->i915 |= b->i915; + a->cache |= b->cache; } -static void -i915LineWidth(GLcontext * ctx, GLfloat widthf) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; - int width; - - DBG("%s\n", __FUNCTION__); - - width = (int) (widthf * 2); - CLAMP_SELF(width, 1, 0xf); - lis4 |= width << S4_LINE_WIDTH_SHIFT; - - if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS4] = lis4; - } -} -static void -i915PointSize(GLcontext * ctx, GLfloat size) +static void xor_states( struct i915_state_flags *result, + const struct i915_state_flags *a, + const struct i915_state_flags *b ) { - struct i915_context *i915 = I915_CONTEXT(ctx); - int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; - GLint point_size = (int) size; - - DBG("%s\n", __FUNCTION__); - - CLAMP_SELF(point_size, 1, 255); - lis4 |= point_size << S4_POINT_WIDTH_SHIFT; - - if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS4] = lis4; - } + result->mesa = a->mesa ^ b->mesa; + result->i915 = a->i915 ^ b->i915; + result->cache = a->cache ^ b->cache; } -/* ============================================================= - * Color masks +/*********************************************************************** + * Emit all state: */ - -static void -i915ColorMask(GLcontext * ctx, - GLboolean r, GLboolean g, GLboolean b, GLboolean a) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK; - - DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, - a); - - if (!r) - tmp |= S5_WRITEDISABLE_RED; - if (!g) - tmp |= S5_WRITEDISABLE_GREEN; - if (!b) - tmp |= S5_WRITEDISABLE_BLUE; - if (!a) - tmp |= S5_WRITEDISABLE_ALPHA; - - if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - i915->state.Ctx[I915_CTXREG_LIS5] = tmp; - } -} - -static void -update_specular(GLcontext * ctx) -{ - /* A hack to trigger the rebuild of the fragment program. - */ - intel_context(ctx)->NewGLState |= _NEW_TEXTURE; -} - -static void -i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param) +void i915_validate_state( struct i915_context *i915 ) { - DBG("%s\n", __FUNCTION__); - - if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { - update_specular(ctx); - } -} - -static void -i915ShadeModel(GLcontext * ctx, GLenum mode) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - - if (mode == GL_SMOOTH) { - i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA | - S4_FLATSHADE_COLOR | - S4_FLATSHADE_SPECULAR); - } - else { - i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA | - S4_FLATSHADE_COLOR | - S4_FLATSHADE_SPECULAR); - } -} - -/* ============================================================= - * Fog - */ -void -i915_update_fog(GLcontext * ctx) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - GLenum mode; - GLboolean enabled; - GLboolean try_pixel_fog; - - if (ctx->FragmentProgram._Active) { - /* Pull in static fog state from program */ + struct i915_state_flags *state = &i915->state.dirty; + GLuint i; - mode = ctx->FragmentProgram._Current->FogOption; - enabled = (mode != GL_NONE); - try_pixel_fog = 0; - } - else { - enabled = ctx->Fog.Enabled; - mode = ctx->Fog.Mode; - - try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && ctx->Hint.Fog == GL_NICEST && 0); /* XXX - DISABLE -- Need ortho fallback */ - } - - if (!enabled) { - i915->vertex_fog = I915_FOG_NONE; - } - else if (try_pixel_fog) { - - I915_STATECHANGE(i915, I915_UPLOAD_FOG); - i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK; - i915->vertex_fog = I915_FOG_PIXEL; - - switch (mode) { - case GL_LINEAR: - if (ctx->Fog.End <= ctx->Fog.Start) { - /* XXX - this won't work with fragment programs. Need to - * either fallback or append fog instructions to end of - * program in the case of linear fog. - */ - i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX; - i915->vertex_fog = I915_FOG_VERTEX; - } - else { - GLfloat c1 = ctx->Fog.End / (ctx->Fog.End - ctx->Fog.Start); - GLfloat c2 = 1.0 / (ctx->Fog.End - ctx->Fog.Start); - - i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_C1_MASK; - i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_LINEAR; - i915->state.Fog[I915_FOGREG_MODE1] |= - ((GLuint) (c1 * FMC1_C1_ONE)) & FMC1_C1_MASK; - - if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) { - i915->state.Fog[I915_FOGREG_MODE2] = - (GLuint) (c2 * FMC2_C2_ONE); - } - else { - union - { - float f; - int i; - } fi; - fi.f = c2; - i915->state.Fog[I915_FOGREG_MODE2] = fi.i; - } - } - break; - case GL_EXP: - i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP; - break; - case GL_EXP2: - i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP2; - break; - default: - break; - } - } - else { /* if (i915->vertex_fog != I915_FOG_VERTEX) */ + state->mesa |= i915->intel.NewGLState; + i915->intel.NewGLState = 0; - I915_STATECHANGE(i915, I915_UPLOAD_FOG); - i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK; - i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX; - i915->vertex_fog = I915_FOG_VERTEX; - } + if (i915->wrap) + state->i915 |= I915_NEW_CONTEXT; - { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled); - if (enabled) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE; + if (i915->emit_state_always) { + state->mesa |= ~0; + state->i915 |= ~0; } - /* always enbale pixel fog - * vertex fog use precaculted fog coord will conflict with appended - * fog program + /* texenv program needs to notify us somehow when this happens: + * Some confusion about which state flag should represent this change. */ - _tnl_allow_vertex_fog( ctx, 0 ); - _tnl_allow_pixel_fog( ctx, 1 ); -} - -static void -i915Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - - switch (pname) { - case GL_FOG_COORDINATE_SOURCE_EXT: - case GL_FOG_MODE: - case GL_FOG_START: - case GL_FOG_END: - break; - - case GL_FOG_DENSITY: - I915_STATECHANGE(i915, I915_UPLOAD_FOG); - - if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) { - i915->state.Fog[I915_FOGREG_MODE3] = (GLuint) (ctx->Fog.Density * - FMC3_D_ONE); - } - else { - union - { - float f; - int i; - } fi; - fi.f = ctx->Fog.Density; - i915->state.Fog[I915_FOGREG_MODE3] = fi.i; - } - break; - - case GL_FOG_COLOR: - I915_STATECHANGE(i915, I915_UPLOAD_FOG); - i915->state.Fog[I915_FOGREG_COLOR] = - (_3DSTATE_FOG_COLOR_CMD | - ((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) | - ((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) | - ((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0)); - break; - - default: - break; + if (i915->fragment_program != i915->attribs.FragmentProgram->_Current) { + i915->fragment_program = i915->attribs.FragmentProgram->_Current; + i915->state.dirty.mesa |= _NEW_PROGRAM; + i915->state.dirty.i915 |= I915_NEW_FRAGMENT_PROGRAM; } -} -static void -i915Hint(GLcontext * ctx, GLenum target, GLenum state) -{ - switch (target) { - case GL_FOG_HINT: - break; - default: - break; - } -} - -/* ============================================================= - */ -static void -i915Enable(GLcontext * ctx, GLenum cap, GLboolean state) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - - switch (cap) { - case GL_TEXTURE_2D: - break; - - case GL_LIGHTING: - case GL_COLOR_SUM: - update_specular(ctx); - break; - - case GL_ALPHA_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE; - break; + if (state->mesa == 0 && + state->cache == 0 && + state->i915 == 0) + return; - case GL_BLEND: - i915EvalLogicOpBlendState(ctx); - break; + if (i915->state.dirty.i915 & I915_NEW_CONTEXT) + i915_clear_batch_cache_flush(i915); - case GL_COLOR_LOGIC_OP: - i915EvalLogicOpBlendState(ctx); - /* Logicop doesn't seem to work at 16bpp: - */ - if (i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */ - FALLBACK(&i915->intel, I915_FALLBACK_LOGICOP, state); - break; - - case GL_FRAGMENT_PROGRAM_ARB: - break; - - case GL_DITHER: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE; - break; - - case GL_DEPTH_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (state) - i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE; - - i915DepthMask(ctx, ctx->Depth.Mask); - break; - - case GL_SCISSOR_TEST: - I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); - if (state) - i915->state.Buffer[I915_DESTREG_SENABLE] = - (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); - else - i915->state.Buffer[I915_DESTREG_SENABLE] = - (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - break; - - case GL_LINE_SMOOTH: - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (state) - i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE; - else - i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE; - break; - - case GL_FOG: - break; - - case GL_CULL_FACE: - i915CullFaceFrontFace(ctx, 0); - break; - - case GL_STENCIL_TEST: - { - GLboolean hw_stencil = GL_FALSE; - if (ctx->DrawBuffer) { - struct intel_renderbuffer *irbStencil - = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); - hw_stencil = (irbStencil && irbStencil->region); - } - if (hw_stencil) { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - if (state) - i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); - else - i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | - S5_STENCIL_WRITE_ENABLE); - } - else { - FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state); - } - } - break; - case GL_POLYGON_STIPPLE: - /* The stipple command worked on my 855GM box, but not my 845G. - * I'll do more testing later to find out exactly which hardware - * supports it. Disabled for now. + if (INTEL_DEBUG) { + /* Debug version which enforces various sanity checks on the + * state flags which are generated and checked to help ensure + * state atoms are ordered correctly in the list. */ - if (i915->intel.hw_stipple && - i915->intel.reduced_primitive == GL_TRIANGLES) { - I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); - if (state) - i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; - else - i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; + struct i915_state_flags examined, prev; + _mesa_memset(&examined, 0, sizeof(examined)); + prev = *state; + + for (i = 0; i < i915->state.nr_atoms; i++) { + const struct i915_tracked_state *atom = i915->state.atoms[i]; + struct i915_state_flags generated; + + assert(atom->dirty.mesa || + atom->dirty.i915 || + atom->dirty.cache); + assert(atom->update); + + if (check_state(state, &atom->dirty)) { + i915->state.atoms[i]->update( i915 ); + +/* emit_foo(i915); */ + } + + accumulate_state(&examined, &atom->dirty); + + /* generated = (prev ^ state) + * if (examined & generated) + * fail; + */ + xor_states(&generated, &prev, state); + assert(!check_state(&examined, &generated)); + prev = *state; } - break; - - case GL_POLYGON_SMOOTH: - break; - - case GL_POINT_SMOOTH: - break; - - default: - ; } -} - - -static void -i915_init_packets(struct i915_context *i915) -{ - intelScreenPrivate *screen = i915->intel.intelScreen; - - /* Zero all state */ - memset(&i915->state, 0, sizeof(i915->state)); - - - { - I915_STATECHANGE(i915, I915_UPLOAD_CTX); - /* Probably don't want to upload all this stuff every time one - * piece changes. - */ - i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(2) | - I1_LOAD_S(4) | - I1_LOAD_S(5) | I1_LOAD_S(6) | (4)); - i915->state.Ctx[I915_CTXREG_LIS2] = 0; - i915->state.Ctx[I915_CTXREG_LIS4] = 0; - i915->state.Ctx[I915_CTXREG_LIS5] = 0; - - if (screen->cpp == 2) /* XXX FBO fix */ - i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; - - - i915->state.Ctx[I915_CTXREG_LIS6] = (S6_COLOR_WRITE_ENABLE | - (2 << S6_TRISTRIP_PV_SHIFT)); - - i915->state.Ctx[I915_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD | - ENABLE_LOGIC_OP_FUNC | - LOGIC_OP_FUNC(LOGICOP_COPY) | - ENABLE_STENCIL_TEST_MASK | - STENCIL_TEST_MASK(0xff) | - ENABLE_STENCIL_WRITE_MASK | - STENCIL_WRITE_MASK(0xff)); - - i915->state.Ctx[I915_CTXREG_IAB] = - (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | - IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR); - - i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = - _3DSTATE_CONST_BLEND_COLOR_CMD; - i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0; - - } - - { - I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); - i915->state.Stipple[I915_STPREG_ST0] = _3DSTATE_STIPPLE; - } - - - { - I915_STATECHANGE(i915, I915_UPLOAD_FOG); - i915->state.Fog[I915_FOGREG_MODE0] = _3DSTATE_FOG_MODE_CMD; - i915->state.Fog[I915_FOGREG_MODE1] = (FMC1_FOGFUNC_MODIFY_ENABLE | - FMC1_FOGFUNC_VERTEX | - FMC1_FOGINDEX_MODIFY_ENABLE | - FMC1_FOGINDEX_W | - FMC1_C1_C2_MODIFY_ENABLE | - FMC1_DENSITY_MODIFY_ENABLE); - i915->state.Fog[I915_FOGREG_COLOR] = _3DSTATE_FOG_COLOR_CMD; - } - - - { - I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); - /* color buffer offset/stride */ - i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; - /* XXX FBO: remove this? Also get set in i915_set_draw_region() */ - i915->state.Buffer[I915_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */ - BUF_3D_USE_FENCE); - - i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; - /* XXX FBO: remove this? Also get set in i915_set_draw_region() */ - i915->state.Buffer[I915_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) | /* pitch in bytes */ - BUF_3D_USE_FENCE); - - i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; - - /* XXX FBO: remove this? Also get set in i915_set_draw_region() */ -#if 0 /* seems we don't need this */ - switch (screen->fbFormat) { - case DV_PF_565: - i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ - DSTORG_VERT_BIAS(0x8) | /* .5 */ - LOD_PRECLAMP_OGL | - TEX_DEFAULT_COLOR_OGL | - DITHER_FULL_ALWAYS | - screen->fbFormat | - DEPTH_FRMT_16_FIXED); - break; - case DV_PF_8888: - i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ - DSTORG_VERT_BIAS(0x8) | /* .5 */ - LOD_PRECLAMP_OGL | - TEX_DEFAULT_COLOR_OGL | - screen->fbFormat | - DEPTH_FRMT_24_FIXED_8_OTHER); - break; + else { + for (i = 0; i < Elements(atoms); i++) { + if (check_state(state, &i915->state.atoms[i]->dirty)) + i915->state.atoms[i]->update( i915 ); } -#endif - - - /* scissor */ - i915->state.Buffer[I915_DESTREG_SENABLE] = - (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; - i915->state.Buffer[I915_DESTREG_SR1] = 0; - i915->state.Buffer[I915_DESTREG_SR2] = 0; - } - - -#if 0 - { - I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS); - i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE; - i915->state.Default[I915_DEFREG_C1] = 0; - i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR; - i915->state.Default[I915_DEFREG_S1] = 0; - i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z; - i915->state.Default[I915_DEFREG_Z1] = 0; } -#endif - - /* These will be emitted every at the head of every buffer, unless - * we get hardware contexts working. - */ - i915->state.active = (I915_UPLOAD_PROGRAM | - I915_UPLOAD_STIPPLE | - I915_UPLOAD_CTX | - I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT); + memset(state, 0, sizeof(*state)); } -void -i915InitStateFunctions(struct dd_function_table *functions) -{ - functions->AlphaFunc = i915AlphaFunc; - functions->BlendColor = i915BlendColor; - functions->BlendEquationSeparate = i915BlendEquationSeparate; - functions->BlendFuncSeparate = i915BlendFuncSeparate; - functions->ColorMask = i915ColorMask; - functions->CullFace = i915CullFaceFrontFace; - functions->DepthFunc = i915DepthFunc; - functions->DepthMask = i915DepthMask; - functions->Enable = i915Enable; - functions->Fogfv = i915Fogfv; - functions->FrontFace = i915CullFaceFrontFace; - functions->Hint = i915Hint; - functions->LightModelfv = i915LightModelfv; - functions->LineWidth = i915LineWidth; - functions->LogicOpcode = i915LogicOp; - functions->PointSize = i915PointSize; - functions->PolygonStipple = i915PolygonStipple; - functions->Scissor = i915Scissor; - functions->ShadeModel = i915ShadeModel; - functions->StencilFuncSeparate = i915StencilFuncSeparate; - functions->StencilMaskSeparate = i915StencilMaskSeparate; - functions->StencilOpSeparate = i915StencilOpSeparate; -} +/* + */ void diff --git a/src/mesa/drivers/dri/i915tex/i915_state.h b/src/mesa/drivers/dri/i915tex/i915_state.h new file mode 100644 index 0000000000..80e692f915 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state.h @@ -0,0 +1,25 @@ +#define DST_BLND_FACT(f) ((f)<nr_constants) { + GLuint nr = p->nr_constants; + + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); + I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); + + i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4); + i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1); + + memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr)); + i915->state.ConstantSize = 2 + (nr) * 4; + + if (0) { + GLuint i; + for (i = 0; i < nr; i++) { + fprintf(stderr, "const[%d]: %f %f %f %f\n", i, + p->constant[i][0], + p->constant[i][1], p->constant[i][2], p->constant[i][3]); + } + } + } + else { + I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); + } + + +/////////////////////// + if (p->nr_params) + _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters); + + for (i = 0; i < p->nr_params; i++) { + GLint reg = p->param[i].reg; + COPY_4V(p->constant[reg], p->param[i].values); + } + + p->params_uptodate = 1; + + +///////////////// + + /* Allocate state in the indirect buffer and upload constants: + */ + + +} + + + + + +static void +track_params(struct i915_fragment_program *p) +{ + GLint i; + + if (p->nr_params) + _mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters); + + for (i = 0; i < p->nr_params; i++) { + GLint reg = p->param[i].reg; + COPY_4V(p->constant[reg], p->param[i].values); + } + + p->params_uptodate = 1; +} + + +/* This tracked state is unique in that the state it monitors varies + * dynamically depending on the parameters tracked by the fragment and + * vertex programs. This is the template used as a starting point, + * each context will maintain a copy of this internally and update as + * required. + */ +const struct i915_tracked_state i915_constant_buffer = { + .dirty = { + .mesa = 0, /* plus fp flags */ + .intel = (I915_NEW_FRAGMENT_PROGRAM), + .cache = (CACHE_NEW_PROGRAM) /* ?? */ + }, + .update = upload_params +}; + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fp.c b/src/mesa/drivers/dri/i915tex/i915_state_fp.c new file mode 100644 index 0000000000..6711bf2fcc --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_fp.c @@ -0,0 +1,92 @@ +/************************************************************************** + * + * 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_program.h" + +#include "program_instruction.h" +#include "program.h" +#include "programopt.h" + + + +void +i915_upload_program() +{ + if (dirty & I915_UPLOAD_PROGRAM) { + if (INTEL_DEBUG & DEBUG_STATE) + fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); + + assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize); + + emit(intel, state->Program, state->ProgramSize * sizeof(GLuint)); + if (INTEL_DEBUG & DEBUG_STATE) + i915_disassemble_program(state->Program, state->ProgramSize); + } +} + + + + +void +i915ValidateFragmentProgram(struct i915_context *i915) +{ + GLcontext *ctx = &i915->intel.ctx; + struct intel_context *intel = intel_context(ctx); + + struct i915_fragment_program *p = + (struct i915_fragment_program *) ctx->FragmentProgram._Current; + + int i, offset = 0; + + if (i915->current_program != p) { + + + i915->current_program = p; + } + + + /* Important: + */ + VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; + + if (!p->translated) + translate_program(p); + + + i915_upload_program(i915, p); +} + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c b/src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c new file mode 100644 index 0000000000..d7ec11500a --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_fp_inputs.c @@ -0,0 +1,150 @@ + +static void +check_wpos(struct i915_fragment_program *p) +{ + GLuint inputs = p->FragProg.Base.InputsRead; + GLint i; + + p->wpos_tex = -1; + + for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { + if (inputs & FRAG_BIT_TEX(i)) + continue; + else if (inputs & FRAG_BIT_WPOS) { + p->wpos_tex = i; + inputs &= ~FRAG_BIT_WPOS; + } + } + + if (inputs & FRAG_BIT_WPOS) { + i915_program_error(p, "No free texcoord for wpos value"); + } +} + + +static void brw_merge_inputs( struct brw_context *brw, + const struct gl_client_array *arrays[]) +{ + struct brw_vertex_element *inputs = brw->vb.inputs; + struct brw_vertex_info old = brw->vb.info; + GLuint i; + + memset(inputs, 0, sizeof(*inputs)); + memset(&brw->vb.info, 0, sizeof(brw->vb.info)); + + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + brw->vb.inputs[i].glarray = arrays[i]; + + /* XXX: metaops passes null arrays */ + if (arrays[i]) { + if (arrays[i]->StrideB != 0) + brw->vb.info.varying |= 1 << i; + + brw->vb.info.sizes[i/16] |= (inputs[i].glarray->Size - 1) << ((i%16) * 2); + } + } + + /* Raise statechanges if input sizes and varying have changed: + */ + if (memcmp(brw->vb.info.sizes, old.sizes, sizeof(old.sizes)) != 0) + brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS; + + if (brw->vb.info.varying != old.varying) + brw->state.dirty.brw |= BRW_NEW_INPUT_VARYING; +} + + + + + + + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + const GLuint inputsRead = p->FragProg.Base.InputsRead; + + + + 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); + } + + if (inputsRead & FRAG_BIT_COL0) { + intel->coloroffset = offset / 4; + EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4); + } + + if (inputsRead & (FRAG_BIT_COL1 | FRAG_BIT_FOGC)) { + + if (inputsRead & FRAG_BIT_COL1) { + intel->specoffset = offset / 4; + EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3); + } + else + EMIT_PAD(3); + + if (inputsRead & FRAG_BIT_FOGC) + EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1); + else + EMIT_PAD(1); + } + + if (inputsRead & FRAG_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)) { + int sz = VB->TexCoordPtr[i]->size; + + s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); + s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); + + EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4); + } + else if (i == p->wpos_tex) { + + /* 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)); + + intel->wpos_offset = offset; + intel->wpos_size = 3 * sizeof(GLuint); + + EMIT_PAD(intel->wpos_size); + } + } + + + + GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; + GLuint s2 = S2_TEXCOORD_NONE; + if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || + s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { + int k; + + I915_STATECHANGE(i915, I915_UPLOAD_CTX); + + /* Must do this *after* statechange, so as not to affect + * buffered vertices reliant on the old state: + */ + intel->vertex_size = _tnl_install_attrs(&intel->ctx, + intel->vertex_attrs, + intel->vertex_attr_count, + intel->ViewportMatrix.m, 0); + + intel->vertex_size >>= 2; + + i915->state.Ctx[I915_CTXREG_LIS2] = s2; + i915->state.Ctx[I915_CTXREG_LIS4] = s4; + } diff --git a/src/mesa/drivers/dri/i915tex/i915_state_immediate.c b/src/mesa/drivers/dri/i915tex/i915_state_immediate.c new file mode 100644 index 0000000000..e3090eb743 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_immediate.c @@ -0,0 +1,315 @@ +/* + 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 + */ + + + +#include "intel_batchbuffer.h" +#include "intel_regions.h" + +#include "brw_context.h" +#include "brw_state.h" +#include "brw_defines.h" + +/*********************************************************************** + * S0,S1: Vertex buffer state. + */ +static void upload_S0S1( struct i915_context *i915 ) +{ + struct intel_context *intel = &i915->intel; + + /* INTEL_NEW_VBO */ + if (intel->vb->state.current_vbo) { + + BEGIN_BATCH(3, 0); + + OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(0) | + I1_LOAD_S(1) | + 2); + + /* INTEL_NEW_VBO, INTEL_NEW_RELOC */ + OUT_RELOC(intel->vb->state.current_vbo->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, + intel->vb->state.hw_vbo_offset); + + /* INTEL_NEW_VERTEX_SIZE */ + OUT_BATCH((intel->vertex_size << 24) | + (intel->vertex_size << 16)); + + ADVANCE_BATCH(); + } +} + +const struct i915_tracked_state i915_upload_S0S1 = { + .dirty = { + .mesa = 0, + .intel = INTEL_NEW_VBO | INTEL_NEW_VERTEX_SIZE | INTEL_NEW_RELOC, + .indirect = 0 + }, + .update = upload_S0S1 +}; + + +/*********************************************************************** + * S2: Vertex format + */ +static void upload_S2( struct i915_context *i915 ) +{ + /* I915_NEW_FRAGPROG */ + i915->state.Ctx[I915_CTXREG_LIS2] = i915->state.fragprog.LIS2; +} + +const struct i915_tracked_state i915_upload_S2 = { + .dirty = { + .mesa = 0, + .intel = I915_NEW_FRAGPROG, + .indirect = 0 + }, + .update = upload_S2 +}; + + + +/*********************************************************************** + * S4: Vertex format, rasterization state + */ +static void upload_S4(struct brw_context *brw) +{ + + /* I915_NEW_FRAGPROG */ + i915->state.Ctx[I915_CTXREG_LIS4] |= i915->state.fragprog.LIS4; + + + /* _NEW_POLYGON, _NEW_BUFFERS */ + { + GLuint mode; + + if (!ctx->Polygon.CullFlag) { + mode = S4_CULLMODE_NONE; + } + else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { + mode = S4_CULLMODE_CW; + + if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) + mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); + if (ctx->Polygon.CullFaceMode == GL_FRONT) + mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); + if (ctx->Polygon.FrontFace != GL_CCW) + mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); + } + else { + mode = S4_CULLMODE_BOTH; + } + i915->state.Ctx[I915_CTXREG_LIS4] |= mode; + } + + + /* _NEW_LINE */ + { + GLint width = (GLint) (ctx->Line.Width * 2); + + CLAMP_SELF(width, 1, 0xf); + i915->state.Ctx[I915_CTXREG_LIS4] |= width << S4_LINE_WIDTH_SHIFT; + + if (ctx->Line.Smooth) + i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE; + } + + /* _NEW_POINT */ + { + GLint point_size = (int) ctx->Point._Size; + + CLAMP_SELF(point_size, 1, 255); + i915->state.Ctx[I915_CTXREG_LIS4] |= point_size << S4_POINT_WIDTH_SHIFT; + } + + /* _NEW_LIGHT */ + if (ctx->Light.ShadeModel == GL_FLAT) { + i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA | + S4_FLATSHADE_COLOR | + S4_FLATSHADE_SPECULAR); + } + + + I915_SET_STATE_IMMEDIATE(i915, , &bcc); +} + + +const struct i915_tracked_state i915_upload_S4 = { + .dirty = { + .mesa = (_NEW_POLYGON | + _NEW_BUFFERS | + _NEW_LINE | + _NEW_POINT | + _NEW_LIGHT), + + .intel = I915_NEW_FRAGPROG, + .indirect = 0 + }, + .update = upload_S4 +}; + + + +/*********************************************************************** + * + */ +static void upload_S5( struct i915_context *i915 ) +{ + /* _NEW_STENCIL */ + if (ctx->Stencil.Enabled) { + GLint test = intel_translate_compare_func(ctx->Stencil.Function[0]); + GLint fop = intel_translate_stencil_op(fail); + GLint dfop = intel_translate_stencil_op(zfail); + GLint dpop = intel_translate_stencil_op(zpass); + + i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | + S5_STENCIL_WRITE_ENABLE); + + i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) | + (test << + S5_STENCIL_TEST_FUNC_SHIFT)); + + + + i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) | + (dfop << + S5_STENCIL_PASS_Z_FAIL_SHIFT) | + (dpop << + S5_STENCIL_PASS_Z_PASS_SHIFT)); + + } + + /* _NEW_COLOR */ + if (RGBA_LOGICOP_ENABLED(ctx)) { + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; + } + + if (ctx->Color.DitherFlag) { + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; + } + + { + const GLubyte *mask = ctx->Color.ColorMask; + + if (!mask[0]) + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_WRITEDISABLE_RED; + + if (!mask[1]) + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_WRITEDISABLE_GREEN; + + if (!mask[2]) + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_WRITEDISABLE_BLUE; + + if (!mask[3]) + i915->state.Ctx[I915_CTXREG_LIS5] |= S5_WRITEDISABLE_ALPHA; + } +} + +const struct i915_tracked_state i915_upload_S5 = { + .dirty = { + .mesa = (_NEW_STENCIL | _NEW_COLOR), + .intel = 0, + .indirect = 0 + }, + .update = upload_S5 +}; + + +/*********************************************************************** + */ +static void upload_S6( struct i915_context *i915 ) +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + + + i915->state.Ctx[I915_CTXREG_LIS6] = (S6_COLOR_WRITE_ENABLE | + (2 << S6_TRISTRIP_PV_SHIFT)); + + /* _NEW_COLOR + */ + if (ctx->Color.AlphaTest) { + int test = intel_translate_compare_func(ctx->Color.AlphaFunc); + GLubyte refByte; + + CLAMPED_FLOAT_TO_UBYTE(refByte, ctx->Color.AlphaRef); + + i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE; + + i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | + (((GLuint) refByte) << S6_ALPHA_REF_SHIFT)); + } + + /* _NEW_COLOR + */ + if (ctx->Color.BlendEnabled && !RGBA_LOGICOP_ENABLED(ctx)) { + + GLuint eqRGB = ctx->Color.BlendEquationRGB; + GLuint eqA = ctx->Color.BlendEquationA; + GLuint srcRGB = ctx->Color.BlendSrcRGB; + GLuint dstRGB = ctx->Color.BlendDstRGB; + GLuint srcA = ctx->Color.BlendSrcA; + GLuint dstA = ctx->Color.BlendDstA; + + if (eqRGB == GL_MIN || eqRGB == GL_MAX) { + srcRGB = dstRGB = GL_ONE; + } + + i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; + + lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB)); + lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB)); + lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT; + } + + /* _NEW_DEPTH + */ + if (ctx->Depth.Test) { + GLint func = intel_translate_compare_func(ctx->Depth.Func); + + i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE; + i915->state.Ctx[I915_CTXREG_LIS6] |= func << S6_DEPTH_TEST_FUNC_SHIFT; + + if (ctx->Depth.Mask) + i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE; + } +} + +const struct i915_tracked_state i915_upload_S6 = { + .dirty = { + .mesa = (_NEW_COLOR | _NEW_DEPTH), + .intel = 0, + .indirect = 0 + }, + .update = upload_S6 +}; + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_indirect.c b/src/mesa/drivers/dri/i915tex/i915_state_indirect.c new file mode 100644 index 0000000000..4d199a139a --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_indirect.c @@ -0,0 +1,61 @@ +/* Emit packets to preserved batch buffers, which can then be + * referenced by the LOAD_INDIRECT command. + * + * Need to figure out what STATIC vs DYNAMIC state is supposed to be. + */ + +/* "constant state", or constant-ish?? + */ +static void emit_static_indirect_state() +{ +} + +/* "slow state", compared probably to the state in + * LOAD_STATE_IMMEDIATE. + */ +static void emit_dynamic_indirect_state() +{ +} + +/* Need to figure out how to do driBO relocations on addresses in the + * indirect state buffers. When do the relocations become invalid? + */ + +static void emit_sampler_state() +{ +} + +static void emit_map_state() +{ +} + +static void emit_program() +{ +} + +static void emit_constants() +{ +} + +void emit_indirect_state() +{ + /* Just emit the packet straight to batch: + */ + + /* Look at the dirty flags and figure out what needs to be sent. + */ +} + +const struct i915_tracked_state i915_indirect_state = { + .dirty = { + .mesa = 0, + .i915 = I915_NEW_STATE_MODE, + .indirect = (INDIRECT_NEW_STATIC | + INDIRECT_NEW_DYNAMIC | + INDIRECT_NEW_SAMPLER | + INDIRECT_NEW_MAP | + INDIRECT_NEW_PROGRAM | + INDIRECT_NEW_CONSTANTS); + }, + .update = upload_indirect_state +}; diff --git a/src/mesa/drivers/dri/i915tex/i915_state_map.c b/src/mesa/drivers/dri/i915tex/i915_state_map.c new file mode 100644 index 0000000000..df85a8c344 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_map.c @@ -0,0 +1,201 @@ +/************************************************************************** + * + * 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 "mtypes.h" +#include "enums.h" +#include "texformat.h" +#include "dri_bufmgr.h" + +#include "intel_mipmap_tree.h" +#include "intel_tex.h" + +#include "i915_context.h" +#include "i915_reg.h" + + +static GLuint +translate_texture_format(GLuint mesa_format) +{ + switch (mesa_format) { + case MESA_FORMAT_L8: + return MAPSURF_8BIT | MT_8BIT_L8; + case MESA_FORMAT_I8: + return MAPSURF_8BIT | MT_8BIT_I8; + case MESA_FORMAT_A8: + return MAPSURF_8BIT | MT_8BIT_A8; + case MESA_FORMAT_AL88: + return MAPSURF_16BIT | MT_16BIT_AY88; + case MESA_FORMAT_RGB565: + return MAPSURF_16BIT | MT_16BIT_RGB565; + case MESA_FORMAT_ARGB1555: + return MAPSURF_16BIT | MT_16BIT_ARGB1555; + case MESA_FORMAT_ARGB4444: + return MAPSURF_16BIT | MT_16BIT_ARGB4444; + case MESA_FORMAT_ARGB8888: + return MAPSURF_32BIT | MT_32BIT_ARGB8888; + case MESA_FORMAT_YCBCR_REV: + return (MAPSURF_422 | MT_422_YCRCB_NORMAL); + case MESA_FORMAT_YCBCR: + return (MAPSURF_422 | MT_422_YCRCB_SWAPY); + case MESA_FORMAT_RGB_FXT1: + case MESA_FORMAT_RGBA_FXT1: + return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); + case MESA_FORMAT_Z16: + return (MAPSURF_16BIT | MT_16BIT_L16); + case MESA_FORMAT_RGBA_DXT1: + case MESA_FORMAT_RGB_DXT1: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); + case MESA_FORMAT_RGBA_DXT3: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); + case MESA_FORMAT_RGBA_DXT5: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); + case MESA_FORMAT_Z24_S8: + return (MAPSURF_32BIT | MT_32BIT_xL824); + default: + assert(0); + return 0; + } +} + + + + + +static void +upload_maps( struct i915_context *i915 ) +{ + GLcontext *ctx = &i915->intel.ctx; + + for (unit = 0; unit < I915_TEX_UNITS; unit++) { + switch (ctx.Texture.Unit[unit]._ReallyEnabled) { + + struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; + struct intel_texture_object *intelObj = intel_texture_object(tObj); + struct gl_texture_image *firstImage; + GLuint *state = i915->state.Tex[unit]; + + memset(state, 0, sizeof(state)); + + /*We need to refcount these. */ + + if (i915->state.tex_buffer[unit] != NULL) { + driBOUnReference(i915->state.tex_buffer[unit]); + i915->state.tex_buffer[unit] = NULL; + } + + if (!intel_finalize_mipmap_tree(intel, unit)) + return GL_FALSE; + + /* Get first image here, since intelObj->firstLevel will get set in + * the intel_finalize_mipmap_tree() call above. + */ + firstImage = tObj->Image[0][intelObj->firstLevel]; + + i915->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->buffer); + i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, + intelObj-> + firstLevel); + + state[I915_TEXREG_MS3] = + (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | + ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | + translate_texture_format(firstImage->TexFormat->MesaFormat) | + MS3_USE_FENCE_REGS); + + state[I915_TEXREG_MS4] = + (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - 1) << MS4_PITCH_SHIFT) | + MS4_CUBE_FACE_ENA_MASK | + ((((intelObj->lastLevel - intelObj->firstLevel) * 4)) << MS4_MAX_LOD_SHIFT) | + ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); + + + DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); + DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); + DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); + + } + } + else { + if (i915->state.active & I915_UPLOAD_TEX(i)) + I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE); + + if (i915->state.tex_buffer[i] != NULL) { + driBOUnReference(i915->state.tex_buffer[i]); + i915->state.tex_buffer[i] = NULL; + } + + break; + } + + + { + int nr = 0; + + for (i = 0; i < I915_TEX_UNITS; i++) + if (dirty & I915_UPLOAD_TEX(i)) + nr++; + + BEGIN_BATCH(2 + nr * 3, 0); + OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); + OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); + for (i = 0; i < I915_TEX_UNITS; i++) { + if (dirty & I915_UPLOAD_TEX(i)) { + + if (state->tex_buffer[i]) { + OUT_RELOC(state->tex_buffer[i], + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, + state->tex_offset[i]); + } + else { + assert(i == 0); + assert(state == &i915->meta); + OUT_BATCH(0); + } + + OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); + OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); + } + } + ADVANCE_BATCH(); + } + + return GL_TRUE; +} + + + + + +const struct i915_tracked_state i915_upload_maps = { + .dirty = { + .mesa = (_NEW_TEXTURE), + .intel = 0, + .indirect = 0 + }, + .update = upload_maps +}; diff --git a/src/mesa/drivers/dri/i915tex/i915_state_misc.c b/src/mesa/drivers/dri/i915tex/i915_state_misc.c new file mode 100644 index 0000000000..8dbed0092f --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_misc.c @@ -0,0 +1,560 @@ +/************************************************************************** + * + * 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 "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +#include "texmem.h" + +#include "intel_fbo.h" +#include "intel_screen.h" +#include "intel_batchbuffer.h" + +#include "i915_context.h" +#include "i915_reg.h" + +#define FILE_DEBUG_FLAG DEBUG_STATE + +/*********************************************************************** + * Modes4: stencil masks and logicop + */ +static void upload_MODES4( struct i915_context *i915 ) +{ + i915->state.Ctx[I915_CTXREG_MODES4] = _3DSTATE_MODES_4_CMD; + + /* _NEW_STENCIL */ + if (ctx->Stencil.Enabled) { + GLint testmask = ctx->Stencil.ValueMask[0] & 0xff; + GLint writemask = ctx->Stencil.WriteMask[0] & 0xff; + + i915->state.Ctx[I915_CTXREG_MODES4] |= (ENABLE_STENCIL_TEST_MASK | + STENCIL_TEST_MASK(mask) | + ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(writemask)); + } + + /* _NEW_COLOR */ + if (ctx->Color._LogicOpEnabled) + { + int tmp = intel_translate_logic_op(ctx->Color.LogicOp); + + i915->state.Ctx[I915_CTXREG_MODES4] |= (ENABLE_LOGIC_OP_FUNC | + LOGIC_OP_FUNC(tmp)); + } + else { + /* This seems to be the only way to turn off logicop. The + * ENABLE_LOGIC_OP_FUNC is just a modify-enable bit to say this + * field is present in the instruction. + */ + i915->state.Ctx[I915_CTXREG_MODES4] |= (ENABLE_LOGIC_OP_FUNC | + LOGICOP_COPY); + } +} + +const struct i915_tracked_state i915_upload_MODES4 = { + .dirty = { + .mesa = _NEW_STENCIL | _NEW_COLOR, + .intel = 0, + .indirect = 0 + }, + .update = upload_MODES4 +}; + + +/*********************************************************************** + * BFO: Backface stencil + */ + +static void upload_BFO( struct i915_context *i915 ) +{ + i915->state.Ctx[I915_CTXREG_BFO] = _3DSTATE_BACKFACE_STENCIL_OPS; + + /* _NEW_STENCIL + */ + if (ctx->Stencil.Enabled) { + GLint test = intel_translate_compare_func(ctx->Stencil.Function[1]); + GLint fop = intel_translate_stencil_op(fail); + GLint dfop = intel_translate_stencil_op(zfail); + GLint dpop = intel_translate_stencil_op(zpass); + + i915->state.Ctx[I915_CTXREG_BFO] |= + (BFO_ENABLE_STENCIL_FUNCS | + BFO_ENABLE_STENCIL_TWO_SIDE | + BFO_ENABLE_STENCIL_REF | + BFO_STENCIL_TWO_SIDE | + (ref << BFO_STENCIL_REF_SHIFT) | + (test << BFO_STENCIL_TEST_FUNC_SHIFT) | + (fop << BFO_STENCIL_FAIL_SHIFT) | + (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) | + (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT)); + } + else { + /* This actually disables two-side stencil: The bit set is a + * modify-enable bit to indicate we are changing the two-side + * setting. Then there is a symbolic zero to show that we are + * setting the flag to zero/off. + */ + i915->state.Ctx[I915_CTXREG_BFO] |= (BFO_ENABLE_STENCIL_TWO_SIDE | + 0); + } +} + +const struct i915_tracked_state i915_upload_BFO = { + .dirty = { + .mesa = _NEW_STENCIL, + .intel = 0, + .indirect = 0 + }, + .update = upload_MODES4 +}; + + +/*********************************************************************** + * BLENDCOLOR + */ +static void upload_BLENDCOLOR( struct i915_context *i915 ) +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + + /* _NEW_COLOR + */ + if (ctx->Color.BlendEnabled) { + const GLfloat *color = ctx->Color.BlendColor; + GLubyte r, g, b, a; + + UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); + + BEGIN_BATCH(2, 0); + OUT_BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); + OUT_BATCH( (a << 24) | (r << 16) | (g << 8) | b ); + ADVANCE_BATCH(); + } +} + +const struct i915_tracked_state i915_upload_BLENDCOLOR = { + .dirty = { + .mesa = _NEW_COLOR, + .i915 = 0, + .cache = 0 + }, + .update = upload_BLENDCOLOR +}; + + +/*********************************************************************** + * IAB: Independent Alpha Blend + */ +static void upload_IAB( struct i915_context *i915 ) +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + + + i915->state.Ctx[I915_CTXREG_IAB] = + + + if (ctx->Color.BlendEnabled) { + + GLuint eqRGB = ctx->Color.BlendEquationRGB; + GLuint eqA = ctx->Color.BlendEquationA; + GLuint srcRGB = ctx->Color.BlendSrcRGB; + GLuint dstRGB = ctx->Color.BlendDstRGB; + GLuint srcA = ctx->Color.BlendSrcA; + GLuint dstA = ctx->Color.BlendDstA; + + if (srcA != srcRGB || + dstA != dstRGB || + eqA != eqRGB) { + + if (eqA == GL_MIN || eqA == GL_MAX) { + srcA = dstA = GL_ONE; + } + + BEGIN_BATCH(1, 0); + + OUT_BATCH( _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | + IAB_MODIFY_ENABLE | + IAB_MODIFY_FUNC | + IAB_MODIFY_SRC_FACTOR | + IAB_MODIFY_DST_FACTOR | + SRC_ABLND_FACT(intel_translate_blend_factor(srcA)) | + DST_ABLND_FACT(intel_translate_blend_factor(dstA)) | + (translate_blend_equation(eqA) << IAB_FUNC_SHIFT) | + IAB_ENABLE ); + + ADVANCE_BATCH(); + } + } +} + +const struct i915_tracked_state i915_upload_IAB = { + .dirty = { + .mesa = _NEW_COLOR, + .i915 = 0, + .cache = 0 + }, + .update = upload_IAB +}; + + +/*********************************************************************** + * Depthbuffer - currently constant, but rotation would change that. + */ + +static void emit_buffers( struct i915_context *i915 ) +{ + if (INTEL_DEBUG & DEBUG_STATE) + fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); + BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, 0); + OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); + OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); + OUT_RELOC(state->draw_region->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + state->draw_region->draw_offset); + + if (state->depth_region) { + OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); + OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); + } + + OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); + ADVANCE_BATCH(); +} + +static void upload_buffers(struct i915_context *i915) +{ + struct intel_region *color_region = state->draw_region; + struct intel_region *depth_region = state->depth_region; + GLuint value; + + if (color_region) { + BEGIN_BATCH(4, 0); + OUT_BATCH( _3DSTATE_BUF_INFO_CMD ); + OUT_BATCH( BUF_3D_ID_COLOR_BACK | + BUF_3D_PITCH(color_region->pitch * color_region->cpp) | + BUF_3D_USE_FENCE); + OUT_RELOC(state->draw_region->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + state->draw_region->draw_offset); + ADVANCE_BATCH(); + } + + if (depth_region) { + BEGIN_BATCH(4, 0); + OUT_BATCH( _3DSTATE_BUF_INFO_CMD ); + OUT_BATCH( BUF_3D_ID_DEPTH | + BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | + BUF_3D_USE_FENCE ); + OUT_RELOC(state->depth_region->buffer, + DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + state->depth_region->draw_offset); + ADVANCE_BATCH(); + } + + /* + * Compute/set I915_DESTREG_DV1 value + */ + BEGIN_BATCH(2, 0); + OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); + + OUT_BATCH( DSTORG_HORT_BIAS(0x8) | /* .5 */ + DSTORG_VERT_BIAS(0x8) | /* .5 */ + LOD_PRECLAMP_OGL | + TEX_DEFAULT_COLOR_OGL | + DITHER_FULL_ALWAYS | + (color_region && color_region->cpp == 4 + ? DV_PF_8888 + : DV_PF_565) | + (depth_region && depth_region->cpp == 4 + ? DEPTH_FRMT_24_FIXED_8_OTHER + : DEPTH_FRMT_16_FIXED) ); + + ADVANCE_BATCH(); +} + +const struct i915_tracked_state i915_upload_buffers = { + .dirty = { + .mesa = 0, + .i915 = I915_NEW_CBUF | I915_NEW_ZBUF, + .cache = 0 + }, + .update = upload_buffers +}; + + + +/*********************************************************************** + * Polygon stipple + * + * The i915 supports a 4x4 stipple natively, GL wants 32x32. + * Fortunately stipple is usually a repeating pattern. + */ +static void upload_stipple( struct i915_context *i915 ) +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte p[4]; + int i, j, k; + + i915->state.Stipple[I915_STPREG_ST1] = 0; + + if (ctx->Polygon.StippleFlag && + i915->intel.reduced_primitive == GL_TRIANGLES) + { + + GLuint newMask; + + p[0] = mask[12] & 0xf; + p[0] |= p[0] << 4; + p[1] = mask[8] & 0xf; + p[1] |= p[1] << 4; + p[2] = mask[4] & 0xf; + p[2] |= p[2] << 4; + p[3] = mask[0] & 0xf; + p[3] |= p[3] << 4; + + for (k = 0; k < 8; k++) + for (j = 3; j >= 0; j--) + for (i = 0; i < 4; i++, m++) + if (*m != p[j]) { + i915->intel.hw_stipple = 0; + return; + } + + newMask = (((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); + + + if (newMask == 0xffff || newMask == 0x0) { + /* this is needed to make conform pass */ + i915->intel.hw_stipple = 0; + return; + } + + i915->state.Stipple[I915_STPREG_ST0] = _3DSTATE_STIPPLE; if (active) { + I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); + i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; + } + + + i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff; + i915->state.Stipple[I915_STPREG_ST1] |= newMask; + i915->intel.hw_stipple = 1; + + if (active) + i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; +} + + +const struct i915_tracked_state i915_polygon_stipple = { + .dirty = { + .mesa = _NEW_POLYGONSTIPPLE, + .i915 = 0, + .cache = 0 + }, + .update = upload_polygon_stipple +}; + + + +/*********************************************************************** + * Misc invarient state packets + */ + +static void upload_invarient_state( struct i915_context *i915 ) +{ + 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), + + /* 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), + }; + + + BATCH_LOCALS; + + 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 i915_tracked_state i915_invarient_state = { + .dirty = { + .mesa = 0, + .i915 = I915_NEW_CONTEXT, + .cache = 0 + }, + .update = upload_invarient_state +}; + + + + + +static void check_fallback() +{ + if (ctx->Color._LogicOpEnabled && i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */ + fallback = 1; + + if (ctx->Stencil.Enabled) { + if (!ctx->DrawBuffer) + return GL_TRUE; + + struct intel_renderbuffer *irbStencil + = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); + + if (!irbStencil || !irbStencil->region) + return GL_TRUE; + } + + +} + + +static void update_scissor() +{ + struct i915_context *i915 = I915_CONTEXT(ctx); + + if (ctx->Scissor.Enabled && ctx->DrawBuffer) { + int x1, y1, x2, y2; + + DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); + + if (ctx->DrawBuffer->Name == 0) { + x1 = x; + y1 = ctx->DrawBuffer->Height - (y + h); + x2 = x + w - 1; + y2 = y1 + h - 1; + DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2); + } + else { + /* FBO - not inverted + */ + x1 = x; + y1 = y; + x2 = x + w - 1; + y2 = y + h - 1; + DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2); + } + + x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); + y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); + x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); + y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); + + DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2); + + I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); + i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; + i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); + i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); + + + i915->state.Buffer[I915_DESTREG_SENABLE] = + (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); + } + else + i915->state.Buffer[I915_DESTREG_SENABLE] = + (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); + +} + + + + diff --git a/src/mesa/drivers/dri/i915tex/i915_state_sampler.c b/src/mesa/drivers/dri/i915tex/i915_state_sampler.c new file mode 100644 index 0000000000..09d28a6bc1 --- /dev/null +++ b/src/mesa/drivers/dri/i915tex/i915_state_sampler.c @@ -0,0 +1,324 @@ +/************************************************************************** + * + * 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 "mtypes.h" +#include "enums.h" +#include "texformat.h" +#include "dri_bufmgr.h" + +#include "intel_mipmap_tree.h" +#include "intel_tex.h" + +#include "i915_context.h" +#include "i915_reg.h" + + +static GLuint +translate_texture_format(GLuint mesa_format) +{ + switch (mesa_format) { + case MESA_FORMAT_L8: + return MAPSURF_8BIT | MT_8BIT_L8; + case MESA_FORMAT_I8: + return MAPSURF_8BIT | MT_8BIT_I8; + case MESA_FORMAT_A8: + return MAPSURF_8BIT | MT_8BIT_A8; + case MESA_FORMAT_AL88: + return MAPSURF_16BIT | MT_16BIT_AY88; + case MESA_FORMAT_RGB565: + return MAPSURF_16BIT | MT_16BIT_RGB565; + case MESA_FORMAT_ARGB1555: + return MAPSURF_16BIT | MT_16BIT_ARGB1555; + case MESA_FORMAT_ARGB4444: + return MAPSURF_16BIT | MT_16BIT_ARGB4444; + case MESA_FORMAT_ARGB8888: + return MAPSURF_32BIT | MT_32BIT_ARGB8888; + case MESA_FORMAT_YCBCR_REV: + return (MAPSURF_422 | MT_422_YCRCB_NORMAL); + case MESA_FORMAT_YCBCR: + return (MAPSURF_422 | MT_422_YCRCB_SWAPY); + case MESA_FORMAT_RGB_FXT1: + case MESA_FORMAT_RGBA_FXT1: + return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); + case MESA_FORMAT_Z16: + return (MAPSURF_16BIT | MT_16BIT_L16); + case MESA_FORMAT_RGBA_DXT1: + case MESA_FORMAT_RGB_DXT1: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); + case MESA_FORMAT_RGBA_DXT3: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); + case MESA_FORMAT_RGBA_DXT5: + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); + case MESA_FORMAT_Z24_S8: + return (MAPSURF_32BIT | MT_32BIT_xL824); + default: + fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format); + abort(); + return 0; + } +} + + + + +/* The i915 (and related graphics cores) do not support GL_CLAMP. The + * Intel drivers for "other operating systems" implement GL_CLAMP as + * GL_CLAMP_TO_EDGE, so the same is done here. + */ +static GLuint +translate_wrap_mode(GLenum wrap) +{ + switch (wrap) { + case GL_REPEAT: + return TEXCOORDMODE_WRAP; + case GL_CLAMP: + return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ + case GL_CLAMP_TO_EDGE: + return TEXCOORDMODE_CLAMP_EDGE; + case GL_CLAMP_TO_BORDER: + return TEXCOORDMODE_CLAMP_BORDER; + case GL_MIRRORED_REPEAT: + return TEXCOORDMODE_MIRROR; + default: + return TEXCOORDMODE_WRAP; + } +} + + + +/* Recalculate all state from scratch. Perhaps not the most + * efficient, but this has gotten complex enough that we need + * something which is understandable and reliable. + */ +static GLboolean +i915_update_sampler(struct intel_context *intel, GLuint unit) +{ + GLcontext *ctx = &intel->ctx; + struct i915_context *i915 = i915_context(ctx); + struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = tUnit->_Current; + struct intel_texture_object *intelObj = intel_texture_object(tObj); + struct gl_texture_image *firstImage; + GLuint *state = i915->state.Tex[unit]; + + memset(state, 0, sizeof(state)); + + + /* Get first image here, since intelObj->firstLevel will get set in + * the intel_finalize_mipmap_tree() call above. + */ + firstImage = tObj->Image[0][intelObj->firstLevel]; + + + { + GLuint minFilt, mipFilt, magFilt; + + switch (tObj->MinFilter) { + case GL_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NONE; + break; + case GL_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_LINEAR; + break; + default: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NONE; + } + + if (tObj->MaxAnisotropy > 1.0) { + minFilt = FILTER_ANISOTROPIC; + magFilt = FILTER_ANISOTROPIC; + } + else { + switch (tObj->MagFilter) { + case GL_NEAREST: + magFilt = FILTER_NEAREST; + break; + case GL_LINEAR: + magFilt = FILTER_LINEAR; + break; + default: + magFilt = FILTER_NEAREST; + break; + } + } + + { + GLint b = (int) ((tObj->LodBias + tUnit->LodBias) * 16.0); + b = CLAMP(b, -256, 255); + + state[I915_TEXREG_SS2] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); + } + + + /* YUV conversion: + */ + if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || + firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) + state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; + + /* Shadow: + */ + if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && + tObj->Target != GL_TEXTURE_3D) { + + state[I915_TEXREG_SS2] |= + (SS2_SHADOW_ENABLE | + intel_translate_compare_func(tObj->CompareFunc)); + + minFilt = FILTER_4X4_FLAT; + magFilt = FILTER_4X4_FLAT; + } + + state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | + (mipFilt << SS2_MIP_FILTER_SHIFT) | + (magFilt << SS2_MAG_FILTER_SHIFT)); + } + + { + GLenum ws = tObj->WrapS; + GLenum wt = tObj->WrapT; + GLenum wr = tObj->WrapR; + + + /* 3D textures don't seem to respect the border color. + * Fallback if there's ever a danger that they might refer to + * it. + * + * Effectively this means fallback on 3D clamp or + * clamp_to_border. + */ + if (tObj->Target == GL_TEXTURE_3D && + (tObj->MinFilter != GL_NEAREST || + tObj->MagFilter != GL_NEAREST) && + (ws == GL_CLAMP || + wt == GL_CLAMP || + wr == GL_CLAMP || + ws == GL_CLAMP_TO_BORDER || + wt == GL_CLAMP_TO_BORDER || + wr == GL_CLAMP_TO_BORDER)) { + +/* return GL_FALSE; */ + sampler->fallback = true; + } + + + /* Or some field in tObj? */ + if (ctx->Texture.Unit[i]._ReallyEnabled == TEXTURE_RECT_BIT) + ss3 = SS3_NORMALIZED_COORDS; + else + ss3 = 0; + + + state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ + + state[I915_TEXREG_SS3] |= + ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | + (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | + (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); + + state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); + } + + + state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], + tObj->_BorderChan[1], + tObj->_BorderChan[2], + tObj->_BorderChan[3]); + + + + I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); + /* memcmp was already disabled, but definitely won't work as the + * region might now change and that wouldn't be detected: + */ + I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); + + + DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); + DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); + DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); + + return GL_TRUE; +} + + + + + + +void +i915_tex_state_emit() +{ + int nr = 0; + + for (i = 0; i < I915_TEX_UNITS; i++) + if (dirty & I915_UPLOAD_TEX(i)) + nr++; + + for (i = 0; i < I915_TEX_UNITS; i++) + update_sampler( i915, i ); + + + BEGIN_BATCH(2 + nr * 3, 0); + OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); + OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); + for (i = 0; i < I915_TEX_UNITS; i++) + if (dirty & I915_UPLOAD_TEX(i)) { + OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); + OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); + OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); + } + ADVANCE_BATCH(); +} + +const struct i915_tracked_state i915_upload_samplers = { + .dirty = { + .mesa = (_NEW_TEXTURE), + .intel = 0, + .indirect = 0 + }, + .update = upload_samplers +}; diff --git a/src/mesa/drivers/dri/i915tex/i915_tex.c b/src/mesa/drivers/dri/i915tex/i915_tex.c deleted file mode 100644 index 59e148ca04..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_tex.c +++ /dev/null @@ -1,78 +0,0 @@ -/************************************************************************** - * - * 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 "mtypes.h" -#include "imports.h" -#include "simple_list.h" -#include "enums.h" -#include "image.h" -#include "texstore.h" -#include "texformat.h" -#include "texmem.h" -#include "swrast/swrast.h" - -#include "mm.h" - -#include "intel_ioctl.h" - -#include "i915_context.h" -#include "i915_reg.h" - - - -static void -i915TexEnv(GLcontext * ctx, GLenum target, - GLenum pname, const GLfloat * param) -{ - struct i915_context *i915 = I915_CONTEXT(ctx); - - switch (pname) { - case GL_TEXTURE_LOD_BIAS:{ - GLuint unit = ctx->Texture.CurrentUnit; - GLint b = (int) ((*param) * 16.0); - if (b > 255) - b = 255; - if (b < -256) - b = -256; - I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - i915->lodbias_ss2[unit] = - ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); - break; - } - - default: - break; - } -} - - -void -i915InitTextureFuncs(struct dd_function_table *functions) -{ - functions->TexEnv = i915TexEnv; -} diff --git a/src/mesa/drivers/dri/i915tex/i915_texstate.c b/src/mesa/drivers/dri/i915tex/i915_texstate.c deleted file mode 100644 index e0ecdfde24..0000000000 --- a/src/mesa/drivers/dri/i915tex/i915_texstate.c +++ /dev/null @@ -1,338 +0,0 @@ -/************************************************************************** - * - * 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 "mtypes.h" -#include "enums.h" -#include "texformat.h" -#include "dri_bufmgr.h" - -#include "intel_mipmap_tree.h" -#include "intel_tex.h" - -#include "i915_context.h" -#include "i915_reg.h" - - -static GLuint -translate_texture_format(GLuint mesa_format) -{ - switch (mesa_format) { - case MESA_FORMAT_L8: - return MAPSURF_8BIT | MT_8BIT_L8; - case MESA_FORMAT_I8: - return MAPSURF_8BIT | MT_8BIT_I8; - case MESA_FORMAT_A8: - return MAPSURF_8BIT | MT_8BIT_A8; - case MESA_FORMAT_AL88: - return MAPSURF_16BIT | MT_16BIT_AY88; - case MESA_FORMAT_RGB565: - return MAPSURF_16BIT | MT_16BIT_RGB565; - case MESA_FORMAT_ARGB1555: - return MAPSURF_16BIT | MT_16BIT_ARGB1555; - case MESA_FORMAT_ARGB4444: - return MAPSURF_16BIT | MT_16BIT_ARGB4444; - case MESA_FORMAT_ARGB8888: - return MAPSURF_32BIT | MT_32BIT_ARGB8888; - case MESA_FORMAT_YCBCR_REV: - return (MAPSURF_422 | MT_422_YCRCB_NORMAL); - case MESA_FORMAT_YCBCR: - return (MAPSURF_422 | MT_422_YCRCB_SWAPY); - case MESA_FORMAT_RGB_FXT1: - case MESA_FORMAT_RGBA_FXT1: - return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); - case MESA_FORMAT_Z16: - return (MAPSURF_16BIT | MT_16BIT_L16); - case MESA_FORMAT_RGBA_DXT1: - case MESA_FORMAT_RGB_DXT1: - return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); - case MESA_FORMAT_RGBA_DXT3: - return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); - case MESA_FORMAT_RGBA_DXT5: - return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); - case MESA_FORMAT_Z24_S8: - return (MAPSURF_32BIT | MT_32BIT_xL824); - default: - fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format); - abort(); - return 0; - } -} - - - - -/* The i915 (and related graphics cores) do not support GL_CLAMP. The - * Intel drivers for "other operating systems" implement GL_CLAMP as - * GL_CLAMP_TO_EDGE, so the same is done here. - */ -static GLuint -translate_wrap_mode(GLenum wrap) -{ - switch (wrap) { - case GL_REPEAT: - return TEXCOORDMODE_WRAP; - case GL_CLAMP: - return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ - case GL_CLAMP_TO_EDGE: - return TEXCOORDMODE_CLAMP_EDGE; - case GL_CLAMP_TO_BORDER: - return TEXCOORDMODE_CLAMP_BORDER; - case GL_MIRRORED_REPEAT: - return TEXCOORDMODE_MIRROR; - default: - return TEXCOORDMODE_WRAP; - } -} - - - -/* Recalculate all state from scratch. Perhaps not the most - * efficient, but this has gotten complex enough that we need - * something which is understandable and reliable. - */ -static GLboolean -i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) -{ - GLcontext *ctx = &intel->ctx; - struct i915_context *i915 = i915_context(ctx); - struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; - struct intel_texture_object *intelObj = intel_texture_object(tObj); - struct gl_texture_image *firstImage; - GLuint *state = i915->state.Tex[unit]; - - memset(state, 0, sizeof(state)); - - /*We need to refcount these. */ - - if (i915->state.tex_buffer[unit] != NULL) { - driBOUnReference(i915->state.tex_buffer[unit]); - i915->state.tex_buffer[unit] = NULL; - } - - if (!intel_finalize_mipmap_tree(intel, unit)) - return GL_FALSE; - - /* Get first image here, since intelObj->firstLevel will get set in - * the intel_finalize_mipmap_tree() call above. - */ - firstImage = tObj->Image[0][intelObj->firstLevel]; - - i915->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->buffer); - i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, - intelObj-> - firstLevel); - - state[I915_TEXREG_MS3] = - (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | - ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | - translate_texture_format(firstImage->TexFormat->MesaFormat) | - MS3_USE_FENCE_REGS); - - state[I915_TEXREG_MS4] = - (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - - 1) << MS4_PITCH_SHIFT) | MS4_CUBE_FACE_ENA_MASK | - ((((intelObj->lastLevel - - intelObj->firstLevel) * - 4)) << MS4_MAX_LOD_SHIFT) | ((firstImage->Depth - - 1) << MS4_VOLUME_DEPTH_SHIFT)); - - - { - GLuint minFilt, mipFilt, magFilt; - - switch (tObj->MinFilter) { - case GL_NEAREST: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_NONE; - break; - case GL_LINEAR: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_NEAREST; - break; - case GL_LINEAR_MIPMAP_NEAREST: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_NEAREST; - break; - case GL_NEAREST_MIPMAP_LINEAR: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_LINEAR; - break; - default: - return GL_FALSE; - } - - if (tObj->MaxAnisotropy > 1.0) { - minFilt = FILTER_ANISOTROPIC; - magFilt = FILTER_ANISOTROPIC; - } - else { - switch (tObj->MagFilter) { - case GL_NEAREST: - magFilt = FILTER_NEAREST; - break; - case GL_LINEAR: - magFilt = FILTER_LINEAR; - break; - default: - return GL_FALSE; - } - } - - state[I915_TEXREG_SS2] = i915->lodbias_ss2[unit]; - - /* YUV conversion: - */ - if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || - firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) - state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; - - /* Shadow: - */ - if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && - tObj->Target != GL_TEXTURE_3D) { - - state[I915_TEXREG_SS2] |= - (SS2_SHADOW_ENABLE | - intel_translate_compare_func(tObj->CompareFunc)); - - minFilt = FILTER_4X4_FLAT; - magFilt = FILTER_4X4_FLAT; - } - - state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | - (mipFilt << SS2_MIP_FILTER_SHIFT) | - (magFilt << SS2_MAG_FILTER_SHIFT)); - } - - { - GLenum ws = tObj->WrapS; - GLenum wt = tObj->WrapT; - GLenum wr = tObj->WrapR; - - - /* 3D textures don't seem to respect the border color. - * Fallback if there's ever a danger that they might refer to - * it. - * - * Effectively this means fallback on 3D clamp or - * clamp_to_border. - */ - if (tObj->Target == GL_TEXTURE_3D && - (tObj->MinFilter != GL_NEAREST || - tObj->MagFilter != GL_NEAREST) && - (ws == GL_CLAMP || - wt == GL_CLAMP || - wr == GL_CLAMP || - ws == GL_CLAMP_TO_BORDER || - wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) - return GL_FALSE; - - - state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ - - state[I915_TEXREG_SS3] |= - ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | - (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | - (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); - - state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); - } - - - state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], - tObj->_BorderChan[1], - tObj->_BorderChan[2], - tObj->_BorderChan[3]); - - - I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); - /* memcmp was already disabled, but definitely won't work as the - * region might now change and that wouldn't be detected: - */ - I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - - -#if 0 - DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); - DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); - DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); - DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); - DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); - DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); -#endif - - return GL_TRUE; -} - - - - -void -i915UpdateTextureState(struct intel_context *intel) -{ - GLboolean ok = GL_TRUE; - GLuint i; - - for (i = 0; i < I915_TEX_UNITS && ok; i++) { - switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { - case TEXTURE_1D_BIT: - case TEXTURE_2D_BIT: - case TEXTURE_CUBE_BIT: - case TEXTURE_3D_BIT: - ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS); - break; - case TEXTURE_RECT_BIT: - ok = i915_update_tex_unit(intel, i, 0); - break; - case 0:{ - struct i915_context *i915 = i915_context(&intel->ctx); - if (i915->state.active & I915_UPLOAD_TEX(i)) - I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE); - - if (i915->state.tex_buffer[i] != NULL) { - driBOUnReference(i915->state.tex_buffer[i]); - i915->state.tex_buffer[i] = NULL; - } - - break; - } - default: - ok = GL_FALSE; - break; - } - } - - FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok); -} diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c index 52db9a95e6..2703ca8d9f 100644 --- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c @@ -55,226 +55,18 @@ i915_render_start(struct intel_context *intel) static void i915_reduced_primitive_state(struct intel_context *intel, GLenum rprim) { - struct i915_context *i915 = i915_context(&intel->ctx); - GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; - - st1 &= ~ST1_ENABLE; - - switch (rprim) { - case GL_TRIANGLES: - if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple) - st1 |= ST1_ENABLE; - break; - case GL_LINES: - case GL_POINTS: - default: - break; - } - - i915->intel.reduced_primitive = rprim; - - if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { - INTEL_FIREVERTICES(intel); - - I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); - i915->state.Stipple[I915_STPREG_ST1] = st1; - } } -/* Pull apart the vertex format registers and figure out how large a - * vertex is supposed to be. - */ -static GLboolean -i915_check_vertex_size(struct intel_context *intel, GLuint expected) -{ - struct i915_context *i915 = i915_context(&intel->ctx); - int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; - int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; - int i, sz = 0; - - switch (lis4 & S4_VFMT_XYZW_MASK) { - case S4_VFMT_XY: - sz = 2; - break; - case S4_VFMT_XYZ: - sz = 3; - break; - case S4_VFMT_XYW: - sz = 3; - break; - case S4_VFMT_XYZW: - sz = 4; - break; - default: - fprintf(stderr, "no xyzw specified\n"); - return 0; - } - if (lis4 & S4_VFMT_SPEC_FOG) - sz++; - if (lis4 & S4_VFMT_COLOR) - sz++; - if (lis4 & S4_VFMT_DEPTH_OFFSET) - sz++; - if (lis4 & S4_VFMT_POINT_WIDTH) - sz++; - if (lis4 & S4_VFMT_FOG_PARAM) - sz++; - - for (i = 0; i < 8; i++) { - switch (lis2 & S2_TEXCOORD_FMT0_MASK) { - case TEXCOORDFMT_2D: - sz += 2; - break; - case TEXCOORDFMT_3D: - sz += 3; - break; - case TEXCOORDFMT_4D: - sz += 4; - break; - case TEXCOORDFMT_1D: - sz += 1; - break; - case TEXCOORDFMT_2D_16: - sz += 1; - break; - case TEXCOORDFMT_4D_16: - sz += 2; - break; - case TEXCOORDFMT_NOT_PRESENT: - break; - default: - fprintf(stderr, "bad texcoord fmt %d\n", i); - return GL_FALSE; - } - lis2 >>= S2_TEXCOORD_FMT1_SHIFT; - } - - if (sz != expected) - fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected); - - return sz == expected; -} static void i915_emit_invarient_state(struct intel_context *intel) { - BATCH_LOCALS; - - BEGIN_BATCH(200, 0); - - OUT_BATCH(_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); - - OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); - OUT_BATCH(0); - - OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD); - OUT_BATCH(0); - - OUT_BATCH(_3DSTATE_DFLT_Z_CMD); - OUT_BATCH(0); - - /* Don't support texture crossbar yet */ - OUT_BATCH(_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)); - - OUT_BATCH(_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. - */ - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (1)); - OUT_BATCH(0); - - /* XXX: Use this */ - OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - - OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); - OUT_BATCH(0); - OUT_BATCH(0); - - OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE); - - OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */ - OUT_BATCH(0); - - - /* Don't support twosided stencil yet */ - OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); - - ADVANCE_BATCH(); -} - - -#define emit(intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size, 0 ) - -static GLuint -get_dirty(struct i915_hw_state *state) -{ - GLuint dirty; - - /* Workaround the multitex hang - if one texture unit state is - * modified, emit all texture units. - */ - dirty = state->active & ~state->emitted; - if (dirty & I915_UPLOAD_TEX_ALL) - state->emitted &= ~I915_UPLOAD_TEX_ALL; - dirty = state->active & ~state->emitted; - return dirty; } -static GLuint -get_state_size(struct i915_hw_state *state) -{ - GLuint dirty = get_dirty(state); - GLuint i; - GLuint sz = 0; - - if (dirty & I915_UPLOAD_CTX) - sz += sizeof(state->Ctx); - - if (dirty & I915_UPLOAD_BUFFERS) - sz += sizeof(state->Buffer); - - if (dirty & I915_UPLOAD_STIPPLE) - sz += sizeof(state->Stipple); - - if (dirty & I915_UPLOAD_FOG) - sz += sizeof(state->Fog); - - if (dirty & I915_UPLOAD_TEX_ALL) { - int nr = 0; - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) - nr++; - - sz += (2 + nr * 3) * sizeof(GLuint) * 2; - } - - if (dirty & I915_UPLOAD_CONSTANTS) - sz += state->ConstantSize * sizeof(GLuint); - - if (dirty & I915_UPLOAD_PROGRAM) - sz += state->ProgramSize * sizeof(GLuint); - - return sz; -} /* Push the state into the sarea and/or texture memory. @@ -282,146 +74,6 @@ get_state_size(struct i915_hw_state *state) static void i915_emit_state(struct intel_context *intel) { - struct i915_context *i915 = i915_context(&intel->ctx); - struct i915_hw_state *state = i915->current; - int i; - GLuint dirty; - BATCH_LOCALS; - - /* We don't hold the lock at this point, so want to make sure that - * there won't be a buffer wrap. - * - * It might be better to talk about explicit places where - * scheduling is allowed, rather than assume that it is whenever a - * batchbuffer fills up. - */ - intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); - - /* Do this here as we may have flushed the batchbuffer above, - * causing more state to be dirty! - */ - dirty = get_dirty(state); - - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); - - if (dirty & I915_UPLOAD_INVARIENT) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); - i915_emit_invarient_state(intel); - } - - if (dirty & I915_UPLOAD_CTX) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_CTX:\n"); - - emit(intel, state->Ctx, sizeof(state->Ctx)); - } - - if (dirty & I915_UPLOAD_BUFFERS) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); - BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, 0); - OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); - OUT_RELOC(state->draw_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - state->draw_region->draw_offset); - - if (state->depth_region) { - OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); - OUT_RELOC(state->depth_region->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - state->depth_region->draw_offset); - } - - OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); - OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); - OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); - OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); - ADVANCE_BATCH(); - } - - if (dirty & I915_UPLOAD_STIPPLE) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); - emit(intel, state->Stipple, sizeof(state->Stipple)); - } - - if (dirty & I915_UPLOAD_FOG) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_FOG:\n"); - emit(intel, state->Fog, sizeof(state->Fog)); - } - - /* Combine all the dirty texture state into a single command to - * avoid lockups on I915 hardware. - */ - if (dirty & I915_UPLOAD_TEX_ALL) { - int nr = 0; - - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) - nr++; - - BEGIN_BATCH(2 + nr * 3, 0); - OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); - OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) { - - if (state->tex_buffer[i]) { - OUT_RELOC(state->tex_buffer[i], - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, - state->tex_offset[i]); - } - else { - assert(i == 0); - assert(state == &i915->meta); - OUT_BATCH(0); - } - - OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); - OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); - } - ADVANCE_BATCH(); - - BEGIN_BATCH(2 + nr * 3, 0); - OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); - OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); - for (i = 0; i < I915_TEX_UNITS; i++) - if (dirty & I915_UPLOAD_TEX(i)) { - OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); - OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); - OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); - } - ADVANCE_BATCH(); - } - - if (dirty & I915_UPLOAD_CONSTANTS) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n"); - emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint)); - } - - if (dirty & I915_UPLOAD_PROGRAM) { - if (INTEL_DEBUG & DEBUG_STATE) - fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); - - assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize); - - emit(intel, state->Program, state->ProgramSize * sizeof(GLuint)); - if (INTEL_DEBUG & DEBUG_STATE) - i915_disassemble_program(state->Program, state->ProgramSize); - } - - state->emitted |= dirty; } static void @@ -457,45 +109,8 @@ i915_state_draw_region(struct intel_context *intel, intel_region_reference(&state->depth_region, depth_region); } - /* - * Set stride/cpp values - */ - if (color_region) { - state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; - state->Buffer[I915_DESTREG_CBUFADDR1] = - (BUF_3D_ID_COLOR_BACK | - BUF_3D_PITCH(color_region->pitch * color_region->cpp) | - BUF_3D_USE_FENCE); - } - - if (depth_region) { - state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; - state->Buffer[I915_DESTREG_DBUFADDR1] = - (BUF_3D_ID_DEPTH | - BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | - BUF_3D_USE_FENCE); - } - - /* - * Compute/set I915_DESTREG_DV1 value + /* Everything else will get done later: */ - value = (DSTORG_HORT_BIAS(0x8) | /* .5 */ - DSTORG_VERT_BIAS(0x8) | /* .5 */ - LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL); - if (color_region && color_region->cpp == 4) { - value |= DV_PF_8888; - } - else { - value |= (DITHER_FULL_ALWAYS | DV_PF_565); - } - if (depth_region && depth_region->cpp == 4) { - value |= DEPTH_FRMT_24_FIXED_8_OTHER; - } - else { - value |= DEPTH_FRMT_16_FIXED; - } - state->Buffer[I915_DESTREG_DV1] = value; - I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); } @@ -537,7 +152,6 @@ i915_assert_not_dirty( struct intel_context *intel ) void i915InitVtbl(struct i915_context *i915) { - i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; i915->intel.vtbl.destroy = i915_destroy_context; i915->intel.vtbl.emit_state = i915_emit_state; i915->intel.vtbl.lost_hardware = i915_lost_hardware; diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index ab88e83853..20c95a88cb 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -131,14 +131,11 @@ struct intel_context struct intel_region * draw_region, struct intel_region * depth_region); - GLuint(*flush_cmd) (void); + GLuint (*flush_cmd) (void); void (*reduced_primitive_state) (struct intel_context * intel, GLenum rprim); - GLboolean(*check_vertex_size) (struct intel_context * intel, - GLuint expected); - /* Metaops: */ diff --git a/src/mesa/drivers/dri/i915tex/intel_idx_render.c b/src/mesa/drivers/dri/i915tex/intel_idx_render.c index b5b57c399f..fa16d670a3 100644 --- a/src/mesa/drivers/dri/i915tex/intel_idx_render.c +++ b/src/mesa/drivers/dri/i915tex/intel_idx_render.c @@ -46,9 +46,6 @@ #include "intel_reg.h" #include "intel_idx_render.h" -/* XXX: NAUGHTY: - */ -#include "i915_reg.h" #define FILE_DEBUG_FLAG DEBUG_IDX @@ -62,7 +59,7 @@ * and the number of indices we can fit in a batchbuffer after * making room for state. */ -#define HW_MAX_INDEXABLE_VERTS ((1<<16)-1) +#define HW_MAX_INDEXABLE_VERTS 0xfffe #define HW_MAX_INDICES ((BATCH_SZ - 1024) / 2) @@ -73,20 +70,35 @@ struct intel_vb { struct intel_buffer_object *vbo[MAX_VBO]; GLuint nr_vbo; - struct intel_buffer_object *current_vbo; GLuint current_vbo_size; GLuint current_vbo_used; void *current_vbo_ptr; - GLuint hw_vbo_offset; GLuint hw_vbo_delta; GLuint vertex_size; - GLuint dirty; + struct { + struct intel_buffer_object *current_vbo; + GLuint hw_vbo_offset; + } state; }; +/* Have to fallback for: + * - points (needs different viewport) + * - twoside light + * - z offset + * - unfilled prims + * - lines && linestipple + * - tris && tristipple && !hwstipple + * - point attenuation (bug!) + * - aa tris && strict-conformance + * - aa points && strict-conformance + * - PLUS: any fallback-to-swrast condition (intel->Fallback) + * + * If binning, need to flush bins and fall + */ static GLboolean check_idx_render(GLcontext *ctx, struct vertex_buffer *VB, GLuint *max_nr_verts, @@ -119,42 +131,6 @@ static GLboolean check_idx_render(GLcontext *ctx, } -static void -emit_vb_state( struct intel_vb *vb ) -{ - struct intel_context *intel = vb->intel; - - DBG("%s\n", __FUNCTION__); - - /* Additionally, emit our vertex buffer state. - * - * XXX: need to push into the regular state mechanism, otherwise - * will fail with multiple apps when they mix up the submit order - * of their batchbuffers. - * - * XXX: need i830 version - */ - BEGIN_BATCH(3, 0); - - OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S(0) | - I1_LOAD_S(1) | - 2); - - OUT_RELOC(vb->current_vbo->buffer, - DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, - vb->hw_vbo_offset); - - OUT_BATCH((vb->vertex_size << 24) | - (vb->vertex_size << 16)); - - ADVANCE_BATCH(); - - vb->dirty = 0; -} - - static void release_current_vbo( struct intel_vb *vb ) { @@ -167,11 +143,12 @@ release_current_vbo( struct intel_vb *vb ) GL_ARRAY_BUFFER_ARB, &vb->current_vbo->Base ); - vb->current_vbo = NULL; + vb->state.current_vbo = NULL; + vb->intel->state.intel |= INTEL_NEW_VBO; + vb->current_vbo_ptr = NULL; vb->current_vbo_size = 0; vb->current_vbo_used = 0; - vb->dirty = 0; } static void @@ -212,11 +189,13 @@ get_next_vbo( struct intel_vb *vb, GLuint size ) if (size < VBO_SIZE) size = VBO_SIZE; - vb->current_vbo = vb->vbo[vb->nr_vbo++]; + vb->state.current_vbo = vb->vbo[vb->nr_vbo++]; + vb->state.hw_vbo_offset = 0; + vb->intel->state.intel |= INTEL_NEW_VBO; + vb->current_vbo_size = size; vb->current_vbo_used = 0; - vb->hw_vbo_offset = 0; - vb->dirty = 1; + /* Clear out buffer contents and break any hardware dependency on * the old memory: @@ -243,8 +222,8 @@ static void *get_space( struct intel_vb *vb, GLuint nr, GLuint vertex_size ) if (vb->vertex_size != vertex_size) { vb->vertex_size = vertex_size; - vb->hw_vbo_offset = vb->current_vbo_used; - vb->dirty = 1; + vb->state.hw_vbo_offset = vb->current_vbo_used; + vb->intel->state.intel |= INTEL_NEW_VBO; } if (!vb->current_vbo_ptr) { @@ -343,13 +322,7 @@ static void emit_prims( GLcontext *ctx, /* XXX: Can emit upto 64k indices, need to split larger prims */ - BEGIN_BATCH(2 + (nr+1)/2, INTEL_BATCH_CLIPRECTS); - - /* Most state has already been emitted by the RenderStart callback. - */ - if (vb->dirty) { - emit_vb_state( vb ); - } + EMIT_STATE_BEGIN_BATCH(2 + (nr+1)/2, INTEL_BATCH_CLIPRECTS); OUT_BATCH(0); OUT_BATCH( _3DPRIMITIVE | @@ -368,10 +341,6 @@ static void emit_prims( GLcontext *ctx, OUT_BATCH( (offset + indices[start+j]) ); ADVANCE_BATCH(); - - /* This won't fail, but only because of the wierd emit above: - */ - assert(!vb->dirty); } -- cgit v1.2.3