Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pipe_unfilled.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 handling glPolygonMode(line/point).29* Convert triangles to points or lines as needed.30*/3132/* Authors: Keith Whitwell <[email protected]>33*/3435#include "util/u_memory.h"36#include "pipe/p_defines.h"37#include "draw_private.h"38#include "draw_pipe.h"39#include "draw_fs.h"404142struct unfilled_stage {43struct draw_stage stage;4445/** [0] = front face, [1] = back face.46* legal values: PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,47* and PIPE_POLYGON_MODE_POINT,48*/49unsigned mode[2];5051int face_slot;52};535455static inline struct unfilled_stage *unfilled_stage( struct draw_stage *stage )56{57return (struct unfilled_stage *)stage;58}5960static void61inject_front_face_info(struct draw_stage *stage,62struct prim_header *header)63{64struct unfilled_stage *unfilled = unfilled_stage(stage);65boolean is_front_face = (66(stage->draw->rasterizer->front_ccw && header->det < 0.0f) ||67(!stage->draw->rasterizer->front_ccw && header->det > 0.0f));68int slot = unfilled->face_slot;69unsigned i;7071/* In case the backend doesn't care about it */72if (slot < 0) {73return;74}7576for (i = 0; i < 3; ++i) {77struct vertex_header *v = header->v[i];78v->data[slot][0] = is_front_face;79v->data[slot][1] = is_front_face;80v->data[slot][2] = is_front_face;81v->data[slot][3] = is_front_face;82v->vertex_id = UNDEFINED_VERTEX_ID;83}84}858687static void point(struct draw_stage *stage,88struct prim_header *header,89struct vertex_header *v0)90{91struct prim_header tmp;92tmp.det = header->det;93tmp.flags = 0;94tmp.v[0] = v0;95stage->next->point(stage->next, &tmp);96}9798static void line(struct draw_stage *stage,99struct prim_header *header,100struct vertex_header *v0,101struct vertex_header *v1)102{103struct prim_header tmp;104tmp.det = header->det;105tmp.flags = 0;106tmp.v[0] = v0;107tmp.v[1] = v1;108stage->next->line(stage->next, &tmp);109}110111112static void points(struct draw_stage *stage,113struct prim_header *header)114{115struct vertex_header *v0 = header->v[0];116struct vertex_header *v1 = header->v[1];117struct vertex_header *v2 = header->v[2];118119inject_front_face_info(stage, header);120121if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag)122point(stage, header, v0);123if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag)124point(stage, header, v1);125if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag)126point(stage, header, v2);127}128129130static void lines(struct draw_stage *stage,131struct prim_header *header)132{133struct vertex_header *v0 = header->v[0];134struct vertex_header *v1 = header->v[1];135struct vertex_header *v2 = header->v[2];136137if (header->flags & DRAW_PIPE_RESET_STIPPLE)138/*139* XXX could revisit this. The only stage which cares is the line140* stipple stage. Could just emit correct reset flags here and not141* bother about all the calling through reset_stipple_counter142* stages. Though technically it is necessary if line stipple is143* handled by the driver, but this is not actually hooked up when144* using vbuf (vbuf stage reset_stipple_counter does nothing).145*/146stage->next->reset_stipple_counter(stage->next);147148inject_front_face_info(stage, header);149150if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag)151line(stage, header, v2, v0);152if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag)153line(stage, header, v0, v1);154if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag)155line(stage, header, v1, v2);156}157158159/** For debugging */160static void161print_header_flags(unsigned flags)162{163debug_printf("header->flags = ");164if (flags & DRAW_PIPE_RESET_STIPPLE)165debug_printf("RESET_STIPPLE ");166if (flags & DRAW_PIPE_EDGE_FLAG_0)167debug_printf("EDGE_FLAG_0 ");168if (flags & DRAW_PIPE_EDGE_FLAG_1)169debug_printf("EDGE_FLAG_1 ");170if (flags & DRAW_PIPE_EDGE_FLAG_2)171debug_printf("EDGE_FLAG_2 ");172debug_printf("\n");173}174175176/* Unfilled tri:177*178* Note edgeflags in the vertex struct is not sufficient as we will179* need to manipulate them when decomposing primitives.180*181* We currently keep the vertex edgeflag and primitive edgeflag mask182* separate until the last possible moment.183*/184static void unfilled_tri( struct draw_stage *stage,185struct prim_header *header )186{187struct unfilled_stage *unfilled = unfilled_stage(stage);188unsigned cw = header->det >= 0.0;189unsigned mode = unfilled->mode[cw];190191if (0)192print_header_flags(header->flags);193194switch (mode) {195case PIPE_POLYGON_MODE_FILL:196stage->next->tri( stage->next, header );197break;198case PIPE_POLYGON_MODE_LINE:199lines( stage, header );200break;201case PIPE_POLYGON_MODE_POINT:202points( stage, header );203break;204default:205assert(0);206}207}208209210static void unfilled_first_tri( struct draw_stage *stage,211struct prim_header *header )212{213struct unfilled_stage *unfilled = unfilled_stage(stage);214const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;215216unfilled->mode[0] = rast->front_ccw ? rast->fill_front : rast->fill_back;217unfilled->mode[1] = rast->front_ccw ? rast->fill_back : rast->fill_front;218219stage->tri = unfilled_tri;220stage->tri( stage, header );221}222223224225static void unfilled_flush( struct draw_stage *stage,226unsigned flags )227{228stage->next->flush( stage->next, flags );229230stage->tri = unfilled_first_tri;231}232233234static void unfilled_reset_stipple_counter( struct draw_stage *stage )235{236stage->next->reset_stipple_counter( stage->next );237}238239240static void unfilled_destroy( struct draw_stage *stage )241{242draw_free_temp_verts( stage );243FREE( stage );244}245246/*247* Try to allocate an output slot which we can use248* to preserve the front face information.249*/250void251draw_unfilled_prepare_outputs( struct draw_context *draw,252struct draw_stage *stage )253{254struct unfilled_stage *unfilled = unfilled_stage(stage);255const struct pipe_rasterizer_state *rast = draw ? draw->rasterizer : 0;256boolean is_unfilled = (rast &&257(rast->fill_front != PIPE_POLYGON_MODE_FILL ||258rast->fill_back != PIPE_POLYGON_MODE_FILL));259const struct draw_fragment_shader *fs = draw ? draw->fs.fragment_shader : 0;260261if (is_unfilled && fs && fs->info.uses_frontface) {262unfilled->face_slot = draw_alloc_extra_vertex_attrib(263stage->draw, TGSI_SEMANTIC_FACE, 0);264} else {265unfilled->face_slot = -1;266}267}268269270/**271* Create unfilled triangle stage.272*/273struct draw_stage *draw_unfilled_stage( struct draw_context *draw )274{275struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);276if (!unfilled)277goto fail;278279unfilled->stage.draw = draw;280unfilled->stage.name = "unfilled";281unfilled->stage.next = NULL;282unfilled->stage.tmp = NULL;283unfilled->stage.point = draw_pipe_passthrough_point;284unfilled->stage.line = draw_pipe_passthrough_line;285unfilled->stage.tri = unfilled_first_tri;286unfilled->stage.flush = unfilled_flush;287unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;288unfilled->stage.destroy = unfilled_destroy;289290unfilled->face_slot = -1;291292if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))293goto fail;294295return &unfilled->stage;296297fail:298if (unfilled)299unfilled->stage.destroy( &unfilled->stage );300301return NULL;302}303304305