#include "brw_sf.h"
-static struct brw_reg get_vert_attr(struct brw_sf_compile *c,
- struct brw_reg vert,
- GLuint attr)
+/**
+ * Determine the vue slot corresponding to the given half of the given register.
+ */
+static inline int vert_reg_to_vue_slot(struct brw_sf_compile *c, GLuint reg,
+ int half)
+{
+ return (reg + c->urb_entry_read_offset) * 2 + half;
+}
+
+/**
+ * Determine the varying corresponding to the given half of the given
+ * register. half=0 means the first half of a register, half=1 means the
+ * second half.
+ */
+static inline int vert_reg_to_varying(struct brw_sf_compile *c, GLuint reg,
+ int half)
{
- GLuint off = c->attr_to_idx[attr] / 2;
- GLuint sub = c->attr_to_idx[attr] % 2;
+ int vue_slot = vert_reg_to_vue_slot(c, reg, half);
+ return c->vue_map.slot_to_varying[vue_slot];
+}
+
+/**
+ * Determine the register corresponding to the given vue slot
+ */
+static struct brw_reg get_vue_slot(struct brw_sf_compile *c,
+ struct brw_reg vert,
+ int vue_slot)
+{
+ GLuint off = vue_slot / 2 - c->urb_entry_read_offset;
+ GLuint sub = vue_slot % 2;
return brw_vec4_grf(vert.nr + off, sub * 4);
}
-static GLboolean have_attr(struct brw_sf_compile *c,
- GLuint attr)
+/**
+ * Determine the register corresponding to the given varying.
+ */
+static struct brw_reg get_varying(struct brw_sf_compile *c,
+ struct brw_reg vert,
+ GLuint varying)
+{
+ int vue_slot = c->vue_map.varying_to_slot[varying];
+ assert (vue_slot >= c->urb_entry_read_offset);
+ return get_vue_slot(c, vert, vue_slot);
+}
+
+static bool
+have_attr(struct brw_sf_compile *c, GLuint attr)
{
- return (c->key.attrs & (1<<attr)) ? 1 : 0;
+ return (c->key.attrs & BITFIELD64_BIT(attr)) ? 1 : 0;
}
/***********************************************************************
GLuint i;
for (i = 0; i < 2; i++) {
- if (have_attr(c, VERT_RESULT_COL0+i) &&
- have_attr(c, VERT_RESULT_BFC0+i))
+ if (have_attr(c, VARYING_SLOT_COL0+i) &&
+ have_attr(c, VARYING_SLOT_BFC0+i))
brw_MOV(p,
- get_vert_attr(c, vert, VERT_RESULT_COL0+i),
- get_vert_attr(c, vert, VERT_RESULT_BFC0+i));
+ get_varying(c, vert, VARYING_SLOT_COL0+i),
+ get_varying(c, vert, VARYING_SLOT_BFC0+i));
}
}
static void do_twoside_color( struct brw_sf_compile *c )
{
struct brw_compile *p = &c->func;
- struct brw_instruction *if_insn;
GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;
/* Already done in clip program:
if (c->key.primitive == SF_UNFILLED_TRIS)
return;
- /* XXX: What happens if BFC isn't present? This could only happen
- * for user-supplied vertex programs, as t_vp_build.c always does
- * the right thing.
+ /* If the vertex shader provides backface color, do the selection. The VS
+ * promises to set up the front color if the backface color is provided, but
+ * it may contain junk if never written to.
*/
- if (!(have_attr(c, VERT_RESULT_COL0) && have_attr(c, VERT_RESULT_BFC0)) &&
- !(have_attr(c, VERT_RESULT_COL1) && have_attr(c, VERT_RESULT_BFC1)))
+ if (!(have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0)) &&
+ !(have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1)))
return;
-
+
/* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order
* to get all channels active inside the IF. In the clipping code
* we run with NoMask, so it's not an option and we can use
*/
brw_push_insn_state(p);
brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));
- if_insn = brw_IF(p, BRW_EXECUTE_4);
+ brw_IF(p, BRW_EXECUTE_4);
{
switch (c->nr_verts) {
case 3: copy_bfc(c, c->vert[2]);
case 1: copy_bfc(c, c->vert[0]);
}
}
- brw_ENDIF(p, if_insn);
+ brw_ENDIF(p);
brw_pop_insn_state(p);
}
* Flat shading
*/
-#define VERT_RESULT_COLOR_BITS ((1<<VERT_RESULT_COL0) | \
- (1<<VERT_RESULT_COL1))
-
-static void copy_colors( struct brw_sf_compile *c,
- struct brw_reg dst,
- struct brw_reg src)
+static void copy_flatshaded_attributes(struct brw_sf_compile *c,
+ struct brw_reg dst,
+ struct brw_reg src)
{
struct brw_compile *p = &c->func;
- GLuint i;
+ int i;
- for (i = VERT_RESULT_COL0; i <= VERT_RESULT_COL1; i++) {
- if (have_attr(c,i))
- brw_MOV(p,
- get_vert_attr(c, dst, i),
- get_vert_attr(c, src, i));
+ for (i = 0; i < c->vue_map.num_slots; i++) {
+ if (c->key.interpolation_mode.mode[i] == INTERP_QUALIFIER_FLAT) {
+ brw_MOV(p,
+ get_vue_slot(c, dst, i),
+ get_vue_slot(c, src, i));
+ }
}
}
+static int count_flatshaded_attributes(struct brw_sf_compile *c)
+{
+ int i;
+ int count = 0;
+
+ for (i = 0; i < c->vue_map.num_slots; i++)
+ if (c->key.interpolation_mode.mode[i] == INTERP_QUALIFIER_FLAT)
+ count++;
+
+ return count;
+}
+
/* Need to use a computed jump to copy flatshaded attributes as the
static void do_flatshade_triangle( struct brw_sf_compile *c )
{
struct brw_compile *p = &c->func;
+ struct brw_context *brw = p->brw;
struct brw_reg ip = brw_ip_reg();
- GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
+ GLuint nr;
GLuint jmpi = 1;
- if (!nr)
- return;
-
/* Already done in clip program:
*/
if (c->key.primitive == SF_UNFILLED_TRIS)
return;
- if (BRW_IS_IGDNG(p->brw))
+ if (brw->gen == 5)
jmpi = 2;
+ nr = count_flatshaded_attributes(c);
+
brw_push_insn_state(p);
-
+
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));
brw_JMPI(p, ip, ip, c->pv);
- copy_colors(c, c->vert[1], c->vert[0]);
- copy_colors(c, c->vert[2], c->vert[0]);
+ copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
+ copy_flatshaded_attributes(c, c->vert[2], c->vert[0]);
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));
- copy_colors(c, c->vert[0], c->vert[1]);
- copy_colors(c, c->vert[2], c->vert[1]);
+ copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
+ copy_flatshaded_attributes(c, c->vert[2], c->vert[1]);
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));
- copy_colors(c, c->vert[0], c->vert[2]);
- copy_colors(c, c->vert[1], c->vert[2]);
+ copy_flatshaded_attributes(c, c->vert[0], c->vert[2]);
+ copy_flatshaded_attributes(c, c->vert[1], c->vert[2]);
brw_pop_insn_state(p);
}
static void do_flatshade_line( struct brw_sf_compile *c )
{
struct brw_compile *p = &c->func;
+ struct brw_context *brw = p->brw;
struct brw_reg ip = brw_ip_reg();
- GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS);
+ GLuint nr;
GLuint jmpi = 1;
- if (!nr)
- return;
-
/* Already done in clip program:
*/
if (c->key.primitive == SF_UNFILLED_TRIS)
return;
- if (BRW_IS_IGDNG(p->brw))
+ if (brw->gen == 5)
jmpi = 2;
+ nr = count_flatshaded_attributes(c);
+
brw_push_insn_state(p);
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));
brw_JMPI(p, ip, ip, c->pv);
- copy_colors(c, c->vert[1], c->vert[0]);
+ copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);
brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));
- copy_colors(c, c->vert[0], c->vert[1]);
+ copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);
brw_pop_insn_state(p);
}
brw_math(&c->func,
c->inv_det,
BRW_MATH_FUNCTION_INV,
- BRW_MATH_SATURATE_NONE,
0,
c->det,
BRW_MATH_DATA_SCALAR,
}
-static GLboolean calculate_masks( struct brw_sf_compile *c,
- GLuint reg,
- GLushort *pc,
- GLushort *pc_persp,
- GLushort *pc_linear)
+static bool
+calculate_masks(struct brw_sf_compile *c,
+ GLuint reg,
+ GLushort *pc,
+ GLushort *pc_persp,
+ GLushort *pc_linear)
{
- GLboolean is_last_attr = (reg == c->nr_setup_regs - 1);
- GLuint persp_mask;
- GLuint linear_mask;
-
- if (c->key.do_flat_shading || c->key.linear_color)
- persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS |
- FRAG_BIT_COL0 |
- FRAG_BIT_COL1);
- else
- persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS);
-
- if (c->key.do_flat_shading)
- linear_mask = c->key.attrs & ~(FRAG_BIT_COL0|FRAG_BIT_COL1);
- else
- linear_mask = c->key.attrs;
+ bool is_last_attr = (reg == c->nr_setup_regs - 1);
+ enum glsl_interp_qualifier interp;
*pc_persp = 0;
*pc_linear = 0;
*pc = 0xf;
- if (persp_mask & (1 << c->idx_to_attr[reg*2]))
+ interp = c->key.interpolation_mode.mode[vert_reg_to_vue_slot(c, reg, 0)];
+ if (interp == INTERP_QUALIFIER_SMOOTH) {
+ *pc_linear = 0xf;
*pc_persp = 0xf;
-
- if (linear_mask & (1 << c->idx_to_attr[reg*2]))
+ } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)
*pc_linear = 0xf;
/* Maybe only processs one attribute on the final round:
*/
- if (reg*2+1 < c->nr_setup_attrs) {
+ if (vert_reg_to_varying(c, reg, 1) != BRW_VARYING_SLOT_COUNT) {
*pc |= 0xf0;
- if (persp_mask & (1 << c->idx_to_attr[reg*2+1]))
- *pc_persp |= 0xf0;
-
- if (linear_mask & (1 << c->idx_to_attr[reg*2+1]))
- *pc_linear |= 0xf0;
+ interp = c->key.interpolation_mode.mode[vert_reg_to_vue_slot(c, reg, 1)];
+ if (interp == INTERP_QUALIFIER_SMOOTH) {
+ *pc_linear |= 0xf0;
+ *pc_persp |= 0xf0;
+ } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)
+ *pc_linear |= 0xf0;
}
return is_last_attr;
}
+/* Calculates the predicate control for which channels of a reg
+ * (containing 2 attrs) to do point sprite coordinate replacement on.
+ */
+static uint16_t
+calculate_point_sprite_mask(struct brw_sf_compile *c, GLuint reg)
+{
+ int varying1, varying2;
+ uint16_t pc = 0;
+ varying1 = vert_reg_to_varying(c, reg, 0);
+ if (varying1 >= VARYING_SLOT_TEX0 && varying1 <= VARYING_SLOT_TEX7) {
+ if (c->key.point_sprite_coord_replace & (1 << (varying1 - VARYING_SLOT_TEX0)))
+ pc |= 0x0f;
+ }
+ if (varying1 == BRW_VARYING_SLOT_PNTC)
+ pc |= 0x0f;
+
+ varying2 = vert_reg_to_varying(c, reg, 1);
+ if (varying2 >= VARYING_SLOT_TEX0 && varying2 <= VARYING_SLOT_TEX7) {
+ if (c->key.point_sprite_coord_replace & (1 << (varying2 -
+ VARYING_SLOT_TEX0)))
+ pc |= 0xf0;
+ }
+ if (varying2 == BRW_VARYING_SLOT_PNTC)
+ pc |= 0xf0;
-void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate)
+ return pc;
+}
+
+
+
+void brw_emit_tri_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_compile *p = &c->func;
GLuint i;
if (c->key.do_twoside_color)
do_twoside_color(c);
- if (c->key.do_flat_shading)
+ if (c->has_flat_shading)
do_flatshade_triangle(c);
struct brw_reg a1 = offset(c->vert[1], i);
struct brw_reg a2 = offset(c->vert[2], i);
GLushort pc, pc_persp, pc_linear;
- GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+ bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
-void brw_emit_line_setup( struct brw_sf_compile *c, GLboolean allocate)
+void brw_emit_line_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_compile *p = &c->func;
GLuint i;
invert_det(c);
copy_z_inv_w(c);
- if (c->key.do_flat_shading)
+ if (c->has_flat_shading)
do_flatshade_line(c);
for (i = 0; i < c->nr_setup_regs; i++)
struct brw_reg a0 = offset(c->vert[0], i);
struct brw_reg a1 = offset(c->vert[1], i);
GLushort pc, pc_persp, pc_linear;
- GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+ bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
}
}
-void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate)
+void brw_emit_point_sprite_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_compile *p = &c->func;
GLuint i;
copy_z_inv_w(c);
for (i = 0; i < c->nr_setup_regs; i++)
{
- struct brw_sf_point_tex *tex = &c->point_attrs[c->idx_to_attr[2*i]];
struct brw_reg a0 = offset(c->vert[0], i);
- GLushort pc, pc_persp, pc_linear;
- GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
-
- if (pc_persp)
- {
- if (!tex->CoordReplace) {
- brw_set_predicate_control_flag_value(p, pc_persp);
- brw_MUL(p, a0, a0, c->inv_w[0]);
- }
+ GLushort pc, pc_persp, pc_linear, pc_coord_replace;
+ bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+
+ pc_coord_replace = calculate_point_sprite_mask(c, i);
+ pc_persp &= ~pc_coord_replace;
+
+ if (pc_persp) {
+ brw_set_predicate_control_flag_value(p, pc_persp);
+ brw_MUL(p, a0, a0, c->inv_w[0]);
}
- if (tex->CoordReplace) {
- /* Caculate 1.0/PointWidth */
- brw_math(&c->func,
+ /* Point sprite coordinate replacement: A texcoord with this
+ * enabled gets replaced with the value (x, y, 0, 1) where x and
+ * y vary from 0 to 1 across the horizontal and vertical of the
+ * point.
+ */
+ if (pc_coord_replace) {
+ brw_set_predicate_control_flag_value(p, pc_coord_replace);
+ /* Caculate 1.0/PointWidth */
+ brw_math(&c->func,
c->tmp,
BRW_MATH_FUNCTION_INV,
- BRW_MATH_SATURATE_NONE,
0,
c->dx0,
BRW_MATH_DATA_SCALAR,
BRW_MATH_PRECISION_FULL);
- if (c->key.SpriteOrigin == GL_LOWER_LEFT) {
- brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
- brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
- brw_MUL(p, c->m2Cy, c->tmp, negate(c->inv_w[0]));
- brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
- } else {
- brw_MUL(p, c->m1Cx, c->tmp, c->inv_w[0]);
- brw_MOV(p, vec1(suboffset(c->m1Cx, 1)), brw_imm_f(0.0));
- brw_MUL(p, c->m2Cy, c->tmp, c->inv_w[0]);
- brw_MOV(p, vec1(suboffset(c->m2Cy, 0)), brw_imm_f(0.0));
- }
- } else {
- brw_MOV(p, c->m1Cx, brw_imm_ud(0));
- brw_MOV(p, c->m2Cy, brw_imm_ud(0));
- }
+ brw_set_access_mode(p, BRW_ALIGN_16);
- {
- brw_set_predicate_control_flag_value(p, pc);
- if (tex->CoordReplace) {
- if (c->key.SpriteOrigin == GL_LOWER_LEFT) {
- brw_MUL(p, c->m3C0, c->inv_w[0], brw_imm_f(1.0));
- brw_MOV(p, vec1(suboffset(c->m3C0, 0)), brw_imm_f(0.0));
- }
- else
- brw_MOV(p, c->m3C0, brw_imm_f(0.0));
+ /* dA/dx, dA/dy */
+ brw_MOV(p, c->m1Cx, brw_imm_f(0.0));
+ brw_MOV(p, c->m2Cy, brw_imm_f(0.0));
+ brw_MOV(p, brw_writemask(c->m1Cx, WRITEMASK_X), c->tmp);
+ if (c->key.sprite_origin_lower_left) {
+ brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), negate(c->tmp));
} else {
- brw_MOV(p, c->m3C0, a0); /* constant value */
+ brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), c->tmp);
}
- /* Copy m0..m3 to URB.
- */
- brw_urb_WRITE(p,
- brw_null_reg(),
- 0,
- brw_vec8_grf(0, 0),
- 0, /* allocate */
- 1, /* used */
- 4, /* msg len */
- 0, /* response len */
- last, /* eot */
- last, /* writes complete */
- i*4, /* urb destination offset */
- BRW_URB_SWIZZLE_TRANSPOSE);
+ /* attribute constant offset */
+ brw_MOV(p, c->m3C0, brw_imm_f(0.0));
+ if (c->key.sprite_origin_lower_left) {
+ brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_YW), brw_imm_f(1.0));
+ } else {
+ brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_W), brw_imm_f(1.0));
+ }
+
+ brw_set_access_mode(p, BRW_ALIGN_1);
}
+
+ if (pc & ~pc_coord_replace) {
+ brw_set_predicate_control_flag_value(p, pc & ~pc_coord_replace);
+ brw_MOV(p, c->m1Cx, brw_imm_ud(0));
+ brw_MOV(p, c->m2Cy, brw_imm_ud(0));
+ brw_MOV(p, c->m3C0, a0); /* constant value */
+ }
+
+
+ brw_set_predicate_control_flag_value(p, pc);
+ /* Copy m0..m3 to URB. */
+ brw_urb_WRITE(p,
+ brw_null_reg(),
+ 0,
+ brw_vec8_grf(0, 0),
+ 0, /* allocate */
+ 1, /* used */
+ 4, /* msg len */
+ 0, /* response len */
+ last, /* eot */
+ last, /* writes complete */
+ i*4, /* urb destination offset */
+ BRW_URB_SWIZZLE_TRANSPOSE);
}
}
/* Points setup - several simplifications as all attributes are
* constant across the face of the point (point sprites excluded!)
*/
-void brw_emit_point_setup( struct brw_sf_compile *c, GLboolean allocate)
+void brw_emit_point_setup(struct brw_sf_compile *c, bool allocate)
{
struct brw_compile *p = &c->func;
GLuint i;
{
struct brw_reg a0 = offset(c->vert[0], i);
GLushort pc, pc_persp, pc_linear;
- GLboolean last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
+ bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear);
if (pc_persp)
{
struct brw_reg payload_prim = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0);
struct brw_reg payload_attr = get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0), 0);
struct brw_reg primmask;
- struct brw_instruction *jmp;
+ int jmp;
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
GLuint saveflag;
(1<<_3DPRIM_POLYGON) |
(1<<_3DPRIM_RECTLIST) |
(1<<_3DPRIM_TRIFAN_NOSTIPPLE)));
- jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
{
saveflag = p->flag_value;
brw_push_insn_state(p);
- brw_emit_tri_setup( c, GL_FALSE );
+ brw_emit_tri_setup( c, false );
brw_pop_insn_state(p);
p->flag_value = saveflag;
/* note - thread killed in subroutine, so must
(1<<_3DPRIM_LINESTRIP_CONT) |
(1<<_3DPRIM_LINESTRIP_BF) |
(1<<_3DPRIM_LINESTRIP_CONT_BF)));
- jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
{
saveflag = p->flag_value;
brw_push_insn_state(p);
- brw_emit_line_setup( c, GL_FALSE );
+ brw_emit_line_setup( c, false );
brw_pop_insn_state(p);
p->flag_value = saveflag;
/* note - thread killed in subroutine */
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z);
brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE));
- jmp = brw_JMPI(p, ip, ip, brw_imm_d(0));
+ jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store;
{
saveflag = p->flag_value;
brw_push_insn_state(p);
- brw_emit_point_sprite_setup( c, GL_FALSE );
+ brw_emit_point_sprite_setup( c, false );
brw_pop_insn_state(p);
p->flag_value = saveflag;
}
brw_land_fwd_jump(p, jmp);
- brw_emit_point_setup( c, GL_FALSE );
+ brw_emit_point_setup( c, false );
}