brw_clip.c revision 1c96e85c9d6b8c636b0636f3320d1057ab5357b3
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 intel_context *intel = &brw->intel;
54   struct brw_clip_compile c;
55   const GLuint *program;
56   GLuint program_size;
57   GLuint delta;
58   GLuint i;
59
60   memset(&c, 0, sizeof(c));
61
62   /* Begin the compilation:
63    */
64   brw_init_compile(brw, &c.func);
65
66   c.func.single_program_flow = 1;
67
68   c.key = *key;
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 (intel->is_ironlake)
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 & BITFIELD64_BIT(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 (intel->is_ironlake)
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   struct intel_context *intel = &brw->intel;
147   GLcontext *ctx = &intel->ctx;
148   struct brw_clip_prog_key key;
149
150   memset(&key, 0, sizeof(key));
151
152   /* Populate the key:
153    */
154   /* BRW_NEW_REDUCED_PRIMITIVE */
155   key.primitive = brw->intel.reduced_primitive;
156   /* CACHE_NEW_VS_PROG */
157   key.attrs = brw->vs.prog_data->outputs_written;
158   /* _NEW_LIGHT */
159   key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
160   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
161   /* _NEW_TRANSFORM */
162   key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
163
164   if (intel->is_ironlake)
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 * brw->intel.polygon_offset_scale;
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   dri_bo_unreference(brw->clip.prog_bo);
256   brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG,
257					&key, sizeof(key),
258					NULL, 0,
259					&brw->clip.prog_data);
260   if (brw->clip.prog_bo == NULL)
261      compile_clip_prog( brw, &key );
262}
263
264
265const struct brw_tracked_state brw_clip_prog = {
266   .dirty = {
267      .mesa  = (_NEW_LIGHT |
268		_NEW_TRANSFORM |
269		_NEW_POLYGON |
270		_NEW_BUFFERS),
271      .brw   = (BRW_NEW_REDUCED_PRIMITIVE),
272      .cache = CACHE_NEW_VS_PROG
273   },
274   .prepare = upload_clip_prog
275};
276