i965: take the secondary color into account when drawing
[mesa.git] / src / mesa / drivers / dri / 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 "intel_batchbuffer.h"
35 #include "intel_regions.h"
36
37 #include "brw_context.h"
38 #include "brw_state.h"
39 #include "brw_defines.h"
40
41
42
43
44
45 /***********************************************************************
46 * Blend color
47 */
48
49 static void upload_blend_constant_color(struct brw_context *brw)
50 {
51 struct brw_blend_constant_color bcc;
52
53 memset(&bcc, 0, sizeof(bcc));
54 bcc.header.opcode = CMD_BLEND_CONSTANT_COLOR;
55 bcc.header.length = sizeof(bcc)/4-2;
56 bcc.blend_constant_color[0] = brw->attribs.Color->BlendColor[0];
57 bcc.blend_constant_color[1] = brw->attribs.Color->BlendColor[1];
58 bcc.blend_constant_color[2] = brw->attribs.Color->BlendColor[2];
59 bcc.blend_constant_color[3] = brw->attribs.Color->BlendColor[3];
60
61 BRW_CACHED_BATCH_STRUCT(brw, &bcc);
62 }
63
64
65 const struct brw_tracked_state brw_blend_constant_color = {
66 .dirty = {
67 .mesa = _NEW_COLOR,
68 .brw = 0,
69 .cache = 0
70 },
71 .update = upload_blend_constant_color
72 };
73
74 /***********************************************************************
75 * Drawing rectangle -- Need for AUB file only.
76 */
77 static void upload_drawing_rect(struct brw_context *brw)
78 {
79 struct intel_context *intel = &brw->intel;
80 __DRIdrawablePrivate *dPriv = intel->driDrawable;
81 struct brw_drawrect bdr;
82 int x1, y1;
83 int x2, y2;
84
85 /* If there is a single cliprect, set it here. Otherwise iterate
86 * over them in brw_draw_prim().
87 */
88 if (brw->intel.numClipRects > 1)
89 return;
90
91 x1 = brw->intel.pClipRects[0].x1;
92 y1 = brw->intel.pClipRects[0].y1;
93 x2 = brw->intel.pClipRects[0].x2;
94 y2 = brw->intel.pClipRects[0].y2;
95
96 if (x1 < 0) x1 = 0;
97 if (y1 < 0) y1 = 0;
98 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
99 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
100
101 memset(&bdr, 0, sizeof(bdr));
102 bdr.header.opcode = CMD_DRAW_RECT;
103 bdr.header.length = sizeof(bdr)/4 - 2;
104 bdr.xmin = x1;
105 bdr.ymin = y1;
106 bdr.xmax = x2;
107 bdr.ymax = y2;
108 bdr.xorg = dPriv->x;
109 bdr.yorg = dPriv->y;
110
111 /* Can't use BRW_CACHED_BATCH_STRUCT because this is also emitted
112 * uncached in brw_draw.c:
113 */
114 BRW_BATCH_STRUCT(brw, &bdr);
115 }
116
117 const struct brw_tracked_state brw_drawing_rect = {
118 .dirty = {
119 .mesa = _NEW_WINDOW_POS,
120 .brw = 0,
121 .cache = 0
122 },
123 .update = upload_drawing_rect
124 };
125
126 /***********************************************************************
127 * Binding table pointers
128 */
129
130 static void upload_binding_table_pointers(struct brw_context *brw)
131 {
132 struct brw_binding_table_pointers btp;
133 memset(&btp, 0, sizeof(btp));
134
135 /* The binding table has been emitted to the SS pool already, so we
136 * know what its offset is. When the batch buffer is fired, the
137 * binding table and surface structs will get fixed up to point to
138 * where the textures actually landed, but that won't change the
139 * value of the offsets here:
140 */
141 btp.header.opcode = CMD_BINDING_TABLE_PTRS;
142 btp.header.length = sizeof(btp)/4 - 2;
143 btp.vs = 0;
144 btp.gs = 0;
145 btp.clp = 0;
146 btp.sf = 0;
147 btp.wm = brw->wm.bind_ss_offset;
148
149 BRW_CACHED_BATCH_STRUCT(brw, &btp);
150 }
151
152 const struct brw_tracked_state brw_binding_table_pointers = {
153 .dirty = {
154 .mesa = 0,
155 .brw = 0,
156 .cache = CACHE_NEW_SURF_BIND
157 },
158 .update = upload_binding_table_pointers
159 };
160
161
162 /***********************************************************************
163 * Pipelined state pointers. This is the key state packet from which
164 * the hardware chases pointers to all the uploaded state in VRAM.
165 */
166
167 static void upload_pipelined_state_pointers(struct brw_context *brw )
168 {
169 struct brw_pipelined_state_pointers psp;
170 memset(&psp, 0, sizeof(psp));
171
172 psp.header.opcode = CMD_PIPELINED_STATE_POINTERS;
173 psp.header.length = sizeof(psp)/4 - 2;
174
175 psp.vs.offset = brw->vs.state_gs_offset >> 5;
176 psp.sf.offset = brw->sf.state_gs_offset >> 5;
177 psp.wm.offset = brw->wm.state_gs_offset >> 5;
178 psp.cc.offset = brw->cc.state_gs_offset >> 5;
179
180 /* GS gets turned on and off regularly. Need to re-emit URB fence
181 * after this occurs.
182 */
183 if (brw->gs.prog_active) {
184 psp.gs.offset = brw->gs.state_gs_offset >> 5;
185 psp.gs.enable = 1;
186 }
187
188 if (!brw->metaops.active) {
189 psp.clp.offset = brw->clip.state_gs_offset >> 5;
190 psp.clp.enable = 1;
191 }
192
193
194 if (BRW_CACHED_BATCH_STRUCT(brw, &psp))
195 brw->state.dirty.brw |= BRW_NEW_PSP;
196 }
197
198 const struct brw_tracked_state brw_pipelined_state_pointers = {
199 .dirty = {
200 .mesa = 0,
201 .brw = BRW_NEW_METAOPS,
202 .cache = (CACHE_NEW_VS_UNIT |
203 CACHE_NEW_GS_UNIT |
204 CACHE_NEW_GS_PROG |
205 CACHE_NEW_CLIP_UNIT |
206 CACHE_NEW_SF_UNIT |
207 CACHE_NEW_WM_UNIT |
208 CACHE_NEW_CC_UNIT)
209 },
210 .update = upload_pipelined_state_pointers
211 };
212
213 static void upload_psp_urb_cbs(struct brw_context *brw )
214 {
215 upload_pipelined_state_pointers(brw);
216 brw_upload_urb_fence(brw);
217 brw_upload_constant_buffer_state(brw);
218 }
219
220
221 const struct brw_tracked_state brw_psp_urb_cbs = {
222 .dirty = {
223 .mesa = 0,
224 .brw = BRW_NEW_URB_FENCE | BRW_NEW_METAOPS,
225 .cache = (CACHE_NEW_VS_UNIT |
226 CACHE_NEW_GS_UNIT |
227 CACHE_NEW_GS_PROG |
228 CACHE_NEW_CLIP_UNIT |
229 CACHE_NEW_SF_UNIT |
230 CACHE_NEW_WM_UNIT |
231 CACHE_NEW_CC_UNIT)
232 },
233 .update = upload_psp_urb_cbs
234 };
235
236
237
238
239 /***********************************************************************
240 * Depthbuffer - currently constant, but rotation would change that.
241 */
242
243 static void upload_depthbuffer(struct brw_context *brw)
244 {
245 /* 0x79050003 Depth Buffer */
246 struct intel_context *intel = &brw->intel;
247 struct intel_region *region = brw->state.depth_region;
248 struct brw_depthbuffer bd;
249 memset(&bd, 0, sizeof(bd));
250
251 bd.header.bits.opcode = CMD_DEPTH_BUFFER;
252 bd.header.bits.length = sizeof(bd)/4-2;
253 bd.dword1.bits.pitch = (region->pitch * region->cpp) - 1;
254
255 switch (region->cpp) {
256 case 2:
257 bd.dword1.bits.format = BRW_DEPTHFORMAT_D16_UNORM;
258 break;
259 case 4:
260 if (intel->depth_buffer_is_float)
261 bd.dword1.bits.format = BRW_DEPTHFORMAT_D32_FLOAT;
262 else
263 bd.dword1.bits.format = BRW_DEPTHFORMAT_D24_UNORM_S8_UINT;
264 break;
265 default:
266 assert(0);
267 return;
268 }
269
270 bd.dword1.bits.depth_offset_disable = 0; /* coordinate offset */
271
272 /* The depthbuffer can only use YMAJOR tiling... This is a bit of
273 * a shame as it clashes with the 2d blitter which only supports
274 * XMAJOR tiling...
275 */
276 bd.dword1.bits.tile_walk = BRW_TILEWALK_YMAJOR;
277 bd.dword1.bits.tiled_surface = intel->depth_region->tiled;
278 bd.dword1.bits.surface_type = BRW_SURFACE_2D;
279
280 /* BRW_NEW_LOCK */
281 bd.dword2_base_addr = bmBufferOffset(intel, region->buffer);
282
283 bd.dword3.bits.mipmap_layout = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
284 bd.dword3.bits.lod = 0;
285 bd.dword3.bits.width = region->pitch - 1; /* XXX: width ? */
286 bd.dword3.bits.height = region->height - 1;
287
288 bd.dword4.bits.min_array_element = 0;
289 bd.dword4.bits.depth = 0;
290
291 BRW_CACHED_BATCH_STRUCT(brw, &bd);
292 }
293
294 const struct brw_tracked_state brw_depthbuffer = {
295 .dirty = {
296 .mesa = 0,
297 .brw = BRW_NEW_CONTEXT | BRW_NEW_LOCK,
298 .cache = 0
299 },
300 .update = upload_depthbuffer
301 };
302
303
304
305 /***********************************************************************
306 * Polygon stipple packet
307 */
308
309 static void upload_polygon_stipple(struct brw_context *brw)
310 {
311 struct brw_polygon_stipple bps;
312 GLuint i;
313
314 memset(&bps, 0, sizeof(bps));
315 bps.header.opcode = CMD_POLY_STIPPLE_PATTERN;
316 bps.header.length = sizeof(bps)/4-2;
317
318 for (i = 0; i < 32; i++)
319 bps.stipple[i] = brw->attribs.PolygonStipple[31 - i]; /* invert */
320
321 BRW_CACHED_BATCH_STRUCT(brw, &bps);
322 }
323
324 const struct brw_tracked_state brw_polygon_stipple = {
325 .dirty = {
326 .mesa = _NEW_POLYGONSTIPPLE,
327 .brw = 0,
328 .cache = 0
329 },
330 .update = upload_polygon_stipple
331 };
332
333
334 /***********************************************************************
335 * Polygon stipple offset packet
336 */
337
338 static void upload_polygon_stipple_offset(struct brw_context *brw)
339 {
340 __DRIdrawablePrivate *dPriv = brw->intel.driDrawable;
341 struct brw_polygon_stipple_offset bpso;
342
343 memset(&bpso, 0, sizeof(bpso));
344 bpso.header.opcode = CMD_POLY_STIPPLE_OFFSET;
345 bpso.header.length = sizeof(bpso)/4-2;
346
347 bpso.bits0.x_offset = (32 - (dPriv->x & 31)) & 31;
348 bpso.bits0.y_offset = (32 - ((dPriv->y + dPriv->h) & 31)) & 31;
349
350 BRW_CACHED_BATCH_STRUCT(brw, &bpso);
351 }
352
353 const struct brw_tracked_state brw_polygon_stipple_offset = {
354 .dirty = {
355 .mesa = _NEW_WINDOW_POS,
356 .brw = 0,
357 .cache = 0
358 },
359 .update = upload_polygon_stipple_offset
360 };
361
362 /***********************************************************************
363 * Line stipple packet
364 */
365
366 static void upload_line_stipple(struct brw_context *brw)
367 {
368 struct brw_line_stipple bls;
369 GLfloat tmp;
370 GLint tmpi;
371
372 memset(&bls, 0, sizeof(bls));
373 bls.header.opcode = CMD_LINE_STIPPLE_PATTERN;
374 bls.header.length = sizeof(bls)/4 - 2;
375
376 bls.bits0.pattern = brw->attribs.Line->StipplePattern;
377 bls.bits1.repeat_count = brw->attribs.Line->StippleFactor;
378
379 tmp = 1.0 / (GLfloat) brw->attribs.Line->StippleFactor;
380 tmpi = tmp * (1<<13);
381
382
383 bls.bits1.inverse_repeat_count = tmpi;
384
385 BRW_CACHED_BATCH_STRUCT(brw, &bls);
386 }
387
388 const struct brw_tracked_state brw_line_stipple = {
389 .dirty = {
390 .mesa = _NEW_LINE,
391 .brw = 0,
392 .cache = 0
393 },
394 .update = upload_line_stipple
395 };
396
397
398
399 /***********************************************************************
400 * Misc constant state packets
401 */
402
403 static void upload_pipe_control(struct brw_context *brw)
404 {
405 struct brw_pipe_control pc;
406
407 return;
408
409 memset(&pc, 0, sizeof(pc));
410
411 pc.header.opcode = CMD_PIPE_CONTROL;
412 pc.header.length = sizeof(pc)/4 - 2;
413 pc.header.post_sync_operation = PIPE_CONTROL_NOWRITE;
414
415 pc.header.instruction_state_cache_flush_enable = 1;
416
417 pc.bits1.dest_addr_type = PIPE_CONTROL_GTTWRITE_GLOBAL;
418
419 BRW_BATCH_STRUCT(brw, &pc);
420 }
421
422 const struct brw_tracked_state brw_pipe_control = {
423 .dirty = {
424 .mesa = 0,
425 .brw = BRW_NEW_CONTEXT,
426 .cache = 0
427 },
428 .update = upload_pipe_control
429 };
430
431
432 /***********************************************************************
433 * Misc invarient state packets
434 */
435
436 static void upload_invarient_state( struct brw_context *brw )
437 {
438 {
439 /* 0x61040000 Pipeline Select */
440 /* PipelineSelect : 0 */
441 struct brw_pipeline_select ps;
442
443 memset(&ps, 0, sizeof(ps));
444 ps.header.opcode = CMD_PIPELINE_SELECT;
445 ps.header.pipeline_select = 0;
446 BRW_BATCH_STRUCT(brw, &ps);
447 }
448
449 {
450 struct brw_global_depth_offset_clamp gdo;
451 memset(&gdo, 0, sizeof(gdo));
452
453 /* Disable depth offset clamping.
454 */
455 gdo.header.opcode = CMD_GLOBAL_DEPTH_OFFSET_CLAMP;
456 gdo.header.length = sizeof(gdo)/4 - 2;
457 gdo.depth_offset_clamp = 0.0;
458
459 BRW_BATCH_STRUCT(brw, &gdo);
460 }
461
462
463 /* 0x61020000 State Instruction Pointer */
464 {
465 struct brw_system_instruction_pointer sip;
466 memset(&sip, 0, sizeof(sip));
467
468 sip.header.opcode = CMD_STATE_INSN_POINTER;
469 sip.header.length = 0;
470 sip.bits0.pad = 0;
471 sip.bits0.system_instruction_pointer = 0;
472 BRW_BATCH_STRUCT(brw, &sip);
473 }
474
475
476 {
477 struct brw_vf_statistics vfs;
478 memset(&vfs, 0, sizeof(vfs));
479
480 vfs.opcode = CMD_VF_STATISTICS;
481 if (INTEL_DEBUG & DEBUG_STATS)
482 vfs.statistics_enable = 1;
483
484 BRW_BATCH_STRUCT(brw, &vfs);
485 }
486 }
487
488 const struct brw_tracked_state brw_invarient_state = {
489 .dirty = {
490 .mesa = 0,
491 .brw = BRW_NEW_CONTEXT,
492 .cache = 0
493 },
494 .update = upload_invarient_state
495 };
496
497
498 /* State pool addresses:
499 */
500 static void upload_state_base_address( struct brw_context *brw )
501 {
502 struct intel_context *intel = &brw->intel;
503 struct brw_state_base_address sba;
504
505 memset(&sba, 0, sizeof(sba));
506
507 sba.header.opcode = CMD_STATE_BASE_ADDRESS;
508 sba.header.length = 0x4;
509
510 /* BRW_NEW_LOCK */
511 sba.bits0.general_state_address = bmBufferOffset(intel, brw->pool[BRW_GS_POOL].buffer) >> 5;
512 sba.bits0.modify_enable = 1;
513
514 /* BRW_NEW_LOCK */
515 sba.bits1.surface_state_address = bmBufferOffset(intel, brw->pool[BRW_SS_POOL].buffer) >> 5;
516 sba.bits1.modify_enable = 1;
517
518 sba.bits2.modify_enable = 1;
519 sba.bits3.modify_enable = 1;
520 sba.bits4.modify_enable = 1;
521
522 BRW_CACHED_BATCH_STRUCT(brw, &sba);
523 }
524
525
526 const struct brw_tracked_state brw_state_base_address = {
527 .dirty = {
528 .mesa = 0,
529 .brw = BRW_NEW_CONTEXT | BRW_NEW_LOCK,
530 .cache = 0
531 },
532 .update = upload_state_base_address
533 };