1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * \brief Drawing stage for polygon culling 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci/* Authors: Keith Whitwell <keithw@vmware.com> 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "util/u_math.h" 37bf215546Sopenharmony_ci#include "util/u_memory.h" 38bf215546Sopenharmony_ci#include "pipe/p_defines.h" 39bf215546Sopenharmony_ci#include "draw_pipe.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cistruct cull_stage { 43bf215546Sopenharmony_ci struct draw_stage stage; 44bf215546Sopenharmony_ci unsigned cull_face; /**< which face(s) to cull (one of PIPE_FACE_x) */ 45bf215546Sopenharmony_ci unsigned front_ccw; 46bf215546Sopenharmony_ci}; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_cistatic inline struct cull_stage *cull_stage( struct draw_stage *stage ) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci return (struct cull_stage *)stage; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/* 55bf215546Sopenharmony_ci * Triangles can be culled using regular face cull. 56bf215546Sopenharmony_ci */ 57bf215546Sopenharmony_cistatic void cull_tri( struct draw_stage *stage, 58bf215546Sopenharmony_ci struct prim_header *header ) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci /* Do the regular face culling */ 61bf215546Sopenharmony_ci { 62bf215546Sopenharmony_ci const unsigned pos = draw_current_shader_position_output(stage->draw); 63bf215546Sopenharmony_ci /* Window coords: */ 64bf215546Sopenharmony_ci const float *v0 = header->v[0]->data[pos]; 65bf215546Sopenharmony_ci const float *v1 = header->v[1]->data[pos]; 66bf215546Sopenharmony_ci const float *v2 = header->v[2]->data[pos]; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci /* edge vectors: e = v0 - v2, f = v1 - v2 */ 69bf215546Sopenharmony_ci const float ex = v0[0] - v2[0]; 70bf215546Sopenharmony_ci const float ey = v0[1] - v2[1]; 71bf215546Sopenharmony_ci const float fx = v1[0] - v2[0]; 72bf215546Sopenharmony_ci const float fy = v1[1] - v2[1]; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci /* det = cross(e,f).z */ 76bf215546Sopenharmony_ci header->det = ex * fy - ey * fx; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (header->det != 0) { 79bf215546Sopenharmony_ci /* if det < 0 then Z points toward the camera and the triangle is 80bf215546Sopenharmony_ci * counter-clockwise winding. 81bf215546Sopenharmony_ci */ 82bf215546Sopenharmony_ci unsigned ccw = (header->det < 0); 83bf215546Sopenharmony_ci unsigned face = ((ccw == cull_stage(stage)->front_ccw) ? 84bf215546Sopenharmony_ci PIPE_FACE_FRONT : 85bf215546Sopenharmony_ci PIPE_FACE_BACK); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci if ((face & cull_stage(stage)->cull_face) == 0) { 88bf215546Sopenharmony_ci /* triangle is not culled, pass to next stage */ 89bf215546Sopenharmony_ci stage->next->tri( stage->next, header ); 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci } else { 92bf215546Sopenharmony_ci /* 93bf215546Sopenharmony_ci * With zero area, this is back facing (because the spec says 94bf215546Sopenharmony_ci * it's front facing if sign is positive?). 95bf215546Sopenharmony_ci * Some apis apparently do not allow us to cull zero area tris 96bf215546Sopenharmony_ci * here, in case of fill mode line (which is rather lame). 97bf215546Sopenharmony_ci */ 98bf215546Sopenharmony_ci if ((PIPE_FACE_BACK & cull_stage(stage)->cull_face) == 0) { 99bf215546Sopenharmony_ci stage->next->tri( stage->next, header ); 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_cistatic void cull_first_tri( struct draw_stage *stage, 106bf215546Sopenharmony_ci struct prim_header *header ) 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci struct cull_stage *cull = cull_stage(stage); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci cull->cull_face = stage->draw->rasterizer->cull_face; 111bf215546Sopenharmony_ci cull->front_ccw = stage->draw->rasterizer->front_ccw; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci stage->tri = cull_tri; 114bf215546Sopenharmony_ci stage->tri( stage, header ); 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_cistatic void cull_flush( struct draw_stage *stage, unsigned flags ) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci stage->tri = cull_first_tri; 121bf215546Sopenharmony_ci stage->next->flush( stage->next, flags ); 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_cistatic void cull_reset_stipple_counter( struct draw_stage *stage ) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci stage->next->reset_stipple_counter( stage->next ); 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic void cull_destroy( struct draw_stage *stage ) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci draw_free_temp_verts( stage ); 134bf215546Sopenharmony_ci FREE( stage ); 135bf215546Sopenharmony_ci} 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci/** 139bf215546Sopenharmony_ci * Create a new polygon culling stage. 140bf215546Sopenharmony_ci */ 141bf215546Sopenharmony_cistruct draw_stage *draw_cull_stage( struct draw_context *draw ) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci struct cull_stage *cull = CALLOC_STRUCT(cull_stage); 144bf215546Sopenharmony_ci if (!cull) 145bf215546Sopenharmony_ci goto fail; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci cull->stage.draw = draw; 148bf215546Sopenharmony_ci cull->stage.name = "cull"; 149bf215546Sopenharmony_ci cull->stage.next = NULL; 150bf215546Sopenharmony_ci cull->stage.point = draw_pipe_passthrough_point; 151bf215546Sopenharmony_ci cull->stage.line = draw_pipe_passthrough_line; 152bf215546Sopenharmony_ci cull->stage.tri = cull_first_tri; 153bf215546Sopenharmony_ci cull->stage.flush = cull_flush; 154bf215546Sopenharmony_ci cull->stage.reset_stipple_counter = cull_reset_stipple_counter; 155bf215546Sopenharmony_ci cull->stage.destroy = cull_destroy; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci if (!draw_alloc_temp_verts( &cull->stage, 0 )) 158bf215546Sopenharmony_ci goto fail; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci return &cull->stage; 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_cifail: 163bf215546Sopenharmony_ci if (cull) 164bf215546Sopenharmony_ci cull->stage.destroy( &cull->stage ); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci return NULL; 167bf215546Sopenharmony_ci} 168