radeon_ioctl.c revision 2972d065265d38c7902ffeaa1e71706895649bec
1/**************************************************************************
2
3Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                     VA Linux Systems Inc., Fremont, California.
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH 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 "radeon_common.h"
47#include "radeon_state.h"
48#include "radeon_ioctl.h"
49#include "radeon_tcl.h"
50#include "radeon_sanity.h"
51
52#define STANDALONE_MMIO
53#include "radeon_macros.h"  /* for INREG() */
54
55#include "drirenderbuffer.h"
56#include "vblank.h"
57
58#define RADEON_TIMEOUT             512
59#define RADEON_IDLE_RETRY           16
60
61
62/* =============================================================
63 * Kernel command buffer handling
64 */
65
66/* The state atoms will be emitted in the order they appear in the atom list,
67 * so this step is important.
68 */
69void radeonSetUpAtomList( r100ContextPtr rmesa )
70{
71   int i, mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
72
73   make_empty_list(&rmesa->radeon.hw.atomlist);
74   rmesa->radeon.hw.atomlist.name = "atom-list";
75
76   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ctx);
77   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.set);
78   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lin);
79   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msk);
80   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.vpt);
81   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tcl);
82   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msc);
83   for (i = 0; i < mtu; ++i) {
84       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i]);
85       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.txr[i]);
86       insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i]);
87   }
88   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.zbs);
89   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mtl);
90   for (i = 0; i < 3 + mtu; ++i)
91      insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i]);
92   for (i = 0; i < 8; ++i)
93      insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]);
94   for (i = 0; i < 6; ++i)
95      insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]);
96   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye);
97   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd);
98   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog);
99   insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.glt);
100}
101
102/* Fire a section of the retained (indexed_verts) buffer as a regular
103 * primtive.
104 */
105extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
106				GLuint vertex_format,
107				GLuint primitive,
108				GLuint vertex_nr )
109{
110   BATCH_LOCALS(&rmesa->radeon);
111
112   assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
113
114   radeonEmitState(&rmesa->radeon);
115
116#if RADEON_OLD_PACKETS
117   BEGIN_BATCH(8);
118   OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3);
119   if (!rmesa->radeon.radeonScreen->kernel_mm) {
120     OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
121   } else {
122     OUT_BATCH(rmesa->ioctl.vertex_offset);
123   }
124
125   OUT_BATCH(vertex_nr);
126   OUT_BATCH(vertex_format);
127   OUT_BATCH(primitive |  RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
128	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
129	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
130	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
131
132   if (rmesa->radeon.radeonScreen->kernel_mm) {
133     radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
134			   rmesa->ioctl.bo,
135			   RADEON_GEM_DOMAIN_GTT,
136			   0, 0);
137   }
138
139   END_BATCH();
140
141#else
142   BEGIN_BATCH(4);
143   OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1);
144   OUT_BATCH(vertex_format);
145   OUT_BATCH(primitive |
146	     RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
147	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
148	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
149	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
150	     (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
151   END_BATCH();
152#endif
153}
154
155void radeonFlushElts( GLcontext *ctx )
156{
157   r100ContextPtr rmesa = R100_CONTEXT(ctx);
158   BATCH_LOCALS(&rmesa->radeon);
159   int nr;
160   uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start);
161   int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw);
162
163   if (RADEON_DEBUG & DEBUG_IOCTL)
164      fprintf(stderr, "%s\n", __FUNCTION__);
165
166   assert( rmesa->radeon.dma.flush == radeonFlushElts );
167   rmesa->radeon.dma.flush = NULL;
168
169   nr = rmesa->tcl.elt_used;
170
171#if RADEON_OLD_PACKETS
172   if (rmesa->radeon.radeonScreen->kernel_mm) {
173     dwords -= 2;
174   }
175#endif
176
177#if RADEON_OLD_PACKETS
178   cmd[1] |= (dwords + 3) << 16;
179   cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
180#else
181   cmd[1] |= (dwords + 2) << 16;
182   cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
183#endif
184
185   rmesa->radeon.cmdbuf.cs->cdw += dwords;
186   rmesa->radeon.cmdbuf.cs->section_cdw += dwords;
187
188#if RADEON_OLD_PACKETS
189   if (rmesa->radeon.radeonScreen->kernel_mm) {
190      radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
191			    rmesa->ioctl.bo,
192			    RADEON_GEM_DOMAIN_GTT,
193			    0, 0);
194   }
195#endif
196
197   END_BATCH();
198
199   if (RADEON_DEBUG & DEBUG_SYNC) {
200      fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
201      radeonFinish( rmesa->radeon.glCtx );
202   }
203
204}
205
206GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
207				    GLuint vertex_format,
208				    GLuint primitive,
209				    GLuint min_nr )
210{
211   GLushort *retval;
212   int align_min_nr;
213   BATCH_LOCALS(&rmesa->radeon);
214
215   if (RADEON_DEBUG & DEBUG_IOCTL)
216      fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
217
218   assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
219
220   radeonEmitState(&rmesa->radeon);
221
222   rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw;
223
224   /* round up min_nr to align the state */
225   align_min_nr = (min_nr + 1) & ~1;
226
227#if RADEON_OLD_PACKETS
228   BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr)/4);
229   OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0);
230   if (!rmesa->radeon.radeonScreen->kernel_mm) {
231     OUT_BATCH_RELOC(rmesa->ioctl.vertex_offset, rmesa->ioctl.bo, rmesa->ioctl.vertex_offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
232   } else {
233     OUT_BATCH(rmesa->ioctl.vertex_offset);
234   }
235   OUT_BATCH(0xffff);
236   OUT_BATCH(vertex_format);
237   OUT_BATCH(primitive |
238	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
239	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
240	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
241
242#else
243   BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr)/4);
244   OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0);
245   OUT_BATCH(vertex_format);
246   OUT_BATCH(primitive |
247	     RADEON_CP_VC_CNTL_PRIM_WALK_IND |
248	     RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
249	     RADEON_CP_VC_CNTL_MAOS_ENABLE |
250	     RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
251#endif
252
253
254   rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw;
255   rmesa->tcl.elt_used = min_nr;
256
257   retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset);
258
259   if (RADEON_DEBUG & DEBUG_PRIMS)
260      fprintf(stderr, "%s: header prim %x \n",
261	      __FUNCTION__, primitive);
262
263   assert(!rmesa->radeon.dma.flush);
264   rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
265   rmesa->radeon.dma.flush = radeonFlushElts;
266
267   return retval;
268}
269
270void radeonEmitVertexAOS( r100ContextPtr rmesa,
271			  GLuint vertex_size,
272			  struct radeon_bo *bo,
273			  GLuint offset )
274{
275#if RADEON_OLD_PACKETS
276   rmesa->ioctl.vertex_offset = offset;
277   rmesa->ioctl.bo = bo;
278#else
279   BATCH_LOCALS(&rmesa->radeon);
280
281   if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
282      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
283	      __FUNCTION__, vertex_size, offset);
284
285   BEGIN_BATCH(7);
286   OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2);
287   OUT_BATCH(1);
288   OUT_BATCH(vertex_size | (vertex_size << 8));
289   OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
290   END_BATCH();
291
292#endif
293}
294
295
296void radeonEmitAOS( r100ContextPtr rmesa,
297		    GLuint nr,
298		    GLuint offset )
299{
300#if RADEON_OLD_PACKETS
301   assert( nr == 1 );
302   rmesa->ioctl.bo = rmesa->tcl.aos[0].bo;
303   rmesa->ioctl.vertex_offset =
304     (rmesa->tcl.aos[0].offset + offset * rmesa->tcl.aos[0].stride * 4);
305#else
306   BATCH_LOCALS(&rmesa->radeon);
307   uint32_t voffset;
308   //   int sz = AOS_BUFSZ(nr);
309   int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
310   int i;
311
312   if (RADEON_DEBUG & DEBUG_IOCTL)
313      fprintf(stderr, "%s\n", __FUNCTION__);
314
315   BEGIN_BATCH(sz+2+(nr * 2));
316   OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1);
317   OUT_BATCH(nr);
318
319   if (!rmesa->radeon.radeonScreen->kernel_mm) {
320      for (i = 0; i + 1 < nr; i += 2) {
321	 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
322		   (rmesa->tcl.aos[i].stride << 8) |
323		   (rmesa->tcl.aos[i + 1].components << 16) |
324		   (rmesa->tcl.aos[i + 1].stride << 24));
325
326	 voffset =  rmesa->tcl.aos[i + 0].offset +
327	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
328	 OUT_BATCH_RELOC(voffset,
329			 rmesa->tcl.aos[i].bo,
330			 voffset,
331			 RADEON_GEM_DOMAIN_GTT,
332			 0, 0);
333	 voffset =  rmesa->tcl.aos[i + 1].offset +
334	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
335	 OUT_BATCH_RELOC(voffset,
336			 rmesa->tcl.aos[i+1].bo,
337			 voffset,
338			 RADEON_GEM_DOMAIN_GTT,
339			 0, 0);
340      }
341
342      if (nr & 1) {
343	 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
344		   (rmesa->tcl.aos[nr - 1].stride << 8));
345	 voffset =  rmesa->tcl.aos[nr - 1].offset +
346	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
347	 OUT_BATCH_RELOC(voffset,
348			 rmesa->tcl.aos[nr - 1].bo,
349			 voffset,
350			 RADEON_GEM_DOMAIN_GTT,
351			 0, 0);
352      }
353   } else {
354      for (i = 0; i + 1 < nr; i += 2) {
355	 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
356		   (rmesa->tcl.aos[i].stride << 8) |
357		   (rmesa->tcl.aos[i + 1].components << 16) |
358		   (rmesa->tcl.aos[i + 1].stride << 24));
359
360	 voffset =  rmesa->tcl.aos[i + 0].offset +
361	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
362	 OUT_BATCH(voffset);
363	 voffset =  rmesa->tcl.aos[i + 1].offset +
364	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
365	 OUT_BATCH(voffset);
366      }
367
368      if (nr & 1) {
369	 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
370		   (rmesa->tcl.aos[nr - 1].stride << 8));
371	 voffset =  rmesa->tcl.aos[nr - 1].offset +
372	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
373	 OUT_BATCH(voffset);
374      }
375      for (i = 0; i + 1 < nr; i += 2) {
376	 voffset =  rmesa->tcl.aos[i + 0].offset +
377	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
378	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
379			       rmesa->tcl.aos[i+0].bo,
380			       RADEON_GEM_DOMAIN_GTT,
381			       0, 0);
382	 voffset =  rmesa->tcl.aos[i + 1].offset +
383	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
384	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
385			       rmesa->tcl.aos[i+1].bo,
386			       RADEON_GEM_DOMAIN_GTT,
387			       0, 0);
388      }
389      if (nr & 1) {
390	 voffset =  rmesa->tcl.aos[nr - 1].offset +
391	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
392	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
393			       rmesa->tcl.aos[nr-1].bo,
394			       RADEON_GEM_DOMAIN_GTT,
395			       0, 0);
396      }
397   }
398   END_BATCH();
399
400#endif
401}
402
403/* ================================================================
404 * Buffer clear
405 */
406#define RADEON_MAX_CLEARS	256
407
408static void radeonClear( GLcontext *ctx, GLbitfield mask )
409{
410   r100ContextPtr rmesa = R100_CONTEXT(ctx);
411   __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
412   drm_radeon_sarea_t *sarea = rmesa->radeon.sarea;
413   uint32_t clear;
414   GLuint flags = 0;
415   GLuint color_mask = 0;
416   GLint ret, i;
417   GLint cx, cy, cw, ch;
418
419   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
420      fprintf( stderr, "radeonClear\n");
421   }
422
423   {
424      LOCK_HARDWARE( &rmesa->radeon );
425      UNLOCK_HARDWARE( &rmesa->radeon );
426      if ( dPriv->numClipRects == 0 )
427	 return;
428   }
429
430   radeonFlush( ctx );
431
432   if ( mask & BUFFER_BIT_FRONT_LEFT ) {
433      flags |= RADEON_FRONT;
434      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
435      mask &= ~BUFFER_BIT_FRONT_LEFT;
436   }
437
438   if ( mask & BUFFER_BIT_BACK_LEFT ) {
439      flags |= RADEON_BACK;
440      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
441      mask &= ~BUFFER_BIT_BACK_LEFT;
442   }
443
444   if ( mask & BUFFER_BIT_DEPTH ) {
445      flags |= RADEON_DEPTH;
446      mask &= ~BUFFER_BIT_DEPTH;
447   }
448
449   if ( (mask & BUFFER_BIT_STENCIL) && rmesa->radeon.state.stencil.hwBuffer ) {
450      flags |= RADEON_STENCIL;
451      mask &= ~BUFFER_BIT_STENCIL;
452   }
453
454   if ( mask ) {
455      if (RADEON_DEBUG & DEBUG_FALLBACKS)
456	 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
457      _swrast_Clear( ctx, mask );
458   }
459
460   if ( !flags )
461      return;
462
463   if (rmesa->using_hyperz) {
464      flags |= RADEON_USE_COMP_ZBUF;
465/*      if (rmesa->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)
466         flags |= RADEON_USE_HIERZ; */
467      if (!(rmesa->radeon.state.stencil.hwBuffer) ||
468	 ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
469	    ((rmesa->radeon.state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
470	  flags |= RADEON_CLEAR_FASTZ;
471      }
472   }
473
474   LOCK_HARDWARE( &rmesa->radeon );
475
476   /* compute region after locking: */
477   cx = ctx->DrawBuffer->_Xmin;
478   cy = ctx->DrawBuffer->_Ymin;
479   cw = ctx->DrawBuffer->_Xmax - cx;
480   ch = ctx->DrawBuffer->_Ymax - cy;
481
482   /* Flip top to bottom */
483   cx += dPriv->x;
484   cy  = dPriv->y + dPriv->h - cy - ch;
485
486   /* Throttle the number of clear ioctls we do.
487    */
488   while ( 1 ) {
489      int ret;
490      drm_radeon_getparam_t gp;
491
492      gp.param = RADEON_PARAM_LAST_CLEAR;
493      gp.value = (int *)&clear;
494      ret = drmCommandWriteRead( rmesa->radeon.dri.fd,
495				 DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
496
497      if ( ret ) {
498	 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
499	 exit(1);
500      }
501
502      if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
503	 break;
504      }
505
506      if ( rmesa->radeon.do_usleeps ) {
507	 UNLOCK_HARDWARE( &rmesa->radeon );
508	 DO_USLEEP( 1 );
509	 LOCK_HARDWARE( &rmesa->radeon );
510      }
511   }
512
513   /* Send current state to the hardware */
514   rcommonFlushCmdBufLocked( &rmesa->radeon, __FUNCTION__ );
515
516   for ( i = 0 ; i < dPriv->numClipRects ; ) {
517      GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
518      drm_clip_rect_t *box = dPriv->pClipRects;
519      drm_clip_rect_t *b = rmesa->radeon.sarea->boxes;
520      drm_radeon_clear_t clear;
521      drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
522      GLint n = 0;
523
524      if (cw != dPriv->w || ch != dPriv->h) {
525         /* clear subregion */
526	 for ( ; i < nr ; i++ ) {
527	    GLint x = box[i].x1;
528	    GLint y = box[i].y1;
529	    GLint w = box[i].x2 - x;
530	    GLint h = box[i].y2 - y;
531
532	    if ( x < cx ) w -= cx - x, x = cx;
533	    if ( y < cy ) h -= cy - y, y = cy;
534	    if ( x + w > cx + cw ) w = cx + cw - x;
535	    if ( y + h > cy + ch ) h = cy + ch - y;
536	    if ( w <= 0 ) continue;
537	    if ( h <= 0 ) continue;
538
539	    b->x1 = x;
540	    b->y1 = y;
541	    b->x2 = x + w;
542	    b->y2 = y + h;
543	    b++;
544	    n++;
545	 }
546      } else {
547         /* clear whole buffer */
548	 for ( ; i < nr ; i++ ) {
549	    *b++ = box[i];
550	    n++;
551	 }
552      }
553
554      rmesa->radeon.sarea->nbox = n;
555
556      clear.flags       = flags;
557      clear.clear_color = rmesa->radeon.state.color.clear;
558      clear.clear_depth = rmesa->radeon.state.depth.clear;
559      clear.color_mask  = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
560      clear.depth_mask  = rmesa->radeon.state.stencil.clear;
561      clear.depth_boxes = depth_boxes;
562
563      n--;
564      b = rmesa->radeon.sarea->boxes;
565      for ( ; n >= 0 ; n-- ) {
566	 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
567	 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
568	 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
569	 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
570	 depth_boxes[n].f[CLEAR_DEPTH] =
571	    (float)rmesa->radeon.state.depth.clear;
572      }
573
574      ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR,
575			     &clear, sizeof(drm_radeon_clear_t));
576
577      if ( ret ) {
578	 UNLOCK_HARDWARE( &rmesa->radeon );
579	 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
580	 exit( 1 );
581      }
582   }
583
584   UNLOCK_HARDWARE( &rmesa->radeon );
585   rmesa->radeon.hw.all_dirty = GL_TRUE;
586}
587
588void radeonInitIoctlFuncs( GLcontext *ctx )
589{
590    ctx->Driver.Clear = radeonClear;
591    ctx->Driver.Finish = radeonFinish;
592    ctx->Driver.Flush = radeonFlush;
593}
594
595