Path: blob/21.2-virgl/src/intel/compiler/brw_clip_line.c
4550 views
/*1Copyright (C) Intel Corp. 2006. All Rights Reserved.2Intel funded Tungsten Graphics to3develop this 3D driver.45Permission is hereby granted, free of charge, to any person obtaining6a copy of this software and associated documentation files (the7"Software"), to deal in the Software without restriction, including8without limitation the rights to use, copy, modify, merge, publish,9distribute, sublicense, and/or sell copies of the Software, and to10permit persons to whom the Software is furnished to do so, subject to11the following conditions:1213The above copyright notice and this permission notice (including the14next paragraph) shall be included in all copies or substantial15portions of the Software.1617THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,18EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.20IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE21LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION22OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2425**********************************************************************/26/*27* Authors:28* Keith Whitwell <[email protected]>29*/3031#include "main/macros.h"32#include "main/enums.h"33#include "program/program.h"3435#include "brw_clip.h"3637static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )38{39const struct intel_device_info *devinfo = c->func.devinfo;40GLuint i = 0,j;4142/* Register usage is static, precompute here:43*/44c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;4546if (c->key.nr_userclip) {47c->reg.fixed_planes = brw_vec4_grf(i, 0);48i += (6 + c->key.nr_userclip + 1) / 2;4950c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;51}52else53c->prog_data.curb_read_length = 0;545556/* Payload vertices plus space for more generated vertices:57*/58for (j = 0; j < 4; j++) {59c->reg.vertex[j] = brw_vec4_grf(i, 0);60i += c->nr_regs;61}6263c->reg.t = brw_vec1_grf(i, 0);64c->reg.t0 = brw_vec1_grf(i, 1);65c->reg.t1 = brw_vec1_grf(i, 2);66c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);67c->reg.plane_equation = brw_vec4_grf(i, 4);68i++;6970c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */71c->reg.dp1 = brw_vec1_grf(i, 4);72i++;7374if (!c->key.nr_userclip) {75c->reg.fixed_planes = brw_vec8_grf(i, 0);76i++;77}7879c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);80c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);81i++;8283if (devinfo->ver == 5) {84c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);85i++;86}8788c->first_tmp = i;89c->last_tmp = i;9091c->prog_data.urb_read_length = c->nr_regs; /* ? */92c->prog_data.total_grf = i;93}949596/* Line clipping, more or less following the following algorithm:97*98* for (p=0;p<MAX_PLANES;p++) {99* if (clipmask & (1 << p)) {100* GLfloat dp0 = DOTPROD( vtx0, plane[p] );101* GLfloat dp1 = DOTPROD( vtx1, plane[p] );102*103* if (dp1 < 0.0f) {104* GLfloat t = dp1 / (dp1 - dp0);105* if (t > t1) t1 = t;106* } else {107* GLfloat t = dp0 / (dp0 - dp1);108* if (t > t0) t0 = t;109* }110*111* if (t0 + t1 >= 1.0)112* return;113* }114* }115*116* interp( ctx, newvtx0, vtx0, vtx1, t0 );117* interp( ctx, newvtx1, vtx1, vtx0, t1 );118*119*/120static void clip_and_emit_line( struct brw_clip_compile *c )121{122struct brw_codegen *p = &c->func;123struct brw_indirect vtx0 = brw_indirect(0, 0);124struct brw_indirect vtx1 = brw_indirect(1, 0);125struct brw_indirect newvtx0 = brw_indirect(2, 0);126struct brw_indirect newvtx1 = brw_indirect(3, 0);127struct brw_indirect plane_ptr = brw_indirect(4, 0);128struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);129GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);130GLint clipdist0_offset = c->key.nr_userclip131? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)132: 0;133134brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));135brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));136brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));137brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));138brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));139140/* Note: init t0, t1 together:141*/142brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));143144brw_clip_init_planes(c);145brw_clip_init_clipmask(c);146147/* -ve rhw workaround */148if (p->devinfo->has_negative_rhw_bug) {149brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),150brw_imm_ud(1<<20));151brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);152brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));153brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);154}155156/* Set the initial vertex source mask: The first 6 planes are the bounds157* of the view volume; the next 8 planes are the user clipping planes.158*/159brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));160161/* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].162* We'll increment 6 times before we start hitting actual user clipping. */163brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));164165brw_DO(p, BRW_EXECUTE_1);166{167/* if (planemask & 1)168*/169brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));170brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);171172brw_IF(p, BRW_EXECUTE_1);173{174brw_AND(p, v1_null_ud, c->reg.vertex_src_mask, brw_imm_ud(1));175brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);176brw_IF(p, BRW_EXECUTE_1);177{178/* user clip distance: just fetch the correct float from each vertex */179struct brw_indirect temp_ptr = brw_indirect(7, 0);180brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx0), c->reg.clipdistance_offset);181brw_MOV(p, c->reg.dp0, deref_1f(temp_ptr, 0));182brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx1), c->reg.clipdistance_offset);183brw_MOV(p, c->reg.dp1, deref_1f(temp_ptr, 0));184}185brw_ELSE(p);186{187/* fixed plane: fetch the hpos, dp4 against the plane. */188if (c->key.nr_userclip)189brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));190else191brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));192193brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation);194brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation);195}196brw_ENDIF(p);197198brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, vec1(c->reg.dp1), brw_imm_f(0.0f));199200brw_IF(p, BRW_EXECUTE_1);201{202/*203* Both can be negative on GM965/G965 due to RHW workaround204* if so, this object should be rejected.205*/206if (p->devinfo->has_negative_rhw_bug) {207brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));208brw_IF(p, BRW_EXECUTE_1);209{210brw_clip_kill_thread(c);211}212brw_ENDIF(p);213}214215brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));216brw_math_invert(p, c->reg.t, c->reg.t);217brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);218219brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );220brw_MOV(p, c->reg.t1, c->reg.t);221brw_inst_set_pred_control(p->devinfo, brw_last_inst,222BRW_PREDICATE_NORMAL);223}224brw_ELSE(p);225{226/* Coming back in. We know that both cannot be negative227* because the line would have been culled in that case.228*/229230/* If both are positive, do nothing */231/* Only on GM965/G965 */232if (p->devinfo->has_negative_rhw_bug) {233brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));234brw_IF(p, BRW_EXECUTE_1);235}236237{238brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));239brw_math_invert(p, c->reg.t, c->reg.t);240brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);241242brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );243brw_MOV(p, c->reg.t0, c->reg.t);244brw_inst_set_pred_control(p->devinfo, brw_last_inst,245BRW_PREDICATE_NORMAL);246}247248if (p->devinfo->has_negative_rhw_bug) {249brw_ENDIF(p);250}251}252brw_ENDIF(p);253}254brw_ENDIF(p);255256/* plane_ptr++;257*/258brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));259260/* while (planemask>>=1) != 0261*/262brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));263brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);264brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));265brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);266brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));267brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);268}269brw_WHILE(p);270brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);271272brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);273brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));274brw_IF(p, BRW_EXECUTE_1);275{276brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false);277brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false);278279brw_clip_emit_vue(c, newvtx0, BRW_URB_WRITE_ALLOCATE_COMPLETE,280(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)281| URB_WRITE_PRIM_START);282brw_clip_emit_vue(c, newvtx1, BRW_URB_WRITE_EOT_COMPLETE,283(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)284| URB_WRITE_PRIM_END);285}286brw_ENDIF(p);287brw_clip_kill_thread(c);288}289290291292void brw_emit_line_clip( struct brw_clip_compile *c )293{294brw_clip_line_alloc_regs(c);295brw_clip_init_ff_sync(c);296297if (c->key.contains_flat_varying) {298if (c->key.pv_first)299brw_clip_copy_flatshaded_attributes(c, 1, 0);300else301brw_clip_copy_flatshaded_attributes(c, 0, 1);302}303304clip_and_emit_line(c);305}306307308