brw_clip.c revision 78be5bcb222d379a07979de98ff5b9e3549de6a7
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 intel_context *intel = &brw->intel;
55   struct brw_clip_compile c;
56   const GLuint *program;
57   void *mem_ctx;
58   GLuint program_size;
59   GLuint i;
60
61   memset(&c, 0, sizeof(c));
62
63   mem_ctx = ralloc_context(NULL);
64
65   /* Begin the compilation:
66    */
67   brw_init_compile(brw, &c.func, mem_ctx);
68
69   c.func.single_program_flow = 1;
70
71   c.key = *key;
72   brw_compute_vue_map(&c.vue_map, intel, c.key.nr_userclip,
73                       c.key.do_twoside_color, c.key.attrs);
74
75   /* nr_regs is the number of registers filled by reading data from the VUE.
76    * This program accesses the entire VUE, so nr_regs needs to be the size of
77    * the VUE (measured in pairs, since two slots are stored in each
78    * register).
79    */
80   c.nr_regs = (c.vue_map.num_slots + 1)/2;
81
82   c.prog_data.clip_mode = c.key.clip_mode; /* XXX */
83
84   /* For some reason the thread is spawned with only 4 channels
85    * unmasked.
86    */
87   brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
88
89
90   /* Would ideally have the option of producing a program which could
91    * do all three:
92    */
93   switch (key->primitive) {
94   case GL_TRIANGLES:
95      if (key->do_unfilled)
96	 brw_emit_unfilled_clip( &c );
97      else
98	 brw_emit_tri_clip( &c );
99      break;
100   case GL_LINES:
101      brw_emit_line_clip( &c );
102      break;
103   case GL_POINTS:
104      brw_emit_point_clip( &c );
105      break;
106   default:
107      assert(0);
108      return;
109   }
110
111
112
113   /* get the program
114    */
115   program = brw_get_program(&c.func, &program_size);
116
117   if (unlikely(INTEL_DEBUG & DEBUG_CLIP)) {
118      printf("clip:\n");
119      for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
120	 brw_disasm(stdout, &((struct brw_instruction *)program)[i],
121		    intel->gen);
122      printf("\n");
123   }
124
125   brw_upload_cache(&brw->cache,
126		    BRW_CLIP_PROG,
127		    &c.key, sizeof(c.key),
128		    program, program_size,
129		    &c.prog_data, sizeof(c.prog_data),
130		    &brw->clip.prog_offset, &brw->clip.prog_data);
131   ralloc_free(mem_ctx);
132}
133
134/* Calculate interpolants for triangle and line rasterization.
135 */
136static void upload_clip_prog(struct brw_context *brw)
137{
138   struct intel_context *intel = &brw->intel;
139   struct gl_context *ctx = &intel->ctx;
140   struct brw_clip_prog_key key;
141
142   memset(&key, 0, sizeof(key));
143
144   /* Populate the key:
145    */
146   /* BRW_NEW_REDUCED_PRIMITIVE */
147   key.primitive = brw->intel.reduced_primitive;
148   /* CACHE_NEW_VS_PROG */
149   key.attrs = brw->vs.prog_data->outputs_written;
150   /* _NEW_LIGHT */
151   key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);
152   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
153   key.do_twoside_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide);
154   /* _NEW_TRANSFORM */
155   key.nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
156
157   if (intel->gen == 5)
158       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
159   else
160       key.clip_mode = BRW_CLIPMODE_NORMAL;
161
162   /* _NEW_POLYGON */
163   if (key.primitive == GL_TRIANGLES) {
164      if (ctx->Polygon.CullFlag &&
165	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
166	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
167      else {
168	 GLuint fill_front = CLIP_CULL;
169	 GLuint fill_back = CLIP_CULL;
170	 GLuint offset_front = 0;
171	 GLuint offset_back = 0;
172
173	 if (!ctx->Polygon.CullFlag ||
174	     ctx->Polygon.CullFaceMode != GL_FRONT) {
175	    switch (ctx->Polygon.FrontMode) {
176	    case GL_FILL:
177	       fill_front = CLIP_FILL;
178	       offset_front = 0;
179	       break;
180	    case GL_LINE:
181	       fill_front = CLIP_LINE;
182	       offset_front = ctx->Polygon.OffsetLine;
183	       break;
184	    case GL_POINT:
185	       fill_front = CLIP_POINT;
186	       offset_front = ctx->Polygon.OffsetPoint;
187	       break;
188	    }
189	 }
190
191	 if (!ctx->Polygon.CullFlag ||
192	     ctx->Polygon.CullFaceMode != GL_BACK) {
193	    switch (ctx->Polygon.BackMode) {
194	    case GL_FILL:
195	       fill_back = CLIP_FILL;
196	       offset_back = 0;
197	       break;
198	    case GL_LINE:
199	       fill_back = CLIP_LINE;
200	       offset_back = ctx->Polygon.OffsetLine;
201	       break;
202	    case GL_POINT:
203	       fill_back = CLIP_POINT;
204	       offset_back = ctx->Polygon.OffsetPoint;
205	       break;
206	    }
207	 }
208
209	 if (ctx->Polygon.BackMode != GL_FILL ||
210	     ctx->Polygon.FrontMode != GL_FILL) {
211	    key.do_unfilled = 1;
212
213	    /* Most cases the fixed function units will handle.  Cases where
214	     * one or more polygon faces are unfilled will require help:
215	     */
216	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
217
218	    if (offset_back || offset_front) {
219	       /* _NEW_POLYGON, _NEW_BUFFERS */
220	       key.offset_units = ctx->Polygon.OffsetUnits * brw->intel.polygon_offset_scale;
221	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
222	    }
223
224	    switch (ctx->Polygon.FrontFace) {
225	    case GL_CCW:
226	       key.fill_ccw = fill_front;
227	       key.fill_cw = fill_back;
228	       key.offset_ccw = offset_front;
229	       key.offset_cw = offset_back;
230	       if (ctx->Light.Model.TwoSide &&
231		   key.fill_cw != CLIP_CULL)
232		  key.copy_bfc_cw = 1;
233	       break;
234	    case GL_CW:
235	       key.fill_cw = fill_front;
236	       key.fill_ccw = fill_back;
237	       key.offset_cw = offset_front;
238	       key.offset_ccw = offset_back;
239	       if (ctx->Light.Model.TwoSide &&
240		   key.fill_ccw != CLIP_CULL)
241		  key.copy_bfc_ccw = 1;
242	       break;
243	    }
244	 }
245      }
246   }
247
248   if (!brw_search_cache(&brw->cache, BRW_CLIP_PROG,
249			 &key, sizeof(key),
250			 &brw->clip.prog_offset, &brw->clip.prog_data)) {
251      compile_clip_prog( brw, &key );
252   }
253}
254
255
256const struct brw_tracked_state brw_clip_prog = {
257   .dirty = {
258      .mesa  = (_NEW_LIGHT |
259		_NEW_TRANSFORM |
260		_NEW_POLYGON |
261		_NEW_BUFFERS),
262      .brw   = (BRW_NEW_REDUCED_PRIMITIVE),
263      .cache = CACHE_NEW_VS_PROG
264   },
265   .prepare = upload_clip_prog
266};
267