Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 /**
     29  * \brief  Drawing stage for handling glPolygonMode(line/point).
     30  * Convert triangles to points or lines as needed.
     31  */
     32 
     33 /* Authors:  Keith Whitwell <keith (at) tungstengraphics.com>
     34  */
     35 
     36 #include "util/u_memory.h"
     37 #include "pipe/p_defines.h"
     38 #include "draw_private.h"
     39 #include "draw_pipe.h"
     40 
     41 
     42 struct unfilled_stage {
     43    struct draw_stage stage;
     44 
     45    /** [0] = front face, [1] = back face.
     46     * legal values:  PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,
     47     * and PIPE_POLYGON_MODE_POINT,
     48     */
     49    unsigned mode[2];
     50 };
     51 
     52 
     53 static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
     54 {
     55    return (struct unfilled_stage *)stage;
     56 }
     57 
     58 
     59 
     60 static void point( struct draw_stage *stage,
     61 		   struct vertex_header *v0 )
     62 {
     63    struct prim_header tmp;
     64    tmp.v[0] = v0;
     65    stage->next->point( stage->next, &tmp );
     66 }
     67 
     68 static void line( struct draw_stage *stage,
     69 		  struct vertex_header *v0,
     70 		  struct vertex_header *v1 )
     71 {
     72    struct prim_header tmp;
     73    tmp.v[0] = v0;
     74    tmp.v[1] = v1;
     75    stage->next->line( stage->next, &tmp );
     76 }
     77 
     78 
     79 static void points( struct draw_stage *stage,
     80 		    struct prim_header *header )
     81 {
     82    struct vertex_header *v0 = header->v[0];
     83    struct vertex_header *v1 = header->v[1];
     84    struct vertex_header *v2 = header->v[2];
     85 
     86    if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) point( stage, v0 );
     87    if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) point( stage, v1 );
     88    if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) point( stage, v2 );
     89 }
     90 
     91 
     92 static void lines( struct draw_stage *stage,
     93 		   struct prim_header *header )
     94 {
     95    struct vertex_header *v0 = header->v[0];
     96    struct vertex_header *v1 = header->v[1];
     97    struct vertex_header *v2 = header->v[2];
     98 
     99    if (header->flags & DRAW_PIPE_RESET_STIPPLE)
    100       stage->next->reset_stipple_counter( stage->next );
    101 
    102    if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) line( stage, v2, v0 );
    103    if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) line( stage, v0, v1 );
    104    if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) line( stage, v1, v2 );
    105 }
    106 
    107 
    108 /** For debugging */
    109 static void
    110 print_header_flags(unsigned flags)
    111 {
    112    debug_printf("header->flags = ");
    113    if (flags & DRAW_PIPE_RESET_STIPPLE)
    114       debug_printf("RESET_STIPPLE ");
    115    if (flags & DRAW_PIPE_EDGE_FLAG_0)
    116       debug_printf("EDGE_FLAG_0 ");
    117    if (flags & DRAW_PIPE_EDGE_FLAG_1)
    118       debug_printf("EDGE_FLAG_1 ");
    119    if (flags & DRAW_PIPE_EDGE_FLAG_2)
    120       debug_printf("EDGE_FLAG_2 ");
    121    debug_printf("\n");
    122 }
    123 
    124 
    125 /* Unfilled tri:
    126  *
    127  * Note edgeflags in the vertex struct is not sufficient as we will
    128  * need to manipulate them when decomposing primitives.
    129  *
    130  * We currently keep the vertex edgeflag and primitive edgeflag mask
    131  * separate until the last possible moment.
    132  */
    133 static void unfilled_tri( struct draw_stage *stage,
    134 			  struct prim_header *header )
    135 {
    136    struct unfilled_stage *unfilled = unfilled_stage(stage);
    137    unsigned cw = header->det >= 0.0;
    138    unsigned mode = unfilled->mode[cw];
    139 
    140    if (0)
    141       print_header_flags(header->flags);
    142 
    143    switch (mode) {
    144    case PIPE_POLYGON_MODE_FILL:
    145       stage->next->tri( stage->next, header );
    146       break;
    147    case PIPE_POLYGON_MODE_LINE:
    148       lines( stage, header );
    149       break;
    150    case PIPE_POLYGON_MODE_POINT:
    151       points( stage, header );
    152       break;
    153    default:
    154       assert(0);
    155    }
    156 }
    157 
    158 
    159 static void unfilled_first_tri( struct draw_stage *stage,
    160 				struct prim_header *header )
    161 {
    162    struct unfilled_stage *unfilled = unfilled_stage(stage);
    163    const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;
    164 
    165    unfilled->mode[0] = rast->front_ccw ? rast->fill_front : rast->fill_back;
    166    unfilled->mode[1] = rast->front_ccw ? rast->fill_back : rast->fill_front;
    167 
    168    stage->tri = unfilled_tri;
    169    stage->tri( stage, header );
    170 }
    171 
    172 
    173 
    174 static void unfilled_flush( struct draw_stage *stage,
    175 			    unsigned flags )
    176 {
    177    stage->next->flush( stage->next, flags );
    178 
    179    stage->tri = unfilled_first_tri;
    180 }
    181 
    182 
    183 static void unfilled_reset_stipple_counter( struct draw_stage *stage )
    184 {
    185    stage->next->reset_stipple_counter( stage->next );
    186 }
    187 
    188 
    189 static void unfilled_destroy( struct draw_stage *stage )
    190 {
    191    draw_free_temp_verts( stage );
    192    FREE( stage );
    193 }
    194 
    195 
    196 /**
    197  * Create unfilled triangle stage.
    198  */
    199 struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
    200 {
    201    struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);
    202    if (unfilled == NULL)
    203       goto fail;
    204 
    205    unfilled->stage.draw = draw;
    206    unfilled->stage.name = "unfilled";
    207    unfilled->stage.next = NULL;
    208    unfilled->stage.tmp = NULL;
    209    unfilled->stage.point = draw_pipe_passthrough_point;
    210    unfilled->stage.line = draw_pipe_passthrough_line;
    211    unfilled->stage.tri = unfilled_first_tri;
    212    unfilled->stage.flush = unfilled_flush;
    213    unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
    214    unfilled->stage.destroy = unfilled_destroy;
    215 
    216    if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
    217       goto fail;
    218 
    219    return &unfilled->stage;
    220 
    221  fail:
    222    if (unfilled)
    223       unfilled->stage.destroy( &unfilled->stage );
    224 
    225    return NULL;
    226 }
    227