00001 /************************************************************************** 00002 * 00003 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 00004 * All Rights Reserved. 00005 * 00006 * Permission is hereby granted, free of charge, to any person obtaining a 00007 * copy of this software and associated documentation files (the 00008 * "Software"), to deal in the Software without restriction, including 00009 * without limitation the rights to use, copy, modify, merge, publish, 00010 * distribute, sub license, and/or sell copies of the Software, and to 00011 * permit persons to whom the Software is furnished to do so, subject to 00012 * the following conditions: 00013 * 00014 * The above copyright notice and this permission notice (including the 00015 * next paragraph) shall be included in all copies or substantial portions 00016 * of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00019 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00020 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 00021 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 00022 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 00023 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 00024 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00025 * 00026 **************************************************************************/ 00027 00032 /* Authors: Keith Whitwell <keith@tungstengraphics.com> 00033 */ 00034 00035 00036 #include "util/u_memory.h" 00037 #include "pipe/p_defines.h" 00038 #include "draw_pipe.h" 00039 00040 00041 struct cull_stage { 00042 struct draw_stage stage; 00043 unsigned winding; 00044 }; 00045 00046 00047 static INLINE struct cull_stage *cull_stage( struct draw_stage *stage ) 00048 { 00049 return (struct cull_stage *)stage; 00050 } 00051 00052 00053 00054 00055 static void cull_tri( struct draw_stage *stage, 00056 struct prim_header *header ) 00057 { 00058 const unsigned pos = stage->draw->vs.position_output; 00059 00060 /* Window coords: */ 00061 const float *v0 = header->v[0]->data[pos]; 00062 const float *v1 = header->v[1]->data[pos]; 00063 const float *v2 = header->v[2]->data[pos]; 00064 00065 /* edge vectors e = v0 - v2, f = v1 - v2 */ 00066 const float ex = v0[0] - v2[0]; 00067 const float ey = v0[1] - v2[1]; 00068 const float fx = v1[0] - v2[0]; 00069 const float fy = v1[1] - v2[1]; 00070 00071 /* det = cross(e,f).z */ 00072 header->det = ex * fy - ey * fx; 00073 00074 if (header->det != 0) { 00075 /* if (det < 0 then Z points toward camera and triangle is 00076 * counter-clockwise winding. 00077 */ 00078 unsigned winding = (header->det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; 00079 00080 if ((winding & cull_stage(stage)->winding) == 0) { 00081 /* triangle is not culled, pass to next stage */ 00082 stage->next->tri( stage->next, header ); 00083 } 00084 } 00085 } 00086 00087 static void cull_first_tri( struct draw_stage *stage, 00088 struct prim_header *header ) 00089 { 00090 struct cull_stage *cull = cull_stage(stage); 00091 00092 cull->winding = stage->draw->rasterizer->cull_mode; 00093 00094 stage->tri = cull_tri; 00095 stage->tri( stage, header ); 00096 } 00097 00098 00099 00100 static void cull_flush( struct draw_stage *stage, unsigned flags ) 00101 { 00102 stage->tri = cull_first_tri; 00103 stage->next->flush( stage->next, flags ); 00104 } 00105 00106 static void cull_reset_stipple_counter( struct draw_stage *stage ) 00107 { 00108 stage->next->reset_stipple_counter( stage->next ); 00109 } 00110 00111 00112 static void cull_destroy( struct draw_stage *stage ) 00113 { 00114 draw_free_temp_verts( stage ); 00115 FREE( stage ); 00116 } 00117 00118 00122 struct draw_stage *draw_cull_stage( struct draw_context *draw ) 00123 { 00124 struct cull_stage *cull = CALLOC_STRUCT(cull_stage); 00125 if (cull == NULL) 00126 goto fail; 00127 00128 if (!draw_alloc_temp_verts( &cull->stage, 0 )) 00129 goto fail; 00130 00131 cull->stage.draw = draw; 00132 cull->stage.next = NULL; 00133 cull->stage.point = draw_pipe_passthrough_point; 00134 cull->stage.line = draw_pipe_passthrough_line; 00135 cull->stage.tri = cull_first_tri; 00136 cull->stage.flush = cull_flush; 00137 cull->stage.reset_stipple_counter = cull_reset_stipple_counter; 00138 cull->stage.destroy = cull_destroy; 00139 00140 return &cull->stage; 00141 00142 fail: 00143 if (cull) 00144 cull->stage.destroy( &cull->stage ); 00145 00146 return NULL; 00147 }