Path: blob/21.2-virgl/src/intel/compiler/brw_clip_unfilled.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"363738/* This is performed against the original triangles, so no indirection39* required:40BZZZT!41*/42static void compute_tri_direction( struct brw_clip_compile *c )43{44struct brw_codegen *p = &c->func;45struct brw_reg e = c->reg.tmp0;46struct brw_reg f = c->reg.tmp1;47GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);48struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset);49struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset);50struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset);515253struct brw_reg v0n = get_tmp(c);54struct brw_reg v1n = get_tmp(c);55struct brw_reg v2n = get_tmp(c);5657/* Convert to NDC.58* NOTE: We can't modify the original vertex coordinates,59* as it may impact further operations.60* So, we have to keep normalized coordinates in temp registers.61*62* TBD-KC63* Try to optimize unnecessary MOV's.64*/65brw_MOV(p, v0n, v0);66brw_MOV(p, v1n, v1);67brw_MOV(p, v2n, v2);6869brw_clip_project_position(c, v0n);70brw_clip_project_position(c, v1n);71brw_clip_project_position(c, v2n);7273/* Calculate the vectors of two edges of the triangle:74*/75brw_ADD(p, e, v0n, negate(v2n));76brw_ADD(p, f, v1n, negate(v2n));7778/* Take their crossproduct:79*/80brw_set_default_access_mode(p, BRW_ALIGN_16);81brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW),82brw_swizzle(f, BRW_SWIZZLE_ZXYW));83brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)),84brw_swizzle(f, BRW_SWIZZLE_YZXW));85brw_set_default_access_mode(p, BRW_ALIGN_1);8687brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));88}899091static void cull_direction( struct brw_clip_compile *c )92{93struct brw_codegen *p = &c->func;94GLuint conditional;9596assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&97c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL));9899if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL)100conditional = BRW_CONDITIONAL_GE;101else102conditional = BRW_CONDITIONAL_L;103104brw_CMP(p,105vec1(brw_null_reg()),106conditional,107get_element(c->reg.dir, 2),108brw_imm_f(0));109110brw_IF(p, BRW_EXECUTE_1);111{112brw_clip_kill_thread(c);113}114brw_ENDIF(p);115}116117118119static void copy_bfc( struct brw_clip_compile *c )120{121struct brw_codegen *p = &c->func;122GLuint conditional;123124/* Do we have any colors to copy?125*/126if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) &&127brw_clip_have_varying(c, VARYING_SLOT_BFC0)) &&128!(brw_clip_have_varying(c, VARYING_SLOT_COL1) &&129brw_clip_have_varying(c, VARYING_SLOT_BFC1)))130return;131132/* In some weird degenerate cases we can end up testing the133* direction twice, once for culling and once for bfc copying. Oh134* well, that's what you get for setting weird GL state.135*/136if (c->key.copy_bfc_ccw)137conditional = BRW_CONDITIONAL_GE;138else139conditional = BRW_CONDITIONAL_L;140141brw_CMP(p,142vec1(brw_null_reg()),143conditional,144get_element(c->reg.dir, 2),145brw_imm_f(0));146147brw_IF(p, BRW_EXECUTE_1);148{149GLuint i;150151for (i = 0; i < 3; i++) {152if (brw_clip_have_varying(c, VARYING_SLOT_COL0) &&153brw_clip_have_varying(c, VARYING_SLOT_BFC0))154brw_MOV(p,155byte_offset(c->reg.vertex[i],156brw_varying_to_offset(&c->vue_map,157VARYING_SLOT_COL0)),158byte_offset(c->reg.vertex[i],159brw_varying_to_offset(&c->vue_map,160VARYING_SLOT_BFC0)));161162if (brw_clip_have_varying(c, VARYING_SLOT_COL1) &&163brw_clip_have_varying(c, VARYING_SLOT_BFC1))164brw_MOV(p,165byte_offset(c->reg.vertex[i],166brw_varying_to_offset(&c->vue_map,167VARYING_SLOT_COL1)),168byte_offset(c->reg.vertex[i],169brw_varying_to_offset(&c->vue_map,170VARYING_SLOT_BFC1)));171}172}173brw_ENDIF(p);174}175176177178179/*180GLfloat iz = 1.0 / dir.z;181GLfloat ac = dir.x * iz;182GLfloat bc = dir.y * iz;183offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;184offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;185if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) {186if (ctx->Polygon.OffsetClamp < 0)187offset = MAX2( offset, ctx->Polygon.OffsetClamp );188else189offset = MIN2( offset, ctx->Polygon.OffsetClamp );190}191offset *= MRD;192*/193static void compute_offset( struct brw_clip_compile *c )194{195struct brw_codegen *p = &c->func;196struct brw_reg off = c->reg.offset;197struct brw_reg dir = c->reg.dir;198199brw_math_invert(p, get_element(off, 2), get_element(dir, 2));200brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2));201202brw_CMP(p,203vec1(brw_null_reg()),204BRW_CONDITIONAL_GE,205brw_abs(get_element(off, 0)),206brw_abs(get_element(off, 1)));207208brw_SEL(p, vec1(off),209brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));210brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);211212brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor));213brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units));214if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) {215brw_CMP(p,216vec1(brw_null_reg()),217c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L,218vec1(off),219brw_imm_f(c->key.offset_clamp));220brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp));221}222}223224225static void merge_edgeflags( struct brw_clip_compile *c )226{227struct brw_codegen *p = &c->func;228struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);229230brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));231brw_CMP(p,232vec1(brw_null_reg()),233BRW_CONDITIONAL_EQ,234tmp0,235brw_imm_ud(_3DPRIM_POLYGON));236237/* Get away with using reg.vertex because we know that this is not238* a _3DPRIM_TRISTRIP_REVERSE:239*/240brw_IF(p, BRW_EXECUTE_1);241{242brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));243brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);244brw_MOV(p, byte_offset(c->reg.vertex[0],245brw_varying_to_offset(&c->vue_map,246VARYING_SLOT_EDGE)),247brw_imm_f(0));248brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);249250brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));251brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);252brw_MOV(p, byte_offset(c->reg.vertex[2],253brw_varying_to_offset(&c->vue_map,254VARYING_SLOT_EDGE)),255brw_imm_f(0));256brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);257}258brw_ENDIF(p);259}260261262263static void apply_one_offset( struct brw_clip_compile *c,264struct brw_indirect vert )265{266struct brw_codegen *p = &c->func;267GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,268BRW_VARYING_SLOT_NDC);269struct brw_reg z = deref_1f(vert, ndc_offset +2702 * type_sz(BRW_REGISTER_TYPE_F));271272brw_ADD(p, z, z, vec1(c->reg.offset));273}274275276277/***********************************************************************278* Output clipped polygon as an unfilled primitive:279*/280static void emit_lines(struct brw_clip_compile *c,281bool do_offset)282{283struct brw_codegen *p = &c->func;284struct brw_indirect v0 = brw_indirect(0, 0);285struct brw_indirect v1 = brw_indirect(1, 0);286struct brw_indirect v0ptr = brw_indirect(2, 0);287struct brw_indirect v1ptr = brw_indirect(3, 0);288289/* Need a separate loop for offset:290*/291if (do_offset) {292brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);293brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));294295brw_DO(p, BRW_EXECUTE_1);296{297brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));298brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));299300apply_one_offset(c, v0);301302brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));303brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);304}305brw_WHILE(p);306brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);307}308309/* v1ptr = &inlist[nr_verts]310* *v1ptr = v0311*/312brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);313brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));314brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));315brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));316brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));317318brw_DO(p, BRW_EXECUTE_1);319{320brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));321brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));322brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));323324/* draw edge if edgeflag != 0 */325brw_CMP(p,326vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,327deref_1f(v0, brw_varying_to_offset(&c->vue_map,328VARYING_SLOT_EDGE)),329brw_imm_f(0));330brw_IF(p, BRW_EXECUTE_1);331{332brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,333(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)334| URB_WRITE_PRIM_START);335brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,336(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)337| URB_WRITE_PRIM_END);338}339brw_ENDIF(p);340341brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));342brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);343}344brw_WHILE(p);345brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);346}347348349350static void emit_points(struct brw_clip_compile *c,351bool do_offset )352{353struct brw_codegen *p = &c->func;354355struct brw_indirect v0 = brw_indirect(0, 0);356struct brw_indirect v0ptr = brw_indirect(2, 0);357358brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);359brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));360361brw_DO(p, BRW_EXECUTE_1);362{363brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));364brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));365366/* draw if edgeflag != 0367*/368brw_CMP(p,369vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,370deref_1f(v0, brw_varying_to_offset(&c->vue_map,371VARYING_SLOT_EDGE)),372brw_imm_f(0));373brw_IF(p, BRW_EXECUTE_1);374{375if (do_offset)376apply_one_offset(c, v0);377378brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,379(_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)380| URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);381}382brw_ENDIF(p);383384brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));385brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);386}387brw_WHILE(p);388brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);389}390391392393394395396397static void emit_primitives( struct brw_clip_compile *c,398GLuint mode,399bool do_offset )400{401switch (mode) {402case BRW_CLIP_FILL_MODE_FILL:403brw_clip_tri_emit_polygon(c);404break;405406case BRW_CLIP_FILL_MODE_LINE:407emit_lines(c, do_offset);408break;409410case BRW_CLIP_FILL_MODE_POINT:411emit_points(c, do_offset);412break;413414case BRW_CLIP_FILL_MODE_CULL:415unreachable("not reached");416}417}418419420421static void emit_unfilled_primitives( struct brw_clip_compile *c )422{423struct brw_codegen *p = &c->func;424425/* Direction culling has already been done.426*/427if (c->key.fill_ccw != c->key.fill_cw &&428c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL &&429c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL)430{431brw_CMP(p,432vec1(brw_null_reg()),433BRW_CONDITIONAL_GE,434get_element(c->reg.dir, 2),435brw_imm_f(0));436437brw_IF(p, BRW_EXECUTE_1);438{439emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);440}441brw_ELSE(p);442{443emit_primitives(c, c->key.fill_cw, c->key.offset_cw);444}445brw_ENDIF(p);446}447else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) {448emit_primitives(c, c->key.fill_cw, c->key.offset_cw);449}450else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) {451emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);452}453}454455456457458static void check_nr_verts( struct brw_clip_compile *c )459{460struct brw_codegen *p = &c->func;461462brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));463brw_IF(p, BRW_EXECUTE_1);464{465brw_clip_kill_thread(c);466}467brw_ENDIF(p);468}469470471void brw_emit_unfilled_clip( struct brw_clip_compile *c )472{473struct brw_codegen *p = &c->func;474475c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||476(c->key.fill_ccw != c->key.fill_cw) ||477c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||478c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL ||479c->key.copy_bfc_cw ||480c->key.copy_bfc_ccw);481482brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);483brw_clip_tri_init_vertices(c);484brw_clip_init_ff_sync(c);485486assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE));487488if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&489c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) {490brw_clip_kill_thread(c);491return;492}493494merge_edgeflags(c);495496/* Need to use the inlist indirection here:497*/498if (c->need_direction)499compute_tri_direction(c);500501if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||502c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)503cull_direction(c);504505if (c->key.offset_ccw ||506c->key.offset_cw)507compute_offset(c);508509if (c->key.copy_bfc_ccw ||510c->key.copy_bfc_cw)511copy_bfc(c);512513/* Need to do this whether we clip or not:514*/515if (c->key.contains_flat_varying)516brw_clip_tri_flat_shade(c);517518brw_clip_init_clipmask(c);519brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));520brw_IF(p, BRW_EXECUTE_1);521{522brw_clip_init_planes(c);523brw_clip_tri(c);524check_nr_verts(c);525}526brw_ENDIF(p);527528emit_unfilled_primitives(c);529brw_clip_kill_thread(c);530}531532533