draw_pipe_wide_line.c revision 507fbe2d327efb8d608ce8e07436b97321560808
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/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
29 */
30
31#include "pipe/p_util.h"
32#include "pipe/p_defines.h"
33#include "pipe/p_shader_tokens.h"
34#include "draw_private.h"
35#include "draw_pipe.h"
36
37
38struct wideline_stage {
39   struct draw_stage stage;
40
41   float half_line_width;
42};
43
44
45
46static INLINE struct wideline_stage *wideline_stage( struct draw_stage *stage )
47{
48   return (struct wideline_stage *)stage;
49}
50
51
52static void wideline_point( struct draw_stage *stage,
53                               struct prim_header *header )
54{
55   stage->next->point( stage->next, header );
56}
57
58
59static void wideline_tri( struct draw_stage *stage,
60                             struct prim_header *header )
61{
62   stage->next->tri(stage->next, header);
63}
64
65
66/**
67 * Draw a wide line by drawing a quad (two triangles).
68 * XXX need to disable polygon stipple.
69 */
70static void wideline_line( struct draw_stage *stage,
71                           struct prim_header *header )
72{
73   /*const struct wideline_stage *wide = wideline_stage(stage);*/
74   const float half_width = 0.5f * stage->draw->rasterizer->line_width;
75
76   struct prim_header tri;
77
78   struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
79   struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
80   struct vertex_header *v2 = dup_vert(stage, header->v[1], 2);
81   struct vertex_header *v3 = dup_vert(stage, header->v[1], 3);
82
83   float *pos0 = v0->data[0];
84   float *pos1 = v1->data[0];
85   float *pos2 = v2->data[0];
86   float *pos3 = v3->data[0];
87
88   const float dx = FABSF(pos0[0] - pos2[0]);
89   const float dy = FABSF(pos0[1] - pos2[1]);
90
91   /* small tweak to meet GL specification */
92   const float bias = 0.125f;
93
94   /*
95    * Draw wide line as a quad (two tris) by "stretching" the line along
96    * X or Y.
97    * We need to tweak coords in several ways to be conformant here.
98    */
99
100   if (dx > dy) {
101      /* x-major line */
102      pos0[1] = pos0[1] - half_width - bias;
103      pos1[1] = pos1[1] + half_width - bias;
104      pos2[1] = pos2[1] - half_width - bias;
105      pos3[1] = pos3[1] + half_width - bias;
106      if (pos0[0] < pos2[0]) {
107         /* left to right line */
108         pos0[0] -= 0.5f;
109         pos1[0] -= 0.5f;
110         pos2[0] -= 0.5f;
111         pos3[0] -= 0.5f;
112      }
113      else {
114         /* right to left line */
115         pos0[0] += 0.5f;
116         pos1[0] += 0.5f;
117         pos2[0] += 0.5f;
118         pos3[0] += 0.5f;
119      }
120   }
121   else {
122      /* y-major line */
123      pos0[0] = pos0[0] - half_width + bias;
124      pos1[0] = pos1[0] + half_width + bias;
125      pos2[0] = pos2[0] - half_width + bias;
126      pos3[0] = pos3[0] + half_width + bias;
127      if (pos0[1] < pos2[1]) {
128         /* top to bottom line */
129         pos0[1] -= 0.5f;
130         pos1[1] -= 0.5f;
131         pos2[1] -= 0.5f;
132         pos3[1] -= 0.5f;
133      }
134      else {
135         /* bottom to top line */
136         pos0[1] += 0.5f;
137         pos1[1] += 0.5f;
138         pos2[1] += 0.5f;
139         pos3[1] += 0.5f;
140      }
141   }
142
143   tri.det = header->det;  /* only the sign matters */
144   tri.v[0] = v0;
145   tri.v[1] = v2;
146   tri.v[2] = v3;
147   stage->next->tri( stage->next, &tri );
148
149   tri.v[0] = v0;
150   tri.v[1] = v3;
151   tri.v[2] = v1;
152   stage->next->tri( stage->next, &tri );
153}
154
155
156static void wideline_flush( struct draw_stage *stage, unsigned flags )
157{
158   stage->next->flush( stage->next, flags );
159}
160
161
162static void wideline_reset_stipple_counter( struct draw_stage *stage )
163{
164   stage->next->reset_stipple_counter( stage->next );
165}
166
167
168static void wideline_destroy( struct draw_stage *stage )
169{
170   draw_free_temp_verts( stage );
171   FREE( stage );
172}
173
174
175struct draw_stage *draw_wide_line_stage( struct draw_context *draw )
176{
177   struct wideline_stage *wide = CALLOC_STRUCT(wideline_stage);
178
179   draw_alloc_temp_verts( &wide->stage, 4 );
180
181   wide->stage.draw = draw;
182   wide->stage.next = NULL;
183   wide->stage.point = wideline_point;
184   wide->stage.line = wideline_line;
185   wide->stage.tri = wideline_tri;
186   wide->stage.flush = wideline_flush;
187   wide->stage.reset_stipple_counter = wideline_reset_stipple_counter;
188   wide->stage.destroy = wideline_destroy;
189
190   return &wide->stage;
191}
192