radeon_ioctl.c revision 7e5e327cea83d9f6d1485f9be440277540ace5c7
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_state.h"
47#include "radeon_ioctl.h"
48#include "radeon_tcl.h"
49#include "radeon_sanity.h"
50
51#define STANDALONE_MMIO
52#include "radeon_macros.h"  /* for INREG() */
53
54#include "drirenderbuffer.h"
55#include "vblank.h"
56
57#define RADEON_TIMEOUT             512
58#define RADEON_IDLE_RETRY           16
59
60
61static int radeonFlushCmdBufLocked( r100ContextPtr rmesa,
62				    const char * caller );
63
64static void print_state_atom( struct radeon_state_atom *state )
65{
66   int i;
67
68   fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
69
70   if (RADEON_DEBUG & DEBUG_VERBOSE)
71      for (i = 0 ; i < state->cmd_size ; i++)
72	 fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
73
74}
75
76static void radeonSaveHwState( r100ContextPtr rmesa )
77{
78   struct radeon_state_atom *atom;
79   char * dest = rmesa->backup_store.cmd_buf;
80
81   if (RADEON_DEBUG & DEBUG_STATE)
82      fprintf(stderr, "%s\n", __FUNCTION__);
83
84   rmesa->backup_store.cmd_used = 0;
85
86   foreach( atom, &rmesa->hw.atomlist ) {
87      if ( atom->check( rmesa->radeon.glCtx, 0 ) ) {
88	 int size = atom->cmd_size * 4;
89	 memcpy( dest, atom->cmd, size);
90	 dest += size;
91	 rmesa->backup_store.cmd_used += size;
92	 if (RADEON_DEBUG & DEBUG_STATE)
93	    print_state_atom( atom );
94      }
95   }
96
97   assert( rmesa->backup_store.cmd_used <= RADEON_CMD_BUF_SZ );
98   if (RADEON_DEBUG & DEBUG_STATE)
99      fprintf(stderr, "Returning to radeonEmitState\n");
100}
101
102/* At this point we were in FlushCmdBufLocked but we had lost our context, so
103 * we need to unwire our current cmdbuf, hook the one with the saved state in
104 * it, flush it, and then put the current one back.  This is so commands at the
105 * start of a cmdbuf can rely on the state being kept from the previous one.
106 */
107static void radeonBackUpAndEmitLostStateLocked( r100ContextPtr rmesa )
108{
109   GLuint nr_released_bufs;
110   struct radeon_store saved_store;
111
112   if (rmesa->backup_store.cmd_used == 0)
113      return;
114
115   if (RADEON_DEBUG & DEBUG_STATE)
116      fprintf(stderr, "Emitting backup state on lost context\n");
117
118   rmesa->radeon.lost_context = GL_FALSE;
119
120   nr_released_bufs = rmesa->dma.nr_released_bufs;
121   saved_store = rmesa->store;
122   rmesa->dma.nr_released_bufs = 0;
123   rmesa->store = rmesa->backup_store;
124   radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
125   rmesa->dma.nr_released_bufs = nr_released_bufs;
126   rmesa->store = saved_store;
127}
128
129/* =============================================================
130 * Kernel command buffer handling
131 */
132
133/* The state atoms will be emitted in the order they appear in the atom list,
134 * so this step is important.
135 */
136void radeonSetUpAtomList( r100ContextPtr rmesa )
137{
138   int i, mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
139
140   make_empty_list(&rmesa->hw.atomlist);
141   rmesa->hw.atomlist.name = "atom-list";
142
143   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ctx);
144   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.set);
145   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lin);
146   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msk);
147   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.vpt);
148   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tcl);
149   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.msc);
150   for (i = 0; i < mtu; ++i) {
151       insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.tex[i]);
152       insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.txr[i]);
153       insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.cube[i]);
154   }
155   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.zbs);
156   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mtl);
157   for (i = 0; i < 3 + mtu; ++i)
158      insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.mat[i]);
159   for (i = 0; i < 8; ++i)
160      insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.lit[i]);
161   for (i = 0; i < 6; ++i)
162      insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.ucp[i]);
163   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.eye);
164   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.grd);
165   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.fog);
166   insert_at_tail(&rmesa->hw.atomlist, &rmesa->hw.glt);
167}
168
169void radeonEmitState( r100ContextPtr rmesa )
170{
171   struct radeon_state_atom *atom;
172   char *dest;
173
174   if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
175      fprintf(stderr, "%s\n", __FUNCTION__);
176
177   if (rmesa->save_on_next_emit) {
178      radeonSaveHwState(rmesa);
179      rmesa->save_on_next_emit = GL_FALSE;
180   }
181
182   /* this code used to return here but now it emits zbs */
183
184   /* To avoid going across the entire set of states multiple times, just check
185    * for enough space for the case of emitting all state, and inline the
186    * radeonAllocCmdBuf code here without all the checks.
187    */
188   radeonEnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size);
189   dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
190
191   /* We always always emit zbs, this is due to a bug found by keithw in
192      the hardware and rediscovered after Erics changes by me.
193      if you ever touch this code make sure you emit zbs otherwise
194      you get tcl lockups on at least M7/7500 class of chips - airlied */
195   rmesa->hw.zbs.dirty=1;
196
197   if (RADEON_DEBUG & DEBUG_STATE) {
198      foreach(atom, &rmesa->hw.atomlist) {
199	 if (atom->dirty || rmesa->hw.all_dirty) {
200	    if (atom->check(rmesa->radeon.glCtx, 0))
201	       print_state_atom(atom);
202	    else
203	       fprintf(stderr, "skip state %s\n", atom->name);
204	 }
205      }
206   }
207
208   foreach(atom, &rmesa->hw.atomlist) {
209      if (rmesa->hw.all_dirty)
210	 atom->dirty = GL_TRUE;
211      if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) &&
212	   atom->is_tcl)
213	 atom->dirty = GL_FALSE;
214      if (atom->dirty) {
215	if (atom->check(rmesa->radeon.glCtx, 0)) {
216	    int size = atom->cmd_size * 4;
217	    memcpy(dest, atom->cmd, size);
218	    dest += size;
219	    rmesa->store.cmd_used += size;
220	    atom->dirty = GL_FALSE;
221	 }
222      }
223   }
224
225   assert(rmesa->store.cmd_used <= RADEON_CMD_BUF_SZ);
226
227   rmesa->hw.is_dirty = GL_FALSE;
228   rmesa->hw.all_dirty = GL_FALSE;
229}
230
231/* Fire a section of the retained (indexed_verts) buffer as a regular
232 * primtive.
233 */
234extern void radeonEmitVbufPrim( r100ContextPtr rmesa,
235				GLuint vertex_format,
236				GLuint primitive,
237				GLuint vertex_nr )
238{
239   drm_radeon_cmd_header_t *cmd;
240
241
242   assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
243
244   radeonEmitState( rmesa );
245
246   if (RADEON_DEBUG & DEBUG_IOCTL)
247      fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
248	      rmesa->store.cmd_used/4);
249
250   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VBUF_BUFSZ,
251						       __FUNCTION__ );
252#if RADEON_OLD_PACKETS
253   cmd[0].i = 0;
254   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
255   cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
256   cmd[2].i = rmesa->ioctl.vertex_offset;
257   cmd[3].i = vertex_nr;
258   cmd[4].i = vertex_format;
259   cmd[5].i = (primitive |
260	       RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
261	       RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
262	       RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
263	       (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
264
265   if (RADEON_DEBUG & DEBUG_PRIMS)
266      fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
267	      __FUNCTION__,
268	      cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
269#else
270   cmd[0].i = 0;
271   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
272   cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
273   cmd[2].i = vertex_format;
274   cmd[3].i = (primitive |
275	       RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
276	       RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
277	       RADEON_CP_VC_CNTL_MAOS_ENABLE |
278	       RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
279	       (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
280
281
282   if (RADEON_DEBUG & DEBUG_PRIMS)
283      fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
284	      __FUNCTION__,
285	      cmd[1].i, cmd[2].i, cmd[3].i);
286#endif
287}
288
289
290void radeonFlushElts( GLcontext *ctx )
291{
292  r100ContextPtr rmesa = R100_CONTEXT(ctx);
293   int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
294   int dwords;
295#if RADEON_OLD_PACKETS
296   int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2;
297#else
298   int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2;
299#endif
300
301   if (RADEON_DEBUG & DEBUG_IOCTL)
302      fprintf(stderr, "%s\n", __FUNCTION__);
303
304   assert( rmesa->dma.flush == radeonFlushElts );
305   rmesa->dma.flush = NULL;
306
307   /* Cope with odd number of elts:
308    */
309   rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
310   dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
311
312#if RADEON_OLD_PACKETS
313   cmd[1] |= (dwords - 3) << 16;
314   cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
315#else
316   cmd[1] |= (dwords - 3) << 16;
317   cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
318#endif
319
320   if (RADEON_DEBUG & DEBUG_SYNC) {
321      fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
322      radeonFinish( rmesa->radeon.glCtx );
323   }
324}
325
326
327GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa,
328				    GLuint vertex_format,
329				    GLuint primitive,
330				    GLuint min_nr )
331{
332   drm_radeon_cmd_header_t *cmd;
333   GLushort *retval;
334
335   if (RADEON_DEBUG & DEBUG_IOCTL)
336      fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr);
337
338   assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
339
340   radeonEmitState( rmesa );
341
342   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
343						       ELTS_BUFSZ(min_nr),
344						       __FUNCTION__ );
345#if RADEON_OLD_PACKETS
346   cmd[0].i = 0;
347   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
348   cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
349   cmd[2].i = rmesa->ioctl.vertex_offset;
350   cmd[3].i = 0xffff;
351   cmd[4].i = vertex_format;
352   cmd[5].i = (primitive |
353	       RADEON_CP_VC_CNTL_PRIM_WALK_IND |
354	       RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
355	       RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
356
357   retval = (GLushort *)(cmd+6);
358#else
359   cmd[0].i = 0;
360   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
361   cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
362   cmd[2].i = vertex_format;
363   cmd[3].i = (primitive |
364	       RADEON_CP_VC_CNTL_PRIM_WALK_IND |
365	       RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
366	       RADEON_CP_VC_CNTL_MAOS_ENABLE |
367	       RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
368
369   retval = (GLushort *)(cmd+4);
370#endif
371
372   if (RADEON_DEBUG & DEBUG_PRIMS)
373      fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n",
374	      __FUNCTION__,
375	      cmd[1].i, vertex_format, primitive);
376
377   assert(!rmesa->dma.flush);
378   rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
379   rmesa->dma.flush = radeonFlushElts;
380
381   rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
382
383   return retval;
384}
385
386
387
388void radeonEmitVertexAOS( r100ContextPtr rmesa,
389			  GLuint vertex_size,
390			  GLuint offset )
391{
392#if RADEON_OLD_PACKETS
393   rmesa->ioctl.vertex_size = vertex_size;
394   rmesa->ioctl.vertex_offset = offset;
395#else
396   drm_radeon_cmd_header_t *cmd;
397
398   if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
399      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
400	      __FUNCTION__, vertex_size, offset);
401
402   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
403						  __FUNCTION__ );
404
405   cmd[0].i = 0;
406   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
407   cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16);
408   cmd[2].i = 1;
409   cmd[3].i = vertex_size | (vertex_size << 8);
410   cmd[4].i = offset;
411#endif
412}
413
414
415void radeonEmitAOS( r100ContextPtr rmesa,
416		    struct radeon_dma_region **component,
417		    GLuint nr,
418		    GLuint offset )
419{
420#if RADEON_OLD_PACKETS
421   assert( nr == 1 );
422   assert( component[0]->aos_size == component[0]->aos_stride );
423   rmesa->ioctl.vertex_size = component[0]->aos_size;
424   rmesa->ioctl.vertex_offset =
425      (component[0]->aos_start + offset * component[0]->aos_stride * 4);
426#else
427   drm_radeon_cmd_header_t *cmd;
428   int sz = AOS_BUFSZ(nr);
429   int i;
430   int *tmp;
431
432   if (RADEON_DEBUG & DEBUG_IOCTL)
433      fprintf(stderr, "%s\n", __FUNCTION__);
434
435
436   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz,
437						  __FUNCTION__ );
438   cmd[0].i = 0;
439   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
440   cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (((sz / sizeof(int))-3) << 16);
441   cmd[2].i = nr;
442   tmp = &cmd[0].i;
443   cmd += 3;
444
445   for (i = 0 ; i < nr ; i++) {
446      if (i & 1) {
447	 cmd[0].i |= ((component[i]->aos_stride << 24) |
448		      (component[i]->aos_size << 16));
449	 cmd[2].i = (component[i]->aos_start +
450		     offset * component[i]->aos_stride * 4);
451	 cmd += 3;
452      }
453      else {
454	 cmd[0].i = ((component[i]->aos_stride << 8) |
455		     (component[i]->aos_size << 0));
456	 cmd[1].i = (component[i]->aos_start +
457		     offset * component[i]->aos_stride * 4);
458      }
459   }
460
461   if (RADEON_DEBUG & DEBUG_VERTS) {
462      fprintf(stderr, "%s:\n", __FUNCTION__);
463      for (i = 0 ; i < sz ; i++)
464	 fprintf(stderr, "   %d: %x\n", i, tmp[i]);
465   }
466#endif
467}
468
469/* using already shifted color_fmt! */
470void radeonEmitBlit( r100ContextPtr rmesa, /* FIXME: which drmMinor is required? */
471		   GLuint color_fmt,
472		   GLuint src_pitch,
473		   GLuint src_offset,
474		   GLuint dst_pitch,
475		   GLuint dst_offset,
476		   GLint srcx, GLint srcy,
477		   GLint dstx, GLint dsty,
478		   GLuint w, GLuint h )
479{
480   drm_radeon_cmd_header_t *cmd;
481
482   if (RADEON_DEBUG & DEBUG_IOCTL)
483      fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
484	      __FUNCTION__,
485	      src_pitch, src_offset, srcx, srcy,
486	      dst_pitch, dst_offset, dstx, dsty,
487	      w, h);
488
489   assert( (src_pitch & 63) == 0 );
490   assert( (dst_pitch & 63) == 0 );
491   assert( (src_offset & 1023) == 0 );
492   assert( (dst_offset & 1023) == 0 );
493   assert( w < (1<<16) );
494   assert( h < (1<<16) );
495
496   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
497						  __FUNCTION__ );
498
499
500   cmd[0].i = 0;
501   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
502   cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
503   cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
504	       RADEON_GMC_DST_PITCH_OFFSET_CNTL |
505	       RADEON_GMC_BRUSH_NONE |
506	       color_fmt |
507	       RADEON_GMC_SRC_DATATYPE_COLOR |
508	       RADEON_ROP3_S |
509	       RADEON_DP_SRC_SOURCE_MEMORY |
510	       RADEON_GMC_CLR_CMP_CNTL_DIS |
511	       RADEON_GMC_WR_MSK_DIS );
512
513   cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
514   cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
515   cmd[5].i = (srcx << 16) | srcy;
516   cmd[6].i = (dstx << 16) | dsty; /* dst */
517   cmd[7].i = (w << 16) | h;
518}
519
520
521void radeonEmitWait( r100ContextPtr rmesa, GLuint flags )
522{
523   drm_radeon_cmd_header_t *cmd;
524
525   assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
526
527   cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
528					   __FUNCTION__ );
529   cmd[0].i = 0;
530   cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
531   cmd[0].wait.flags = flags;
532}
533
534
535static int radeonFlushCmdBufLocked( r100ContextPtr rmesa,
536				    const char * caller )
537{
538   int ret, i;
539   drm_radeon_cmd_buffer_t cmd;
540
541   if (rmesa->radeon.lost_context)
542      radeonBackUpAndEmitLostStateLocked(rmesa);
543
544   if (RADEON_DEBUG & DEBUG_IOCTL) {
545      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
546
547      if (RADEON_DEBUG & DEBUG_VERBOSE)
548	 for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
549	    fprintf(stderr, "%d: %x\n", i/4,
550		    *(int *)(&rmesa->store.cmd_buf[i]));
551   }
552
553   if (RADEON_DEBUG & DEBUG_DMA)
554      fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
555	      rmesa->dma.nr_released_bufs);
556
557
558   if (RADEON_DEBUG & DEBUG_SANITY) {
559      if (rmesa->radeon.state.scissor.enabled)
560	 ret = radeonSanityCmdBuffer( rmesa,
561				      rmesa->radeon.state.scissor.numClipRects,
562				      rmesa->radeon.state.scissor.pClipRects);
563      else
564	 ret = radeonSanityCmdBuffer( rmesa,
565				      rmesa->radeon.numClipRects,
566				      rmesa->radeon.pClipRects);
567      if (ret) {
568	 fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
569	 goto out;
570      }
571   }
572
573
574   cmd.bufsz = rmesa->store.cmd_used;
575   cmd.buf = rmesa->store.cmd_buf;
576
577   if (rmesa->radeon.state.scissor.enabled) {
578      cmd.nbox = rmesa->radeon.state.scissor.numClipRects;
579      cmd.boxes = rmesa->radeon.state.scissor.pClipRects;
580   } else {
581      cmd.nbox = rmesa->radeon.numClipRects;
582      cmd.boxes = rmesa->radeon.pClipRects;
583   }
584
585   ret = drmCommandWrite( rmesa->radeon.dri.fd,
586			  DRM_RADEON_CMDBUF,
587			  &cmd, sizeof(cmd) );
588
589   if (ret)
590      fprintf(stderr, "drmCommandWrite: %d\n", ret);
591
592   if (RADEON_DEBUG & DEBUG_SYNC) {
593      fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__);
594      radeonWaitForIdleLocked( &rmesa->radeon );
595   }
596
597 out:
598   rmesa->store.primnr = 0;
599   rmesa->store.statenr = 0;
600   rmesa->store.cmd_used = 0;
601   rmesa->dma.nr_released_bufs = 0;
602   rmesa->save_on_next_emit = 1;
603
604   return ret;
605}
606
607
608/* Note: does not emit any commands to avoid recursion on
609 * radeonAllocCmdBuf.
610 */
611void radeonFlushCmdBuf( r100ContextPtr rmesa, const char *caller )
612{
613   int ret;
614
615
616   LOCK_HARDWARE( &rmesa->radeon );
617
618   ret = radeonFlushCmdBufLocked( rmesa, caller );
619
620   UNLOCK_HARDWARE( &rmesa->radeon );
621
622   if (ret) {
623      fprintf(stderr, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret);
624      exit(ret);
625   }
626}
627
628/* =============================================================
629 * Hardware vertex buffer handling
630 */
631
632
633void radeonRefillCurrentDmaRegion( r100ContextPtr rmesa )
634{
635   struct radeon_dma_buffer *dmabuf;
636   int fd = rmesa->radeon.dri.fd;
637   int index = 0;
638   int size = 0;
639   drmDMAReq dma;
640   int ret;
641
642   if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
643      fprintf(stderr, "%s\n", __FUNCTION__);
644
645   if (rmesa->dma.flush) {
646      rmesa->dma.flush( rmesa->radeon.glCtx );
647   }
648
649   if (rmesa->dma.current.buf)
650      radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
651
652   if (rmesa->dma.nr_released_bufs > 4)
653      radeonFlushCmdBuf( rmesa, __FUNCTION__ );
654
655   dma.context = rmesa->radeon.dri.hwContext;
656   dma.send_count = 0;
657   dma.send_list = NULL;
658   dma.send_sizes = NULL;
659   dma.flags = 0;
660   dma.request_count = 1;
661   dma.request_size = RADEON_BUFFER_SIZE;
662   dma.request_list = &index;
663   dma.request_sizes = &size;
664   dma.granted_count = 0;
665
666   LOCK_HARDWARE(&rmesa->radeon);	/* no need to validate */
667
668   ret = drmDMA( fd, &dma );
669
670   if (ret != 0) {
671      /* Free some up this way?
672       */
673      if (rmesa->dma.nr_released_bufs) {
674	 radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
675      }
676
677      if (RADEON_DEBUG & DEBUG_DMA)
678	 fprintf(stderr, "Waiting for buffers\n");
679
680      radeonWaitForIdleLocked( &rmesa->radeon );
681      ret = drmDMA( fd, &dma );
682
683      if ( ret != 0 ) {
684	 UNLOCK_HARDWARE( &rmesa->radeon );
685	 fprintf( stderr, "Error: Could not get dma buffer... exiting\n" );
686	 exit( -1 );
687      }
688   }
689
690   UNLOCK_HARDWARE(&rmesa->radeon);
691
692   if (RADEON_DEBUG & DEBUG_DMA)
693      fprintf(stderr, "Allocated buffer %d\n", index);
694
695   dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
696   dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
697   dmabuf->refcount = 1;
698
699   rmesa->dma.current.buf = dmabuf;
700   rmesa->dma.current.address = dmabuf->buf->address;
701   rmesa->dma.current.end = dmabuf->buf->total;
702   rmesa->dma.current.start = 0;
703   rmesa->dma.current.ptr = 0;
704
705   rmesa->c_vertexBuffers++;
706}
707
708void radeonReleaseDmaRegion( r100ContextPtr rmesa,
709			     struct radeon_dma_region *region,
710			     const char *caller )
711{
712   if (RADEON_DEBUG & DEBUG_IOCTL)
713      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
714
715   if (!region->buf)
716      return;
717
718   if (rmesa->dma.flush)
719      rmesa->dma.flush( rmesa->radeon.glCtx );
720
721   if (--region->buf->refcount == 0) {
722      drm_radeon_cmd_header_t *cmd;
723
724      if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
725	 fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
726		 region->buf->buf->idx);
727
728      cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sizeof(*cmd),
729						     __FUNCTION__ );
730      cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
731      cmd->dma.buf_idx = region->buf->buf->idx;
732      FREE(region->buf);
733      rmesa->dma.nr_released_bufs++;
734   }
735
736   region->buf = NULL;
737   region->start = 0;
738}
739
740/* Allocates a region from rmesa->dma.current.  If there isn't enough
741 * space in current, grab a new buffer (and discard what was left of current)
742 */
743void radeonAllocDmaRegion( r100ContextPtr rmesa,
744			   struct radeon_dma_region *region,
745			   int bytes,
746			   int alignment )
747{
748   if (RADEON_DEBUG & DEBUG_IOCTL)
749      fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
750
751   if (rmesa->dma.flush)
752      rmesa->dma.flush( rmesa->radeon.glCtx );
753
754   if (region->buf)
755      radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ );
756
757   alignment--;
758   rmesa->dma.current.start = rmesa->dma.current.ptr =
759      (rmesa->dma.current.ptr + alignment) & ~alignment;
760
761   if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
762      radeonRefillCurrentDmaRegion( rmesa );
763
764   region->start = rmesa->dma.current.start;
765   region->ptr = rmesa->dma.current.start;
766   region->end = rmesa->dma.current.start + bytes;
767   region->address = rmesa->dma.current.address;
768   region->buf = rmesa->dma.current.buf;
769   region->buf->refcount++;
770
771   rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
772   rmesa->dma.current.start =
773      rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
774}
775
776/* ================================================================
777 * Buffer clear
778 */
779#define RADEON_MAX_CLEARS	256
780
781static void radeonClear( GLcontext *ctx, GLbitfield mask )
782{
783   r100ContextPtr rmesa = R100_CONTEXT(ctx);
784   __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable;
785   drm_radeon_sarea_t *sarea = rmesa->radeon.sarea;
786   uint32_t clear;
787   GLuint flags = 0;
788   GLuint color_mask = 0;
789   GLint ret, i;
790   GLint cx, cy, cw, ch;
791
792   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
793      fprintf( stderr, "radeonClear\n");
794   }
795
796   {
797      LOCK_HARDWARE( &rmesa->radeon );
798      UNLOCK_HARDWARE( &rmesa->radeon );
799      if ( dPriv->numClipRects == 0 )
800	 return;
801   }
802
803   radeonFlush( ctx );
804
805   if ( mask & BUFFER_BIT_FRONT_LEFT ) {
806      flags |= RADEON_FRONT;
807      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
808      mask &= ~BUFFER_BIT_FRONT_LEFT;
809   }
810
811   if ( mask & BUFFER_BIT_BACK_LEFT ) {
812      flags |= RADEON_BACK;
813      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
814      mask &= ~BUFFER_BIT_BACK_LEFT;
815   }
816
817   if ( mask & BUFFER_BIT_DEPTH ) {
818      flags |= RADEON_DEPTH;
819      mask &= ~BUFFER_BIT_DEPTH;
820   }
821
822   if ( (mask & BUFFER_BIT_STENCIL) && rmesa->radeon.state.stencil.hwBuffer ) {
823      flags |= RADEON_STENCIL;
824      mask &= ~BUFFER_BIT_STENCIL;
825   }
826
827   if ( mask ) {
828      if (RADEON_DEBUG & DEBUG_FALLBACKS)
829	 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
830      _swrast_Clear( ctx, mask );
831   }
832
833   if ( !flags )
834      return;
835
836   if (rmesa->using_hyperz) {
837      flags |= RADEON_USE_COMP_ZBUF;
838/*      if (rmesa->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)
839         flags |= RADEON_USE_HIERZ; */
840      if (!(rmesa->radeon.state.stencil.hwBuffer) ||
841	 ((flags & RADEON_DEPTH) && (flags & RADEON_STENCIL) &&
842	    ((rmesa->radeon.state.stencil.clear & RADEON_STENCIL_WRITE_MASK) == RADEON_STENCIL_WRITE_MASK))) {
843	  flags |= RADEON_CLEAR_FASTZ;
844      }
845   }
846
847   LOCK_HARDWARE( &rmesa->radeon );
848
849   /* compute region after locking: */
850   cx = ctx->DrawBuffer->_Xmin;
851   cy = ctx->DrawBuffer->_Ymin;
852   cw = ctx->DrawBuffer->_Xmax - cx;
853   ch = ctx->DrawBuffer->_Ymax - cy;
854
855   /* Flip top to bottom */
856   cx += dPriv->x;
857   cy  = dPriv->y + dPriv->h - cy - ch;
858
859   /* Throttle the number of clear ioctls we do.
860    */
861   while ( 1 ) {
862      int ret;
863      drm_radeon_getparam_t gp;
864
865      gp.param = RADEON_PARAM_LAST_CLEAR;
866      gp.value = (int *)&clear;
867      ret = drmCommandWriteRead( rmesa->radeon.dri.fd,
868				 DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
869
870      if ( ret ) {
871	 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
872	 exit(1);
873      }
874
875      if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
876	 break;
877      }
878
879      if ( rmesa->radeon.do_usleeps ) {
880	 UNLOCK_HARDWARE( &rmesa->radeon );
881	 DO_USLEEP( 1 );
882	 LOCK_HARDWARE( &rmesa->radeon );
883      }
884   }
885
886   /* Send current state to the hardware */
887   radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
888
889   for ( i = 0 ; i < dPriv->numClipRects ; ) {
890      GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
891      drm_clip_rect_t *box = dPriv->pClipRects;
892      drm_clip_rect_t *b = rmesa->radeon.sarea->boxes;
893      drm_radeon_clear_t clear;
894      drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
895      GLint n = 0;
896
897      if (cw != dPriv->w || ch != dPriv->h) {
898         /* clear subregion */
899	 for ( ; i < nr ; i++ ) {
900	    GLint x = box[i].x1;
901	    GLint y = box[i].y1;
902	    GLint w = box[i].x2 - x;
903	    GLint h = box[i].y2 - y;
904
905	    if ( x < cx ) w -= cx - x, x = cx;
906	    if ( y < cy ) h -= cy - y, y = cy;
907	    if ( x + w > cx + cw ) w = cx + cw - x;
908	    if ( y + h > cy + ch ) h = cy + ch - y;
909	    if ( w <= 0 ) continue;
910	    if ( h <= 0 ) continue;
911
912	    b->x1 = x;
913	    b->y1 = y;
914	    b->x2 = x + w;
915	    b->y2 = y + h;
916	    b++;
917	    n++;
918	 }
919      } else {
920         /* clear whole buffer */
921	 for ( ; i < nr ; i++ ) {
922	    *b++ = box[i];
923	    n++;
924	 }
925      }
926
927      rmesa->radeon.sarea->nbox = n;
928
929      clear.flags       = flags;
930      clear.clear_color = rmesa->radeon.state.color.clear;
931      clear.clear_depth = rmesa->radeon.state.depth.clear;
932      clear.color_mask  = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
933      clear.depth_mask  = rmesa->radeon.state.stencil.clear;
934      clear.depth_boxes = depth_boxes;
935
936      n--;
937      b = rmesa->radeon.sarea->boxes;
938      for ( ; n >= 0 ; n-- ) {
939	 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
940	 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
941	 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
942	 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
943	 depth_boxes[n].f[CLEAR_DEPTH] =
944	    (float)rmesa->radeon.state.depth.clear;
945      }
946
947      ret = drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_CLEAR,
948			     &clear, sizeof(drm_radeon_clear_t));
949
950      if ( ret ) {
951	 UNLOCK_HARDWARE( &rmesa->radeon );
952	 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
953	 exit( 1 );
954      }
955   }
956
957   UNLOCK_HARDWARE( &rmesa->radeon );
958   rmesa->hw.all_dirty = GL_TRUE;
959}
960
961void radeonFlush( GLcontext *ctx )
962{
963   r100ContextPtr rmesa = R100_CONTEXT( ctx );
964
965   if (RADEON_DEBUG & DEBUG_IOCTL)
966      fprintf(stderr, "%s\n", __FUNCTION__);
967
968   if (rmesa->dma.flush)
969      rmesa->dma.flush( rmesa->radeon.glCtx );
970
971   radeonEmitState( rmesa );
972
973   if (rmesa->store.cmd_used)
974      radeonFlushCmdBuf( rmesa, __FUNCTION__ );
975}
976
977/* Make sure all commands have been sent to the hardware and have
978 * completed processing.
979 */
980void radeonFinish( GLcontext *ctx )
981{
982   radeonFlush( ctx );
983   radeon_common_finish(ctx);
984}
985
986
987void radeonInitIoctlFuncs( GLcontext *ctx )
988{
989    ctx->Driver.Clear = radeonClear;
990    ctx->Driver.Finish = radeonFinish;
991    ctx->Driver.Flush = radeonFlush;
992}
993
994