diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/i830.h | 2 | ||||
-rw-r--r-- | src/i830_driver.c | 2 | ||||
-rw-r--r-- | src/i830_rotate.c | 171 | ||||
-rw-r--r-- | src/i915_3d.h | 431 | ||||
-rw-r--r-- | src/i915_reg.h | 17 |
6 files changed, 564 insertions, 60 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 9c2a5c21..c2e49ac3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,6 +58,7 @@ i810_drv_la_SOURCES = \ i830_3d.c \ i830_reg.h \ i915_3d.c \ + i915_3d.h \ i915_reg.h \ i830_exa.c \ i830_xaa.c \ @@ -241,12 +241,12 @@ typedef struct _I830Rec { CreateScreenResourcesProcPtr CreateScreenResources; int *used3D; + I830MemRange ContextMem; #ifdef XF86DRI I830MemRange BackBuffer; I830MemRange DepthBuffer; I830MemRange TexMem; int TexGranularity; - I830MemRange ContextMem; int drmMinor; Bool have3DWindows; #endif diff --git a/src/i830_driver.c b/src/i830_driver.c index 39f539eb..b7a8097e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -5797,7 +5797,7 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) * The extra WindowTable check detects a rotation at startup. */ if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) && - !pI830->DGAactive ) { + !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved) ) { if (!I830Rotate(pScrn, mode)) ret = FALSE; } diff --git a/src/i830_rotate.c b/src/i830_rotate.c index aed0871f..e57a0878 100644 --- a/src/i830_rotate.c +++ b/src/i830_rotate.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset: 3 -*- */ /************************************************************************** Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. @@ -57,6 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "shadow.h" #include "i830.h" +#include "i915_reg.h" +#include "i915_3d.h" #ifdef XF86DRI #include "dri.h" @@ -259,93 +262,138 @@ I915UpdateRotate (ScreenPtr pScreen, #endif if (updateInvarient) { + FS_LOCALS(3); *pI830->used3D = pScrn->scrnIndex; #ifdef XF86DRI if (sarea) sarea->ctxOwner = myContext; #endif - BEGIN_LP_RING(64); + BEGIN_LP_RING(54); /* invarient state */ OUT_RING(MI_NOOP); - OUT_RING(0x66014140); - OUT_RING(0x7d990000); + OUT_RING(_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_RING(_3DSTATE_DFLT_DIFFUSE_CMD); OUT_RING(0x00000000); - OUT_RING(0x7d9a0000); + + OUT_RING(_3DSTATE_DFLT_SPEC_CMD); OUT_RING(0x00000000); - OUT_RING(0x7d980000); + + OUT_RING(_3DSTATE_DFLT_Z_CMD); OUT_RING(0x00000000); - OUT_RING(0x76fac688); - OUT_RING(0x6700a770); - OUT_RING(0x7d040081); + + OUT_RING(_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_RING(_3DSTATE_RASTER_RULES_CMD | + ENABLE_TRI_FAN_PROVOKE_VRTX | TRI_FAN_PROVOKE_VRTX(2) | + ENABLE_LINE_STRIP_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) | + ENABLE_TEXKILL_3D_4D | TEXKILL_4D | + ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | 1); OUT_RING(0x00000000); + /* flush map & render cache */ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE); OUT_RING(0x00000000); + /* draw rect */ - OUT_RING(0x7d800003); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - OUT_RING((pScrn->virtualX - 1) | (pScrn->virtualY - 1) << 16); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - /* scissor */ - OUT_RING(0x7c800002); - OUT_RING(0x7d810001); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - OUT_RING(0x7c000003); + OUT_RING(_3DSTATE_DRAW_RECT_CMD); + OUT_RING(DRAW_DITHER_OFS_X(0) | DRAW_DITHER_OFS_Y(0)); + OUT_RING(DRAW_XMIN(0) | DRAW_YMIN(0)); + OUT_RING(DRAW_XMAX(pScrn->virtualX - 1) | + DRAW_YMAX(pScrn->virtualY - 1)); + OUT_RING(DRAW_XORG(0) | DRAW_YORG(0)); + + OUT_RING(MI_NOOP); + + OUT_RING(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); + OUT_RING(_3DSTATE_SCISSOR_RECT_0_CMD); + OUT_RING(0x00000000); /* ymin, xmin */ + OUT_RING(0x00000000); /* ymax, xmax */ + + OUT_RING(0x7c000003); /* XXX: magic numbers */ OUT_RING(0x7d070000); OUT_RING(0x00000000); OUT_RING(0x68000002); + /* context setup */ - OUT_RING(0x6db3ffff); - OUT_RING(0x7d040744); - OUT_RING(0xfffffff0); - OUT_RING(0x00902c80); - OUT_RING(0x00000000); - OUT_RING(0x00020216); - OUT_RING(0x6ba008a1); - OUT_RING(0x7d880000); - OUT_RING(0x00000000); - /* dv0 */ - OUT_RING(0x7d850000); - /* dv1 */ - if (pI830->cpp == 1) - OUT_RING(0x10880000); - else if (pI830->cpp == 2) - OUT_RING(0x10880200); - else - OUT_RING(0x10880308); - /* stipple */ - OUT_RING(0x7d830000); - OUT_RING(0x00000000); - /* fragment program - texture blend replace*/ - OUT_RING(0x7d050008); - OUT_RING(0x19180000); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - OUT_RING(0x19083c00); + OUT_RING(_3DSTATE_MODES_4_CMD | + ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(LOGICOP_COPY) | + MODE4_ENABLE_STENCIL_WRITE_MASK | + MODE4_ENABLE_STENCIL_TEST_MASK); + + OUT_RING(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | + I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | 4); + + OUT_RING(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | + S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(2, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(3, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(4, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(5, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(6, TEXCOORDFMT_NOT_PRESENT) | + S2_TEXCOORD_FMT(7, TEXCOORDFMT_NOT_PRESENT)); + OUT_RING((1 << S4_POINT_WIDTH_SHIFT) | S4_LINE_WIDTH_ONE | + S4_CULLMODE_NONE | S4_VFMT_SPEC_FOG | S4_VFMT_COLOR | + S4_VFMT_XYZW); + OUT_RING(0x00000000); /* S5 -- enable bits */ + OUT_RING((2 << S6_DEPTH_TEST_FUNC_SHIFT) | + (2 << S6_CBUF_SRC_BLEND_FACT_SHIFT) | + (1 << S6_CBUF_DST_BLEND_FACT_SHIFT) | S6_COLOR_WRITE_ENABLE | + (2 << S6_TRISTRIP_PV_SHIFT)); + + OUT_RING(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | + IAB_MODIFY_ENABLE | + IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) | + IAB_MODIFY_SRC_FACTOR | + (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) | + IAB_MODIFY_DST_FACTOR | + (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT)); + + OUT_RING(_3DSTATE_CONST_BLEND_COLOR_CMD); OUT_RING(0x00000000); + + OUT_RING(_3DSTATE_DST_BUF_VARS_CMD); + if (pI830->cpp == 1) { + OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) | + DSTORG_VERT_BIAS(0x8) | COLR_BUF_8BIT); + } else if (pI830->cpp == 2) { + OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) | + DSTORG_VERT_BIAS(0x8) | COLR_BUF_RGB565); + } else { + OUT_RING(LOD_PRECLAMP_OGL | DSTORG_HORT_BIAS(0x8) | + DSTORG_VERT_BIAS(0x8) | COLR_BUF_ARGB8888 | + DEPTH_FRMT_24_FIXED_8_OTHER); + } + + OUT_RING(_3DSTATE_STIPPLE); OUT_RING(0x00000000); - OUT_RING(0x15200000); - OUT_RING(0x01000000); - OUT_RING(0x00000000); + /* texture sampler state */ - OUT_RING(0x7d010003); + OUT_RING(_3DSTATE_SAMPLER_STATE | 3); OUT_RING(0x00000001); OUT_RING(0x00000000); OUT_RING(0x00000000); OUT_RING(0x00000000); + /* front buffer, pitch, offset */ - OUT_RING(0x7d8e0001); - OUT_RING(0x03800000 | (((pI830->displayWidth * pI830->cpp) / 4) << 2)); + OUT_RING(_3DSTATE_BUF_INFO_CMD); + OUT_RING(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE | + BUF_3D_PITCH(pI830->displayWidth * pI830->cpp)); if (I830IsPrimary(pScrn)) OUT_RING(pI830->FrontBuffer.Start); else OUT_RING(pI8301->FrontBuffer2.Start); /* Set the entire frontbuffer up as a texture */ - OUT_RING(0x7d000003); + OUT_RING(_3DSTATE_MAP_STATE | 3); OUT_RING(0x00000001); if (I830IsPrimary(pScrn)) @@ -359,15 +407,22 @@ I915UpdateRotate (ScreenPtr pScreen, use_fence = 4; if (pI830->cpp == 1) - use_fence |= 0x80; /* MAPSURF_8BIT */ + use_fence |= MAPSURF_8BIT; else if (pI830->cpp == 2) - use_fence |= 0x100; /* MAPSURF_16BIT */ + use_fence |= MAPSURF_16BIT; else - use_fence |= 0x180; /* MAPSURF_32BIT */ + use_fence |= MAPSURF_32BIT; OUT_RING(use_fence | (pScreen->height - 1) << 21 | (pScreen->width - 1) << 10); OUT_RING(((((pScrn->displayWidth * pI830->cpp) / 4) - 1) << 21)); ADVANCE_LP_RING(); + + /* fragment program - texture blend replace*/ + FS_BEGIN(); + i915_fs_dcl(FS_S0); + i915_fs_dcl(FS_T0); + i915_fs_texld(FS_OC, FS_S0, FS_T0); + FS_END(); } { @@ -395,7 +450,7 @@ I915UpdateRotate (ScreenPtr pScreen, OUT_RING(MI_NOOP); /* vertex data */ - OUT_RING(0x7f0c001f); + OUT_RING(PRIM3D_INLINE | PRIM3D_TRIFAN | (32 - 1)); verts[0][0] = box_x1; verts[0][1] = box_y1; verts[1][0] = box_x2; verts[1][1] = box_y1; verts[2][0] = box_x2; verts[2][1] = box_y2; diff --git a/src/i915_3d.h b/src/i915_3d.h new file mode 100644 index 00000000..fc4ca603 --- /dev/null +++ b/src/i915_3d.h @@ -0,0 +1,431 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2006 Intel Corporation + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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: + * Eric Anholt <eric@anholt.net> + * + */ + +/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic + * operations + */ +#define MASK_X 0x1 +#define MASK_Y 0x2 +#define MASK_Z 0x4 +#define MASK_W 0x8 +#define MASK_XYZ (MASK_X | MASK_Y | MASK_W) +#define MASK_XYZW (MASK_XYZ | MASK_W) +#define MASK_SATURATE 0x10 + +/* Temporary, undeclared regs. Preserved between phases */ +#define FS_R0 ((REG_TYPE_R << 8) | 0) +#define FS_R1 ((REG_TYPE_R << 8) | 1) +#define FS_R2 ((REG_TYPE_R << 8) | 2) +#define FS_R3 ((REG_TYPE_R << 8) | 3) + +/* Texture coordinate regs. Must be declared. */ +#define FS_T0 ((REG_TYPE_T << 8) | 0) +#define FS_T1 ((REG_TYPE_T << 8) | 1) +#define FS_T2 ((REG_TYPE_T << 8) | 2) +#define FS_T3 ((REG_TYPE_T << 8) | 3) +#define FS_T4 ((REG_TYPE_T << 8) | 4) +#define FS_T5 ((REG_TYPE_T << 8) | 5) +#define FS_T6 ((REG_TYPE_T << 8) | 6) +#define FS_T7 ((REG_TYPE_T << 8) | 7) +#define FS_T8 ((REG_TYPE_T << 8) | 8) +#define FS_T9 ((REG_TYPE_T << 8) | 9) +#define FS_T10 ((REG_TYPE_T << 8) | 10) + +/* Constant values */ +#define FS_C0 ((REG_TYPE_CONST << 8) | 0) +#define FS_C1 ((REG_TYPE_CONST << 8) | 1) +#define FS_C2 ((REG_TYPE_CONST << 8) | 2) +#define FS_C3 ((REG_TYPE_CONST << 8) | 3) + +/* Sampler regs */ +#define FS_S0 ((REG_TYPE_S << 8) | 0) +#define FS_S1 ((REG_TYPE_S << 8) | 1) +#define FS_S2 ((REG_TYPE_S << 8) | 2) +#define FS_S3 ((REG_TYPE_S << 8) | 3) + +/* Output color */ +#define FS_OC ((REG_TYPE_OC << 8) | 0) + +/* Output depth */ +#define FS_OD ((REG_TYPE_OD << 8) | 0) + +/* Unpreserved temporary regs */ +#define FS_U0 ((REG_TYPE_U << 8) | 0) +#define FS_U1 ((REG_TYPE_U << 8) | 1) +#define FS_U2 ((REG_TYPE_U << 8) | 2) +#define FS_U3 ((REG_TYPE_U << 8) | 3) + +#define REG_TYPE(reg) ((reg) >> 8) +#define REG_NR(reg) ((reg) & 0xff) + +struct i915_fs_op { + CARD32 ui[3]; +}; + +#define X_CHANNEL_VAL 1 +#define Y_CHANNEL_VAL 2 +#define Z_CHANNEL_VAL 3 +#define W_CHANNEL_VAL 4 +#define ZERO_CHANNEL_VAL 5 +#define ONE_CHANNEL_VAL 6 + +/** + * This structure represents the contents of an operand to an i915 fragment + * shader. + * + * It is not a hardware representation, though closely related. + */ +struct i915_fs_operand { + /**< REG_TYPE_* register type */ + int reg; + /**< *_CHANNEL_VAL swizzle value, with optional negation */ + int x; + /**< *_CHANNEL_VAL swizzle value, with optional negation */ + int y; + /**< *_CHANNEL_VAL swizzle value, with optional negation */ + int z; + /**< *_CHANNEL_VAL swizzle value, with optional negation */ + int w; +}; + +/** + * Construct an operand description for the fragment shader. + * + * \param regtype FS_* register used as the source value for X/Y/Z/W sources. + * \param x *_CHANNEL_VAL swizzle value prefix for operand X channel, with + * optional negation. + * \param y *_CHANNEL_VAL swizzle value prefix for operand Y channel, with + * optional negation. + * \param z *_CHANNEL_VAL swizzle value prefix for operand Z channel, with + * optional negation. + * \param w *_CHANNEL_VAL swizzle value prefix for operand W channel, with + * optional negation. + */ +#define i915_fs_operand(reg, x, y, z, w) \ + _i915_fs_operand(reg, \ + x##_CHANNEL_VAL, y##_CHANNEL_VAL, \ + z##_CHANNEL_VAL, w##_CHANNEL_VAL) + +/** + * Construct an oeprand description for using a register with no swizzling + */ +#define i915_fs_operand_reg(reg) \ + i915_fs_operand(reg, X, Y, Z, W) + +static inline struct i915_fs_operand +_i915_fs_operand(int reg, int x, int y, int z, int w) +{ + struct i915_fs_operand operand; + + operand.reg = reg; + operand.x = x; + operand.y = y; + operand.z = z; + operand.w = w; + + return operand; +} + +/** + * Returns an operand containing (0.0, 0.0, 0.0, 0.0). + */ +static inline struct i915_fs_operand +i915_fs_operand_zero(void) +{ + return i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO); +} + +/** + * Returns an unused operand + */ +#define i915_fs_operand_none() i915_fs_operand_zero() + +/** + * Returns an operand containing (1.0, 1.0, 1.0, 1.0). + */ +static inline struct i915_fs_operand +i915_fs_operand_one(void) +{ + return i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE); +} + +static inline int +i915_get_hardware_channel_val(int channel_val) +{ + if (channel_val < 0) + channel_val = -channel_val; + + switch (channel_val) { + case X_CHANNEL_VAL: + return SRC_X; + case Y_CHANNEL_VAL: + return SRC_Y; + case Z_CHANNEL_VAL: + return SRC_Z; + case W_CHANNEL_VAL: + return SRC_W; + case ZERO_CHANNEL_VAL: + return SRC_ZERO; + case ONE_CHANNEL_VAL: + return SRC_ONE; + } + FatalError("Bad channel value %d\n", channel_val); +} + +/** + * Outputs a fragment shader command to declare a sampler or texture register. + */ +#define i915_fs_dcl(reg) \ +do { \ + FS_OUT(_i915_fs_dcl(reg)); \ +} while (0) + +/** + * Constructs a fragment shader command to declare a sampler or texture + * register. + */ +static inline struct i915_fs_op +_i915_fs_dcl(int reg) +{ + struct i915_fs_op op; + + op.ui[0] = D0_DCL | (REG_TYPE(reg) << D0_TYPE_SHIFT) | + (REG_NR(reg) << D0_NR_SHIFT); + op.ui[1] = 0; + op.ui[2] = 0; + if (REG_TYPE(reg) != REG_TYPE_S) + op.ui[0] |= D0_CHANNEL_ALL; + + return op; +} + +/** + * Constructs a fragment shader command to load from a texture sampler. + */ +#define i915_fs_texld(dest_reg, sampler_reg, address_reg) \ +do { \ + FS_OUT(_i915_fs_texld(T0_TEXLD, dest_reg, sampler_reg, address_reg)); \ +} while (0) + +static inline struct i915_fs_op +_i915_fs_texld(int load_op, int dest_reg, int sampler_reg, int address_reg) +{ + struct i915_fs_op op; + + op.ui[0] = 0; + op.ui[1] = 0; + op.ui[2] = 0; + + if (REG_TYPE(sampler_reg) != REG_TYPE_S) + FatalError("Bad sampler reg type\n"); + + op.ui[0] |= load_op; + op.ui[0] |= REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT; + op.ui[0] |= REG_NR(dest_reg) << T0_DEST_NR_SHIFT; + op.ui[0] |= REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT; + op.ui[1] |= REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT; + op.ui[1] |= REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT; + + return op; +} + +#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \ + _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2) + +static inline struct i915_fs_op +_i915_fs_arith(int cmd, int dest_reg, + struct i915_fs_operand operand0, + struct i915_fs_operand operand1, + struct i915_fs_operand operand2) +{ + struct i915_fs_op op; + + op.ui[0] = 0; + op.ui[1] = 0; + op.ui[2] = 0; + + /* Set up destination register and write mask */ + op.ui[0] |= cmd; + op.ui[0] |= REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT; + op.ui[0] |= REG_NR(dest_reg) << A0_DEST_NR_SHIFT; + op.ui[0] |= A0_DEST_CHANNEL_ALL; + + /* Set up operand 0 */ + op.ui[0] |= REG_TYPE(operand0.reg) << A0_SRC0_TYPE_SHIFT; + op.ui[0] |= REG_NR(operand0.reg) << A0_SRC0_NR_SHIFT; + + op.ui[1] |= i915_get_hardware_channel_val(operand0.x) << + A1_SRC0_CHANNEL_X_SHIFT; + if (operand0.x < 0) + op.ui[1] |= A1_SRC0_CHANNEL_X_NEGATE; + + op.ui[1] |= i915_get_hardware_channel_val(operand0.y) << + A1_SRC0_CHANNEL_Y_SHIFT; + if (operand0.y < 0) + op.ui[1] |= A1_SRC0_CHANNEL_Y_NEGATE; + + op.ui[1] |= i915_get_hardware_channel_val(operand0.z) << + A1_SRC0_CHANNEL_Z_SHIFT; + if (operand0.z < 0) + op.ui[1] |= A1_SRC0_CHANNEL_Z_NEGATE; + + op.ui[1] |= i915_get_hardware_channel_val(operand0.w) << + A1_SRC0_CHANNEL_W_SHIFT; + if (operand0.w < 0) + op.ui[1] |= A1_SRC0_CHANNEL_W_NEGATE; + + /* Set up operand 1 */ + op.ui[1] |= REG_TYPE(operand1.reg) << A1_SRC1_TYPE_SHIFT; + op.ui[1] |= REG_NR(operand1.reg) << A1_SRC1_NR_SHIFT; + + op.ui[1] |= i915_get_hardware_channel_val(operand1.x) << + A1_SRC1_CHANNEL_X_SHIFT; + if (operand1.x < 0) + op.ui[1] |= A1_SRC1_CHANNEL_X_NEGATE; + + op.ui[1] |= i915_get_hardware_channel_val(operand1.y) << + A1_SRC1_CHANNEL_Y_SHIFT; + if (operand1.y < 0) + op.ui[1] |= A1_SRC1_CHANNEL_Y_NEGATE; + + op.ui[2] |= i915_get_hardware_channel_val(operand1.z) << + A2_SRC1_CHANNEL_Z_SHIFT; + if (operand1.z < 0) + op.ui[2] |= A2_SRC1_CHANNEL_Z_NEGATE; + + op.ui[2] |= i915_get_hardware_channel_val(operand1.w) << + A2_SRC1_CHANNEL_W_SHIFT; + if (operand1.w < 0) + op.ui[2] |= A2_SRC1_CHANNEL_W_NEGATE; + + /* Set up operand 2 */ + op.ui[2] |= REG_TYPE(operand2.reg) << A2_SRC2_TYPE_SHIFT; + op.ui[2] |= REG_NR(operand2.reg) << A2_SRC2_NR_SHIFT; + + op.ui[2] |= i915_get_hardware_channel_val(operand2.x) << + A2_SRC2_CHANNEL_X_SHIFT; + if (operand2.x < 0) + op.ui[2] |= A2_SRC2_CHANNEL_X_NEGATE; + + op.ui[2] |= i915_get_hardware_channel_val(operand2.y) << + A2_SRC2_CHANNEL_Y_SHIFT; + if (operand2.y < 0) + op.ui[2] |= A2_SRC2_CHANNEL_Y_NEGATE; + + op.ui[2] |= i915_get_hardware_channel_val(operand2.z) << + A2_SRC2_CHANNEL_Z_SHIFT; + if (operand2.z < 0) + op.ui[2] |= A2_SRC2_CHANNEL_Z_NEGATE; + + op.ui[2] |= i915_get_hardware_channel_val(operand2.w) << + A2_SRC2_CHANNEL_W_SHIFT; + if (operand2.w < 0) + op.ui[2] |= A2_SRC2_CHANNEL_W_NEGATE; + + return op; +} + +/** + * Move the values in operand0 to the dest reg with the masking/saturation + * specified. + */ +#define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \ +do { \ + struct i915_fs_op op; \ + \ + op = i915_fs_arith(MOV, dest_reg, operand0, i915_fs_operand_none(), \ + i915_fs_operand_none()); \ + op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ + op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ + if ((dest_mask) & MASK_SATURATE) \ + op.ui[0] |= A0_DEST_SATURATE; \ + \ + FS_OUT(op); \ +} while (0) + +/** Add operand0 and operand1 and put the result in dest_reg */ +#define i915_fs_add(dest_reg, operand0, operand1) \ +do { \ + FS_OUT(i915_fs_arith(ADD, dest_reg, operand0, operand1, \ + i915_fs_operand_none())); \ +} while (0) + +/** + * Perform a 3-component dot-product of operand0 and operand1 and put the + * resulting scalar in the channels of dest_reg specified by the dest_mask. + */ +#define i915_fs_dp3_masked(dest_reg, dest_mask, operand0, operand1) \ +do { \ + struct i915_fs_op op; \ + \ + op = i915_fs_arith(DP3, dest_reg, operand0, i915_fs_operand_none(), \ + i915_fs_operand_none()); \ + op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ + op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ + if ((dest_mask) & MASK_SATURATE) \ + op.ui[0] |= A0_DEST_SATURATE; \ + \ + FS_OUT(op); \ +} while (0) + +/** + * Sets up local state for accumulating a fragment shader buffer. + * + * \param x maximum number of shader commands that may be used between + * a FS_START and FS_END + */ +#define FS_LOCALS(x) \ + CARD32 _shader_buf[(x) * 3]; \ + int _max_shader_commands = x; \ + int _cur_shader_commands + +#define FS_BEGIN() \ +do { \ + _cur_shader_commands = 0; \ +} while (0) + +#define FS_OUT(_shaderop) \ +do { \ + _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0]; \ + _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1]; \ + _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2]; \ + if (++_cur_shader_commands > _max_shader_commands) \ + FatalError("fragment shader command buffer exceeded (%d)\n", \ + _cur_shader_commands); \ +} while (0) + +#define FS_END() \ +do { \ + int _i; \ + BEGIN_LP_RING(_cur_shader_commands * 3 + 1); \ + OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM | \ + (_cur_shader_commands * 3 - 1)); \ + for (_i = 0; _i < _cur_shader_commands * 3; _i++) \ + OUT_RING(_shader_buf[_i]); \ + ADVANCE_LP_RING(); \ +} while (0); diff --git a/src/i915_reg.h b/src/i915_reg.h index e2d7b9d9..b9f7ef8e 100644 --- a/src/i915_reg.h +++ b/src/i915_reg.h @@ -236,6 +236,22 @@ #define IAB_DST_FACTOR_SHIFT 0 #define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0) +#define BLENDFACT_ZERO 0x01 +#define BLENDFACT_ONE 0x02 +#define BLENDFACT_SRC_COLR 0x03 +#define BLENDFACT_INV_SRC_COLR 0x04 +#define BLENDFACT_SRC_ALPHA 0x05 +#define BLENDFACT_INV_SRC_ALPHA 0x06 +#define BLENDFACT_DST_ALPHA 0x07 +#define BLENDFACT_INV_DST_ALPHA 0x08 +#define BLENDFACT_DST_COLR 0x09 +#define BLENDFACT_INV_DST_COLR 0x0a +#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b +#define BLENDFACT_CONST_COLOR 0x0c +#define BLENDFACT_INV_CONST_COLOR 0x0d +#define BLENDFACT_CONST_ALPHA 0x0e +#define BLENDFACT_INV_CONST_ALPHA 0x0f +#define BLENDFACT_MASK 0x0f #define BLENDFUNC_ADD 0x0 #define BLENDFUNC_SUBTRACT 0x1 @@ -433,6 +449,7 @@ #define ENABLE_LOGIC_OP_FUNC (1<<23) #define LOGIC_OP_FUNC(x) ((x)<<18) #define LOGICOP_MASK (0xf<<18) +#define LOGICOP_COPY 0xc #define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00)) #define ENABLE_STENCIL_TEST_MASK (1<<17) #define STENCIL_TEST_MASK(x) ((x)<<8) |