r100: fix 3D texture fallback
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_ioctl.c
1 /**************************************************************************
2
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Kevin E. Martin <martin@valinux.com>
33 * Gareth Hughes <gareth@valinux.com>
34 * Keith Whitwell <keith@tungstengraphics.com>
35 */
36
37 #include <sched.h>
38 #include <errno.h>
39
40 #include "main/glheader.h"
41 #include "main/imports.h"
42 #include "main/simple_list.h"
43 #include "swrast/swrast.h"
44
45 #include "radeon_context.h"
46 #include "common_cmdbuf.h"
47 #include "radeon_cs.h"
48 #include "radeon_state.h"
49 #include "radeon_ioctl.h"
50 #include "radeon_tcl.h"
51 #include "radeon_sanity.h"
52
53 #define STANDALONE_MMIO
54 #include "radeon_macros.h" /* for INREG() */
55
56 #include "drirenderbuffer.h"
57 #include "vblank.h"
58
59 #define RADEON_TIMEOUT 512
60 #define RADEON_IDLE_RETRY 16
61
62 #define DEBUG_CMDBUF 1
63
64 static void radeonSaveHwState( r100ContextPtr rmesa )
65 {
66 struct radeon_state_atom *atom;
67 char * dest = rmesa->backup_store.cmd_buf;
68
69 if (RADEON_DEBUG & DEBUG_STATE)
70 fprintf(stderr, "%s\n", __FUNCTION__);
71
72 rmesa->backup_store.cmd_used = 0;
73
74 foreach( atom, &rmesa->hw.atomlist ) {
75 if ( atom->check( rmesa->radeon.glCtx, 0 ) ) {
76 int size = atom->cmd_size * 4;
77 memcpy( dest, atom->cmd, size);
78 dest += size;
79 rmesa->backup_store.cmd_used += size;
80 if (RADEON_DEBUG & DEBUG_STATE)
81 radeon_print_state_atom( atom );
82 }
83 }
84
85 assert( rmesa->backup_store.cmd_used <= RADEON_CMD_BUF_SZ );
86 if (RADEON_DEBUG & DEBUG_STATE)
87 fprintf(stderr, "Returning to radeonEmitState\n");
88 }
89
90 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
91 * we need to unwire our current cmdbuf, hook the one with the saved state in
92 * it, flush it, and then put the current one back. This is so commands at the
93 * start of a cmdbuf can rely on the state being kept from the previous one.
94 */
95 static void radeonBackUpAndEmitLostStateLocked( r100ContextPtr rmesa )
96 {
97 GLuint nr_released_bufs;
98 struct radeon_store saved_store;
99
100 if (rmesa->backup_store.cmd_used == 0)
101 return;
102
103 if (RADEON_DEBUG & DEBUG_STATE)
104 fprintf(stderr, "Emitting backup state on lost context\n");
105
106 rmesa->radeon.lost_context = GL_FALSE;
107
108 nr_released_bufs = rmesa->radeon.dma.nr_released_bufs;
109 saved_store = rmesa->store;
110 rmesa->radeon.dma.nr_released_bufs = 0;
111 rmesa->store = rmesa->backup_store;
112 rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
113 rmesa->radeon.dma.nr_released_bufs = nr_released_bufs;
114 rmesa->store = saved_store;
115 }
116
117 /* =============================================================
118 * Kernel command buffer handling
119 */
120
121 /* The state atoms will be emitted in the order they appear in the atom list,
122 * so this step is important.
123 */
124 void radeonSetUpAtomList( r100ContextPtr rmesa )
125 {
126 int i, mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
127
128 make_empty_list(&rmesa->hw.atomlist);
129 rmesa->hw.atomlist.name = "atom-list";
130
131 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ctx);
132 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.set);
133 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lin);
134 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msk);
135 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.vpt);
136 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tcl);
137 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msc);
138 for (i = 0; i < mtu; ++i) {
139 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tex[i]);
140 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.txr[i]);
141 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.cube[i]);
142 }
143 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.zbs);
144 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mtl);
145 for (i = 0; i < 3 + mtu; ++i)
146 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mat[i]);
147 for (i = 0; i < 8; ++i)
148 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lit[i]);
149 for (i = 0; i < 6; ++i)
150 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ucp[i]);
151 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.eye);
152 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.grd);
153 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.fog);
154 insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.glt);
155 }
156
157 static INLINE void radeonEmitAtoms(r100ContextPtr r100, GLboolean dirty)
158 {
159 BATCH_LOCALS(&r100->radeon);
160 struct radeon_state_atom *atom;
161 int dwords;
162
163 /* Emit actual atoms */
164 foreach(atom, &r100->hw.atomlist) {
165 if ((atom->dirty || r100->hw.all_dirty) == dirty) {
166 dwords = (*atom->check) (r100->radeon.glCtx, atom);
167 if (dwords) {
168 if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
169 radeon_print_state_atom(atom);
170 }
171 if (atom->emit) {
172 (*atom->emit)(r100->radeon.glCtx, atom);
173 } else {
174 BEGIN_BATCH_NO_AUTOSTATE(dwords);
175 OUT_BATCH_TABLE(atom->cmd, dwords);
176 END_BATCH();
177 }
178 atom->dirty = GL_FALSE;
179 } else {
180 if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
181 fprintf(stderr, " skip state %s\n",
182 atom->name);
183 }
184 }
185 }
186 }
187
188 COMMIT_BATCH();
189 }
190
191 void radeonEmitState( r100ContextPtr rmesa )
192 {
193 if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
194 fprintf(stderr, "%s\n", __FUNCTION__);
195
196 if (rmesa->save_on_next_emit) {
197 radeonSaveHwState(rmesa);
198 rmesa->save_on_next_emit = GL_FALSE;
199 }
200
201 /* this code used to return here but now it emits zbs */
202
203 /* To avoid going across the entire set of states multiple times, just check
204 * for enough space for the case of emitting all state, and inline the
205 * radeonAllocCmdBuf code here without all the checks.
206 */
207 rcommonEnsureCmdBufSpace(&rmesa->radeon, rmesa->hw.max_state_size, __FUNCTION__);
208
209 /* We always always emit zbs, this is due to a bug found by keithw in
210 the hardware and rediscovered after Erics changes by me.
211 if you ever touch this code make sure you emit zbs otherwise
212 you get tcl lockups on at least M7/7500 class of chips - airlied */
213 rmesa->hw.zbs.dirty=1;
214
215 if (!rmesa->radeon.cmdbuf.cs->cdw) {
216 if (RADEON_DEBUG & DEBUG_STATE)
217 fprintf(stderr, "Begin reemit state\n");
218
219 radeonEmitAtoms(rmesa, GL_FALSE);
220 }
221
222 if (RADEON_DEBUG & DEBUG_STATE)
223 fprintf(stderr, "Begin dirty state\n");
224
225 radeonEmitAtoms(rmesa, GL_TRUE);
226 rmesa->hw.is_dirty = GL_FALSE;
227 rmesa->hw.all_dirty = GL_FALSE;
228
229 }
230
231 /* Fire a section of the retained (indexed_verts) buffer as a regular
232 * primtive.
233 */
234 extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
235 GLuint vertex_format,
236 GLuint primitive,
237 GLuint vertex_nr )
238 {
239 BATCH_LOCALS(&rmesa->radeon);
240
241 assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
242
243 radeonEmitState( rmesa );
244
245 #if RADEON_OLD_PACKETS
246 BEGIN_BATCH(8);
247 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3);
248 OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
249 OUT_BATCH(vertex_nr);
250 OUT_BATCH(vertex_format);
251 OUT_BATCH(primitive | RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
252 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
253 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
254 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
255 END_BATCH();
256
257 #else
258 BEGIN_BATCH(4);
259 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1);
260 OUT_BATCH(vertex_format);
261 OUT_BATCH(primitive |
262 RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
263 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
264 RADEON_CP_VC_CNTL_MAOS_ENABLE |
265 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
266 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
267 END_BATCH();
268 #endif
269 }
270
271 void radeonFlushElts( GLcontext *ctx )
272 {
273 r100ContextPtr rmesa = R100_CONTEXT(ctx);
274 BATCH_LOCALS(&rmesa->radeon);
275 int nr;
276 uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start);
277 int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw);
278
279 if (RADEON_DEBUG & DEBUG_IOCTL)
280 fprintf(stderr, "%s\n", __FUNCTION__);
281
282 assert( rmesa->radeon.dma.flush == radeonFlushElts );
283 rmesa->radeon.dma.flush = NULL;
284
285 nr = rmesa->tcl.elt_used;
286
287 rmesa->radeon.cmdbuf.cs->cdw += dwords;
288
289 #if RADEON_OLD_PACKETS
290 cmd[1] |= (dwords + 3) << 16;
291 cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
292 #else
293 cmd[1] |= (dwords + 2) << 16;
294 cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
295 #endif
296
297 rmesa->radeon.cmdbuf.cs->section_cdw += dwords;
298 END_BATCH();
299
300 if (RADEON_DEBUG & DEBUG_SYNC) {
301 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
302 radeonFinish( rmesa->radeon.glCtx );
303 }
304
305 }
306
307 GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
308 GLuint vertex_format,
309 GLuint primitive,
310 GLuint min_nr )
311 {
312 GLushort *retval;
313 int align_min_nr;
314 BATCH_LOCALS(&rmesa->radeon);
315
316 if (RADEON_DEBUG & DEBUG_IOCTL)
317 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
318
319 assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
320
321 radeonEmitState( rmesa );
322
323 rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw;
324
325 /* round up min_nr to align the state */
326 align_min_nr = (min_nr + 1) & ~1;
327
328 #if RADEON_OLD_PACKETS
329 BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr)/4);
330 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0);
331 OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
332 OUT_BATCH(0xffff);
333 OUT_BATCH(vertex_format);
334 OUT_BATCH(primitive |
335 RADEON_CP_VC_CNTL_PRIM_WALK_IND |
336 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
337 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
338
339 #else
340 BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr)/4);
341 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0);
342 OUT_BATCH(vertex_format);
343 OUT_BATCH(primitive |
344 RADEON_CP_VC_CNTL_PRIM_WALK_IND |
345 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
346 RADEON_CP_VC_CNTL_MAOS_ENABLE |
347 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
348 #endif
349
350
351 rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw;
352 rmesa->tcl.elt_used = min_nr;
353
354 retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset);
355
356 if (RADEON_DEBUG & DEBUG_PRIMS)
357 fprintf(stderr, "%s: header prim %x \n",
358 __FUNCTION__, primitive);
359
360 assert(!rmesa->radeon.dma.flush);
361 rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
362 rmesa->radeon.dma.flush = radeonFlushElts;
363
364 return retval;
365 }
366
367 void radeonEmitVertexAOS( r100ContextPtr rmesa,
368 GLuint vertex_size,
369 struct radeon_bo *bo,
370 GLuint offset )
371 {
372 #if RADEON_OLD_PACKETS
373 rmesa->ioctl.vertex_offset = offset;
374 rmesa->ioctl.bo = bo;
375 #else
376 BATCH_LOCALS(&rmesa->radeon);
377
378 if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
379 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
380 __FUNCTION__, vertex_size, offset);
381
382 BEGIN_BATCH(7);
383 OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2);
384 OUT_BATCH(1);
385 OUT_BATCH(vertex_size | (vertex_size << 8));
386 OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
387 END_BATCH();
388
389 #endif
390 }
391
392
393 void radeonEmitAOS( r100ContextPtr rmesa,
394 GLuint nr,
395 GLuint offset )
396 {
397 #if RADEON_OLD_PACKETS
398 assert( nr == 1 );
399 rmesa->ioctl.bo = rmesa->tcl.aos[0].bo;
400 rmesa->ioctl.vertex_offset =
401 (rmesa->tcl.aos[0].offset + offset * rmesa->tcl.aos[0].stride * 4);
402 #else
403 BATCH_LOCALS(&rmesa->radeon);
404 uint32_t voffset;
405 // int sz = AOS_BUFSZ(nr);
406 int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
407 int i;
408
409 if (RADEON_DEBUG & DEBUG_IOCTL)
410 fprintf(stderr, "%s\n", __FUNCTION__);
411
412 BEGIN_BATCH(sz+2+(nr * 2));
413 OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
414 OUT_BATCH(nr);
415
416 if (!rmesa->radeon.radeonScreen->kernel_mm) {
417 for (i = 0; i + 1 < nr; i += 2) {
418 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
419 (rmesa->tcl.aos[i].stride << 8) |
420 (rmesa->tcl.aos[i + 1].components << 16) |
421 (rmesa->tcl.aos[i + 1].stride << 24));
422
423 voffset = rmesa->tcl.aos[i + 0].offset +
424 offset * 4 * rmesa->tcl.aos[i + 0].stride;
425 OUT_BATCH_RELOC(voffset,
426 rmesa->tcl.aos[i].bo,
427 voffset,
428 RADEON_GEM_DOMAIN_GTT,
429 0, 0);
430 voffset = rmesa->tcl.aos[i + 1].offset +
431 offset * 4 * rmesa->tcl.aos[i + 1].stride;
432 OUT_BATCH_RELOC(voffset,
433 rmesa->tcl.aos[i+1].bo,
434 voffset,
435 RADEON_GEM_DOMAIN_GTT,
436 0, 0);
437 }
438
439 if (nr & 1) {
440 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
441 (rmesa->tcl.aos[nr - 1].stride << 8));
442 voffset = rmesa->tcl.aos[nr - 1].offset +
443 offset * 4 * rmesa->tcl.aos[nr - 1].stride;
444 OUT_BATCH_RELOC(voffset,
445 rmesa->tcl.aos[nr - 1].bo,
446 voffset,
447 RADEON_GEM_DOMAIN_GTT,
448 0, 0);
449 }
450 } else {
451 for (i = 0; i + 1 < nr; i += 2) {
452 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
453 (rmesa->tcl.aos[i].stride << 8) |
454 (rmesa->tcl.aos[i + 1].components << 16) |
455 (rmesa->tcl.aos[i + 1].stride << 24));
456
457 voffset = rmesa->tcl.aos[i + 0].offset +
458 offset * 4 * rmesa->tcl.aos[i + 0].stride;
459 OUT_BATCH(voffset);
460 voffset = rmesa->tcl.aos[i + 1].offset +
461 offset * 4 * rmesa->tcl.aos[i + 1].stride;
462 OUT_BATCH(voffset);
463 }
464
465 if (nr & 1) {
466 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
467 (rmesa->tcl.aos[nr - 1].stride << 8));
468 voffset = rmesa->tcl.aos[nr - 1].offset +
469 offset * 4 * rmesa->tcl.aos[nr - 1].stride;
470 OUT_BATCH(voffset);
471 }
472 for (i = 0; i + 1 < nr; i += 2) {
473 voffset = rmesa->tcl.aos[i + 0].offset +
474 offset * 4 * rmesa->tcl.aos[i + 0].stride;
475 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
476 rmesa->tcl.aos[i+0].bo,
477 RADEON_GEM_DOMAIN_GTT,
478 0, 0);
479 voffset = rmesa->tcl.aos[i + 1].offset +
480 offset * 4 * rmesa->tcl.aos[i + 1].stride;
481 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
482 rmesa->tcl.aos[i+1].bo,
483 RADEON_GEM_DOMAIN_GTT,
484 0, 0);
485 }
486 if (nr & 1) {
487 voffset = rmesa->tcl.aos[nr - 1].offset +
488 offset * 4 * rmesa->tcl.aos[nr - 1].stride;
489 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
490 rmesa->tcl.aos[nr-1].bo,
491 RADEON_GEM_DOMAIN_GTT,
492 0, 0);
493 }
494 }
495 END_BATCH();
496
497 #endif
498 }
499
500 /* ================================================================
501 * Buffer clear
502 */
503 #define RADEON_MAX_CLEARS 256
504
505 static void radeonClear( GLcontext *ctx, GLbitfield mask )
506 {
507 r100ContextPtr rmesa = R100_CONTEXT(ctx);
508 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
509 drm_radeon_sarea_t *sarea = rmesa->radeon.sarea;
510 uint32_t clear;
511 GLuint flags = 0;
512 GLuint color_mask = 0;
513 GLint ret, i;
514 GLint cx, cy, cw, ch;
515
516 if ( RADEON_DEBUG & DEBUG_IOCTL ) {
517 fprintf( stderr, "radeonClear\n");
518 }
519
520 {
521 LOCK_HARDWARE( &rmesa->radeon );
522 UNLOCK_HARDWARE( &rmesa->radeon );
523 if ( dPriv->numClipRects == 0 )
524 return;
525 }
526
527 radeonFlush( ctx );
528
529 if ( mask & BUFFER_BIT_FRONT_LEFT ) {
530 flags |= RADEON_FRONT;
531 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
532 mask &= ~BUFFER_BIT_FRONT_LEFT;
533 }
534
535 if ( mask & BUFFER_BIT_BACK_LEFT ) {
536 flags |= RADEON_BACK;
537 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
538 mask &= ~BUFFER_BIT_BACK_LEFT;
539 }
540
541 if ( mask & BUFFER_BIT_DEPTH ) {
542 flags |= RADEON_DEPTH;
543 mask &= ~BUFFER_BIT_DEPTH;
544 }
545
546 if ( (mask & BUFFER_BIT_STENCIL) && rmesa->radeon.state.stencil.hwBuffer ) {
547 flags |= RADEON_STENCIL;
548 mask &= ~BUFFER_BIT_STENCIL;
549 }
550
551 if ( mask ) {
552 if (RADEON_DEBUG & DEBUG_FALLBACKS)
553 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
554 _swrast_Clear( ctx, mask );
555 }
556
557 if ( !flags )
558 return;
559
560 if (rmesa->using_hyperz) {
561 flags |= RADEON_USE_COMP_ZBUF;
562 /* if (rmesa->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)
563 flags |= RADEON_USE_HIERZ; */
564 if (!(rmesa->radeon.state.stencil.hwBuffer) ||
565 ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
566 ((rmesa->radeon.state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
567 flags |= RADEON_CLEAR_FASTZ;
568 }
569 }
570
571 LOCK_HARDWARE( &rmesa->radeon );
572
573 /* compute region after locking: */
574 cx = ctx->DrawBuffer->_Xmin;
575 cy = ctx->DrawBuffer->_Ymin;
576 cw = ctx->DrawBuffer->_Xmax - cx;
577 ch = ctx->DrawBuffer->_Ymax - cy;
578
579 /* Flip top to bottom */
580 cx += dPriv->x;
581 cy = dPriv->y + dPriv->h - cy - ch;
582
583 /* Throttle the number of clear ioctls we do.
584 */
585 while ( 1 ) {
586 int ret;
587 drm_radeon_getparam_t gp;
588
589 gp.param = RADEON_PARAM_LAST_CLEAR;
590 gp.value = (int *)&clear;
591 ret = drmCommandWriteRead( rmesa->radeon.dri.fd,
592 DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
593
594 if ( ret ) {
595 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
596 exit(1);
597 }
598
599 if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
600 break;
601 }
602
603 if ( rmesa->radeon.do_usleeps ) {
604 UNLOCK_HARDWARE( &rmesa->radeon );
605 DO_USLEEP( 1 );
606 LOCK_HARDWARE( &rmesa->radeon );
607 }
608 }
609
610 /* Send current state to the hardware */
611 rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
612
613 for ( i = 0 ; i < dPriv->numClipRects ; ) {
614 GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
615 drm_clip_rect_t *box = dPriv->pClipRects;
616 drm_clip_rect_t *b = rmesa->radeon.sarea->boxes;
617 drm_radeon_clear_t clear;
618 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
619 GLint n = 0;
620
621 if (cw != dPriv->w || ch != dPriv->h) {
622 /* clear subregion */
623 for ( ; i < nr ; i++ ) {
624 GLint x = box[i].x1;
625 GLint y = box[i].y1;
626 GLint w = box[i].x2 - x;
627 GLint h = box[i].y2 - y;
628
629 if ( x < cx ) w -= cx - x, x = cx;
630 if ( y < cy ) h -= cy - y, y = cy;
631 if ( x + w > cx + cw ) w = cx + cw - x;
632 if ( y + h > cy + ch ) h = cy + ch - y;
633 if ( w <= 0 ) continue;
634 if ( h <= 0 ) continue;
635
636 b->x1 = x;
637 b->y1 = y;
638 b->x2 = x + w;
639 b->y2 = y + h;
640 b++;
641 n++;
642 }
643 } else {
644 /* clear whole buffer */
645 for ( ; i < nr ; i++ ) {
646 *b++ = box[i];
647 n++;
648 }
649 }
650
651 rmesa->radeon.sarea->nbox = n;
652
653 clear.flags = flags;
654 clear.clear_color = rmesa->radeon.state.color.clear;
655 clear.clear_depth = rmesa->radeon.state.depth.clear;
656 clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
657 clear.depth_mask = rmesa->radeon.state.stencil.clear;
658 clear.depth_boxes = depth_boxes;
659
660 n--;
661 b = rmesa->radeon.sarea->boxes;
662 for ( ; n >= 0 ; n-- ) {
663 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
664 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
665 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
666 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
667 depth_boxes[n].f[CLEAR_DEPTH] =
668 (float)rmesa->radeon.state.depth.clear;
669 }
670
671 ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR,
672 &clear, sizeof(drm_radeon_clear_t));
673
674 if ( ret ) {
675 UNLOCK_HARDWARE( &rmesa->radeon );
676 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
677 exit( 1 );
678 }
679 }
680
681 UNLOCK_HARDWARE( &rmesa->radeon );
682 rmesa->hw.all_dirty = GL_TRUE;
683 }
684
685 void radeonFlush( GLcontext *ctx )
686 {
687 r100ContextPtr rmesa = R100_CONTEXT( ctx );
688
689 if (RADEON_DEBUG & DEBUG_IOCTL)
690 fprintf(stderr, "%s\n", __FUNCTION__);
691
692 if (rmesa->radeon.dma.flush)
693 rmesa->radeon.dma.flush( ctx );
694
695 radeonEmitState( rmesa );
696
697 if (rmesa->radeon.cmdbuf.cs->cdw)
698 rcommonFlushCmdBuf( &rmesa->radeon, __FUNCTION__ );
699 }
700
701 /* Make sure all commands have been sent to the hardware and have
702 * completed processing.
703 */
704 void radeonFinish( GLcontext *ctx )
705 {
706 radeonFlush( ctx );
707 radeon_common_finish(ctx);
708 }
709
710
711 void radeonInitIoctlFuncs( GLcontext *ctx )
712 {
713 ctx->Driver.Clear = radeonClear;
714 ctx->Driver.Finish = radeonFinish;
715 ctx->Driver.Flush = radeonFlush;
716 }
717