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 "brw_context.h"
33 #include "brw_state.h"
34 #include "brw_defines.h"
35 #include "main/framebuffer.h"
36 
37 static void
38 upload_clip_vp(struct brw_context *brw)
39 {
40    struct gl_context *ctx = &brw->ctx;
41    struct brw_clipper_viewport *vp;
42 
43    vp = brw_state_batch(brw, AUB_TRACE_CLIP_VP_STATE,
44                         sizeof(*vp), 32, &brw->clip.vp_offset);
45 
46    const float maximum_post_clamp_delta = 4096;
47    float gbx = maximum_post_clamp_delta / ctx->ViewportArray[0].Width;
48    float gby = maximum_post_clamp_delta / ctx->ViewportArray[0].Height;
49 
50    vp->xmin = -gbx;
51    vp->xmax = gbx;
52    vp->ymin = -gby;
53    vp->ymax = gby;
54 }
55 
56 static void
57 brw_upload_clip_unit(struct brw_context *brw)
58 {
59    struct gl_context *ctx = &brw->ctx;
60    struct brw_clip_unit_state *clip;
61 
62    /* _NEW_BUFFERS */
63    const struct gl_framebuffer *fb = ctx->DrawBuffer;
64    const float fb_width = (float)_mesa_geometric_width(fb);
65    const float fb_height = (float)_mesa_geometric_height(fb);
66 
67    upload_clip_vp(brw);
68 
69    clip = brw_state_batch(brw, AUB_TRACE_CLIP_STATE,
70 			  sizeof(*clip), 32, &brw->clip.state_offset);
71    memset(clip, 0, sizeof(*clip));
72 
73    /* BRW_NEW_PROGRAM_CACHE | BRW_NEW_CLIP_PROG_DATA */
74    clip->thread0.grf_reg_count = (ALIGN(brw->clip.prog_data->total_grf, 16) /
75 				 16 - 1);
76    clip->thread0.kernel_start_pointer =
77       brw_program_reloc(brw,
78 			brw->clip.state_offset +
79 			offsetof(struct brw_clip_unit_state, thread0),
80 			brw->clip.prog_offset +
81 			(clip->thread0.grf_reg_count << 1)) >> 6;
82 
83    clip->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
84    clip->thread1.single_program_flow = 1;
85 
86    clip->thread3.urb_entry_read_length = brw->clip.prog_data->urb_read_length;
87    clip->thread3.const_urb_entry_read_length =
88       brw->clip.prog_data->curb_read_length;
89 
90    /* BRW_NEW_CURBE_OFFSETS */
91    clip->thread3.const_urb_entry_read_offset = brw->curbe.clip_start * 2;
92    clip->thread3.dispatch_grf_start_reg = 1;
93    clip->thread3.urb_entry_read_offset = 0;
94 
95    /* BRW_NEW_URB_FENCE */
96    clip->thread4.nr_urb_entries = brw->urb.nr_clip_entries;
97    clip->thread4.urb_entry_allocation_size = brw->urb.vsize - 1;
98    /* If we have enough clip URB entries to run two threads, do so.
99     */
100    if (brw->urb.nr_clip_entries >= 10) {
101       /* Half of the URB entries go to each thread, and it has to be an
102        * even number.
103        */
104       assert(brw->urb.nr_clip_entries % 2 == 0);
105 
106       /* Although up to 16 concurrent Clip threads are allowed on Ironlake,
107        * only 2 threads can output VUEs at a time.
108        */
109       if (brw->gen == 5)
110          clip->thread4.max_threads = 16 - 1;
111       else
112          clip->thread4.max_threads = 2 - 1;
113    } else {
114       assert(brw->urb.nr_clip_entries >= 5);
115       clip->thread4.max_threads = 1 - 1;
116    }
117 
118    if (unlikely(INTEL_DEBUG & DEBUG_STATS))
119       clip->thread4.stats_enable = 1;
120 
121    /* _NEW_TRANSFORM */
122    if (brw->gen == 5 || brw->is_g4x)
123       clip->clip5.userclip_enable_flags = ctx->Transform.ClipPlanesEnabled;
124    else
125       /* Up to 6 actual clip flags, plus the 7th for negative RHW workaround. */
126       clip->clip5.userclip_enable_flags = (ctx->Transform.ClipPlanesEnabled & 0x3f) | 0x40;
127 
128    clip->clip5.userclip_must_clip = 1;
129 
130    /* enable guardband clipping if we can */
131    if (ctx->ViewportArray[0].X == 0 &&
132        ctx->ViewportArray[0].Y == 0 &&
133        ctx->ViewportArray[0].Width == fb_width &&
134        ctx->ViewportArray[0].Height == fb_height)
135    {
136       clip->clip5.guard_band_enable = 1;
137       clip->clip6.clipper_viewport_state_ptr =
138          (brw->batch.bo->offset64 + brw->clip.vp_offset) >> 5;
139 
140       /* emit clip viewport relocation */
141       drm_intel_bo_emit_reloc(brw->batch.bo,
142                               (brw->clip.state_offset +
143                                offsetof(struct brw_clip_unit_state, clip6)),
144                               brw->batch.bo, brw->clip.vp_offset,
145                               I915_GEM_DOMAIN_INSTRUCTION, 0);
146    }
147 
148    /* _NEW_TRANSFORM */
149    if (!ctx->Transform.DepthClamp)
150       clip->clip5.viewport_z_clip_enable = 1;
151    clip->clip5.viewport_xy_clip_enable = 1;
152    clip->clip5.vertex_position_space = BRW_CLIP_NDCSPACE;
153    if (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE)
154       clip->clip5.api_mode = BRW_CLIP_API_DX;
155    else
156       clip->clip5.api_mode = BRW_CLIP_API_OGL;
157    clip->clip5.clip_mode = brw->clip.prog_data->clip_mode;
158 
159    if (brw->is_g4x)
160       clip->clip5.negative_w_clip_test = 1;
161 
162    clip->viewport_xmin = -1;
163    clip->viewport_xmax = 1;
164    clip->viewport_ymin = -1;
165    clip->viewport_ymax = 1;
166 
167    brw->ctx.NewDriverState |= BRW_NEW_GEN4_UNIT_STATE;
168 }
169 
170 const struct brw_tracked_state brw_clip_unit = {
171    .dirty = {
172       .mesa  = _NEW_BUFFERS |
173                _NEW_TRANSFORM |
174                _NEW_VIEWPORT,
175       .brw   = BRW_NEW_BATCH |
176                BRW_NEW_BLORP |
177                BRW_NEW_CLIP_PROG_DATA |
178                BRW_NEW_CURBE_OFFSETS |
179                BRW_NEW_PROGRAM_CACHE |
180                BRW_NEW_URB_FENCE,
181    },
182    .emit = brw_upload_clip_unit,
183 };
184