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_FS_PROG_DATA |
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   /* BRW_NEW_FS_PROG_DATA */
153   const struct brw_wm_prog_data *wm_prog_data =
154      brw_wm_prog_data(brw->wm.base.prog_data);
155   if (wm_prog_data) {
156      key.contains_flat_varying = wm_prog_data->contains_flat_varying;
157      key.contains_noperspective_varying =
158         wm_prog_data->contains_noperspective_varying;
159      key.interp_mode = wm_prog_data->interp_mode;
160   }
161
162   /* BRW_NEW_REDUCED_PRIMITIVE */
163   key.primitive = brw->reduced_primitive;
164   /* BRW_NEW_VUE_MAP_GEOM_OUT */
165   key.attrs = brw->vue_map_geom_out.slots_valid;
166
167   /* _NEW_LIGHT */
168   key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);
169   /* _NEW_TRANSFORM (also part of VUE map)*/
170   if (ctx->Transform.ClipPlanesEnabled)
171      key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
172
173   if (brw->gen == 5)
174       key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP;
175   else
176       key.clip_mode = BRW_CLIPMODE_NORMAL;
177
178   /* _NEW_POLYGON */
179   if (key.primitive == GL_TRIANGLES) {
180      if (ctx->Polygon.CullFlag &&
181	  ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
182	 key.clip_mode = BRW_CLIPMODE_REJECT_ALL;
183      else {
184	 GLuint fill_front = CLIP_CULL;
185	 GLuint fill_back = CLIP_CULL;
186	 GLuint offset_front = 0;
187	 GLuint offset_back = 0;
188
189	 if (!ctx->Polygon.CullFlag ||
190	     ctx->Polygon.CullFaceMode != GL_FRONT) {
191	    switch (ctx->Polygon.FrontMode) {
192	    case GL_FILL:
193	       fill_front = CLIP_FILL;
194	       offset_front = 0;
195	       break;
196	    case GL_LINE:
197	       fill_front = CLIP_LINE;
198	       offset_front = ctx->Polygon.OffsetLine;
199	       break;
200	    case GL_POINT:
201	       fill_front = CLIP_POINT;
202	       offset_front = ctx->Polygon.OffsetPoint;
203	       break;
204	    }
205	 }
206
207	 if (!ctx->Polygon.CullFlag ||
208	     ctx->Polygon.CullFaceMode != GL_BACK) {
209	    switch (ctx->Polygon.BackMode) {
210	    case GL_FILL:
211	       fill_back = CLIP_FILL;
212	       offset_back = 0;
213	       break;
214	    case GL_LINE:
215	       fill_back = CLIP_LINE;
216	       offset_back = ctx->Polygon.OffsetLine;
217	       break;
218	    case GL_POINT:
219	       fill_back = CLIP_POINT;
220	       offset_back = ctx->Polygon.OffsetPoint;
221	       break;
222	    }
223	 }
224
225	 if (ctx->Polygon.BackMode != GL_FILL ||
226	     ctx->Polygon.FrontMode != GL_FILL) {
227	    key.do_unfilled = 1;
228
229	    /* Most cases the fixed function units will handle.  Cases where
230	     * one or more polygon faces are unfilled will require help:
231	     */
232	    key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED;
233
234	    if (offset_back || offset_front) {
235	       /* _NEW_POLYGON, _NEW_BUFFERS */
236	       key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2;
237	       key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD;
238	       key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD;
239	    }
240
241	    if (!ctx->Polygon._FrontBit) {
242	       key.fill_ccw = fill_front;
243	       key.fill_cw = fill_back;
244	       key.offset_ccw = offset_front;
245	       key.offset_cw = offset_back;
246	       if (ctx->Light.Model.TwoSide &&
247		   key.fill_cw != CLIP_CULL)
248		  key.copy_bfc_cw = 1;
249	    } else {
250	       key.fill_cw = fill_front;
251	       key.fill_ccw = fill_back;
252	       key.offset_cw = offset_front;
253	       key.offset_ccw = offset_back;
254	       if (ctx->Light.Model.TwoSide &&
255		   key.fill_ccw != CLIP_CULL)
256		  key.copy_bfc_ccw = 1;
257	    }
258	 }
259      }
260   }
261
262   if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG,
263			 &key, sizeof(key),
264			 &brw->clip.prog_offset, &brw->clip.prog_data)) {
265      compile_clip_prog( brw, &key );
266   }
267}
268