Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pipe_user_cull.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/**28* \brief Drawing stage for user culling29*/3031#include "util/u_math.h"32#include "util/u_memory.h"33#include "pipe/p_defines.h"34#include "draw_pipe.h"3536struct user_cull_stage {37struct draw_stage stage;38};3940static inline struct user_cull_stage *user_cull_stage( struct draw_stage *stage )41{42return (struct user_cull_stage *)stage;43}4445static inline boolean46cull_distance_is_out(float dist)47{48return (dist < 0.0f) || util_is_inf_or_nan(dist);49}5051/*52* If the shader writes the culldistance then we can53* perform distance based culling. Distance based54* culling doesn't require a face and can be performed55* on primitives without faces (e.g. points and lines)56*/57static void user_cull_point( struct draw_stage *stage,58struct prim_header *header )59{60const unsigned num_written_culldistances =61draw_current_shader_num_written_culldistances(stage->draw);62const unsigned num_written_clipdistances =63draw_current_shader_num_written_clipdistances(stage->draw);64unsigned i;6566debug_assert(num_written_culldistances);6768for (i = 0; i < num_written_culldistances; ++i) {69unsigned cull_idx = (num_written_clipdistances + i) / 4;70unsigned out_idx =71draw_current_shader_ccdistance_output(stage->draw, cull_idx);72unsigned idx = (num_written_clipdistances + i) % 4;73float cull1 = header->v[0]->data[out_idx][idx];74boolean vert1_out = cull_distance_is_out(cull1);75if (vert1_out)76return;77}78stage->next->point( stage->next, header );79}8081/*82* If the shader writes the culldistance then we can83* perform distance based culling. Distance based84* culling doesn't require a face and can be performed85* on primitives without faces (e.g. points and lines)86*/87static void user_cull_line( struct draw_stage *stage,88struct prim_header *header )89{90const unsigned num_written_culldistances =91draw_current_shader_num_written_culldistances(stage->draw);92const unsigned num_written_clipdistances =93draw_current_shader_num_written_clipdistances(stage->draw);94unsigned i;9596debug_assert(num_written_culldistances);9798for (i = 0; i < num_written_culldistances; ++i) {99unsigned cull_idx = (num_written_clipdistances + i) / 4;100unsigned out_idx =101draw_current_shader_ccdistance_output(stage->draw, cull_idx);102unsigned idx = (num_written_clipdistances + i) % 4;103float cull1 = header->v[0]->data[out_idx][idx];104float cull2 = header->v[1]->data[out_idx][idx];105boolean vert1_out = cull_distance_is_out(cull1);106boolean vert2_out = cull_distance_is_out(cull2);107if (vert1_out && vert2_out)108return;109}110stage->next->line( stage->next, header );111}112113/*114* Triangles can be culled either using the cull distance115* shader outputs or the regular face culling. If required116* this function performs both, starting with distance culling.117*/118static void user_cull_tri( struct draw_stage *stage,119struct prim_header *header )120{121const unsigned num_written_culldistances =122draw_current_shader_num_written_culldistances(stage->draw);123const unsigned num_written_clipdistances =124draw_current_shader_num_written_clipdistances(stage->draw);125unsigned i;126127debug_assert(num_written_culldistances);128129/* Do the distance culling */130for (i = 0; i < num_written_culldistances; ++i) {131unsigned cull_idx = (num_written_clipdistances + i) / 4;132unsigned out_idx =133draw_current_shader_ccdistance_output(stage->draw, cull_idx);134unsigned idx = (num_written_clipdistances + i) % 4;135float cull1 = header->v[0]->data[out_idx][idx];136float cull2 = header->v[1]->data[out_idx][idx];137float cull3 = header->v[2]->data[out_idx][idx];138boolean vert1_out = cull_distance_is_out(cull1);139boolean vert2_out = cull_distance_is_out(cull2);140boolean vert3_out = cull_distance_is_out(cull3);141if (vert1_out && vert2_out && vert3_out) {142return;143}144}145stage->next->tri( stage->next, header );146}147148static void user_cull_flush( struct draw_stage *stage, unsigned flags )149{150stage->point = user_cull_point;151stage->line = user_cull_line;152stage->tri = user_cull_tri;153stage->next->flush( stage->next, flags );154}155156static void user_cull_reset_stipple_counter( struct draw_stage *stage )157{158stage->next->reset_stipple_counter( stage->next );159}160161static void user_cull_destroy( struct draw_stage *stage )162{163draw_free_temp_verts( stage );164FREE( stage );165}166167/**168* Create a new polygon culling stage.169*/170struct draw_stage *draw_user_cull_stage( struct draw_context *draw )171{172struct user_cull_stage *user_cull = CALLOC_STRUCT(user_cull_stage);173if (!user_cull)174goto fail;175176user_cull->stage.draw = draw;177user_cull->stage.name = "user_cull";178user_cull->stage.next = NULL;179user_cull->stage.point = user_cull_point;180user_cull->stage.line = user_cull_line;181user_cull->stage.tri = user_cull_tri;182user_cull->stage.flush = user_cull_flush;183user_cull->stage.reset_stipple_counter = user_cull_reset_stipple_counter;184user_cull->stage.destroy = user_cull_destroy;185186if (!draw_alloc_temp_verts( &user_cull->stage, 0 ))187goto fail;188189return &user_cull->stage;190191fail:192if (user_cull)193user_cull->stage.destroy( &user_cull->stage );194195return NULL;196}197198199