1fa225cbcSrjs/* -*- c-basic-offset: 4 -*- */ 2fa225cbcSrjs/* 3fa225cbcSrjs * Copyright © 2006 Intel Corporation 4fa225cbcSrjs * 5fa225cbcSrjs * Permission is hereby granted, free of charge, to any person obtaining a 6fa225cbcSrjs * copy of this software and associated documentation files (the "Software"), 7fa225cbcSrjs * to deal in the Software without restriction, including without limitation 8fa225cbcSrjs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9fa225cbcSrjs * and/or sell copies of the Software, and to permit persons to whom the 10fa225cbcSrjs * Software is furnished to do so, subject to the following conditions: 11fa225cbcSrjs * 12fa225cbcSrjs * The above copyright notice and this permission notice (including the next 13fa225cbcSrjs * paragraph) shall be included in all copies or substantial portions of the 14fa225cbcSrjs * Software. 15fa225cbcSrjs * 16fa225cbcSrjs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17fa225cbcSrjs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18fa225cbcSrjs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19fa225cbcSrjs * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20fa225cbcSrjs * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21fa225cbcSrjs * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22fa225cbcSrjs * SOFTWARE. 23fa225cbcSrjs * 24fa225cbcSrjs * Authors: 25fa225cbcSrjs * Eric Anholt <eric@anholt.net> 26fa225cbcSrjs * 27fa225cbcSrjs */ 28fa225cbcSrjs 29fa225cbcSrjs/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic 30fa225cbcSrjs * operations 31fa225cbcSrjs */ 32fa225cbcSrjs#define MASK_X 0x1 33fa225cbcSrjs#define MASK_Y 0x2 34fa225cbcSrjs#define MASK_Z 0x4 35fa225cbcSrjs#define MASK_W 0x8 36fa225cbcSrjs#define MASK_XYZ (MASK_X | MASK_Y | MASK_Z) 37fa225cbcSrjs#define MASK_XYZW (MASK_XYZ | MASK_W) 38fa225cbcSrjs#define MASK_SATURATE 0x10 39fa225cbcSrjs 40fa225cbcSrjs/* Temporary, undeclared regs. Preserved between phases */ 41fa225cbcSrjs#define FS_R0 ((REG_TYPE_R << 8) | 0) 42fa225cbcSrjs#define FS_R1 ((REG_TYPE_R << 8) | 1) 43fa225cbcSrjs#define FS_R2 ((REG_TYPE_R << 8) | 2) 44fa225cbcSrjs#define FS_R3 ((REG_TYPE_R << 8) | 3) 45fa225cbcSrjs 46fa225cbcSrjs/* Texture coordinate regs. Must be declared. */ 47fa225cbcSrjs#define FS_T0 ((REG_TYPE_T << 8) | 0) 48fa225cbcSrjs#define FS_T1 ((REG_TYPE_T << 8) | 1) 49fa225cbcSrjs#define FS_T2 ((REG_TYPE_T << 8) | 2) 50fa225cbcSrjs#define FS_T3 ((REG_TYPE_T << 8) | 3) 51fa225cbcSrjs#define FS_T4 ((REG_TYPE_T << 8) | 4) 52fa225cbcSrjs#define FS_T5 ((REG_TYPE_T << 8) | 5) 53fa225cbcSrjs#define FS_T6 ((REG_TYPE_T << 8) | 6) 54fa225cbcSrjs#define FS_T7 ((REG_TYPE_T << 8) | 7) 55fa225cbcSrjs#define FS_T8 ((REG_TYPE_T << 8) | 8) 56fa225cbcSrjs#define FS_T9 ((REG_TYPE_T << 8) | 9) 57fa225cbcSrjs#define FS_T10 ((REG_TYPE_T << 8) | 10) 58fa225cbcSrjs 59fa225cbcSrjs/* Constant values */ 60fa225cbcSrjs#define FS_C0 ((REG_TYPE_CONST << 8) | 0) 61fa225cbcSrjs#define FS_C1 ((REG_TYPE_CONST << 8) | 1) 62fa225cbcSrjs#define FS_C2 ((REG_TYPE_CONST << 8) | 2) 63fa225cbcSrjs#define FS_C3 ((REG_TYPE_CONST << 8) | 3) 64fa225cbcSrjs#define FS_C4 ((REG_TYPE_CONST << 8) | 4) 65fa225cbcSrjs#define FS_C5 ((REG_TYPE_CONST << 8) | 5) 66fa225cbcSrjs#define FS_C6 ((REG_TYPE_CONST << 8) | 6) 67fa225cbcSrjs#define FS_C7 ((REG_TYPE_CONST << 8) | 7) 68fa225cbcSrjs 69fa225cbcSrjs/* Sampler regs */ 70fa225cbcSrjs#define FS_S0 ((REG_TYPE_S << 8) | 0) 71fa225cbcSrjs#define FS_S1 ((REG_TYPE_S << 8) | 1) 72fa225cbcSrjs#define FS_S2 ((REG_TYPE_S << 8) | 2) 73fa225cbcSrjs#define FS_S3 ((REG_TYPE_S << 8) | 3) 74fa225cbcSrjs 75fa225cbcSrjs/* Output color */ 76fa225cbcSrjs#define FS_OC ((REG_TYPE_OC << 8) | 0) 77fa225cbcSrjs 78fa225cbcSrjs/* Output depth */ 79fa225cbcSrjs#define FS_OD ((REG_TYPE_OD << 8) | 0) 80fa225cbcSrjs 81fa225cbcSrjs/* Unpreserved temporary regs */ 82fa225cbcSrjs#define FS_U0 ((REG_TYPE_U << 8) | 0) 83fa225cbcSrjs#define FS_U1 ((REG_TYPE_U << 8) | 1) 84fa225cbcSrjs#define FS_U2 ((REG_TYPE_U << 8) | 2) 85fa225cbcSrjs#define FS_U3 ((REG_TYPE_U << 8) | 3) 86fa225cbcSrjs 87fa225cbcSrjs#define REG_TYPE(reg) ((reg) >> 8) 88fa225cbcSrjs#define REG_NR(reg) ((reg) & 0xff) 89fa225cbcSrjs 90fa225cbcSrjsstruct i915_fs_op { 91fa225cbcSrjs uint32_t ui[3]; 92fa225cbcSrjs}; 93fa225cbcSrjs 94fa225cbcSrjs#define X_CHANNEL_VAL 1 95fa225cbcSrjs#define Y_CHANNEL_VAL 2 96fa225cbcSrjs#define Z_CHANNEL_VAL 3 97fa225cbcSrjs#define W_CHANNEL_VAL 4 98fa225cbcSrjs#define ZERO_CHANNEL_VAL 5 99fa225cbcSrjs#define ONE_CHANNEL_VAL 6 100fa225cbcSrjs 101fa225cbcSrjs/** 102fa225cbcSrjs * This structure represents the contents of an operand to an i915 fragment 103fa225cbcSrjs * shader. 104fa225cbcSrjs * 105fa225cbcSrjs * It is not a hardware representation, though closely related. 106fa225cbcSrjs */ 107fa225cbcSrjsstruct i915_fs_operand { 108fa225cbcSrjs /**< REG_TYPE_* register type */ 109fa225cbcSrjs int reg; 110fa225cbcSrjs /**< *_CHANNEL_VAL swizzle value, with optional negation */ 111fa225cbcSrjs int x; 112fa225cbcSrjs /**< *_CHANNEL_VAL swizzle value, with optional negation */ 113fa225cbcSrjs int y; 114fa225cbcSrjs /**< *_CHANNEL_VAL swizzle value, with optional negation */ 115fa225cbcSrjs int z; 116fa225cbcSrjs /**< *_CHANNEL_VAL swizzle value, with optional negation */ 117fa225cbcSrjs int w; 118fa225cbcSrjs}; 119fa225cbcSrjs 120fa225cbcSrjs/** 121fa225cbcSrjs * Construct an operand description for the fragment shader. 122fa225cbcSrjs * 123fa225cbcSrjs * \param regtype FS_* register used as the source value for X/Y/Z/W sources. 124fa225cbcSrjs * \param x *_CHANNEL_VAL swizzle value prefix for operand X channel, with 125fa225cbcSrjs * optional negation. 126fa225cbcSrjs * \param y *_CHANNEL_VAL swizzle value prefix for operand Y channel, with 127fa225cbcSrjs * optional negation. 128fa225cbcSrjs * \param z *_CHANNEL_VAL swizzle value prefix for operand Z channel, with 129fa225cbcSrjs * optional negation. 130fa225cbcSrjs * \param w *_CHANNEL_VAL swizzle value prefix for operand W channel, with 131fa225cbcSrjs * optional negation. 132fa225cbcSrjs */ 133fa225cbcSrjs#define i915_fs_operand(reg, x, y, z, w) \ 134fa225cbcSrjs _i915_fs_operand(reg, \ 135fa225cbcSrjs x##_CHANNEL_VAL, y##_CHANNEL_VAL, \ 136fa225cbcSrjs z##_CHANNEL_VAL, w##_CHANNEL_VAL) 137fa225cbcSrjs 138fa225cbcSrjs/** 139fa225cbcSrjs * Construct an oeprand description for using a register with no swizzling 140fa225cbcSrjs */ 141fa225cbcSrjs#define i915_fs_operand_reg(reg) \ 142fa225cbcSrjs i915_fs_operand(reg, X, Y, Z, W) 143fa225cbcSrjs 144fa225cbcSrjsstatic inline struct i915_fs_operand 145fa225cbcSrjs_i915_fs_operand(int reg, int x, int y, int z, int w) 146fa225cbcSrjs{ 147fa225cbcSrjs struct i915_fs_operand operand; 148fa225cbcSrjs 149fa225cbcSrjs operand.reg = reg; 150fa225cbcSrjs operand.x = x; 151fa225cbcSrjs operand.y = y; 152fa225cbcSrjs operand.z = z; 153fa225cbcSrjs operand.w = w; 154fa225cbcSrjs 155fa225cbcSrjs return operand; 156fa225cbcSrjs} 157fa225cbcSrjs 158fa225cbcSrjs/** 159fa225cbcSrjs * Returns an operand containing (0.0, 0.0, 0.0, 0.0). 160fa225cbcSrjs */ 161fa225cbcSrjsstatic inline struct i915_fs_operand 162fa225cbcSrjsi915_fs_operand_zero(void) 163fa225cbcSrjs{ 164fa225cbcSrjs return i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO); 165fa225cbcSrjs} 166fa225cbcSrjs 167fa225cbcSrjs/** 168fa225cbcSrjs * Returns an unused operand 169fa225cbcSrjs */ 170fa225cbcSrjs#define i915_fs_operand_none() i915_fs_operand_zero() 171fa225cbcSrjs 172fa225cbcSrjs/** 173fa225cbcSrjs * Returns an operand containing (1.0, 1.0, 1.0, 1.0). 174fa225cbcSrjs */ 175fa225cbcSrjsstatic inline struct i915_fs_operand 176fa225cbcSrjsi915_fs_operand_one(void) 177fa225cbcSrjs{ 178fa225cbcSrjs return i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE); 179fa225cbcSrjs} 180fa225cbcSrjs 181fa225cbcSrjsstatic inline int 182fa225cbcSrjsi915_get_hardware_channel_val(int channel_val) 183fa225cbcSrjs{ 184fa225cbcSrjs if (channel_val < 0) 185fa225cbcSrjs channel_val = -channel_val; 186fa225cbcSrjs 187fa225cbcSrjs switch (channel_val) { 188fa225cbcSrjs case X_CHANNEL_VAL: 189fa225cbcSrjs return SRC_X; 190fa225cbcSrjs case Y_CHANNEL_VAL: 191fa225cbcSrjs return SRC_Y; 192fa225cbcSrjs case Z_CHANNEL_VAL: 193fa225cbcSrjs return SRC_Z; 194fa225cbcSrjs case W_CHANNEL_VAL: 195fa225cbcSrjs return SRC_W; 196fa225cbcSrjs case ZERO_CHANNEL_VAL: 197fa225cbcSrjs return SRC_ZERO; 198fa225cbcSrjs case ONE_CHANNEL_VAL: 199fa225cbcSrjs return SRC_ONE; 200fa225cbcSrjs } 201fa225cbcSrjs FatalError("Bad channel value %d\n", channel_val); 202fa225cbcSrjs} 203fa225cbcSrjs 204fa225cbcSrjs/** 205fa225cbcSrjs * Outputs a fragment shader command to declare a sampler or texture register. 206fa225cbcSrjs */ 207fa225cbcSrjs#define i915_fs_dcl(reg) \ 208fa225cbcSrjsdo { \ 209fa225cbcSrjs FS_OUT(_i915_fs_dcl(reg)); \ 210fa225cbcSrjs} while (0) 211fa225cbcSrjs 212fa225cbcSrjs/** 213fa225cbcSrjs * Constructs a fragment shader command to declare a sampler or texture 214fa225cbcSrjs * register. 215fa225cbcSrjs */ 216fa225cbcSrjsstatic inline struct i915_fs_op 217fa225cbcSrjs_i915_fs_dcl(int reg) 218fa225cbcSrjs{ 219fa225cbcSrjs struct i915_fs_op op; 220fa225cbcSrjs 221fa225cbcSrjs op.ui[0] = D0_DCL | (REG_TYPE(reg) << D0_TYPE_SHIFT) | 222fa225cbcSrjs (REG_NR(reg) << D0_NR_SHIFT); 223fa225cbcSrjs op.ui[1] = 0; 224fa225cbcSrjs op.ui[2] = 0; 225fa225cbcSrjs if (REG_TYPE(reg) != REG_TYPE_S) 226fa225cbcSrjs op.ui[0] |= D0_CHANNEL_ALL; 227fa225cbcSrjs 228fa225cbcSrjs return op; 229fa225cbcSrjs} 230fa225cbcSrjs 231fa225cbcSrjs/** 232fa225cbcSrjs * Constructs a fragment shader command to load from a texture sampler. 233fa225cbcSrjs */ 234fa225cbcSrjs#define i915_fs_texld(dest_reg, sampler_reg, address_reg) \ 235fa225cbcSrjsdo { \ 236fa225cbcSrjs FS_OUT(_i915_fs_texld(T0_TEXLD, dest_reg, sampler_reg, address_reg)); \ 237fa225cbcSrjs} while (0) 238fa225cbcSrjs 239fa225cbcSrjs#define i915_fs_texldp(dest_reg, sampler_reg, address_reg) \ 240fa225cbcSrjsdo { \ 241fa225cbcSrjs FS_OUT(_i915_fs_texld(T0_TEXLDP, dest_reg, sampler_reg, address_reg)); \ 242fa225cbcSrjs} while (0) 243fa225cbcSrjs 244fa225cbcSrjsstatic inline struct i915_fs_op 245fa225cbcSrjs_i915_fs_texld(int load_op, int dest_reg, int sampler_reg, int address_reg) 246fa225cbcSrjs{ 247fa225cbcSrjs struct i915_fs_op op; 248fa225cbcSrjs 249fa225cbcSrjs op.ui[0] = 0; 250fa225cbcSrjs op.ui[1] = 0; 251fa225cbcSrjs op.ui[2] = 0; 252fa225cbcSrjs 253fa225cbcSrjs if (REG_TYPE(sampler_reg) != REG_TYPE_S) 254fa225cbcSrjs FatalError("Bad sampler reg type\n"); 255fa225cbcSrjs 256fa225cbcSrjs op.ui[0] |= load_op; 257fa225cbcSrjs op.ui[0] |= REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT; 258fa225cbcSrjs op.ui[0] |= REG_NR(dest_reg) << T0_DEST_NR_SHIFT; 259fa225cbcSrjs op.ui[0] |= REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT; 260fa225cbcSrjs op.ui[1] |= REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT; 261fa225cbcSrjs op.ui[1] |= REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT; 262fa225cbcSrjs 263fa225cbcSrjs return op; 264fa225cbcSrjs} 265fa225cbcSrjs 266fa225cbcSrjs#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \ 267fa225cbcSrjs _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2) 268fa225cbcSrjs 269fa225cbcSrjsstatic inline struct i915_fs_op 270fa225cbcSrjs_i915_fs_arith(int cmd, int dest_reg, 271fa225cbcSrjs struct i915_fs_operand operand0, 272fa225cbcSrjs struct i915_fs_operand operand1, 273fa225cbcSrjs struct i915_fs_operand operand2) 274fa225cbcSrjs{ 275fa225cbcSrjs struct i915_fs_op op; 276fa225cbcSrjs 277fa225cbcSrjs op.ui[0] = 0; 278fa225cbcSrjs op.ui[1] = 0; 279fa225cbcSrjs op.ui[2] = 0; 280fa225cbcSrjs 281fa225cbcSrjs /* Set up destination register and write mask */ 282fa225cbcSrjs op.ui[0] |= cmd; 283fa225cbcSrjs op.ui[0] |= REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT; 284fa225cbcSrjs op.ui[0] |= REG_NR(dest_reg) << A0_DEST_NR_SHIFT; 285fa225cbcSrjs op.ui[0] |= A0_DEST_CHANNEL_ALL; 286fa225cbcSrjs 287fa225cbcSrjs /* Set up operand 0 */ 288fa225cbcSrjs op.ui[0] |= REG_TYPE(operand0.reg) << A0_SRC0_TYPE_SHIFT; 289fa225cbcSrjs op.ui[0] |= REG_NR(operand0.reg) << A0_SRC0_NR_SHIFT; 290fa225cbcSrjs 291fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand0.x) << 292fa225cbcSrjs A1_SRC0_CHANNEL_X_SHIFT; 293fa225cbcSrjs if (operand0.x < 0) 294fa225cbcSrjs op.ui[1] |= A1_SRC0_CHANNEL_X_NEGATE; 295fa225cbcSrjs 296fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand0.y) << 297fa225cbcSrjs A1_SRC0_CHANNEL_Y_SHIFT; 298fa225cbcSrjs if (operand0.y < 0) 299fa225cbcSrjs op.ui[1] |= A1_SRC0_CHANNEL_Y_NEGATE; 300fa225cbcSrjs 301fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand0.z) << 302fa225cbcSrjs A1_SRC0_CHANNEL_Z_SHIFT; 303fa225cbcSrjs if (operand0.z < 0) 304fa225cbcSrjs op.ui[1] |= A1_SRC0_CHANNEL_Z_NEGATE; 305fa225cbcSrjs 306fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand0.w) << 307fa225cbcSrjs A1_SRC0_CHANNEL_W_SHIFT; 308fa225cbcSrjs if (operand0.w < 0) 309fa225cbcSrjs op.ui[1] |= A1_SRC0_CHANNEL_W_NEGATE; 310fa225cbcSrjs 311fa225cbcSrjs /* Set up operand 1 */ 312fa225cbcSrjs op.ui[1] |= REG_TYPE(operand1.reg) << A1_SRC1_TYPE_SHIFT; 313fa225cbcSrjs op.ui[1] |= REG_NR(operand1.reg) << A1_SRC1_NR_SHIFT; 314fa225cbcSrjs 315fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand1.x) << 316fa225cbcSrjs A1_SRC1_CHANNEL_X_SHIFT; 317fa225cbcSrjs if (operand1.x < 0) 318fa225cbcSrjs op.ui[1] |= A1_SRC1_CHANNEL_X_NEGATE; 319fa225cbcSrjs 320fa225cbcSrjs op.ui[1] |= i915_get_hardware_channel_val(operand1.y) << 321fa225cbcSrjs A1_SRC1_CHANNEL_Y_SHIFT; 322fa225cbcSrjs if (operand1.y < 0) 323fa225cbcSrjs op.ui[1] |= A1_SRC1_CHANNEL_Y_NEGATE; 324fa225cbcSrjs 325fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand1.z) << 326fa225cbcSrjs A2_SRC1_CHANNEL_Z_SHIFT; 327fa225cbcSrjs if (operand1.z < 0) 328fa225cbcSrjs op.ui[2] |= A2_SRC1_CHANNEL_Z_NEGATE; 329fa225cbcSrjs 330fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand1.w) << 331fa225cbcSrjs A2_SRC1_CHANNEL_W_SHIFT; 332fa225cbcSrjs if (operand1.w < 0) 333fa225cbcSrjs op.ui[2] |= A2_SRC1_CHANNEL_W_NEGATE; 334fa225cbcSrjs 335fa225cbcSrjs /* Set up operand 2 */ 336fa225cbcSrjs op.ui[2] |= REG_TYPE(operand2.reg) << A2_SRC2_TYPE_SHIFT; 337fa225cbcSrjs op.ui[2] |= REG_NR(operand2.reg) << A2_SRC2_NR_SHIFT; 338fa225cbcSrjs 339fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand2.x) << 340fa225cbcSrjs A2_SRC2_CHANNEL_X_SHIFT; 341fa225cbcSrjs if (operand2.x < 0) 342fa225cbcSrjs op.ui[2] |= A2_SRC2_CHANNEL_X_NEGATE; 343fa225cbcSrjs 344fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand2.y) << 345fa225cbcSrjs A2_SRC2_CHANNEL_Y_SHIFT; 346fa225cbcSrjs if (operand2.y < 0) 347fa225cbcSrjs op.ui[2] |= A2_SRC2_CHANNEL_Y_NEGATE; 348fa225cbcSrjs 349fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand2.z) << 350fa225cbcSrjs A2_SRC2_CHANNEL_Z_SHIFT; 351fa225cbcSrjs if (operand2.z < 0) 352fa225cbcSrjs op.ui[2] |= A2_SRC2_CHANNEL_Z_NEGATE; 353fa225cbcSrjs 354fa225cbcSrjs op.ui[2] |= i915_get_hardware_channel_val(operand2.w) << 355fa225cbcSrjs A2_SRC2_CHANNEL_W_SHIFT; 356fa225cbcSrjs if (operand2.w < 0) 357fa225cbcSrjs op.ui[2] |= A2_SRC2_CHANNEL_W_NEGATE; 358fa225cbcSrjs 359fa225cbcSrjs return op; 360fa225cbcSrjs} 361fa225cbcSrjs 362fa225cbcSrjs/** Move operand0 to dest_reg */ 363fa225cbcSrjs#define i915_fs_mov(dest_reg, operand0) \ 364fa225cbcSrjsdo { \ 365fa225cbcSrjs FS_OUT(i915_fs_arith(MOV, dest_reg, operand0, \ 366fa225cbcSrjs i915_fs_operand_none(), \ 367fa225cbcSrjs i915_fs_operand_none())); \ 368fa225cbcSrjs} while (0) 369fa225cbcSrjs 370fa225cbcSrjs/** 371fa225cbcSrjs * Move the value in operand0 to the dest reg with the masking/saturation 372fa225cbcSrjs * specified. 373fa225cbcSrjs */ 374fa225cbcSrjs#define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \ 375fa225cbcSrjsdo { \ 376fa225cbcSrjs struct i915_fs_op op; \ 377fa225cbcSrjs \ 378fa225cbcSrjs op = i915_fs_arith(MOV, dest_reg, operand0, i915_fs_operand_none(), \ 379fa225cbcSrjs i915_fs_operand_none()); \ 380fa225cbcSrjs op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ 381fa225cbcSrjs op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ 382fa225cbcSrjs if ((dest_mask) & MASK_SATURATE) \ 383fa225cbcSrjs op.ui[0] |= A0_DEST_SATURATE; \ 384fa225cbcSrjs \ 385fa225cbcSrjs FS_OUT(op); \ 386fa225cbcSrjs} while (0) 387fa225cbcSrjs 388fa225cbcSrjs/** Add operand0 and operand1 and put the result in dest_reg */ 389fa225cbcSrjs#define i915_fs_add(dest_reg, operand0, operand1) \ 390fa225cbcSrjsdo { \ 391fa225cbcSrjs FS_OUT(i915_fs_arith(ADD, dest_reg, operand0, operand1, \ 392fa225cbcSrjs i915_fs_operand_none())); \ 393fa225cbcSrjs} while (0) 394fa225cbcSrjs 395fa225cbcSrjs/** Add operand0 and operand1 and put the result in dest_reg */ 396fa225cbcSrjs#define i915_fs_mul(dest_reg, operand0, operand1) \ 397fa225cbcSrjsdo { \ 398fa225cbcSrjs FS_OUT(i915_fs_arith(MUL, dest_reg, operand0, operand1, \ 399fa225cbcSrjs i915_fs_operand_none())); \ 400fa225cbcSrjs} while (0) 401fa225cbcSrjs 402fa225cbcSrjs/** 403fa225cbcSrjs * Perform a 3-component dot-product of operand0 and operand1 and put the 404fa225cbcSrjs * resulting scalar in the channels of dest_reg specified by the dest_mask. 405fa225cbcSrjs */ 406fa225cbcSrjs#define i915_fs_dp3_masked(dest_reg, dest_mask, operand0, operand1) \ 407fa225cbcSrjsdo { \ 408fa225cbcSrjs struct i915_fs_op op; \ 409fa225cbcSrjs \ 410fa225cbcSrjs op = i915_fs_arith(DP3, dest_reg, operand0, operand1, \ 411fa225cbcSrjs i915_fs_operand_none()); \ 412fa225cbcSrjs op.ui[0] &= ~A0_DEST_CHANNEL_ALL; \ 413fa225cbcSrjs op.ui[0] |= ((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT; \ 414fa225cbcSrjs if ((dest_mask) & MASK_SATURATE) \ 415fa225cbcSrjs op.ui[0] |= A0_DEST_SATURATE; \ 416fa225cbcSrjs \ 417fa225cbcSrjs FS_OUT(op); \ 418fa225cbcSrjs} while (0) 419fa225cbcSrjs 420fa225cbcSrjs/** 421fa225cbcSrjs * Sets up local state for accumulating a fragment shader buffer. 422fa225cbcSrjs * 423fa225cbcSrjs * \param x maximum number of shader commands that may be used between 424fa225cbcSrjs * a FS_START and FS_END 425fa225cbcSrjs */ 426fa225cbcSrjs#define FS_LOCALS(x) \ 427fa225cbcSrjs uint32_t _shader_buf[(x) * 3]; \ 428fa225cbcSrjs int _max_shader_commands = x; \ 429fa225cbcSrjs int _cur_shader_commands 430fa225cbcSrjs 431fa225cbcSrjs#define FS_BEGIN() \ 432fa225cbcSrjsdo { \ 433fa225cbcSrjs _cur_shader_commands = 0; \ 434fa225cbcSrjs} while (0) 435fa225cbcSrjs 436fa225cbcSrjs#define FS_OUT(_shaderop) \ 437fa225cbcSrjsdo { \ 438fa225cbcSrjs _shader_buf[_cur_shader_commands * 3 + 0] = _shaderop.ui[0]; \ 439fa225cbcSrjs _shader_buf[_cur_shader_commands * 3 + 1] = _shaderop.ui[1]; \ 440fa225cbcSrjs _shader_buf[_cur_shader_commands * 3 + 2] = _shaderop.ui[2]; \ 441fa225cbcSrjs if (++_cur_shader_commands > _max_shader_commands) \ 442fa225cbcSrjs FatalError("fragment shader command buffer exceeded (%d)\n", \ 443fa225cbcSrjs _cur_shader_commands); \ 444fa225cbcSrjs} while (0) 445fa225cbcSrjs 446fa225cbcSrjs#define FS_END() \ 447fa225cbcSrjsdo { \ 448fa225cbcSrjs int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1; \ 449fa225cbcSrjs BEGIN_BATCH(_cur_shader_commands * 3 + 1 + _pad); \ 450fa225cbcSrjs OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM | \ 451fa225cbcSrjs (_cur_shader_commands * 3 - 1)); \ 452fa225cbcSrjs for (_i = 0; _i < _cur_shader_commands * 3; _i++) \ 453fa225cbcSrjs OUT_BATCH(_shader_buf[_i]); \ 454fa225cbcSrjs if (_pad != 0) \ 455fa225cbcSrjs OUT_BATCH(MI_NOOP); \ 456fa225cbcSrjs ADVANCE_BATCH(); \ 457fa225cbcSrjs} while (0); 458