brw_clip.c revision a7bdd4cba8ddcab8dff59ecaaa7efbd436c6c307
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 "main/glheader.h"
33#include "main/macros.h"
34#include "main/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#include "glsl/ralloc.h"
46
47#define FRONT_UNFILLED_BIT  0x1
48#define BACK_UNFILLED_BIT   0x2
49
50
51static void compile_clip_prog( struct brw_context *brw,
52			     struct brw_clip_prog_key *key )
53{
54   struct brw_clip_compile c;
55   const GLuint *program;
56   void *mem_ctx;
57   GLuint program_size;
58   GLuint i;
59
60   memset(&c, 0, sizeof(c));
61
62   mem_ctx = ralloc_context(NULL);
63
64   /* Begin the compilation:
65    */
66   brw_init_compile(brw, &c.func, mem_ctx);
67
68   c.func.single_program_flow = 1;
69
70   c.key = *key;
71   c.vue_map = brw->vue_map_geom_out;
72
73   c.has_flat_shading =
74      brw_any_flat_varyings(&key->interpolation_mode);
75   c.has_noperspective_shading =
76      brw_any_noperspective_varyings(&key->interpolation_mode);
77
78   /* nr_regs is the number of registers filled by reading data from the VUE.
79    * This program accesses the entire VUE, so nr_regs needs to be the size of
80    * the VUE (measured in pairs, since two slots are stored in each
81    * register).
82    */
83   c.nr_regs = (c.vue_map.num_slots + 1)/2;
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   if (unlikely(INTEL_DEBUG & DEBUG_CLIP)) {
121      printf("clip:\n");
122      for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
123	 brw_disasm(stdout, &((struct brw_instruction *)program)[i],
124		    brw->gen);
125      printf("\n");
126   }
127
128   brw_upload_cache(&brw->cache,
129		    BRW_CLIP_PROG,
130		    &c.key, sizeof(c.key),
131		    program, program_size,
132		    &c.prog_data, sizeof(c.prog_data),
133		    &brw->clip.prog_offset, &brw->clip.prog_data);
134   ralloc_free(mem_ctx);
135}
136
137/* Calculate interpolants for triangle and line rasterization.
138 */
139static void
140brw_upload_clip_prog(struct brw_context *brw)
141{
142   struct gl_context *ctx = &brw->ctx;
143   struct brw_clip_prog_key key;
144
145   memset(&key, 0, sizeof(key));
146
147   /* Populate the key:
148    */
149
150   /* BRW_NEW_INTERPOLATION_MAP */
151   key.interpolation_mode = brw->interpolation_mode;
152
153   /* BRW_NEW_REDUCED_PRIMITIVE */
154   key.primitive = brw->reduced_primitive;
155   /* BRW_NEW_VUE_MAP_GEOM_OUT */
156   key.attrs = brw->vue_map_geom_out.slots_valid;
157
158   /* _NEW_LIGHT */
159   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
160   /* _NEW_TRANSFORM (also part of VUE map)*/
161   if (ctx->Transform.ClipPlanesEnabled)
162      key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
163
164   if (brw->gen == 5)
165       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
166   else
167       key.clip_mode = BRW_CLIPMODE_NORMAL;
168
169   /* _NEW_POLYGON */
170   if (key.primitive == GL_TRIANGLES) {
171      if (ctx->Polygon.CullFlag &&
172	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
173	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
174      else {
175	 GLuint fill_front = CLIP_CULL;
176	 GLuint fill_back = CLIP_CULL;
177	 GLuint offset_front = 0;
178	 GLuint offset_back = 0;
179
180	 if (!ctx->Polygon.CullFlag ||
181	     ctx->Polygon.CullFaceMode != GL_FRONT) {
182	    switch (ctx->Polygon.FrontMode) {
183	    case GL_FILL:
184	       fill_front = CLIP_FILL;
185	       offset_front = 0;
186	       break;
187	    case GL_LINE:
188	       fill_front = CLIP_LINE;
189	       offset_front = ctx->Polygon.OffsetLine;
190	       break;
191	    case GL_POINT:
192	       fill_front = CLIP_POINT;
193	       offset_front = ctx->Polygon.OffsetPoint;
194	       break;
195	    }
196	 }
197
198	 if (!ctx->Polygon.CullFlag ||
199	     ctx->Polygon.CullFaceMode != GL_BACK) {
200	    switch (ctx->Polygon.BackMode) {
201	    case GL_FILL:
202	       fill_back = CLIP_FILL;
203	       offset_back = 0;
204	       break;
205	    case GL_LINE:
206	       fill_back = CLIP_LINE;
207	       offset_back = ctx->Polygon.OffsetLine;
208	       break;
209	    case GL_POINT:
210	       fill_back = CLIP_POINT;
211	       offset_back = ctx->Polygon.OffsetPoint;
212	       break;
213	    }
214	 }
215
216	 if (ctx->Polygon.BackMode != GL_FILL ||
217	     ctx->Polygon.FrontMode != GL_FILL) {
218	    key.do_unfilled = 1;
219
220	    /* Most cases the fixed function units will handle.  Cases where
221	     * one or more polygon faces are unfilled will require help:
222	     */
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 = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2;
228	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
229	    }
230
231	    switch (ctx->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 (ctx->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 (ctx->Light.Model.TwoSide &&
247		   key.fill_ccw != CLIP_CULL)
248		  key.copy_bfc_ccw = 1;
249	       break;
250	    }
251	 }
252      }
253   }
254
255   if (!brw_search_cache(&brw->cache, BRW_CLIP_PROG,
256			 &key, sizeof(key),
257			 &brw->clip.prog_offset, &brw->clip.prog_data)) {
258      compile_clip_prog( brw, &key );
259   }
260}
261
262
263const struct brw_tracked_state brw_clip_prog = {
264   .dirty = {
265      .mesa  = (_NEW_LIGHT |
266		_NEW_TRANSFORM |
267		_NEW_POLYGON |
268		_NEW_BUFFERS),
269      .brw   = (BRW_NEW_REDUCED_PRIMITIVE |
270                BRW_NEW_VUE_MAP_GEOM_OUT |
271                BRW_NEW_INTERPOLATION_MAP)
272   },
273   .emit = brw_upload_clip_prog
274};
275