| /* |
| Copyright (C) Intel Corp. 2006. All Rights Reserved. |
| Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
| develop this 3D driver. |
| |
| Permission is hereby granted, free of charge, to any person obtaining |
| a copy of this software and associated documentation files (the |
| "Software"), to deal in the Software without restriction, including |
| without limitation the rights to use, copy, modify, merge, publish, |
| distribute, sublicense, and/or sell copies of the Software, and to |
| permit persons to whom the Software is furnished to do so, subject to |
| the following conditions: |
| |
| The above copyright notice and this permission notice (including the |
| next paragraph) shall be included in all copies or substantial |
| portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| **********************************************************************/ |
| /* |
| * Authors: |
| * Keith Whitwell <keith@tungstengraphics.com> |
| */ |
| |
| |
| #include "glheader.h" |
| #include "macros.h" |
| #include "enums.h" |
| |
| #include "intel_batchbuffer.h" |
| |
| #include "brw_defines.h" |
| #include "brw_context.h" |
| #include "brw_eu.h" |
| #include "brw_util.h" |
| #include "brw_sf.h" |
| |
| |
| static struct brw_reg get_vert_attr(struct brw_sf_compile *c, |
| struct brw_reg vert, |
| GLuint attr) |
| { |
| GLuint off = c->attr_to_idx[attr] / 2; |
| GLuint sub = c->attr_to_idx[attr] % 2; |
| |
| return brw_vec4_grf(vert.nr + off, sub * 4); |
| } |
| |
| static GLboolean have_attr(struct brw_sf_compile *c, |
| GLuint attr) |
| { |
| return (c->key.attrs & (1<<attr)) ? 1 : 0; |
| } |
| |
| /** |
| * Sets VERT_RESULT_FOGC.Y for gl_FrontFacing |
| * |
| * This is currently executed if the fragment program uses VERT_RESULT_FOGC |
| * at all, but this could be eliminated with a scan of the FP contents. |
| */ |
| static void |
| do_front_facing( struct brw_sf_compile *c ) |
| { |
| struct brw_compile *p = &c->func; |
| int i; |
| |
| if (!have_attr(c, VERT_RESULT_FOGC)) |
| return; |
| |
| brw_push_insn_state(p); |
| brw_CMP(p, brw_null_reg(), |
| c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L, |
| c->det, brw_imm_f(0)); |
| brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
| for (i = 0; i < 3; i++) { |
| struct brw_reg fogc = get_vert_attr(c, c->vert[i],FRAG_ATTRIB_FOGC); |
| brw_MOV(p, get_element(fogc, 1), brw_imm_f(0)); |
| brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); |
| brw_MOV(p, get_element(fogc, 1), brw_imm_f(1)); |
| brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
| } |
| brw_pop_insn_state(p); |
| } |
| |
| |
| /*********************************************************************** |
| * Twoside lighting |
| */ |
| static void copy_bfc( struct brw_sf_compile *c, |
| struct brw_reg vert ) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| for (i = 0; i < 2; i++) { |
| if (have_attr(c, VERT_RESULT_COL0+i) && |
| have_attr(c, VERT_RESULT_BFC0+i)) |
| brw_MOV(p, |
| get_vert_attr(c, vert, VERT_RESULT_COL0+i), |
| get_vert_attr(c, vert, VERT_RESULT_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 (!(have_attr(c, VERT_RESULT_COL0) && have_attr(c, VERT_RESULT_BFC0)) && |
| !(have_attr(c, VERT_RESULT_COL1) && have_attr(c, VERT_RESULT_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_EXECUTE_1 for all comparisions. |
| */ |
| 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); |
| { |
| switch (c->nr_verts) { |
| case 3: copy_bfc(c, c->vert[2]); |
| case 2: copy_bfc(c, c->vert[1]); |
| case 1: copy_bfc(c, c->vert[0]); |
| } |
| } |
| brw_ENDIF(p, if_insn); |
| 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) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint 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)); |
| } |
| } |
| |
| |
| |
| /* Need to use a computed jump to copy flatshaded attributes as the |
| * vertices are ordered according to y-coordinate before reaching this |
| * point, so the PV could be anywhere. |
| */ |
| static void do_flatshade_triangle( struct brw_sf_compile *c ) |
| { |
| struct brw_compile *p = &c->func; |
| struct brw_reg ip = brw_ip_reg(); |
| GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS); |
| if (!nr) |
| return; |
| |
| /* Already done in clip program: |
| */ |
| if (c->key.primitive == SF_UNFILLED_TRIS) |
| return; |
| |
| brw_push_insn_state(p); |
| |
| brw_MUL(p, c->pv, c->pv, brw_imm_ud(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]); |
| brw_JMPI(p, ip, ip, brw_imm_ud(nr*4+1)); |
| |
| copy_colors(c, c->vert[0], c->vert[1]); |
| copy_colors(c, c->vert[2], c->vert[1]); |
| brw_JMPI(p, ip, ip, brw_imm_ud(nr*2)); |
| |
| copy_colors(c, c->vert[0], c->vert[2]); |
| copy_colors(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_reg ip = brw_ip_reg(); |
| GLuint nr = brw_count_bits(c->key.attrs & VERT_RESULT_COLOR_BITS); |
| |
| if (!nr) |
| return; |
| |
| /* Already done in clip program: |
| */ |
| if (c->key.primitive == SF_UNFILLED_TRIS) |
| return; |
| |
| brw_push_insn_state(p); |
| |
| brw_MUL(p, c->pv, c->pv, brw_imm_ud(nr+1)); |
| brw_JMPI(p, ip, ip, c->pv); |
| copy_colors(c, c->vert[1], c->vert[0]); |
| |
| brw_JMPI(p, ip, ip, brw_imm_ud(nr)); |
| copy_colors(c, c->vert[0], c->vert[1]); |
| |
| brw_pop_insn_state(p); |
| } |
| |
| |
| |
| /*********************************************************************** |
| * Triangle setup. |
| */ |
| |
| |
| static void alloc_regs( struct brw_sf_compile *c ) |
| { |
| GLuint reg, i; |
| |
| /* Values computed by fixed function unit: |
| */ |
| c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_UD); |
| c->det = brw_vec1_grf(1, 2); |
| c->dx0 = brw_vec1_grf(1, 3); |
| c->dx2 = brw_vec1_grf(1, 4); |
| c->dy0 = brw_vec1_grf(1, 5); |
| c->dy2 = brw_vec1_grf(1, 6); |
| |
| /* z and 1/w passed in seperately: |
| */ |
| c->z[0] = brw_vec1_grf(2, 0); |
| c->inv_w[0] = brw_vec1_grf(2, 1); |
| c->z[1] = brw_vec1_grf(2, 2); |
| c->inv_w[1] = brw_vec1_grf(2, 3); |
| c->z[2] = brw_vec1_grf(2, 4); |
| c->inv_w[2] = brw_vec1_grf(2, 5); |
| |
| /* The vertices: |
| */ |
| reg = 3; |
| for (i = 0; i < c->nr_verts; i++) { |
| c->vert[i] = brw_vec8_grf(reg, 0); |
| reg += c->nr_attr_regs; |
| } |
| |
| /* Temporaries, allocated after last vertex reg. |
| */ |
| c->inv_det = brw_vec1_grf(reg, 0); reg++; |
| c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++; |
| c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++; |
| c->tmp = brw_vec8_grf(reg, 0); reg++; |
| |
| /* Note grf allocation: |
| */ |
| c->prog_data.total_grf = reg; |
| |
| |
| /* Outputs of this program - interpolation coefficients for |
| * rasterization: |
| */ |
| c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0); |
| c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0); |
| c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0); |
| } |
| |
| |
| static void copy_z_inv_w( struct brw_sf_compile *c ) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| brw_push_insn_state(p); |
| |
| /* Copy both scalars with a single MOV: |
| */ |
| for (i = 0; i < c->nr_verts; i++) |
| brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i])); |
| |
| brw_pop_insn_state(p); |
| } |
| |
| |
| static void invert_det( struct brw_sf_compile *c) |
| { |
| /* Looks like we invert all 8 elements just to get 1/det in |
| * position 2 !?! |
| */ |
| brw_math(&c->func, |
| c->inv_det, |
| BRW_MATH_FUNCTION_INV, |
| BRW_MATH_SATURATE_NONE, |
| 0, |
| c->det, |
| BRW_MATH_DATA_SCALAR, |
| BRW_MATH_PRECISION_FULL); |
| |
| } |
| |
| #define NON_PERPECTIVE_ATTRS (FRAG_BIT_WPOS | \ |
| FRAG_BIT_COL0 | \ |
| FRAG_BIT_COL1) |
| |
| static GLboolean 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 = c->key.attrs & ~NON_PERPECTIVE_ATTRS; |
| GLuint linear_mask; |
| |
| if (c->key.do_flat_shading) |
| linear_mask = c->key.attrs & ~(FRAG_BIT_COL0|FRAG_BIT_COL1); |
| else |
| linear_mask = c->key.attrs; |
| |
| *pc_persp = 0; |
| *pc_linear = 0; |
| *pc = 0xf; |
| |
| if (persp_mask & (1 << c->idx_to_attr[reg*2])) |
| *pc_persp = 0xf; |
| |
| if (linear_mask & (1 << c->idx_to_attr[reg*2])) |
| *pc_linear = 0xf; |
| |
| /* Maybe only processs one attribute on the final round: |
| */ |
| if (reg*2+1 < c->nr_setup_attrs) { |
| *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; |
| } |
| |
| return is_last_attr; |
| } |
| |
| |
| |
| void brw_emit_tri_setup( struct brw_sf_compile *c, GLboolean allocate) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| c->nr_verts = 3; |
| |
| if (allocate) |
| alloc_regs(c); |
| |
| invert_det(c); |
| copy_z_inv_w(c); |
| do_front_facing(c); |
| |
| if (c->key.do_twoside_color) |
| do_twoside_color(c); |
| |
| if (c->key.do_flat_shading) |
| do_flatshade_triangle(c); |
| |
| |
| for (i = 0; i < c->nr_setup_regs; i++) |
| { |
| /* Pair of incoming attributes: |
| */ |
| struct brw_reg a0 = offset(c->vert[0], i); |
| 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); |
| |
| if (pc_persp) |
| { |
| brw_set_predicate_control_flag_value(p, pc_persp); |
| brw_MUL(p, a0, a0, c->inv_w[0]); |
| brw_MUL(p, a1, a1, c->inv_w[1]); |
| brw_MUL(p, a2, a2, c->inv_w[2]); |
| } |
| |
| |
| /* Calculate coefficients for interpolated values: |
| */ |
| if (pc_linear) |
| { |
| brw_set_predicate_control_flag_value(p, pc_linear); |
| |
| brw_ADD(p, c->a1_sub_a0, a1, negate(a0)); |
| brw_ADD(p, c->a2_sub_a0, a2, negate(a0)); |
| |
| /* calculate dA/dx |
| */ |
| brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2); |
| brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0)); |
| brw_MUL(p, c->m1Cx, c->tmp, c->inv_det); |
| |
| /* calculate dA/dy |
| */ |
| brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0); |
| brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2)); |
| brw_MUL(p, c->m2Cy, c->tmp, c->inv_det); |
| } |
| |
| { |
| brw_set_predicate_control_flag_value(p, pc); |
| /* start point for interpolation |
| */ |
| brw_MOV(p, c->m3C0, a0); |
| |
| /* Copy m0..m3 to URB. m0 is implicitly copied from r0 in |
| * the send instruction: |
| */ |
| brw_urb_WRITE(p, |
| brw_null_reg(), |
| 0, |
| brw_vec8_grf(0, 0), /* r0, will be copied to m0 */ |
| 0, /* allocate */ |
| 1, /* used */ |
| 4, /* msg len */ |
| 0, /* response len */ |
| last, /* eot */ |
| last, /* writes complete */ |
| i*4, /* offset */ |
| BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */ |
| } |
| } |
| } |
| |
| |
| |
| void brw_emit_line_setup( struct brw_sf_compile *c, GLboolean allocate) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| |
| c->nr_verts = 2; |
| |
| if (allocate) |
| alloc_regs(c); |
| |
| invert_det(c); |
| copy_z_inv_w(c); |
| |
| if (c->key.do_flat_shading) |
| do_flatshade_line(c); |
| |
| for (i = 0; i < c->nr_setup_regs; i++) |
| { |
| /* Pair of incoming attributes: |
| */ |
| 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); |
| |
| if (pc_persp) |
| { |
| brw_set_predicate_control_flag_value(p, pc_persp); |
| brw_MUL(p, a0, a0, c->inv_w[0]); |
| brw_MUL(p, a1, a1, c->inv_w[1]); |
| } |
| |
| /* Calculate coefficients for position, color: |
| */ |
| if (pc_linear) { |
| brw_set_predicate_control_flag_value(p, pc_linear); |
| |
| brw_ADD(p, c->a1_sub_a0, a1, negate(a0)); |
| |
| brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0); |
| brw_MUL(p, c->m1Cx, c->tmp, c->inv_det); |
| |
| brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0); |
| brw_MUL(p, c->m2Cy, c->tmp, c->inv_det); |
| } |
| |
| { |
| brw_set_predicate_control_flag_value(p, pc); |
| |
| /* start point for interpolation |
| */ |
| brw_MOV(p, c->m3C0, a0); |
| |
| /* 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); |
| } |
| } |
| } |
| |
| void brw_emit_point_sprite_setup( struct brw_sf_compile *c, GLboolean allocate) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| c->nr_verts = 1; |
| |
| if (allocate) |
| alloc_regs(c); |
| |
| 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]); |
| } |
| } |
| |
| if (tex->CoordReplace) { |
| /* 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_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)); |
| } else { |
| brw_MOV(p, c->m3C0, a0); /* constant value */ |
| } |
| |
| /* 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) |
| { |
| struct brw_compile *p = &c->func; |
| GLuint i; |
| |
| c->nr_verts = 1; |
| |
| if (allocate) |
| alloc_regs(c); |
| |
| copy_z_inv_w(c); |
| |
| brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */ |
| brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */ |
| |
| for (i = 0; i < c->nr_setup_regs; 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) |
| { |
| /* This seems odd as the values are all constant, but the |
| * fragment shader will be expecting it: |
| */ |
| brw_set_predicate_control_flag_value(p, pc_persp); |
| brw_MUL(p, a0, a0, c->inv_w[0]); |
| } |
| |
| |
| /* The delta values are always zero, just send the starting |
| * coordinate. Again, this is to fit in with the interpolation |
| * code in the fragment shader. |
| */ |
| { |
| brw_set_predicate_control_flag_value(p, pc); |
| |
| brw_MOV(p, c->m3C0, a0); /* constant value */ |
| |
| /* 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); |
| } |
| } |
| } |
| |
| void brw_emit_anyprim_setup( struct brw_sf_compile *c ) |
| { |
| struct brw_compile *p = &c->func; |
| struct brw_reg ip = brw_ip_reg(); |
| 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; |
| struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD)); |
| |
| GLuint saveflag; |
| |
| c->nr_verts = 3; |
| alloc_regs(c); |
| |
| primmask = retype(get_element(c->tmp, 0), BRW_REGISTER_TYPE_UD); |
| |
| brw_MOV(p, primmask, brw_imm_ud(1)); |
| brw_SHL(p, primmask, primmask, payload_prim); |
| |
| brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
| brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_TRILIST) | |
| (1<<_3DPRIM_TRISTRIP) | |
| (1<<_3DPRIM_TRIFAN) | |
| (1<<_3DPRIM_TRISTRIP_REVERSE) | |
| (1<<_3DPRIM_POLYGON) | |
| (1<<_3DPRIM_RECTLIST) | |
| (1<<_3DPRIM_TRIFAN_NOSTIPPLE))); |
| jmp = brw_JMPI(p, ip, ip, brw_imm_w(0)); |
| { |
| saveflag = p->flag_value; |
| brw_push_insn_state(p); |
| brw_emit_tri_setup( c, GL_FALSE ); |
| brw_pop_insn_state(p); |
| p->flag_value = saveflag; |
| /* note - thread killed in subroutine, so must |
| * restore the flag which is changed when building |
| * the subroutine. fix #13240 |
| */ |
| } |
| brw_land_fwd_jump(p, jmp); |
| |
| brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
| brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_LINELIST) | |
| (1<<_3DPRIM_LINESTRIP) | |
| (1<<_3DPRIM_LINELOOP) | |
| (1<<_3DPRIM_LINESTRIP_CONT) | |
| (1<<_3DPRIM_LINESTRIP_BF) | |
| (1<<_3DPRIM_LINESTRIP_CONT_BF))); |
| jmp = brw_JMPI(p, ip, ip, brw_imm_w(0)); |
| { |
| saveflag = p->flag_value; |
| brw_push_insn_state(p); |
| brw_emit_line_setup( c, GL_FALSE ); |
| brw_pop_insn_state(p); |
| p->flag_value = saveflag; |
| /* note - thread killed in subroutine */ |
| } |
| brw_land_fwd_jump(p, jmp); |
| |
| 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_w(0)); |
| { |
| saveflag = p->flag_value; |
| brw_push_insn_state(p); |
| brw_emit_point_sprite_setup( c, GL_FALSE ); |
| brw_pop_insn_state(p); |
| p->flag_value = saveflag; |
| } |
| brw_land_fwd_jump(p, jmp); |
| |
| brw_emit_point_setup( c, GL_FALSE ); |
| } |
| |
| |
| |
| |