brw_clip.c revision 81d555068408d4343d7627c8bedda5675f09bd21
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
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(brw, &c.func);
64
65   c.func.single_program_flow = 1;
66
67   c.key = *key;
68   c.need_ff_sync = BRW_IS_IGDNG(brw);
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   if (BRW_IS_IGDNG(brw))
76       delta = 3 * REG_SIZE;
77   else
78       delta = REG_SIZE;
79
80   for (i = 0; i < VERT_RESULT_MAX; i++)
81      if (c.key.attrs & (1<<i)) {
82	 c.offset[i] = delta;
83	 delta += ATTR_SIZE;
84      }
85
86   c.nr_attrs = brw_count_bits(c.key.attrs);
87
88   if (BRW_IS_IGDNG(brw))
89       c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
90   else
91       c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
92
93   c.nr_bytes = c.nr_regs * REG_SIZE;
94
95   c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
96
97   /* For some reason the thread is spawned with only 4 channels
98    * unmasked.
99    */
100   brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
101
102
103   /* Would ideally have the option of producing a program which could
104    * do all three:
105    */
106   switch (key->primitive) {
107   case GL_TRIANGLES:
108      if (key->do_unfilled)
109	 brw_emit_unfilled_clip( &c );
110      else
111	 brw_emit_tri_clip( &c );
112      break;
113   case GL_LINES:
114      brw_emit_line_clip( &c );
115      break;
116   case GL_POINTS:
117      brw_emit_point_clip( &c );
118      break;
119   default:
120      assert(0);
121      return;
122   }
123
124
125
126   /* get the program
127    */
128   program = brw_get_program(&c.func, &program_size);
129
130   /* Upload
131    */
132   dri_bo_unreference(brw->clip.prog_bo);
133   brw->clip.prog_bo = brw_upload_cache( &brw->cache,
134					 BRW_CLIP_PROG,
135					 &c.key, sizeof(c.key),
136					 NULL, 0,
137					 program, program_size,
138					 &c.prog_data,
139					 &brw->clip.prog_data );
140}
141
142/* Calculate interpolants for triangle and line rasterization.
143 */
144static void upload_clip_prog(struct brw_context *brw)
145{
146   GLcontext *ctx = &brw->intel.ctx;
147   struct brw_clip_prog_key key;
148
149   memset(&key, 0, sizeof(key));
150
151   /* Populate the key:
152    */
153   /* BRW_NEW_REDUCED_PRIMITIVE */
154   key.primitive = brw->intel.reduced_primitive;
155   /* CACHE_NEW_VS_PROG */
156   key.attrs = brw->vs.prog_data->outputs_written;
157   /* _NEW_LIGHT */
158   key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
159   /* _NEW_TRANSFORM */
160   key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
161
162   if (BRW_IS_IGDNG(brw))
163       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
164   else
165       key.clip_mode = BRW_CLIPMODE_NORMAL;
166
167   /* _NEW_POLYGON */
168   if (key.primitive == GL_TRIANGLES) {
169      if (ctx->Polygon.CullFlag &&
170	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
171	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
172      else {
173	 GLuint fill_front = CLIP_CULL;
174	 GLuint fill_back = CLIP_CULL;
175	 GLuint offset_front = 0;
176	 GLuint offset_back = 0;
177
178	 if (!ctx->Polygon.CullFlag ||
179	     ctx->Polygon.CullFaceMode != GL_FRONT) {
180	    switch (ctx->Polygon.FrontMode) {
181	    case GL_FILL:
182	       fill_front = CLIP_FILL;
183	       offset_front = 0;
184	       break;
185	    case GL_LINE:
186	       fill_front = CLIP_LINE;
187	       offset_front = ctx->Polygon.OffsetLine;
188	       break;
189	    case GL_POINT:
190	       fill_front = CLIP_POINT;
191	       offset_front = ctx->Polygon.OffsetPoint;
192	       break;
193	    }
194	 }
195
196	 if (!ctx->Polygon.CullFlag ||
197	     ctx->Polygon.CullFaceMode != GL_BACK) {
198	    switch (ctx->Polygon.BackMode) {
199	    case GL_FILL:
200	       fill_back = CLIP_FILL;
201	       offset_back = 0;
202	       break;
203	    case GL_LINE:
204	       fill_back = CLIP_LINE;
205	       offset_back = ctx->Polygon.OffsetLine;
206	       break;
207	    case GL_POINT:
208	       fill_back = CLIP_POINT;
209	       offset_back = ctx->Polygon.OffsetPoint;
210	       break;
211	    }
212	 }
213
214	 if (ctx->Polygon.BackMode != GL_FILL ||
215	     ctx->Polygon.FrontMode != GL_FILL) {
216	    key.do_unfilled = 1;
217
218	    /* Most cases the fixed function units will handle.  Cases where
219	     * one or more polygon faces are unfilled will require help:
220	     */
221	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
222
223	    if (offset_back || offset_front) {
224	       /* _NEW_POLYGON, _NEW_BUFFERS */
225	       key.offset_units = ctx->Polygon.OffsetUnits * brw->intel.polygon_offset_scale;
226	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
227	    }
228
229	    switch (ctx->Polygon.FrontFace) {
230	    case GL_CCW:
231	       key.fill_ccw = fill_front;
232	       key.fill_cw = fill_back;
233	       key.offset_ccw = offset_front;
234	       key.offset_cw = offset_back;
235	       if (ctx->Light.Model.TwoSide &&
236		   key.fill_cw != CLIP_CULL)
237		  key.copy_bfc_cw = 1;
238	       break;
239	    case GL_CW:
240	       key.fill_cw = fill_front;
241	       key.fill_ccw = fill_back;
242	       key.offset_cw = offset_front;
243	       key.offset_ccw = offset_back;
244	       if (ctx->Light.Model.TwoSide &&
245		   key.fill_ccw != CLIP_CULL)
246		  key.copy_bfc_ccw = 1;
247	       break;
248	    }
249	 }
250      }
251   }
252
253   dri_bo_unreference(brw->clip.prog_bo);
254   brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG,
255					&key, sizeof(key),
256					NULL, 0,
257					&brw->clip.prog_data);
258   if (brw->clip.prog_bo == NULL)
259      compile_clip_prog( brw, &key );
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      .cache = CACHE_NEW_VS_PROG
271   },
272   .prepare = upload_clip_prog
273};
274