1b2cffc91ee2dca240af6c9ae9d7dbe60539fb9e
[mesa.git] / src / gallium / drivers / i915 / i915_state_emit.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 #include "i915_reg.h"
30 #include "i915_context.h"
31 #include "i915_batch.h"
32 #include "i915_debug.h"
33 #include "i915_resource.h"
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_defines.h"
37
38 #include "util/u_math.h"
39
40 /**
41 * Examine framebuffer state to determine width, height.
42 */
43 static boolean
44 framebuffer_size(const struct pipe_framebuffer_state *fb,
45 uint *width, uint *height)
46 {
47 if (fb->cbufs[0]) {
48 *width = fb->cbufs[0]->width;
49 *height = fb->cbufs[0]->height;
50 return TRUE;
51 }
52 else if (fb->zsbuf) {
53 *width = fb->zsbuf->width;
54 *height = fb->zsbuf->height;
55 return TRUE;
56 }
57 else {
58 *width = *height = 0;
59 return FALSE;
60 }
61 }
62
63
64 /* Push the state into the sarea and/or texture memory.
65 */
66 void
67 i915_emit_hardware_state(struct i915_context *i915 )
68 {
69 /* XXX: there must be an easier way */
70 const unsigned dwords = ( 14 +
71 7 +
72 I915_MAX_DYNAMIC +
73 8 +
74 2 + I915_TEX_UNITS*3 +
75 2 + I915_TEX_UNITS*3 +
76 2 + I915_MAX_CONSTANT*4 +
77 #if 0
78 i915->current.program_len +
79 #else
80 i915->fs->program_len +
81 #endif
82 6
83 ) * 3/2; /* plus 50% margin */
84 const unsigned relocs = ( I915_TEX_UNITS +
85 3
86 ) * 3/2; /* plus 50% margin */
87
88 uintptr_t save_ptr;
89 size_t save_relocs;
90
91 if (I915_DBG_ON(DBG_ATOMS))
92 i915_dump_hardware_dirty(i915, __FUNCTION__);
93
94 if(!BEGIN_BATCH(dwords, relocs)) {
95 FLUSH_BATCH(NULL);
96 assert(BEGIN_BATCH(dwords, relocs));
97 }
98
99 save_ptr = (uintptr_t)i915->batch->ptr;
100 save_relocs = i915->batch->relocs;
101
102 /* 14 dwords, 0 relocs */
103 if (i915->hardware_dirty & I915_HW_INVARIANT)
104 {
105 OUT_BATCH(_3DSTATE_AA_CMD |
106 AA_LINE_ECAAR_WIDTH_ENABLE |
107 AA_LINE_ECAAR_WIDTH_1_0 |
108 AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
109
110 OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
111 OUT_BATCH(0);
112
113 OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD);
114 OUT_BATCH(0);
115
116 OUT_BATCH(_3DSTATE_DFLT_Z_CMD);
117 OUT_BATCH(0);
118
119 OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS |
120 CSB_TCB(0, 0) |
121 CSB_TCB(1, 1) |
122 CSB_TCB(2, 2) |
123 CSB_TCB(3, 3) |
124 CSB_TCB(4, 4) |
125 CSB_TCB(5, 5) |
126 CSB_TCB(6, 6) |
127 CSB_TCB(7, 7));
128
129 OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
130 ENABLE_POINT_RASTER_RULE |
131 OGL_POINT_RASTER_RULE |
132 ENABLE_LINE_STRIP_PROVOKE_VRTX |
133 ENABLE_TRI_FAN_PROVOKE_VRTX |
134 LINE_STRIP_PROVOKE_VRTX(1) |
135 TRI_FAN_PROVOKE_VRTX(2) |
136 ENABLE_TEXKILL_3D_4D |
137 TEXKILL_4D);
138
139 OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE);
140
141 /* disable indirect state for now
142 */
143 OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0);
144 OUT_BATCH(0);
145 }
146
147 /* 7 dwords, 1 relocs */
148 if (i915->hardware_dirty & I915_HW_IMMEDIATE)
149 {
150 /* remove unwatned bits and S7 */
151 unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
152 1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
153 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
154 1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
155 i915->immediate_dirty;
156 int i, num = util_bitcount(dirty);
157 assert(num && num <= I915_MAX_IMMEDIATE);
158
159 OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
160 dirty << 4 | (num - 1));
161
162 if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0)) {
163 if (i915->vbo)
164 OUT_RELOC(i915->vbo, I915_USAGE_VERTEX,
165 i915->current.immediate[I915_IMMEDIATE_S0]);
166 else
167 OUT_BATCH(0);
168 }
169
170 for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
171 if (dirty & (1 << i))
172 OUT_BATCH(i915->current.immediate[i]);
173 }
174 }
175
176 #if 01
177 /* I915_MAX_DYNAMIC dwords, 0 relocs */
178 if (i915->hardware_dirty & I915_HW_DYNAMIC)
179 {
180 int i;
181 for (i = 0; i < I915_MAX_DYNAMIC; i++) {
182 if (i915->dynamic_dirty & (1 << i))
183 OUT_BATCH(i915->current.dynamic[i]);
184 }
185 }
186 #endif
187
188 #if 01
189 /* 8 dwords, 2 relocs */
190 if (i915->hardware_dirty & I915_HW_STATIC)
191 {
192 if (i915->current.cbuf_bo) {
193 OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
194 OUT_BATCH(i915->current.cbuf_flags);
195 OUT_RELOC(i915->current.cbuf_bo,
196 I915_USAGE_RENDER,
197 0);
198 }
199
200 /* What happens if no zbuf??
201 */
202 if (i915->current.depth_bo) {
203 OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
204 OUT_BATCH(i915->current.depth_flags);
205 OUT_RELOC(i915->current.depth_bo,
206 I915_USAGE_RENDER,
207 0);
208 }
209
210 {
211 OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
212 OUT_BATCH(i915->current.dst_buf_vars);
213 }
214 }
215 #endif
216
217 #if 01
218 /* texture images */
219 /* 2 + I915_TEX_UNITS*3 dwords, I915_TEX_UNITS relocs */
220 if (i915->hardware_dirty & (I915_HW_MAP | I915_HW_SAMPLER))
221 {
222 const uint nr = i915->current.sampler_enable_nr;
223 if (nr) {
224 const uint enabled = i915->current.sampler_enable_flags;
225 uint unit;
226 uint count = 0;
227 OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr));
228 OUT_BATCH(enabled);
229 for (unit = 0; unit < I915_TEX_UNITS; unit++) {
230 if (enabled & (1 << unit)) {
231 struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture);
232 struct i915_winsys_buffer *buf = texture->buffer;
233 assert(buf);
234
235 count++;
236
237 OUT_RELOC(buf, I915_USAGE_SAMPLER, 0);
238 OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */
239 OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */
240 }
241 }
242 assert(count == nr);
243 }
244 }
245 #endif
246
247 #if 01
248 /* samplers */
249 /* 2 + I915_TEX_UNITS*3 dwords, 0 relocs */
250 if (i915->hardware_dirty & I915_HW_SAMPLER)
251 {
252 if (i915->current.sampler_enable_nr) {
253 int i;
254
255 OUT_BATCH( _3DSTATE_SAMPLER_STATE |
256 (3 * i915->current.sampler_enable_nr) );
257
258 OUT_BATCH( i915->current.sampler_enable_flags );
259
260 for (i = 0; i < I915_TEX_UNITS; i++) {
261 if (i915->current.sampler_enable_flags & (1<<i)) {
262 OUT_BATCH( i915->current.sampler[i][0] );
263 OUT_BATCH( i915->current.sampler[i][1] );
264 OUT_BATCH( i915->current.sampler[i][2] );
265 }
266 }
267 }
268 }
269 #endif
270
271 #if 01
272 /* constants */
273 /* 2 + I915_MAX_CONSTANT*4 dwords, 0 relocs */
274 if (i915->hardware_dirty & I915_HW_CONSTANTS)
275 {
276 /* Collate the user-defined constants with the fragment shader's
277 * immediates according to the constant_flags[] array.
278 */
279 const uint nr = i915->fs->num_constants;
280 if (nr) {
281 uint i;
282
283 OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) );
284 OUT_BATCH((1 << nr) - 1);
285
286 for (i = 0; i < nr; i++) {
287 const uint *c;
288 if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) {
289 /* grab user-defined constant */
290 c = (uint *) i915_buffer(i915->constants[PIPE_SHADER_FRAGMENT])->data;
291 c += 4 * i;
292 }
293 else {
294 /* emit program constant */
295 c = (uint *) i915->fs->constants[i];
296 }
297 #if 0 /* debug */
298 {
299 float *f = (float *) c;
300 printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3],
301 (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER
302 ? "user" : "immediate"));
303 }
304 #endif
305 OUT_BATCH(*c++);
306 OUT_BATCH(*c++);
307 OUT_BATCH(*c++);
308 OUT_BATCH(*c++);
309 }
310 }
311 }
312 #endif
313
314 #if 01
315 /* Fragment program */
316 /* i915->current.program_len dwords, 0 relocs */
317 if (i915->hardware_dirty & I915_HW_PROGRAM)
318 {
319 uint i;
320 /* we should always have, at least, a pass-through program */
321 assert(i915->fs->program_len > 0);
322 for (i = 0; i < i915->fs->program_len; i++) {
323 OUT_BATCH(i915->fs->program[i]);
324 }
325 }
326 #endif
327
328 #if 01
329 /* drawing surface size */
330 /* 6 dwords, 0 relocs */
331 if (i915->hardware_dirty & I915_HW_STATIC)
332 {
333 uint w, h;
334 struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0];
335 unsigned x, y;
336 int layer;
337 uint32_t draw_offset;
338 boolean ret;
339
340 ret = framebuffer_size(&i915->framebuffer, &w, &h);
341 assert(ret);
342
343 if (cbuf_surface) {
344 struct i915_texture *tex = i915_texture(cbuf_surface->texture);
345 layer = cbuf_surface->u.tex.first_layer;
346
347 x = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksx;
348 y = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksy;
349
350 } else
351 x = y = 0;
352
353 draw_offset = x | (y << 16);
354
355 /* XXX flush only required when the draw_offset changes! */
356 OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE);
357 OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
358 OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
359 OUT_BATCH(draw_offset);
360 OUT_BATCH((w - 1 + x) | ((h - 1 + y) << 16));
361 OUT_BATCH(draw_offset);
362 }
363 #endif
364
365 I915_DBG(DBG_EMIT, "%s: used %d dwords, %d relocs\n", __FUNCTION__,
366 ((uintptr_t)i915->batch->ptr - save_ptr) / 4,
367 i915->batch->relocs - save_relocs);
368
369 i915->hardware_dirty = 0;
370 i915->immediate_dirty = 0;
371 i915->dynamic_dirty = 0;
372 }