brw_clip.c revision 125bd4cae51c6deaacd2e90f14931c2052f146ab
1/*
2 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28  * Authors:
29  *   Keith Whitwell <keith@tungstengraphics.com>
30  */
31
32#include "glheader.h"
33#include "macros.h"
34#include "enums.h"
35
36#include "intel_batchbuffer.h"
37
38#include "brw_defines.h"
39#include "brw_context.h"
40#include "brw_eu.h"
41#include "brw_util.h"
42#include "brw_state.h"
43#include "brw_clip.h"
44
45
46#define FRONT_UNFILLED_BIT  0x1
47#define BACK_UNFILLED_BIT   0x2
48
49
50static void compile_clip_prog( struct brw_context *brw,
51			     struct brw_clip_prog_key *key )
52{
53   struct brw_clip_compile c;
54   const GLuint *program;
55   GLuint program_size;
56   GLuint delta;
57   GLuint i;
58
59   memset(&c, 0, sizeof(c));
60
61   /* Begin the compilation:
62    */
63   brw_init_compile(&c.func);
64
65   c.func.single_program_flow = 1;
66
67   c.key = *key;
68
69
70   /* Need to locate the two positions present in vertex + header.
71    * These are currently hardcoded:
72    */
73   c.header_position_offset = ATTR_SIZE;
74
75   for (i = 0, delta = REG_SIZE; i < VERT_RESULT_MAX; i++)
76      if (c.key.attrs & (1<<i)) {
77	 c.offset[i] = delta;
78	 delta += ATTR_SIZE;
79      }
80
81   c.nr_attrs = brw_count_bits(c.key.attrs);
82   c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
83   c.nr_bytes = c.nr_regs * REG_SIZE;
84
85   c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
86
87   /* For some reason the thread is spawned with only 4 channels
88    * unmasked.
89    */
90   brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
91
92
93   /* Would ideally have the option of producing a program which could
94    * do all three:
95    */
96   switch (key->primitive) {
97   case GL_TRIANGLES:
98      if (key->do_unfilled)
99	 brw_emit_unfilled_clip( &c );
100      else
101	 brw_emit_tri_clip( &c );
102      break;
103   case GL_LINES:
104      brw_emit_line_clip( &c );
105      break;
106   case GL_POINTS:
107      brw_emit_point_clip( &c );
108      break;
109   default:
110      assert(0);
111      return;
112   }
113
114
115
116   /* get the program
117    */
118   program = brw_get_program(&c.func, &program_size);
119
120   /* Upload
121    */
122   brw->clip.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_CLIP_PROG],
123						&c.key,
124						sizeof(c.key),
125						program,
126						program_size,
127						&c.prog_data,
128						&brw->clip.prog_data );
129}
130
131
132static GLboolean search_cache( struct brw_context *brw,
133			       struct brw_clip_prog_key *key )
134{
135   return brw_search_cache(&brw->cache[BRW_CLIP_PROG],
136			   key, sizeof(*key),
137			   &brw->clip.prog_data,
138			   &brw->clip.prog_gs_offset);
139}
140
141
142
143
144/* Calculate interpolants for triangle and line rasterization.
145 */
146static void upload_clip_prog( struct brw_context *brw )
147{
148   GLcontext *ctx = &brw->intel.ctx;
149   struct brw_clip_prog_key key;
150
151   memset(&key, 0, sizeof(key));
152
153   /* Populate the key:
154    */
155   /* BRW_NEW_REDUCED_PRIMITIVE */
156   key.primitive = brw->intel.reduced_primitive;
157   /* CACHE_NEW_VS_PROG */
158   key.attrs = brw->vs.prog_data->outputs_written;
159   /* _NEW_LIGHT */
160   key.do_flat_shading = (brw->attribs.Light->ShadeModel == GL_FLAT);
161   /* _NEW_TRANSFORM */
162   key.nr_userclip = brw_count_bits(brw->attribs.Transform->ClipPlanesEnabled);
163   key.clip_mode = BRW_CLIPMODE_NORMAL;
164
165   /* _NEW_POLYGON */
166   if (key.primitive == GL_TRIANGLES) {
167      if (brw->attribs.Polygon->CullFaceMode == GL_FRONT_AND_BACK)
168	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
169      else {
170	 GLuint fill_front = CLIP_CULL;
171	 GLuint fill_back = CLIP_CULL;
172	 GLuint offset_front = 0;
173	 GLuint offset_back = 0;
174
175	 if (!brw->attribs.Polygon->CullFlag ||
176	     brw->attribs.Polygon->CullFaceMode != GL_FRONT) {
177	    switch (brw->attribs.Polygon->FrontMode) {
178	    case GL_FILL:
179	       fill_front = CLIP_FILL;
180	       offset_front = 0;
181	       break;
182	    case GL_LINE:
183	       key.do_unfilled = 1;
184	       fill_front = CLIP_LINE;
185	       offset_front = brw->attribs.Polygon->OffsetLine;
186	       break;
187	    case GL_POINT:
188	       key.do_unfilled = 1;
189	       fill_front = CLIP_POINT;
190	       offset_front = brw->attribs.Polygon->OffsetPoint;
191	       break;
192	    }
193	 }
194
195	 if (!brw->attribs.Polygon->CullFlag ||
196	     brw->attribs.Polygon->CullFaceMode != GL_BACK) {
197	    switch (brw->attribs.Polygon->BackMode) {
198	    case GL_FILL:
199	       fill_back = CLIP_FILL;
200	       offset_back = 0;
201	       break;
202	    case GL_LINE:
203	       key.do_unfilled = 1;
204	       fill_back = CLIP_LINE;
205	       offset_back = brw->attribs.Polygon->OffsetLine;
206	       break;
207	    case GL_POINT:
208	       key.do_unfilled = 1;
209	       fill_back = CLIP_POINT;
210	       offset_back = brw->attribs.Polygon->OffsetPoint;
211	       break;
212	    }
213	 }
214
215    if (brw->attribs.Polygon->BackMode != GL_FILL ||
216        brw->attribs.Polygon->FrontMode != GL_FILL)
217        key.do_unfilled = 1;
218
219	 /* Most cases the fixed function units will handle.  Cases where
220	  * one or more polygon faces are unfilled will require help:
221	  */
222	 if (key.do_unfilled) {
223	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
224
225	    if (offset_back || offset_front) {
226	       /* _NEW_POLYGON, _NEW_BUFFERS */
227	       key.offset_units = brw->attribs.Polygon->OffsetUnits * brw->intel.polygon_offset_scale;
228	       key.offset_factor = brw->attribs.Polygon->OffsetFactor * ctx->DrawBuffer->_MRD;
229	    }
230
231	    switch (brw->attribs.Polygon->FrontFace) {
232	    case GL_CCW:
233	       key.fill_ccw = fill_front;
234	       key.fill_cw = fill_back;
235	       key.offset_ccw = offset_front;
236	       key.offset_cw = offset_back;
237	       if (brw->attribs.Light->Model.TwoSide &&
238		   key.fill_cw != CLIP_CULL)
239		  key.copy_bfc_cw = 1;
240	       break;
241	    case GL_CW:
242	       key.fill_cw = fill_front;
243	       key.fill_ccw = fill_back;
244	       key.offset_cw = offset_front;
245	       key.offset_ccw = offset_back;
246	       if (brw->attribs.Light->Model.TwoSide &&
247		   key.fill_ccw != CLIP_CULL)
248		  key.copy_bfc_ccw = 1;
249	       break;
250	    }
251	 }
252      }
253   }
254
255   if (!search_cache(brw, &key))
256      compile_clip_prog( brw, &key );
257}
258
259
260const struct brw_tracked_state brw_clip_prog = {
261   .dirty = {
262      .mesa  = (_NEW_LIGHT |
263		_NEW_TRANSFORM |
264		_NEW_POLYGON |
265		_NEW_BUFFERS),
266      .brw   = (BRW_NEW_REDUCED_PRIMITIVE),
267      .cache = CACHE_NEW_VS_PROG
268   },
269   .update = upload_clip_prog
270};
271