18e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell/**************************************************************************
28e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell *
38e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
48e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * All Rights Reserved.
58e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell *
68e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
78e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * copy of this software and associated documentation files (the
88e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * "Software"), to deal in the Software without restriction, including
98e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * without limitation the rights to use, copy, modify, merge, publish,
108e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * distribute, sub license, and/or sell copies of the Software, and to
118e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * permit persons to whom the Software is furnished to do so, subject to
128e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * the following conditions:
138e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell *
148e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * The above copyright notice and this permission notice (including the
158e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * next paragraph) shall be included in all copies or substantial portions
168e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * of the Software.
178e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell *
188e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
198e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
208e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
218e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
228e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
238e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
248e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell *
268e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell **************************************************************************/
278e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
28720c0eb71db9908c5ecef15263c2ae638d61d07bBrian/**
29720c0eb71db9908c5ecef15263c2ae638d61d07bBrian * \brief  Drawing stage for polygon culling
30720c0eb71db9908c5ecef15263c2ae638d61d07bBrian */
31720c0eb71db9908c5ecef15263c2ae638d61d07bBrian
328e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
338e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell */
348e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
35720c0eb71db9908c5ecef15263c2ae638d61d07bBrian
364f25420bdd834e81a3e22733304efc5261c2998aBrian Paul#include "util/u_memory.h"
37f79c225d9e5adee6287a9bba35f014c3fe00d3f9Brian#include "pipe/p_defines.h"
38507fbe2d327efb8d608ce8e07436b97321560808Keith Whitwell#include "draw_pipe.h"
398e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
408e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
418e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwellstruct cull_stage {
42ea470eec86715cd2bc9aa86d36e6ea803d0d4017Brian   struct draw_stage stage;
430bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell   unsigned cull_face;  /**< which face(s) to cull (one of PIPE_FACE_x) */
440bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell   unsigned front_ccw;
458e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell};
468e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
478e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
48ea470eec86715cd2bc9aa86d36e6ea803d0d4017Brianstatic INLINE struct cull_stage *cull_stage( struct draw_stage *stage )
498e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell{
508e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   return (struct cull_stage *)stage;
518e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell}
528e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
538e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
54ea470eec86715cd2bc9aa86d36e6ea803d0d4017Brianstatic void cull_tri( struct draw_stage *stage,
558e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell		      struct prim_header *header )
568e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell{
5789d8577fb3036547ef0b47498cc8dc5c77f886e0Zack Rusin   const unsigned pos = draw_current_shader_position_output(stage->draw);
582161b0fafcdc16703162dd489d2ec1e7114cce4cKeith Whitwell
598e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   /* Window coords: */
602161b0fafcdc16703162dd489d2ec1e7114cce4cKeith Whitwell   const float *v0 = header->v[0]->data[pos];
612161b0fafcdc16703162dd489d2ec1e7114cce4cKeith Whitwell   const float *v1 = header->v[1]->data[pos];
622161b0fafcdc16703162dd489d2ec1e7114cce4cKeith Whitwell   const float *v2 = header->v[2]->data[pos];
638e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
645023a7f53f4b11cdea1ed90d7e856b6eda6dd68eBrian Paul   /* edge vectors: e = v0 - v2, f = v1 - v2 */
653fc926f3740da9ec27853d158243055f3cb43d43Brian   const float ex = v0[0] - v2[0];
663fc926f3740da9ec27853d158243055f3cb43d43Brian   const float ey = v0[1] - v2[1];
673fc926f3740da9ec27853d158243055f3cb43d43Brian   const float fx = v1[0] - v2[0];
683fc926f3740da9ec27853d158243055f3cb43d43Brian   const float fy = v1[1] - v2[1];
698e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
706aa9c8ebc19ffa4425669862caeb99b22c079090Brian   /* det = cross(e,f).z */
718e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   header->det = ex * fy - ey * fx;
728e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
738e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   if (header->det != 0) {
745023a7f53f4b11cdea1ed90d7e856b6eda6dd68eBrian Paul      /* if det < 0 then Z points toward the camera and the triangle is
75dc313b578386dc07f4916fba98da061af3ab18e5Brian       * counter-clockwise winding.
76dc313b578386dc07f4916fba98da061af3ab18e5Brian       */
770bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell      unsigned ccw = (header->det < 0);
780bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell      unsigned face = ((ccw == cull_stage(stage)->front_ccw) ?
790bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell                       PIPE_FACE_FRONT :
800bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell                       PIPE_FACE_BACK);
81f79c225d9e5adee6287a9bba35f014c3fe00d3f9Brian
820bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell      if ((face & cull_stage(stage)->cull_face) == 0) {
83279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian         /* triangle is not culled, pass to next stage */
848e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell	 stage->next->tri( stage->next, header );
85279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian      }
868e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   }
878e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell}
888e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
895023a7f53f4b11cdea1ed90d7e856b6eda6dd68eBrian Paul
900bfd085e2866fbbd40209dcee23f0e6240583fe8Brianstatic void cull_first_tri( struct draw_stage *stage,
910bfd085e2866fbbd40209dcee23f0e6240583fe8Brian			    struct prim_header *header )
920bfd085e2866fbbd40209dcee23f0e6240583fe8Brian{
930bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   struct cull_stage *cull = cull_stage(stage);
940bfd085e2866fbbd40209dcee23f0e6240583fe8Brian
950bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell   cull->cull_face = stage->draw->rasterizer->cull_face;
960bd1cbcd0d28dbadfb0c3e1f8b048a18b56bc72cKeith Whitwell   cull->front_ccw = stage->draw->rasterizer->front_ccw;
970bfd085e2866fbbd40209dcee23f0e6240583fe8Brian
980bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   stage->tri = cull_tri;
990bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   stage->tri( stage, header );
1000bfd085e2866fbbd40209dcee23f0e6240583fe8Brian}
1010bfd085e2866fbbd40209dcee23f0e6240583fe8Brian
1020bfd085e2866fbbd40209dcee23f0e6240583fe8Brian
1030bfd085e2866fbbd40209dcee23f0e6240583fe8Brianstatic void cull_flush( struct draw_stage *stage, unsigned flags )
1048e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell{
1050bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   stage->tri = cull_first_tri;
1060bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   stage->next->flush( stage->next, flags );
1078e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell}
1088e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
1095023a7f53f4b11cdea1ed90d7e856b6eda6dd68eBrian Paul
1100360b49afbcd839f99ba0745d01cf9dc5be4d122Brianstatic void cull_reset_stipple_counter( struct draw_stage *stage )
1110360b49afbcd839f99ba0745d01cf9dc5be4d122Brian{
1120360b49afbcd839f99ba0745d01cf9dc5be4d122Brian   stage->next->reset_stipple_counter( stage->next );
1130360b49afbcd839f99ba0745d01cf9dc5be4d122Brian}
1140360b49afbcd839f99ba0745d01cf9dc5be4d122Brian
115d75454840672f462de933724daae24a839aac48eMichal
116d75454840672f462de933724daae24a839aac48eMichalstatic void cull_destroy( struct draw_stage *stage )
117d75454840672f462de933724daae24a839aac48eMichal{
118b08102a8f3ef558743f5f952c726ba2c28b6e82eBrian   draw_free_temp_verts( stage );
119d75454840672f462de933724daae24a839aac48eMichal   FREE( stage );
120d75454840672f462de933724daae24a839aac48eMichal}
121d75454840672f462de933724daae24a839aac48eMichal
122d75454840672f462de933724daae24a839aac48eMichal
123279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian/**
124279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian * Create a new polygon culling stage.
125279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian */
126ea470eec86715cd2bc9aa86d36e6ea803d0d4017Brianstruct draw_stage *draw_cull_stage( struct draw_context *draw )
1278e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell{
1288e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   struct cull_stage *cull = CALLOC_STRUCT(cull_stage);
1290d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell   if (cull == NULL)
1300d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell      goto fail;
1318e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
132279ffe3f163fd6a5e7bfa108db14c81acbb06eceBrian   cull->stage.draw = draw;
133eb979cef8535914f428d2462e78f713da558fc18Keith Whitwell   cull->stage.name = "cull";
1348e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   cull->stage.next = NULL;
135a918a9c744f656c8bf2e3fd2841732e01a5ccefcKeith Whitwell   cull->stage.point = draw_pipe_passthrough_point;
136a918a9c744f656c8bf2e3fd2841732e01a5ccefcKeith Whitwell   cull->stage.line = draw_pipe_passthrough_line;
1370bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   cull->stage.tri = cull_first_tri;
1380bfd085e2866fbbd40209dcee23f0e6240583fe8Brian   cull->stage.flush = cull_flush;
1390360b49afbcd839f99ba0745d01cf9dc5be4d122Brian   cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
140d75454840672f462de933724daae24a839aac48eMichal   cull->stage.destroy = cull_destroy;
1418e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell
1421c377cea1094c0b5414c663adf2fd393bf41ddfbAlan Hourihane   if (!draw_alloc_temp_verts( &cull->stage, 0 ))
1431c377cea1094c0b5414c663adf2fd393bf41ddfbAlan Hourihane      goto fail;
1441c377cea1094c0b5414c663adf2fd393bf41ddfbAlan Hourihane
1458e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell   return &cull->stage;
1460d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell
1475023a7f53f4b11cdea1ed90d7e856b6eda6dd68eBrian Paulfail:
1480d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell   if (cull)
1490d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell      cull->stage.destroy( &cull->stage );
1500d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell
1510d4ece4c5a243dc4b684331bad49f220311e5520Keith Whitwell   return NULL;
1528e4a95a93d15a6707a29454cd47e10b08314cda2Keith Whitwell}
153