Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / i965 / brw_misc_state.c
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
33
34 #include "brw_debug.h"
35 #include "brw_batchbuffer.h"
36 #include "brw_context.h"
37 #include "brw_state.h"
38 #include "brw_defines.h"
39 #include "brw_screen.h"
40 #include "brw_pipe_rast.h"
41
42
43
44
45
46 /***********************************************************************
47  * Blend color
48  */
49
50 static int upload_blend_constant_color(struct brw_context *brw)
51 {
52    BRW_CACHED_BATCH_STRUCT(brw, &brw->curr.bcc);
53    return 0;
54 }
55
56
57 const struct brw_tracked_state brw_blend_constant_color = {
58    .dirty = {
59       .mesa = PIPE_NEW_BLEND_COLOR,
60       .brw = 0,
61       .cache = 0
62    },
63    .emit = upload_blend_constant_color
64 };
65
66 /***********************************************************************
67  * Drawing rectangle - framebuffer dimensions
68  */
69 static int upload_drawing_rect(struct brw_context *brw)
70 {
71    BEGIN_BATCH(4, NO_LOOP_CLIPRECTS);
72    OUT_BATCH(_3DSTATE_DRAWRECT_INFO_I965);
73    OUT_BATCH(0);
74    OUT_BATCH(((brw->curr.fb.width - 1) & 0xffff) |
75             ((brw->curr.fb.height - 1) << 16));
76    OUT_BATCH(0);
77    ADVANCE_BATCH();
78    return 0;
79 }
80
81 const struct brw_tracked_state brw_drawing_rect = {
82    .dirty = {
83       .mesa = PIPE_NEW_FRAMEBUFFER_DIMENSIONS,
84       .brw = 0,
85       .cache = 0
86    },
87    .emit = upload_drawing_rect
88 };
89
90
91 /***********************************************************************
92  * Binding table pointers
93  */
94
95 static int prepare_binding_table_pointers(struct brw_context *brw)
96 {
97    brw_add_validated_bo(brw, brw->vs.bind_bo);
98    brw_add_validated_bo(brw, brw->wm.bind_bo);
99    return 0;
100 }
101
102 /**
103  * Upload the binding table pointers, which point each stage's array of surface
104  * state pointers.
105  *
106  * The binding table pointers are relative to the surface state base address,
107  * which is 0.
108  */
109 static int upload_binding_table_pointers(struct brw_context *brw)
110 {
111    BEGIN_BATCH(6, IGNORE_CLIPRECTS);
112    OUT_BATCH(CMD_BINDING_TABLE_PTRS << 16 | (6 - 2));
113    if (brw->vs.bind_bo != NULL)
114       OUT_RELOC(brw->vs.bind_bo, 
115                 BRW_USAGE_SAMPLER,
116                 0); /* vs */
117    else
118       OUT_BATCH(0);
119    OUT_BATCH(0); /* gs */
120    OUT_BATCH(0); /* clip */
121    OUT_BATCH(0); /* sf */
122    OUT_RELOC(brw->wm.bind_bo,
123              BRW_USAGE_SAMPLER,
124              0); /* wm/ps */
125    ADVANCE_BATCH();
126    return 0;
127 }
128
129 const struct brw_tracked_state brw_binding_table_pointers = {
130    .dirty = {
131       .mesa = 0,
132       .brw = BRW_NEW_BATCH,
133       .cache = CACHE_NEW_SURF_BIND,
134    },
135    .prepare = prepare_binding_table_pointers,
136    .emit = upload_binding_table_pointers,
137 };
138
139
140 /**********************************************************************
141  * Upload pointers to the per-stage state.
142  *
143  * The state pointers in this packet are all relative to the general state
144  * base address set by CMD_STATE_BASE_ADDRESS, which is 0.
145  */
146 static int upload_pipelined_state_pointers(struct brw_context *brw )
147 {
148    BEGIN_BATCH(7, IGNORE_CLIPRECTS);
149    OUT_BATCH(CMD_PIPELINED_STATE_POINTERS << 16 | (7 - 2));
150    OUT_RELOC(brw->vs.state_bo, 
151              BRW_USAGE_STATE,
152              0);
153    if (brw->gs.prog_active)
154       OUT_RELOC(brw->gs.state_bo, 
155                 BRW_USAGE_STATE,
156                 1);
157    else
158       OUT_BATCH(0);
159    OUT_RELOC(brw->clip.state_bo, 
160              BRW_USAGE_STATE,
161              1);
162    OUT_RELOC(brw->sf.state_bo,
163              BRW_USAGE_STATE,
164              0);
165    OUT_RELOC(brw->wm.state_bo,
166              BRW_USAGE_STATE,
167              0);
168    OUT_RELOC(brw->cc.state_bo,
169              BRW_USAGE_STATE,
170              0);
171    ADVANCE_BATCH();
172
173    brw->state.dirty.brw |= BRW_NEW_PSP;
174    return 0;
175 }
176
177
178 static int prepare_psp_urb_cbs(struct brw_context *brw)
179 {
180    brw_add_validated_bo(brw, brw->vs.state_bo);
181    brw_add_validated_bo(brw, brw->gs.state_bo);
182    brw_add_validated_bo(brw, brw->clip.state_bo);
183    brw_add_validated_bo(brw, brw->sf.state_bo);
184    brw_add_validated_bo(brw, brw->wm.state_bo);
185    brw_add_validated_bo(brw, brw->cc.state_bo);
186    return 0;
187 }
188
189 static int upload_psp_urb_cbs(struct brw_context *brw )
190 {
191    int ret;
192    
193    ret = upload_pipelined_state_pointers(brw);
194    if (ret)
195       return ret;
196
197    ret = brw_upload_urb_fence(brw);
198    if (ret)
199       return ret;
200
201    ret = brw_upload_cs_urb_state(brw);
202    if (ret)
203       return ret;
204
205    return 0;
206 }
207
208 const struct brw_tracked_state brw_psp_urb_cbs = {
209    .dirty = {
210       .mesa = 0,
211       .brw = BRW_NEW_URB_FENCE | BRW_NEW_BATCH,
212       .cache = (CACHE_NEW_VS_UNIT | 
213                 CACHE_NEW_GS_UNIT | 
214                 CACHE_NEW_GS_PROG | 
215                 CACHE_NEW_CLIP_UNIT | 
216                 CACHE_NEW_SF_UNIT | 
217                 CACHE_NEW_WM_UNIT | 
218                 CACHE_NEW_CC_UNIT)
219    },
220    .prepare = prepare_psp_urb_cbs,
221    .emit = upload_psp_urb_cbs,
222 };
223
224
225 /***********************************************************************
226  * Depth buffer 
227  */
228
229 static int prepare_depthbuffer(struct brw_context *brw)
230 {
231    struct pipe_surface *zsbuf = brw->curr.fb.zsbuf;
232
233    if (zsbuf)
234       brw_add_validated_bo(brw, brw_surface(zsbuf)->bo);
235
236    return 0;
237 }
238
239 static int emit_depthbuffer(struct brw_context *brw)
240 {
241    struct pipe_surface *surface = brw->curr.fb.zsbuf;
242    unsigned int len = (brw->is_g4x || brw->gen == 5) ? 6 : 5;
243
244    if (surface == NULL) {
245       BEGIN_BATCH(len, IGNORE_CLIPRECTS);
246       OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2));
247       OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) |
248                 (BRW_SURFACE_NULL << 29));
249       OUT_BATCH(0);
250       OUT_BATCH(0);
251       OUT_BATCH(0);
252
253       if (brw->is_g4x || brw->gen == 5)
254          OUT_BATCH(0);
255
256       ADVANCE_BATCH();
257    } else {
258       struct brw_winsys_buffer *bo;
259       unsigned int format;
260       unsigned int pitch;
261       unsigned int cpp;
262
263       switch (surface->format) {
264       case PIPE_FORMAT_Z16_UNORM:
265          format = BRW_DEPTHFORMAT_D16_UNORM;
266          cpp = 2;
267          break;
268       case PIPE_FORMAT_Z24X8_UNORM:
269       case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
270          format = BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
271          cpp = 4;
272          break;
273       case PIPE_FORMAT_Z32_FLOAT:
274          format = BRW_DEPTHFORMAT_D32_FLOAT;
275          cpp = 4;
276          break;
277       default:
278          assert(0);
279          return PIPE_ERROR_BAD_INPUT;
280       }
281
282       bo = brw_surface(surface)->bo;
283       pitch = brw_surface(surface)->pitch;
284
285       BEGIN_BATCH(len, IGNORE_CLIPRECTS);
286       OUT_BATCH(CMD_DEPTH_BUFFER << 16 | (len - 2));
287       OUT_BATCH(((pitch * cpp) - 1) |
288                 (format << 18) |
289                 (BRW_TILEWALK_YMAJOR << 26) |
290                 /* always linear ?
291                 ((surface->layout != PIPE_SURFACE_LAYOUT_LINEAR) << 27) |*/
292                 (BRW_SURFACE_2D << 29));
293       OUT_RELOC(bo,
294                 BRW_USAGE_DEPTH_BUFFER,
295                 brw_surface(surface)->offset);
296       OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) |
297                 ((pitch - 1) << 6) |
298                 ((surface->height - 1) << 19));
299       OUT_BATCH(0);
300
301       if (brw->is_g4x || brw->gen == 5)
302          OUT_BATCH(0);
303
304       ADVANCE_BATCH();
305    }
306
307    return 0;
308 }
309
310 const struct brw_tracked_state brw_depthbuffer = {
311    .dirty = {
312       .mesa = PIPE_NEW_DEPTH_BUFFER,
313       .brw = BRW_NEW_BATCH,
314       .cache = 0,
315    },
316    .prepare = prepare_depthbuffer,
317    .emit = emit_depthbuffer,
318 };
319
320
321
322 /***********************************************************************
323  * Polygon stipple packet
324  */
325
326 static int upload_polygon_stipple(struct brw_context *brw)
327 {
328    BRW_CACHED_BATCH_STRUCT(brw, &brw->curr.bps);
329    return 0;
330 }
331
332 const struct brw_tracked_state brw_polygon_stipple = {
333    .dirty = {
334       .mesa = PIPE_NEW_POLYGON_STIPPLE,
335       .brw = 0,
336       .cache = 0
337    },
338    .emit = upload_polygon_stipple
339 };
340
341
342 /***********************************************************************
343  * Line stipple packet
344  */
345
346 static int upload_line_stipple(struct brw_context *brw)
347 {
348    const struct brw_line_stipple *bls = &brw->curr.rast->bls;
349    if (bls->header.opcode) {
350       BRW_CACHED_BATCH_STRUCT(brw, bls);
351    }
352    return 0;
353 }
354
355 const struct brw_tracked_state brw_line_stipple = {
356    .dirty = {
357       .mesa = PIPE_NEW_RAST,
358       .brw = 0,
359       .cache = 0
360    },
361    .emit = upload_line_stipple
362 };
363
364
365 /***********************************************************************
366  * Misc invariant state packets
367  */
368
369 static int upload_invariant_state( struct brw_context *brw )
370 {
371    {
372       /* 0x61040000  Pipeline Select */
373       /*     PipelineSelect            : 0 */
374       struct brw_pipeline_select ps;
375
376       memset(&ps, 0, sizeof(ps));
377       if (brw->is_g4x || brw->gen == 5)
378          ps.header.opcode = CMD_PIPELINE_SELECT_GM45;
379       else
380          ps.header.opcode = CMD_PIPELINE_SELECT_965;
381       ps.header.pipeline_select = 0;
382       BRW_BATCH_STRUCT(brw, &ps);
383    }
384
385    {
386       struct brw_global_depth_offset_clamp gdo;
387       memset(&gdo, 0, sizeof(gdo));
388
389       /* Disable depth offset clamping. 
390        */
391       gdo.header.opcode = CMD_GLOBAL_DEPTH_OFFSET_CLAMP;
392       gdo.header.length = sizeof(gdo)/4 - 2;
393       gdo.depth_offset_clamp = 0.0;
394
395       BRW_BATCH_STRUCT(brw, &gdo);
396    }
397
398
399    /* 0x61020000  State Instruction Pointer */
400    {
401       struct brw_system_instruction_pointer sip;
402       memset(&sip, 0, sizeof(sip));
403
404       sip.header.opcode = CMD_STATE_INSN_POINTER;
405       sip.header.length = 0;
406       sip.bits0.pad = 0;
407       sip.bits0.system_instruction_pointer = 0;
408       BRW_BATCH_STRUCT(brw, &sip);
409    }
410
411    /* VF Statistics */
412    {
413       struct brw_vf_statistics vfs;
414       memset(&vfs, 0, sizeof(vfs));
415
416       if (brw->is_g4x || brw->gen == 5)
417          vfs.opcode = CMD_VF_STATISTICS_GM45;
418       else 
419          vfs.opcode = CMD_VF_STATISTICS_965;
420
421       if (BRW_DEBUG & DEBUG_STATS)
422          vfs.statistics_enable = 1; 
423
424       BRW_BATCH_STRUCT(brw, &vfs);
425    }
426    
427    if (!(brw->gen == 4))
428    {
429       struct brw_aa_line_parameters balp;
430
431       /* use legacy aa line coverage computation */
432       memset(&balp, 0, sizeof(balp));
433       balp.header.opcode = CMD_AA_LINE_PARAMETERS;
434       balp.header.length = sizeof(balp) / 4 - 2;
435    
436       BRW_BATCH_STRUCT(brw, &balp);
437    }
438
439    {
440       struct brw_polygon_stipple_offset bpso;
441       
442       /* This is invariant state in gallium:
443        */
444       memset(&bpso, 0, sizeof(bpso));
445       bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
446       bpso.header.length = sizeof(bpso)/4-2;
447       bpso.bits0.y_offset = 0;
448       bpso.bits0.x_offset = 0;
449
450       BRW_BATCH_STRUCT(brw, &bpso);
451    }
452    
453    return 0;
454 }
455
456 const struct brw_tracked_state brw_invariant_state = {
457    .dirty = {
458       .mesa = 0,
459       .brw = BRW_NEW_CONTEXT,
460       .cache = 0
461    },
462    .emit = upload_invariant_state
463 };
464
465
466 /***********************************************************************
467  * State base address 
468  */
469
470 /**
471  * Define the base addresses which some state is referenced from.
472  *
473  * This allows us to avoid having to emit relocations in many places for
474  * cached state, and instead emit pointers inside of large, mostly-static
475  * state pools.  This comes at the expense of memory, and more expensive cache
476  * misses.
477  */
478 static int upload_state_base_address( struct brw_context *brw )
479 {
480    /* Output the structure (brw_state_base_address) directly to the
481     * batchbuffer, so we can emit relocations inline.
482     */
483    if (brw->gen == 5) {
484        BEGIN_BATCH(8, IGNORE_CLIPRECTS);
485        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
486        OUT_BATCH(1); /* General state base address */
487        OUT_BATCH(1); /* Surface state base address */
488        OUT_BATCH(1); /* Indirect object base address */
489        OUT_BATCH(1); /* Instruction base address */
490        OUT_BATCH(1); /* General state upper bound */
491        OUT_BATCH(1); /* Indirect object upper bound */
492        OUT_BATCH(1); /* Instruction access upper bound */
493        ADVANCE_BATCH();
494    } else {
495        BEGIN_BATCH(6, IGNORE_CLIPRECTS);
496        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2));
497        OUT_BATCH(1); /* General state base address */
498        OUT_BATCH(1); /* Surface state base address */
499        OUT_BATCH(1); /* Indirect object base address */
500        OUT_BATCH(1); /* General state upper bound */
501        OUT_BATCH(1); /* Indirect object upper bound */
502        ADVANCE_BATCH();
503    }
504    return 0;
505 }
506
507 const struct brw_tracked_state brw_state_base_address = {
508    .dirty = {
509       .mesa = 0,
510       .brw = BRW_NEW_CONTEXT,
511       .cache = 0,
512    },
513    .emit = upload_state_base_address
514 };