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