brw_clip.c revision 91d61fbf7cb61a44adcaae51ee08ad0dd6b2a03b
1/*
2 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3 Intel funded Tungsten Graphics 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 <keithw@vmware.com>
30  */
31
32#include "main/macros.h"
33#include "main/enums.h"
34
35#include "intel_batchbuffer.h"
36
37#include "brw_defines.h"
38#include "brw_context.h"
39#include "brw_eu.h"
40#include "brw_util.h"
41#include "brw_state.h"
42#include "brw_clip.h"
43
44#include "util/ralloc.h"
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   void *mem_ctx;
56   GLuint program_size;
57
58   memset(&c, 0, sizeof(c));
59
60   mem_ctx = ralloc_context(NULL);
61
62   /* Begin the compilation:
63    */
64   brw_init_codegen(&brw->screen->devinfo, &c.func, mem_ctx);
65
66   c.func.single_program_flow = 1;
67
68   c.key = *key;
69   c.vue_map = brw->vue_map_geom_out;
70
71   /* nr_regs is the number of registers filled by reading data from the VUE.
72    * This program accesses the entire VUE, so nr_regs needs to be the size of
73    * the VUE (measured in pairs, since two slots are stored in each
74    * register).
75    */
76   c.nr_regs = (c.vue_map.num_slots + 1)/2;
77
78   c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
79
80   /* For some reason the thread is spawned with only 4 channels
81    * unmasked.
82    */
83   brw_set_default_mask_control(&c.func, BRW_MASK_DISABLE);
84
85
86   /* Would ideally have the option of producing a program which could
87    * do all three:
88    */
89   switch (key->primitive) {
90   case GL_TRIANGLES:
91      if (key->do_unfilled)
92	 brw_emit_unfilled_clip( &c );
93      else
94	 brw_emit_tri_clip( &c );
95      break;
96   case GL_LINES:
97      brw_emit_line_clip( &c );
98      break;
99   case GL_POINTS:
100      brw_emit_point_clip( &c );
101      break;
102   default:
103      unreachable("not reached");
104   }
105
106   brw_compact_instructions(&c.func, 0, 0, NULL);
107
108   /* get the program
109    */
110   program = brw_get_program(&c.func, &program_size);
111
112   if (unlikely(INTEL_DEBUG & DEBUG_CLIP)) {
113      fprintf(stderr, "clip:\n");
114      brw_disassemble(&brw->screen->devinfo, c.func.store,
115                      0, program_size, stderr);
116      fprintf(stderr, "\n");
117   }
118
119   brw_upload_cache(&brw->cache,
120		    BRW_CACHE_CLIP_PROG,
121		    &c.key, sizeof(c.key),
122		    program, program_size,
123		    &c.prog_data, sizeof(c.prog_data),
124		    &brw->clip.prog_offset, &brw->clip.prog_data);
125   ralloc_free(mem_ctx);
126}
127
128/* Calculate interpolants for triangle and line rasterization.
129 */
130void
131brw_upload_clip_prog(struct brw_context *brw)
132{
133   struct gl_context *ctx = &brw->ctx;
134   struct brw_clip_prog_key key;
135
136   if (!brw_state_dirty(brw,
137                        _NEW_BUFFERS |
138                        _NEW_LIGHT |
139                        _NEW_POLYGON |
140                        _NEW_TRANSFORM,
141                        BRW_NEW_BLORP |
142                        BRW_NEW_FRAGMENT_PROGRAM |
143                        BRW_NEW_REDUCED_PRIMITIVE |
144                        BRW_NEW_VUE_MAP_GEOM_OUT))
145      return;
146
147   memset(&key, 0, sizeof(key));
148
149   /* Populate the key:
150    */
151
152   const struct gl_fragment_program *fprog = brw->fragment_program;
153   if (fprog) {
154      assert(brw->gen < 6);
155      struct gen4_fragment_program *p = (struct gen4_fragment_program *) fprog;
156
157      /* BRW_NEW_FRAGMENT_PROGRAM */
158      key.contains_flat_varying = p->contains_flat_varying;
159      key.contains_noperspective_varying = p->contains_noperspective_varying;
160      key.interp_mode = p->interp_mode;
161   }
162
163   /* BRW_NEW_REDUCED_PRIMITIVE */
164   key.primitive = brw->reduced_primitive;
165   /* BRW_NEW_VUE_MAP_GEOM_OUT */
166   key.attrs = brw->vue_map_geom_out.slots_valid;
167
168   /* _NEW_LIGHT */
169   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
170   /* _NEW_TRANSFORM (also part of VUE map)*/
171   if (ctx->Transform.ClipPlanesEnabled)
172      key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
173
174   if (brw->gen == 5)
175       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
176   else
177       key.clip_mode = BRW_CLIPMODE_NORMAL;
178
179   /* _NEW_POLYGON */
180   if (key.primitive == GL_TRIANGLES) {
181      if (ctx->Polygon.CullFlag &&
182	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
183	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
184      else {
185	 GLuint fill_front = CLIP_CULL;
186	 GLuint fill_back = CLIP_CULL;
187	 GLuint offset_front = 0;
188	 GLuint offset_back = 0;
189
190	 if (!ctx->Polygon.CullFlag ||
191	     ctx->Polygon.CullFaceMode != GL_FRONT) {
192	    switch (ctx->Polygon.FrontMode) {
193	    case GL_FILL:
194	       fill_front = CLIP_FILL;
195	       offset_front = 0;
196	       break;
197	    case GL_LINE:
198	       fill_front = CLIP_LINE;
199	       offset_front = ctx->Polygon.OffsetLine;
200	       break;
201	    case GL_POINT:
202	       fill_front = CLIP_POINT;
203	       offset_front = ctx->Polygon.OffsetPoint;
204	       break;
205	    }
206	 }
207
208	 if (!ctx->Polygon.CullFlag ||
209	     ctx->Polygon.CullFaceMode != GL_BACK) {
210	    switch (ctx->Polygon.BackMode) {
211	    case GL_FILL:
212	       fill_back = CLIP_FILL;
213	       offset_back = 0;
214	       break;
215	    case GL_LINE:
216	       fill_back = CLIP_LINE;
217	       offset_back = ctx->Polygon.OffsetLine;
218	       break;
219	    case GL_POINT:
220	       fill_back = CLIP_POINT;
221	       offset_back = ctx->Polygon.OffsetPoint;
222	       break;
223	    }
224	 }
225
226	 if (ctx->Polygon.BackMode != GL_FILL ||
227	     ctx->Polygon.FrontMode != GL_FILL) {
228	    key.do_unfilled = 1;
229
230	    /* Most cases the fixed function units will handle.  Cases where
231	     * one or more polygon faces are unfilled will require help:
232	     */
233	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
234
235	    if (offset_back || offset_front) {
236	       /* _NEW_POLYGON, _NEW_BUFFERS */
237	       key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2;
238	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
239	       key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD;
240	    }
241
242	    if (!ctx->Polygon._FrontBit) {
243	       key.fill_ccw = fill_front;
244	       key.fill_cw = fill_back;
245	       key.offset_ccw = offset_front;
246	       key.offset_cw = offset_back;
247	       if (ctx->Light.Model.TwoSide &&
248		   key.fill_cw != CLIP_CULL)
249		  key.copy_bfc_cw = 1;
250	    } else {
251	       key.fill_cw = fill_front;
252	       key.fill_ccw = fill_back;
253	       key.offset_cw = offset_front;
254	       key.offset_ccw = offset_back;
255	       if (ctx->Light.Model.TwoSide &&
256		   key.fill_ccw != CLIP_CULL)
257		  key.copy_bfc_ccw = 1;
258	    }
259	 }
260      }
261   }
262
263   if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG,
264			 &key, sizeof(key),
265			 &brw->clip.prog_offset, &brw->clip.prog_data)) {
266      compile_clip_prog( brw, &key );
267   }
268}
269