/** * Point size attenuation computation. */ static void build_atten_pointsize( struct tnl_program *p ) { struct ureg eye = get_eye_position_z(p); struct ureg state_size = register_param1(p, STATE_POINT_SIZE); struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION); struct ureg out = register_output(p, VERT_RESULT_PSIZ); struct ureg ut = get_temp(p); /* dist = |eyez| */ emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z)); /* p1 + dist * (p2 + dist * p3); */ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y), swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y)); emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y), ut, swizzle1(state_attenuation, X)); /* 1 / sqrt(factor) */ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut ); #if 0 /* out = pointSize / sqrt(factor) */ emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size); #else /* this is a good place to clamp the point size since there's likely * no hardware registers to clamp point size at rasterization time. */ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size); emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y)); emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z)); #endif release_temp(p, ut); }
/* Seems like it could be tighter: */ static void build_pointsize( struct tnl_program *p ) { struct ureg eye = get_eye_position(p); struct ureg state_size = register_param1(p, STATE_POINT_SIZE); struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION); struct ureg out = register_output(p, VERT_RESULT_PSIZ); struct ureg ut = get_temp(p); /* 1, Z, Z * Z, 1 */ emit_op1(p, OPCODE_MOV, ut, WRITEMASK_XW, swizzle1(get_identity_param(p), W)); emit_op1(p, OPCODE_ABS, ut, WRITEMASK_YZ, swizzle1(eye, Z)); emit_op2(p, OPCODE_MUL, ut, WRITEMASK_Z, ut, ut); /* p1 + p2 * dist + p3 * dist * dist, 0 */ emit_op2(p, OPCODE_DP3, ut, WRITEMASK_X, ut, state_attenuation); /* 1 / sqrt(factor) */ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut ); /* ut = pointSize / factor */ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size); /* Clamp to min/max - state_size.[yz] */ emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y)); emit_op2(p, OPCODE_MIN, out, 0, swizzle1(ut, X), swizzle1(state_size, Z)); release_temp(p, ut); }
static void build_pointsize( struct tnl_program *p ) { struct ureg eye = get_eye_position(p); struct ureg state_size = register_param1(p, STATE_POINT_SIZE); struct ureg state_attenuation = register_param1(p, STATE_POINT_ATTENUATION); struct ureg out = register_output(p, VERT_RESULT_PSIZ); struct ureg ut = get_temp(p); /* dist = |eyez| */ emit_op1(p, OPCODE_ABS, ut, WRITEMASK_Y, swizzle1(eye, Z)); /* p1 + dist * (p2 + dist * p3); */ emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y), swizzle1(state_attenuation, Z), swizzle1(state_attenuation, Y)); emit_op3(p, OPCODE_MAD, ut, WRITEMASK_X, swizzle1(ut, Y), ut, swizzle1(state_attenuation, X)); /* 1 / sqrt(factor) */ emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut ); #if 1 /* out = pointSize / sqrt(factor) */ emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size); #else /* not sure, might make sense to do clamping here, but it's not done in t_vb_points neither */ emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size); emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y)); emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z)); #endif release_temp(p, ut); }
static void emit_normalize_vec3( struct tnl_program *p, struct ureg dest, struct ureg src ) { emit_op2(p, OPCODE_DP3, dest, WRITEMASK_W, src, src); emit_op1(p, OPCODE_RSQ, dest, WRITEMASK_W, swizzle1(dest,W)); emit_op2(p, OPCODE_MUL, dest, WRITEMASK_XYZ, src, swizzle1(dest,W)); }
static void emit_matrix_transform_vec3( struct tnl_program *p, struct ureg dest, const struct ureg *mat, struct ureg src) { emit_op2(p, OPCODE_DP3, dest, WRITEMASK_X, src, mat[0]); emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Y, src, mat[1]); emit_op2(p, OPCODE_DP3, dest, WRITEMASK_Z, src, mat[2]); }
static void build_fog( struct tnl_program *p ) { struct ureg fog = register_output(p, VERT_RESULT_FOGC); struct ureg input; GLuint useabs = p->state->fog_source_is_depth && p->state->fog_option && (p->state->fog_option != FOG_EXP2); if (p->state->fog_source_is_depth) { input = swizzle1(get_eye_position(p), Z); } else { input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X); } if (p->state->fog_option && p->state->tnl_do_vertex_fog) { struct ureg params = register_param2(p, STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED); struct ureg tmp = get_temp(p); struct ureg id = get_identity_param(p); emit_op1(p, OPCODE_MOV, fog, 0, id); if (useabs) { emit_op1(p, OPCODE_ABS, tmp, 0, input); } switch (p->state->fog_option) { case FOG_LINEAR: { emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input, swizzle1(params,X), swizzle1(params,Y)); emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */ emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W)); break; } case FOG_EXP: emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input, swizzle1(params,Z)); emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, ureg_negate(tmp)); break; case FOG_EXP2: emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W)); emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, ureg_negate(tmp)); break; } release_temp(p, tmp); } else { /* results = incoming fog coords (compute fog per-fragment later) * * KW: Is it really necessary to do anything in this case? */ emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, 0, input); } }
static void build_fog( struct tnl_program *p ) { struct ureg fog = register_output(p, VERT_RESULT_FOGC); struct ureg input; if (p->state->fog_source_is_depth) { input = swizzle1(get_eye_position(p), Z); } else { input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X); } if (p->state->fog_mode && p->state->tnl_do_vertex_fog) { struct ureg params = register_param2(p, STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED); struct ureg tmp = get_temp(p); GLboolean useabs = (p->state->fog_mode != FOG_EXP2); if (useabs) { emit_op1(p, OPCODE_ABS, tmp, 0, input); } switch (p->state->fog_mode) { case FOG_LINEAR: { struct ureg id = get_identity_param(p); emit_op3(p, OPCODE_MAD, tmp, 0, useabs ? tmp : input, swizzle1(params,X), swizzle1(params,Y)); emit_op2(p, OPCODE_MAX, tmp, 0, tmp, swizzle1(id,X)); /* saturate */ emit_op2(p, OPCODE_MIN, fog, WRITEMASK_X, tmp, swizzle1(id,W)); break; } case FOG_EXP: emit_op2(p, OPCODE_MUL, tmp, 0, useabs ? tmp : input, swizzle1(params,Z)); emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp)); break; case FOG_EXP2: emit_op2(p, OPCODE_MUL, tmp, 0, input, swizzle1(params,W)); emit_op2(p, OPCODE_MUL, tmp, 0, tmp, tmp); emit_op1(p, OPCODE_EX2, fog, WRITEMASK_X, negate(tmp)); break; } release_temp(p, tmp); } else { /* results = incoming fog coords (compute fog per-fragment later) * * KW: Is it really necessary to do anything in this case? * BP: Yes, we always need to compute the absolute value, unless * we want to push that down into the fragment program... */ GLboolean useabs = GL_TRUE; emit_op1(p, useabs ? OPCODE_ABS : OPCODE_MOV, fog, WRITEMASK_X, input); } }
static void emit_normalize_vec3( struct tnl_program *p, struct ureg dest, struct ureg src ) { struct ureg tmp = get_temp(p); emit_op2(p, OPCODE_DP3, tmp, WRITEMASK_X, src, src); emit_op1(p, OPCODE_RSQ, tmp, WRITEMASK_X, tmp); emit_op2(p, OPCODE_MUL, dest, 0, src, swizzle1(tmp, X)); release_temp(p, tmp); }
static void emit_normalize_vec3( struct tnl_program *p, struct ureg dest, struct ureg src ) { #if 0 /* XXX use this when drivers are ready for NRM3 */ emit_op1(p, OPCODE_NRM3, dest, WRITEMASK_XYZ, src); #else struct ureg tmp = get_temp(p); emit_op2(p, OPCODE_DP3, tmp, WRITEMASK_X, src, src); emit_op1(p, OPCODE_RSQ, tmp, WRITEMASK_X, tmp); emit_op2(p, OPCODE_MUL, dest, 0, src, swizzle1(tmp, X)); release_temp(p, tmp); #endif }
static struct ureg get_eye_normal( struct tnl_program *p ) { if (is_undef(p->eye_normal)) { struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL ); struct ureg mvinv[3]; register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2, STATE_MATRIX_INVTRANS, mvinv ); p->eye_normal = reserve_temp(p); /* Transform to eye space: */ emit_matrix_transform_vec3( p, p->eye_normal, mvinv, normal ); /* Normalize/Rescale: */ if (p->state->normalize) { emit_normalize_vec3( p, p->eye_normal, p->eye_normal ); } else if (p->state->rescale_normals) { struct ureg rescale = register_param2(p, STATE_INTERNAL, STATE_NORMAL_SCALE); emit_op2( p, OPCODE_MUL, p->eye_normal, 0, p->eye_normal, swizzle1(rescale, X)); } } return p->eye_normal; }
static void build_fog( struct tnl_program *p ) { struct ureg fog = register_output(p, VARYING_SLOT_FOGC); struct ureg input; if (p->state->fog_source_is_depth) { switch (p->state->fog_distance_mode) { case FDM_EYE_RADIAL: /* Z = sqrt(Xe*Xe + Ye*Ye + Ze*Ze) */ input = get_eye_position(p); emit_op2(p, OPCODE_DP3, fog, WRITEMASK_X, input, input); emit_op1(p, OPCODE_RSQ, fog, WRITEMASK_X, fog); emit_op1(p, OPCODE_RCP, fog, WRITEMASK_X, fog); break; case FDM_EYE_PLANE: /* Z = Ze */ input = get_eye_position_z(p); emit_op1(p, OPCODE_MOV, fog, WRITEMASK_X, input); break; case FDM_EYE_PLANE_ABS: /* Z = abs(Ze) */ input = get_eye_position_z(p); emit_op1(p, OPCODE_ABS, fog, WRITEMASK_X, input); break; default: assert(0); break; /* can't happen */ } } else { input = swizzle1(register_input(p, VERT_ATTRIB_FOG), X); emit_op1(p, OPCODE_ABS, fog, WRITEMASK_X, input); } emit_op1(p, OPCODE_MOV, fog, WRITEMASK_YZW, get_identity_param(p)); }
static void build_reflect_texgen( struct tnl_program *p, struct ureg dest, GLuint writemask ) { struct ureg normal = get_transformed_normal(p); struct ureg eye_hat = get_eye_position_normalized(p); struct ureg tmp = get_temp(p); /* n.u */ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); /* 2n.u */ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); /* (-2n.u)n + u */ emit_op3(p, OPCODE_MAD, dest, writemask, negate(tmp), normal, eye_hat); release_temp(p, tmp); }
/** * Compute: * lit.y = MAX(0, dots.x) * lit.z = SLT(0, dots.x) */ static void emit_degenerate_lit( struct tnl_program *p, struct ureg lit, struct ureg dots ) { struct ureg id = get_identity_param(p); /* id = {0,0,0,1} */ /* Note that lit.x & lit.w will not be examined. Note also that * dots.xyzw == dots.xxxx. */ /* MAX lit, id, dots; */ emit_op2(p, OPCODE_MAX, lit, WRITEMASK_XYZW, id, dots); /* result[2] = (in > 0 ? 1 : 0) * SLT lit.z, id.z, dots; # lit.z = (0 < dots.z) ? 1 : 0 */ emit_op2(p, OPCODE_SLT, lit, WRITEMASK_Z, swizzle1(id,Z), dots); }
static struct ureg calculate_light_attenuation( struct tnl_program *p, GLuint i, struct ureg VPpli, struct ureg dist ) { struct ureg attenuation = register_param3(p, STATE_LIGHT, i, STATE_ATTENUATION); struct ureg att = undef; /* Calculate spot attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180) { struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL, STATE_LIGHT_SPOT_DIR_NORMALIZED, i); struct ureg spot = get_temp(p); struct ureg slt = get_temp(p); att = get_temp(p); emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm); emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot); emit_op1(p, OPCODE_ABS, spot, 0, spot); emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W)); emit_op2(p, OPCODE_MUL, att, 0, slt, spot); release_temp(p, spot); release_temp(p, slt); } /* Calculate distance attenuation(See formula (2.4) at glspec 2.1 page 62): * * Skip the calucation when _dist_ is undefined(light_eyepos3_is_zero) */ if (p->state->unit[i].light_attenuated && !is_undef(dist)) { if (is_undef(att)) att = get_temp(p); /* 1/d,d,d,1/d */ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist); /* 1,d,d*d,1/d */ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y)); /* 1/dist-atten */ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist); if (!p->state->unit[i].light_spotcutoff_is_180) { /* dist-atten */ emit_op1(p, OPCODE_RCP, dist, 0, dist); /* spot-atten * dist-atten */ emit_op2(p, OPCODE_MUL, att, 0, dist, att); } else { /* dist-atten */ emit_op1(p, OPCODE_RCP, att, 0, dist); } } return att; }
static void build_sphere_texgen( struct tnl_program *p, struct ureg dest, GLuint writemask ) { struct ureg normal = get_transformed_normal(p); struct ureg eye_hat = get_eye_position_normalized(p); struct ureg tmp = get_temp(p); struct ureg half = register_scalar_const(p, .5); struct ureg r = get_temp(p); struct ureg inv_m = get_temp(p); struct ureg id = get_identity_param(p); /* Could share the above calculations, but it would be * a fairly odd state for someone to set (both sphere and * reflection active for different texture coordinate * components. Of course - if two texture units enable * reflect and/or sphere, things start to tilt in favour * of seperating this out: */ /* n.u */ emit_op2(p, OPCODE_DP3, tmp, 0, normal, eye_hat); /* 2n.u */ emit_op2(p, OPCODE_ADD, tmp, 0, tmp, tmp); /* (-2n.u)n + u */ emit_op3(p, OPCODE_MAD, r, 0, negate(tmp), normal, eye_hat); /* r + 0,0,1 */ emit_op2(p, OPCODE_ADD, tmp, 0, r, swizzle(id,X,Y,W,Z)); /* rx^2 + ry^2 + (rz+1)^2 */ emit_op2(p, OPCODE_DP3, tmp, 0, tmp, tmp); /* 2/m */ emit_op1(p, OPCODE_RSQ, tmp, 0, tmp); /* 1/m */ emit_op2(p, OPCODE_MUL, inv_m, 0, tmp, half); /* r/m + 1/2 */ emit_op3(p, OPCODE_MAD, dest, writemask, r, inv_m, half); release_temp(p, tmp); release_temp(p, r); release_temp(p, inv_m); }
static struct ureg get_lightprod( struct tnl_program *p, GLuint light, GLuint side, GLuint property ) { GLuint attrib = material_attrib(side, property); if (p->materials & (1<<attrib)) { struct ureg light_value = register_param3(p, STATE_LIGHT, light, property); struct ureg material_value = get_material(p, side, property); struct ureg tmp = get_temp(p); emit_op2(p, OPCODE_MUL, tmp, 0, light_value, material_value); return tmp; } else return register_param4(p, STATE_LIGHTPROD, light, side, property); }
static struct ureg calculate_light_attenuation( struct tnl_program *p, GLuint i, struct ureg VPpli, struct ureg dist ) { struct ureg attenuation = register_param3(p, STATE_LIGHT, i, STATE_ATTENUATION); struct ureg att = get_temp(p); /* Calculate spot attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180) { struct ureg spot_dir_norm = register_param3(p, STATE_INTERNAL, STATE_LIGHT_SPOT_DIR_NORMALIZED, i); struct ureg spot = get_temp(p); struct ureg slt = get_temp(p); emit_op2(p, OPCODE_DP3, spot, 0, negate(VPpli), spot_dir_norm); emit_op2(p, OPCODE_SLT, slt, 0, swizzle1(spot_dir_norm,W), spot); emit_op2(p, OPCODE_POW, spot, 0, spot, swizzle1(attenuation, W)); emit_op2(p, OPCODE_MUL, att, 0, slt, spot); release_temp(p, spot); release_temp(p, slt); } /* Calculate distance attenuation: */ if (p->state->unit[i].light_attenuated) { /* 1/d,d,d,1/d */ emit_op1(p, OPCODE_RCP, dist, WRITEMASK_YZ, dist); /* 1,d,d*d,1/d */ emit_op2(p, OPCODE_MUL, dist, WRITEMASK_XZ, dist, swizzle1(dist,Y)); /* 1/dist-atten */ emit_op2(p, OPCODE_DP3, dist, 0, attenuation, dist); if (!p->state->unit[i].light_spotcutoff_is_180) { /* dist-atten */ emit_op1(p, OPCODE_RCP, dist, 0, dist); /* spot-atten * dist-atten */ emit_op2(p, OPCODE_MUL, att, 0, dist, att); } else { /* dist-atten */ emit_op1(p, OPCODE_RCP, att, 0, dist); } } return att; }
static struct ureg get_transformed_normal( struct tnl_program *p ) { if (is_undef(p->transformed_normal) && !p->state->need_eye_coords && !p->state->normalize && !(p->state->need_eye_coords == p->state->rescale_normals)) { p->transformed_normal = register_input(p, VERT_ATTRIB_NORMAL ); } else if (is_undef(p->transformed_normal)) { struct ureg normal = register_input(p, VERT_ATTRIB_NORMAL ); struct ureg mvinv[3]; struct ureg transformed_normal = reserve_temp(p); if (p->state->need_eye_coords) { register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 2, STATE_MATRIX_INVTRANS, mvinv ); /* Transform to eye space: */ emit_matrix_transform_vec3( p, transformed_normal, mvinv, normal ); normal = transformed_normal; } /* Normalize/Rescale: */ if (p->state->normalize) { emit_normalize_vec3( p, transformed_normal, normal ); normal = transformed_normal; } else if (p->state->need_eye_coords == p->state->rescale_normals) { /* This is already adjusted for eye/non-eye rendering: */ struct ureg rescale = register_param2(p, STATE_INTERNAL, STATE_NORMAL_SCALE); emit_op2( p, OPCODE_MUL, transformed_normal, 0, normal, rescale ); normal = transformed_normal; } assert(normal.file == PROGRAM_TEMPORARY); p->transformed_normal = normal; } return p->transformed_normal; }
static struct ureg get_eye_position_z( struct tnl_program *p ) { if (!is_undef(p->eye_position)) return swizzle1(p->eye_position, Z); if (is_undef(p->eye_position_z)) { struct ureg pos = register_input( p, VERT_ATTRIB_POS ); struct ureg modelview[4]; p->eye_position_z = reserve_temp(p); register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3, 0, modelview ); emit_op2(p, OPCODE_DP4, p->eye_position_z, 0, pos, modelview[2]); } return p->eye_position_z; }
/** * Emit code for TXP. */ static void precalc_txp( struct brw_wm_compile *c, struct brw_fp_dst dst, unsigned target, unsigned unit, struct brw_fp_src src0, struct brw_fp_src sampler ) { if (projtex(c, target, src0)) { struct brw_fp_dst tmp = get_temp(c); /* tmp0.w = RCP inst.arg[0][3] */ emit_op1(c, TGSI_OPCODE_RCP, dst_mask(tmp, BRW_WRITEMASK_W), src_scalar(src0, W)); /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww */ emit_op2(c, TGSI_OPCODE_MUL, dst_mask(tmp, BRW_WRITEMASK_XYZ), src0, src_scalar(src_reg_from_dst(tmp), W)); /* dst = TEX tmp0 */ precalc_tex(c, dst, target, unit, src_reg_from_dst(tmp), sampler ); release_temp(c, tmp); } else { /* dst = TEX src0 */ precalc_tex(c, dst, target, unit, src0, sampler); } }
static struct ureg get_eye_z( struct tnl_program *p ) { if (!is_undef(p->eye_position)) { return swizzle1(p->eye_position, Z); } else if (!is_undef(p->eye_z)) { struct ureg pos = register_input( p, BRW_ATTRIB_POS ); struct ureg modelview2; p->eye_z = reserve_temp(p); register_matrix_param6( p, STATE_MATRIX, STATE_MODELVIEW, 0, 2, 1, STATE_MATRIX, &modelview2 ); emit_matrix_transform_vec4(p, p->eye_position, modelview, pos); emit_op2(p, OPCODE_DP4, p->eye_z, WRITEMASK_Z, pos, modelview2); } return swizzle1(p->eye_z, Z) }
/* This version is much easier to implement if writemasks are not * supported natively on the target or (like SSE), the target doesn't * have a clean/obvious dotproduct implementation. */ static void emit_transpose_matrix_transform_vec4( struct tnl_program *p, struct ureg dest, const struct ureg *mat, struct ureg src) { struct ureg tmp; if (dest.file != PROGRAM_TEMPORARY) tmp = get_temp(p); else tmp = dest; emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]); emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp); emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp); emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp); if (dest.file != PROGRAM_TEMPORARY) release_temp(p, tmp); }
/*********************************************************************** * Expand various instructions here to simpler forms. */ static void precalc_dst( struct brw_wm_compile *c, struct brw_fp_dst dst, struct brw_fp_src src0, struct brw_fp_src src1 ) { if (dst.writemask & BRW_WRITEMASK_Y) { /* dst.y = mul src0.y, src1.y */ emit_op2(c, TGSI_OPCODE_MUL, dst_mask(dst, BRW_WRITEMASK_Y), src0, src1); } if (dst.writemask & BRW_WRITEMASK_XZ) { /* dst.z = mov src0.zzzz */ emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_Z), src_scalar(src0, Z)); /* dst.x = imm1f(1.0) */ emit_op1(c, TGSI_OPCODE_MOV, dst_saturate(dst_mask(dst, BRW_WRITEMASK_X), 0), src_imm1f(c, 1.0)); } if (dst.writemask & BRW_WRITEMASK_W) { /* dst.w = mov src1.w */ emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_W), src1); } }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_eye_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, ureg_negate(swizzle1(shininess,X))); release_temp(p, shininess); _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ /* KW: changed to do this always - v1.17 "Fix lighting alpha result"? */ if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } } if (separate && (p->state->fragprog_inputs_read & FRAG_BIT_COL1)) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); if (twoside) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_LIGHT, i, STATE_POSITION_NORMALIZED); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_LIGHT, i, STATE_HALF_VECTOR); } } else { struct ureg Ppli = register_param3(p, STATE_LIGHT, i, STATE_POSITION); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); half = get_temp(p); /* Calulate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); release_temp(p, dist); } /* Calculate dot products: */ emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, dots); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_COL0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_COL0 ); } } emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; emit_op1(p, OPCODE_LIT, lit, 0, ureg_negate(swizzle(dots,X,Y,W,Z))); if (!is_undef(att)) emit_op2(p, OPCODE_MUL, lit, 0, lit, att); mask0 = 0; mask1 = 0; res0 = _bfc0; res1 = _bfc1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res0 = register_output( p, VERT_RESULT_BFC0 ); if (p->state->fragprog_inputs_read & FRAG_BIT_COL1) res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask1 = WRITEMASK_XYZ; if (p->state->fragprog_inputs_read & FRAG_BIT_COL0) res1 = register_output( p, VERT_RESULT_BFC0 ); } } emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
static void emit_insn( struct brw_wm_compile *c, const struct tgsi_full_instruction *inst ) { unsigned opcode = inst->Instruction.Opcode; struct brw_fp_dst dst; struct brw_fp_src src[3]; int i; dst = translate_dst( c, &inst->Dst[0], inst->Instruction.Saturate ); for (i = 0; i < inst->Instruction.NumSrcRegs; i++) src[i] = translate_src( c, &inst->Src[i] ); switch (opcode) { case TGSI_OPCODE_ABS: emit_op1(c, TGSI_OPCODE_MOV, dst, src_abs(src[0])); break; case TGSI_OPCODE_SUB: emit_op2(c, TGSI_OPCODE_ADD, dst, src[0], src_negate(src[1])); break; case TGSI_OPCODE_SCS: emit_op1(c, TGSI_OPCODE_SCS, dst_mask(dst, BRW_WRITEMASK_XY), src[0]); break; case TGSI_OPCODE_DST: precalc_dst(c, dst, src[0], src[1]); break; case TGSI_OPCODE_LIT: precalc_lit(c, dst, src[0]); break; case TGSI_OPCODE_TEX: precalc_tex(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx */ src[0], /* coord */ src[1]); /* sampler */ break; case TGSI_OPCODE_TXP: precalc_txp(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx */ src[0], /* coord */ src[1]); /* sampler */ break; case TGSI_OPCODE_TXB: /* XXX: TXB not done */ precalc_tex(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx*/ src[0], src[1]); break; case TGSI_OPCODE_XPD: emit_op2(c, TGSI_OPCODE_XPD, dst_mask(dst, BRW_WRITEMASK_XYZ), src[0], src[1]); break; case TGSI_OPCODE_KIL: emit_op1(c, TGSI_OPCODE_KIL, dst_mask(dst_undef(), 0), src[0]); break; case TGSI_OPCODE_END: emit_fb_write(c); break; default: if (!c->key.has_flow_control && brw_wm_is_scalar_result(opcode)) emit_scalar_insn(c, opcode, dst, src[0], src[1], src[2]); else emit_op3(c, opcode, dst, src[0], src[1], src[2]); break; } }
static void build_texture_transform( struct tnl_program *p ) { GLuint i, j; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (!(p->state->fragprog_inputs_read & FRAG_BIT_TEX(i))) continue; if (p->state->unit[i].texgen_enabled || p->state->unit[i].texmat_enabled) { GLuint texmat_enabled = p->state->unit[i].texmat_enabled; struct ureg out = register_output(p, VERT_RESULT_TEX0 + i); struct ureg out_texgen = undef; if (p->state->unit[i].texgen_enabled) { GLuint copy_mask = 0; GLuint sphere_mask = 0; GLuint reflect_mask = 0; GLuint normal_mask = 0; GLuint modes[4]; if (texmat_enabled) out_texgen = get_temp(p); else out_texgen = out; modes[0] = p->state->unit[i].texgen_mode0; modes[1] = p->state->unit[i].texgen_mode1; modes[2] = p->state->unit[i].texgen_mode2; modes[3] = p->state->unit[i].texgen_mode3; for (j = 0; j < 4; j++) { switch (modes[j]) { case TXG_OBJ_LINEAR: { struct ureg obj = register_input(p, VERT_ATTRIB_POS); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_OBJECT_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, obj, plane ); break; } case TXG_EYE_LINEAR: { struct ureg eye = get_eye_position(p); struct ureg plane = register_param3(p, STATE_TEXGEN, i, STATE_TEXGEN_EYE_S + j); emit_op2(p, OPCODE_DP4, out_texgen, WRITEMASK_X << j, eye, plane ); break; } case TXG_SPHERE_MAP: sphere_mask |= WRITEMASK_X << j; break; case TXG_REFLECTION_MAP: reflect_mask |= WRITEMASK_X << j; break; case TXG_NORMAL_MAP: normal_mask |= WRITEMASK_X << j; break; case TXG_NONE: copy_mask |= WRITEMASK_X << j; } } if (sphere_mask) { build_sphere_texgen(p, out_texgen, sphere_mask); } if (reflect_mask) { build_reflect_texgen(p, out_texgen, reflect_mask); } if (normal_mask) { struct ureg normal = get_transformed_normal(p); emit_op1(p, OPCODE_MOV, out_texgen, normal_mask, normal ); } if (copy_mask) { struct ureg in = register_input(p, VERT_ATTRIB_TEX0+i); emit_op1(p, OPCODE_MOV, out_texgen, copy_mask, in ); } } if (texmat_enabled) { struct ureg texmat[4]; struct ureg in = (!is_undef(out_texgen) ? out_texgen : register_input(p, VERT_ATTRIB_TEX0+i)); if (p->mvp_with_dp4) { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, 0, texmat ); emit_matrix_transform_vec4( p, out, texmat, in ); } else { register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3, STATE_MATRIX_TRANSPOSE, texmat ); emit_transpose_matrix_transform_vec4( p, out, texmat, in ); } } release_temps(p); } else { emit_passthrough(p, VERT_ATTRIB_TEX0+i, VERT_RESULT_TEX0+i); } } }
static void emit_interp( struct brw_wm_compile *c, GLuint idx, GLuint semantic, GLuint interp_mode ) { struct brw_fp_dst dst = dst_reg(TGSI_FILE_INPUT, idx); struct brw_fp_src interp = src_reg(BRW_FILE_PAYLOAD, idx); struct brw_fp_src deltas = get_delta_xy(c); /* Need to use PINTERP on attributes which have been * multiplied by 1/W in the SF program, and LINTERP on those * which have not: */ switch (semantic) { case TGSI_SEMANTIC_POSITION: /* Have to treat wpos.xy specially: */ emit_op1(c, WM_WPOSXY, dst_mask(dst, BRW_WRITEMASK_XY), get_pixel_xy(c)); /* TGSI_FILE_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw */ emit_op2(c, WM_LINTERP, dst_mask(dst, BRW_WRITEMASK_ZW), interp, deltas); break; case TGSI_SEMANTIC_COLOR: if (c->key.flat_shade) { emit_op1(c, WM_CINTERP, dst, interp); } else if (interp_mode == TGSI_INTERPOLATE_LINEAR) { emit_op2(c, WM_LINTERP, dst, interp, deltas); } else { emit_op3(c, WM_PINTERP, dst, interp, deltas, get_pixel_w(c)); } break; case TGSI_SEMANTIC_FOG: /* Interpolate the fog coordinate */ emit_op3(c, WM_PINTERP, dst_mask(dst, BRW_WRITEMASK_X), interp, deltas, get_pixel_w(c)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_YZ), src_imm1f(c, 0.0)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_W), src_imm1f(c, 1.0)); break; case TGSI_SEMANTIC_FACE: /* XXX review/test this case */ emit_op0(c, WM_FRONTFACING, dst_mask(dst, BRW_WRITEMASK_X)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_YZ), src_imm1f(c, 0.0)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_W), src_imm1f(c, 1.0)); break; case TGSI_SEMANTIC_PSIZE: /* XXX review/test this case */ emit_op3(c, WM_PINTERP, dst_mask(dst, BRW_WRITEMASK_XY), interp, deltas, get_pixel_w(c)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_Z), src_imm1f(c, 0.0f)); emit_op1(c, TGSI_OPCODE_MOV, dst_mask(dst, BRW_WRITEMASK_W), src_imm1f(c, 1.0f)); break; default: switch (interp_mode) { case TGSI_INTERPOLATE_CONSTANT: emit_op1(c, WM_CINTERP, dst, interp); break; case TGSI_INTERPOLATE_LINEAR: emit_op2(c, WM_LINTERP, dst, interp, deltas); break; case TGSI_INTERPOLATE_PERSPECTIVE: emit_op3(c, WM_PINTERP, dst, interp, deltas, get_pixel_w(c)); break; } break; } }
/* Need to add some addtional parameters to allow lighting in object * space - STATE_SPOT_DIRECTION and STATE_HALF_VECTOR implicitly assume eye * space lighting. */ static void build_lighting( struct tnl_program *p ) { const GLboolean twoside = p->state->light_twoside; const GLboolean separate = p->state->separate_specular; GLuint nr_lights = 0, count = 0; struct ureg normal = get_transformed_normal(p); struct ureg lit = get_temp(p); struct ureg dots = get_temp(p); struct ureg _col0 = undef, _col1 = undef; struct ureg _bfc0 = undef, _bfc1 = undef; GLuint i; /* * NOTE: * dots.x = dot(normal, VPpli) * dots.y = dot(normal, halfAngle) * dots.z = back.shininess * dots.w = front.shininess */ for (i = 0; i < MAX_LIGHTS; i++) if (p->state->unit[i].light_enabled) nr_lights++; set_material_flags(p); { if (!p->state->material_shininess_is_zero) { struct ureg shininess = get_material(p, 0, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_W, swizzle1(shininess,X)); release_temp(p, shininess); } _col0 = make_temp(p, get_scenecolor(p, 0)); if (separate) _col1 = make_temp(p, get_identity_param(p)); else _col1 = _col0; } if (twoside) { if (!p->state->material_shininess_is_zero) { /* Note that we negate the back-face specular exponent here. * The negation will be un-done later in the back-face code below. */ struct ureg shininess = get_material(p, 1, STATE_SHININESS); emit_op1(p, OPCODE_MOV, dots, WRITEMASK_Z, negate(swizzle1(shininess,X))); release_temp(p, shininess); } _bfc0 = make_temp(p, get_scenecolor(p, 1)); if (separate) _bfc1 = make_temp(p, get_identity_param(p)); else _bfc1 = _bfc0; } /* If no lights, still need to emit the scenecolor. */ { struct ureg res0 = register_output( p, VERT_RESULT_COL0 ); emit_op1(p, OPCODE_MOV, res0, 0, _col0); } if (separate) { struct ureg res1 = register_output( p, VERT_RESULT_COL1 ); emit_op1(p, OPCODE_MOV, res1, 0, _col1); } if (twoside) { struct ureg res0 = register_output( p, VERT_RESULT_BFC0 ); emit_op1(p, OPCODE_MOV, res0, 0, _bfc0); } if (twoside && separate) { struct ureg res1 = register_output( p, VERT_RESULT_BFC1 ); emit_op1(p, OPCODE_MOV, res1, 0, _bfc1); } if (nr_lights == 0) { release_temps(p); return; } for (i = 0; i < MAX_LIGHTS; i++) { if (p->state->unit[i].light_enabled) { struct ureg half = undef; struct ureg att = undef, VPpli = undef; count++; if (p->state->unit[i].light_eyepos3_is_zero) { /* Can used precomputed constants in this case. * Attenuation never applies to infinite lights. */ VPpli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION_NORMALIZED, i); if (!p->state->material_shininess_is_zero) { if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); half = get_temp(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); emit_normalize_vec3(p, half, half); } else { half = register_param3(p, STATE_INTERNAL, STATE_LIGHT_HALF_VECTOR, i); } } } else { struct ureg Ppli = register_param3(p, STATE_INTERNAL, STATE_LIGHT_POSITION, i); struct ureg V = get_eye_position(p); struct ureg dist = get_temp(p); VPpli = get_temp(p); /* Calculate VPpli vector */ emit_op2(p, OPCODE_SUB, VPpli, 0, Ppli, V); /* Normalize VPpli. The dist value also used in * attenuation below. */ emit_op2(p, OPCODE_DP3, dist, 0, VPpli, VPpli); emit_op1(p, OPCODE_RSQ, dist, 0, dist); emit_op2(p, OPCODE_MUL, VPpli, 0, VPpli, dist); /* Calculate attenuation: */ if (!p->state->unit[i].light_spotcutoff_is_180 || p->state->unit[i].light_attenuated) { att = calculate_light_attenuation(p, i, VPpli, dist); } /* Calculate viewer direction, or use infinite viewer: */ if (!p->state->material_shininess_is_zero) { half = get_temp(p); if (p->state->light_local_viewer) { struct ureg eye_hat = get_eye_position_normalized(p); emit_op2(p, OPCODE_SUB, half, 0, VPpli, eye_hat); } else { struct ureg z_dir = swizzle(get_identity_param(p),X,Y,W,Z); emit_op2(p, OPCODE_ADD, half, 0, VPpli, z_dir); } emit_normalize_vec3(p, half, half); } release_temp(p, dist); } /* Calculate dot products: */ if (p->state->material_shininess_is_zero) { emit_op2(p, OPCODE_DP3, dots, 0, normal, VPpli); } else { emit_op2(p, OPCODE_DP3, dots, WRITEMASK_X, normal, VPpli); emit_op2(p, OPCODE_DP3, dots, WRITEMASK_Y, normal, half); } /* Front face lighting: */ { struct ureg ambient = get_lightprod(p, i, 0, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 0, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 0, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_COL0 ); res1 = register_output( p, VERT_RESULT_COL1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _col0; res1 = register_output( p, VERT_RESULT_COL0 ); } } else { mask0 = 0; mask1 = 0; res0 = _col0; res1 = _col1; } if (!is_undef(att)) { /* light is attenuated by distance */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _col0, 0, swizzle1(lit,X), ambient, _col0); } else if (!p->state->material_shininess_is_zero) { /* there's a non-zero specular term */ emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } else { /* no attenutation, no specular */ emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _col0, 0, ambient, _col0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _col0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _col1); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } /* Back face lighting: */ if (twoside) { struct ureg ambient = get_lightprod(p, i, 1, STATE_AMBIENT); struct ureg diffuse = get_lightprod(p, i, 1, STATE_DIFFUSE); struct ureg specular = get_lightprod(p, i, 1, STATE_SPECULAR); struct ureg res0, res1; GLuint mask0, mask1; if (count == nr_lights) { if (separate) { mask0 = WRITEMASK_XYZ; mask1 = WRITEMASK_XYZ; res0 = register_output( p, VERT_RESULT_BFC0 ); res1 = register_output( p, VERT_RESULT_BFC1 ); } else { mask0 = 0; mask1 = WRITEMASK_XYZ; res0 = _bfc0; res1 = register_output( p, VERT_RESULT_BFC0 ); } } else { res0 = _bfc0; res1 = _bfc1; mask0 = 0; mask1 = 0; } /* For the back face we need to negate the X and Y component * dot products. dots.Z has the negated back-face specular * exponent. We swizzle that into the W position. This * negation makes the back-face specular term positive again. */ dots = negate(swizzle(dots,X,Y,W,Z)); if (!is_undef(att)) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_MUL, lit, 0, lit, att); emit_op3(p, OPCODE_MAD, _bfc0, 0, swizzle1(lit,X), ambient, _bfc0); } else if (!p->state->material_shininess_is_zero) { emit_op1(p, OPCODE_LIT, lit, 0, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); /**/ } else { emit_degenerate_lit(p, lit, dots); emit_op2(p, OPCODE_ADD, _bfc0, 0, ambient, _bfc0); } emit_op3(p, OPCODE_MAD, res0, mask0, swizzle1(lit,Y), diffuse, _bfc0); emit_op3(p, OPCODE_MAD, res1, mask1, swizzle1(lit,Z), specular, _bfc1); /* restore dots to its original state for subsequent lights * by negating and swizzling again. */ dots = negate(swizzle(dots,X,Y,W,Z)); release_temp(p, ambient); release_temp(p, diffuse); release_temp(p, specular); } release_temp(p, half); release_temp(p, VPpli); release_temp(p, att); } } release_temps( p ); }
/** * Some TEX instructions require extra code, cube map coordinate * normalization, or coordinate scaling for RECT textures, etc. * This function emits those extra instructions and the TEX * instruction itself. */ static void precalc_tex( struct brw_wm_compile *c, struct brw_fp_dst dst, unsigned target, unsigned unit, struct brw_fp_src src0, struct brw_fp_src sampler ) { struct brw_fp_src coord; struct brw_fp_dst tmp = dst_undef(); assert(unit < BRW_MAX_TEX_UNIT); /* Cubemap: find longest component of coord vector and normalize * it. */ if (target == TGSI_TEXTURE_CUBE) { struct brw_fp_src tmpsrc; tmp = get_temp(c); tmpsrc = src_reg_from_dst(tmp); /* tmp = abs(src0) */ emit_op1(c, TGSI_OPCODE_MOV, tmp, src_abs(src0)); /* tmp.X = MAX(tmp.X, tmp.Y) */ emit_op2(c, TGSI_OPCODE_MAX, dst_mask(tmp, BRW_WRITEMASK_X), src_scalar(tmpsrc, X), src_scalar(tmpsrc, Y)); /* tmp.X = MAX(tmp.X, tmp.Z) */ emit_op2(c, TGSI_OPCODE_MAX, dst_mask(tmp, BRW_WRITEMASK_X), tmpsrc, src_scalar(tmpsrc, Z)); /* tmp.X = 1 / tmp.X */ emit_op1(c, TGSI_OPCODE_RCP, dst_mask(tmp, BRW_WRITEMASK_X), tmpsrc); /* tmp = src0 * tmp.xxxx */ emit_op2(c, TGSI_OPCODE_MUL, tmp, src0, src_scalar(tmpsrc, X)); coord = tmpsrc; } else if (target == TGSI_TEXTURE_RECT || target == TGSI_TEXTURE_SHADOWRECT) { /* XXX: need a mechanism for internally generated constants. */ coord = src0; } else { coord = src0; } /* Need to emit YUV texture conversions by hand. Probably need to * do this here - the alternative is in brw_wm_emit.c, but the * conversion requires allocating a temporary variable which we * don't have the facility to do that late in the compilation. */ if (c->key.yuvtex_mask & (1 << unit)) { /* convert ycbcr to RGBA */ GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit); struct brw_fp_dst tmp = get_temp(c); struct brw_fp_src tmpsrc = src_reg_from_dst(tmp); struct brw_fp_src C0 = src_imm4f( c, -.5, -.0625, -.5, 1.164 ); struct brw_fp_src C1 = src_imm4f( c, 1.596, -0.813, 2.018, -.391 ); /* tmp = TEX ... */ emit_tex_op(c, TGSI_OPCODE_TEX, dst_saturate(tmp, dst.saturate), unit, target, sampler.index, coord, src_undef(), src_undef()); /* tmp.xyz = ADD TMP, C0 */ emit_op2(c, TGSI_OPCODE_ADD, dst_mask(tmp, BRW_WRITEMASK_XYZ), tmpsrc, C0); /* YUV.y = MUL YUV.y, C0.w */ emit_op2(c, TGSI_OPCODE_MUL, dst_mask(tmp, BRW_WRITEMASK_Y), tmpsrc, src_scalar(C0, W)); /* * if (UV swaped) * RGB.xyz = MAD YUV.zzx, C1, YUV.y * else * RGB.xyz = MAD YUV.xxz, C1, YUV.y */ emit_op3(c, TGSI_OPCODE_MAD, dst_mask(dst, BRW_WRITEMASK_XYZ), ( swap_uv ? src_swizzle(tmpsrc, Z,Z,X,X) : src_swizzle(tmpsrc, X,X,Z,Z)), C1, src_scalar(tmpsrc, Y)); /* RGB.y = MAD YUV.z, C1.w, RGB.y */ emit_op3(c, TGSI_OPCODE_MAD, dst_mask(dst, BRW_WRITEMASK_Y), src_scalar(tmpsrc, Z), src_scalar(C1, W), src_scalar(src_reg_from_dst(dst), Y)); release_temp(c, tmp); } else { /* ordinary RGBA tex instruction */ emit_tex_op(c, TGSI_OPCODE_TEX, dst, unit, target, sampler.index, coord, src_undef(), src_undef()); } /* XXX: add GL_EXT_texture_swizzle support to gallium -- by * generating shader variants in mesa state tracker. */ /* Release this temp if we ended up allocating it: */ if (!dst_is_undef(tmp)) release_temp(c, tmp); }