build fixes
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_ioctl.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
36 */
37
38 #include <sched.h>
39 #include <errno.h>
40
41 #include "glheader.h"
42 #include "imports.h"
43 #include "simple_list.h"
44 #include "swrast/swrast.h"
45
46 #include "radeon_context.h"
47 #include "radeon_state.h"
48 #include "radeon_ioctl.h"
49 #include "radeon_tcl.h"
50 #include "radeon_sanity.h"
51
52 #include "radeon_macros.h" /* for INREG() */
53
54 #include "vblank.h"
55
56 #define RADEON_TIMEOUT 512
57 #define RADEON_IDLE_RETRY 16
58
59
60 static void radeonWaitForIdle( radeonContextPtr rmesa );
61
62 /* =============================================================
63 * Kernel command buffer handling
64 */
65
66 static void print_state_atom( struct radeon_state_atom *state )
67 {
68 int i;
69
70 fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
71
72 if (RADEON_DEBUG & DEBUG_VERBOSE)
73 for (i = 0 ; i < state->cmd_size ; i++)
74 fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
75
76 }
77
78 static void radeon_emit_state_list( radeonContextPtr rmesa,
79 struct radeon_state_atom *list )
80 {
81 struct radeon_state_atom *state, *tmp;
82 char *dest;
83 int i, size, texunits;
84
85 /* It appears that some permutations of state atoms lock up the
86 * chip. Therefore we make sure that state atoms are emitted in a
87 * fixed order. First mark all dirty state atoms and then go
88 * through all state atoms in a well defined order and emit only
89 * the marked ones.
90 * FIXME: This requires knowledge of which state atoms exist.
91 * FIXME: Is the zbs hack below still needed?
92 */
93 size = 0;
94 foreach_s( state, tmp, list ) {
95 if (state->check( rmesa->glCtx )) {
96 size += state->cmd_size;
97 state->dirty = GL_TRUE;
98 move_to_head( &(rmesa->hw.clean), state );
99 if (RADEON_DEBUG & DEBUG_STATE)
100 print_state_atom( state );
101 }
102 else if (RADEON_DEBUG & DEBUG_STATE)
103 fprintf(stderr, "skip state %s\n", state->name);
104 }
105 /* short cut */
106 if (!size)
107 return;
108
109 dest = radeonAllocCmdBuf( rmesa, size * 4, __FUNCTION__);
110 texunits = rmesa->glCtx->Const.MaxTextureUnits;
111
112 #define EMIT_ATOM(ATOM) \
113 do { \
114 if (rmesa->hw.ATOM.dirty) { \
115 rmesa->hw.ATOM.dirty = GL_FALSE; \
116 memcpy( dest, rmesa->hw.ATOM.cmd, rmesa->hw.ATOM.cmd_size * 4); \
117 dest += rmesa->hw.ATOM.cmd_size * 4; \
118 } \
119 } while (0)
120
121 EMIT_ATOM (ctx);
122 EMIT_ATOM (set);
123 EMIT_ATOM (lin);
124 EMIT_ATOM (msk);
125 EMIT_ATOM (vpt);
126 EMIT_ATOM (tcl);
127 EMIT_ATOM (msc);
128 for (i = 0; i < texunits; ++i) {
129 EMIT_ATOM (tex[i]);
130 EMIT_ATOM (txr[i]);
131 }
132 EMIT_ATOM (zbs);
133 EMIT_ATOM (mtl);
134 for (i = 0; i < 3 + texunits; ++i)
135 EMIT_ATOM (mat[i]);
136 for (i = 0; i < 8; ++i)
137 EMIT_ATOM (lit[i]);
138 for (i = 0; i < 6; ++i)
139 EMIT_ATOM (ucp[i]);
140 EMIT_ATOM (eye);
141 EMIT_ATOM (grd);
142 EMIT_ATOM (fog);
143 EMIT_ATOM (glt);
144
145 #undef EMIT_ATOM
146 }
147
148
149 void radeonEmitState( radeonContextPtr rmesa )
150 {
151 struct radeon_state_atom *state, *tmp;
152
153 if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
154 fprintf(stderr, "%s\n", __FUNCTION__);
155
156 /* Somewhat overkill:
157 */
158 if (rmesa->lost_context) {
159 if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
160 fprintf(stderr, "%s - lost context\n", __FUNCTION__);
161
162 foreach_s( state, tmp, &(rmesa->hw.clean) )
163 move_to_tail(&(rmesa->hw.dirty), state );
164
165 rmesa->lost_context = 0;
166 }
167 else if (1) {
168 /* This is a darstardly kludge to work around a lockup that I
169 * haven't otherwise figured out.
170 */
171 move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) );
172 }
173
174 if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
175 foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
176 if (state->is_tcl) {
177 move_to_head( &(rmesa->hw.clean), state );
178 }
179 }
180 }
181
182 radeon_emit_state_list( rmesa, &rmesa->hw.dirty );
183 }
184
185
186
187 /* Fire a section of the retained (indexed_verts) buffer as a regular
188 * primtive.
189 */
190 extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
191 GLuint vertex_format,
192 GLuint primitive,
193 GLuint vertex_nr )
194 {
195 drm_radeon_cmd_header_t *cmd;
196
197
198 assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
199
200 radeonEmitState( rmesa );
201
202 if (RADEON_DEBUG & DEBUG_IOCTL)
203 fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
204 rmesa->store.cmd_used/4);
205
206 #if RADEON_OLD_PACKETS
207 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd),
208 __FUNCTION__ );
209 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
210 cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
211 cmd[2].i = rmesa->ioctl.vertex_offset;
212 cmd[3].i = vertex_nr;
213 cmd[4].i = vertex_format;
214 cmd[5].i = (primitive |
215 RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
216 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
217 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
218 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
219
220 if (RADEON_DEBUG & DEBUG_PRIMS)
221 fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
222 __FUNCTION__,
223 cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
224 #else
225 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd),
226 __FUNCTION__ );
227 cmd[0].i = 0;
228 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
229 cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
230 cmd[2].i = vertex_format;
231 cmd[3].i = (primitive |
232 RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
233 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
234 RADEON_CP_VC_CNTL_MAOS_ENABLE |
235 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
236 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
237
238
239 if (RADEON_DEBUG & DEBUG_PRIMS)
240 fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
241 __FUNCTION__,
242 cmd[1].i, cmd[2].i, cmd[3].i);
243 #endif
244 }
245
246
247 void radeonFlushElts( radeonContextPtr rmesa )
248 {
249 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
250 int dwords;
251 #if RADEON_OLD_PACKETS
252 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2;
253 #else
254 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2;
255 #endif
256
257 if (RADEON_DEBUG & DEBUG_IOCTL)
258 fprintf(stderr, "%s\n", __FUNCTION__);
259
260 assert( rmesa->dma.flush == radeonFlushElts );
261 rmesa->dma.flush = 0;
262
263 /* Cope with odd number of elts:
264 */
265 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
266 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
267
268 #if RADEON_OLD_PACKETS
269 cmd[1] |= (dwords - 3) << 16;
270 cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
271 #else
272 cmd[1] |= (dwords - 3) << 16;
273 cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
274 #endif
275 }
276
277
278 GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
279 GLuint vertex_format,
280 GLuint primitive,
281 GLuint min_nr )
282 {
283 drm_radeon_cmd_header_t *cmd;
284 GLushort *retval;
285
286 if (RADEON_DEBUG & DEBUG_IOCTL)
287 fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr);
288
289 assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
290
291 radeonEmitState( rmesa );
292
293 #if RADEON_OLD_PACKETS
294 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
295 24 + min_nr*2,
296 __FUNCTION__ );
297 cmd[0].i = 0;
298 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
299 cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
300 cmd[2].i = rmesa->ioctl.vertex_offset;
301 cmd[3].i = 0xffff;
302 cmd[4].i = vertex_format;
303 cmd[5].i = (primitive |
304 RADEON_CP_VC_CNTL_PRIM_WALK_IND |
305 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
306 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
307
308 retval = (GLushort *)(cmd+6);
309 #else
310 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa,
311 16 + min_nr*2,
312 __FUNCTION__ );
313 cmd[0].i = 0;
314 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
315 cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
316 cmd[2].i = vertex_format;
317 cmd[3].i = (primitive |
318 RADEON_CP_VC_CNTL_PRIM_WALK_IND |
319 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
320 RADEON_CP_VC_CNTL_MAOS_ENABLE |
321 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
322
323 retval = (GLushort *)(cmd+4);
324 #endif
325
326 if (RADEON_DEBUG & DEBUG_PRIMS)
327 fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n",
328 __FUNCTION__,
329 cmd[1].i, vertex_format, primitive);
330
331 assert(!rmesa->dma.flush);
332 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
333 rmesa->dma.flush = radeonFlushElts;
334
335 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
336
337 return retval;
338 }
339
340
341
342 void radeonEmitVertexAOS( radeonContextPtr rmesa,
343 GLuint vertex_size,
344 GLuint offset )
345 {
346 #if RADEON_OLD_PACKETS
347 rmesa->ioctl.vertex_size = vertex_size;
348 rmesa->ioctl.vertex_offset = offset;
349 #else
350 drm_radeon_cmd_header_t *cmd;
351
352 if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
353 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
354 __FUNCTION__, vertex_size, offset);
355
356 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int),
357 __FUNCTION__ );
358
359 cmd[0].i = 0;
360 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
361 cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16);
362 cmd[2].i = 1;
363 cmd[3].i = vertex_size | (vertex_size << 8);
364 cmd[4].i = offset;
365 #endif
366 }
367
368
369 void radeonEmitAOS( radeonContextPtr rmesa,
370 struct radeon_dma_region **component,
371 GLuint nr,
372 GLuint offset )
373 {
374 #if RADEON_OLD_PACKETS
375 assert( nr == 1 );
376 assert( component[0]->aos_size == component[0]->aos_stride );
377 rmesa->ioctl.vertex_size = component[0]->aos_size;
378 rmesa->ioctl.vertex_offset =
379 (component[0]->aos_start + offset * component[0]->aos_stride * 4);
380 #else
381 drm_radeon_cmd_header_t *cmd;
382 int sz = 3 + (nr/2 * 3) + (nr & 1) * 2;
383 int i;
384 int *tmp;
385
386 if (RADEON_DEBUG & DEBUG_IOCTL)
387 fprintf(stderr, "%s\n", __FUNCTION__);
388
389
390 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz * sizeof(int),
391 __FUNCTION__ );
392 cmd[0].i = 0;
393 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
394 cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16);
395 cmd[2].i = nr;
396 tmp = &cmd[0].i;
397 cmd += 3;
398
399 for (i = 0 ; i < nr ; i++) {
400 if (i & 1) {
401 cmd[0].i |= ((component[i]->aos_stride << 24) |
402 (component[i]->aos_size << 16));
403 cmd[2].i = (component[i]->aos_start +
404 offset * component[i]->aos_stride * 4);
405 cmd += 3;
406 }
407 else {
408 cmd[0].i = ((component[i]->aos_stride << 8) |
409 (component[i]->aos_size << 0));
410 cmd[1].i = (component[i]->aos_start +
411 offset * component[i]->aos_stride * 4);
412 }
413 }
414
415 if (RADEON_DEBUG & DEBUG_VERTS) {
416 fprintf(stderr, "%s:\n", __FUNCTION__);
417 for (i = 0 ; i < sz ; i++)
418 fprintf(stderr, " %d: %x\n", i, tmp[i]);
419 }
420 #endif
421 }
422
423 /* using already shifted color_fmt! */
424 void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */
425 GLuint color_fmt,
426 GLuint src_pitch,
427 GLuint src_offset,
428 GLuint dst_pitch,
429 GLuint dst_offset,
430 GLint srcx, GLint srcy,
431 GLint dstx, GLint dsty,
432 GLuint w, GLuint h )
433 {
434 drm_radeon_cmd_header_t *cmd;
435
436 if (RADEON_DEBUG & DEBUG_IOCTL)
437 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
438 __FUNCTION__,
439 src_pitch, src_offset, srcx, srcy,
440 dst_pitch, dst_offset, dstx, dsty,
441 w, h);
442
443 assert( (src_pitch & 63) == 0 );
444 assert( (dst_pitch & 63) == 0 );
445 assert( (src_offset & 1023) == 0 );
446 assert( (dst_offset & 1023) == 0 );
447 assert( w < (1<<16) );
448 assert( h < (1<<16) );
449
450 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
451 __FUNCTION__ );
452
453
454 cmd[0].i = 0;
455 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
456 cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
457 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
458 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
459 RADEON_GMC_BRUSH_NONE |
460 color_fmt |
461 RADEON_GMC_SRC_DATATYPE_COLOR |
462 RADEON_ROP3_S |
463 RADEON_DP_SRC_SOURCE_MEMORY |
464 RADEON_GMC_CLR_CMP_CNTL_DIS |
465 RADEON_GMC_WR_MSK_DIS );
466
467 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
468 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
469 cmd[5].i = (srcx << 16) | srcy;
470 cmd[6].i = (dstx << 16) | dsty; /* dst */
471 cmd[7].i = (w << 16) | h;
472 }
473
474
475 void radeonEmitWait( radeonContextPtr rmesa, GLuint flags )
476 {
477 if (rmesa->dri.drmMinor >= 6) {
478 drm_radeon_cmd_header_t *cmd;
479
480 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
481
482 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
483 __FUNCTION__ );
484 cmd[0].i = 0;
485 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
486 cmd[0].wait.flags = flags;
487 }
488 }
489
490
491 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa,
492 const char * caller )
493 {
494 int ret, i;
495 drm_radeon_cmd_buffer_t cmd;
496
497 if (RADEON_DEBUG & DEBUG_IOCTL) {
498 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
499
500 if (RADEON_DEBUG & DEBUG_VERBOSE)
501 for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
502 fprintf(stderr, "%d: %x\n", i/4,
503 *(int *)(&rmesa->store.cmd_buf[i]));
504 }
505
506 if (RADEON_DEBUG & DEBUG_DMA)
507 fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
508 rmesa->dma.nr_released_bufs);
509
510
511 if (RADEON_DEBUG & DEBUG_SANITY) {
512 if (rmesa->state.scissor.enabled)
513 ret = radeonSanityCmdBuffer( rmesa,
514 rmesa->state.scissor.numClipRects,
515 rmesa->state.scissor.pClipRects);
516 else
517 ret = radeonSanityCmdBuffer( rmesa,
518 rmesa->numClipRects,
519 rmesa->pClipRects);
520 if (ret) {
521 fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);
522 goto out;
523 }
524 }
525
526
527 cmd.bufsz = rmesa->store.cmd_used;
528 cmd.buf = rmesa->store.cmd_buf;
529
530 if (rmesa->state.scissor.enabled) {
531 cmd.nbox = rmesa->state.scissor.numClipRects;
532 cmd.boxes = rmesa->state.scissor.pClipRects;
533 } else {
534 cmd.nbox = rmesa->numClipRects;
535 cmd.boxes = rmesa->pClipRects;
536 }
537
538 ret = drmCommandWrite( rmesa->dri.fd,
539 DRM_RADEON_CMDBUF,
540 &cmd, sizeof(cmd) );
541
542 if (ret)
543 fprintf(stderr, "drmCommandWrite: %d\n", ret);
544
545 out:
546 rmesa->store.primnr = 0;
547 rmesa->store.statenr = 0;
548 rmesa->store.cmd_used = 0;
549 rmesa->dma.nr_released_bufs = 0;
550 rmesa->lost_context = 1;
551 return ret;
552 }
553
554
555 /* Note: does not emit any commands to avoid recursion on
556 * radeonAllocCmdBuf.
557 */
558 void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller )
559 {
560 int ret;
561
562
563 LOCK_HARDWARE( rmesa );
564
565 ret = radeonFlushCmdBufLocked( rmesa, caller );
566
567 UNLOCK_HARDWARE( rmesa );
568
569 if (ret) {
570 fprintf(stderr, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret);
571 exit(ret);
572 }
573 }
574
575 /* =============================================================
576 * Hardware vertex buffer handling
577 */
578
579
580 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa )
581 {
582 struct radeon_dma_buffer *dmabuf;
583 int fd = rmesa->dri.fd;
584 int index = 0;
585 int size = 0;
586 drmDMAReq dma;
587 int ret;
588
589 if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
590 fprintf(stderr, "%s\n", __FUNCTION__);
591
592 if (rmesa->dma.flush) {
593 rmesa->dma.flush( rmesa );
594 }
595
596 if (rmesa->dma.current.buf)
597 radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
598
599 if (rmesa->dma.nr_released_bufs > 4)
600 radeonFlushCmdBuf( rmesa, __FUNCTION__ );
601
602 dma.context = rmesa->dri.hwContext;
603 dma.send_count = 0;
604 dma.send_list = NULL;
605 dma.send_sizes = NULL;
606 dma.flags = 0;
607 dma.request_count = 1;
608 dma.request_size = RADEON_BUFFER_SIZE;
609 dma.request_list = &index;
610 dma.request_sizes = &size;
611 dma.granted_count = 0;
612
613 LOCK_HARDWARE(rmesa); /* no need to validate */
614
615 ret = drmDMA( fd, &dma );
616
617 if (ret != 0) {
618 /* Free some up this way?
619 */
620 if (rmesa->dma.nr_released_bufs) {
621 radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
622 }
623
624 if (RADEON_DEBUG & DEBUG_DMA)
625 fprintf(stderr, "Waiting for buffers\n");
626
627 radeonWaitForIdleLocked( rmesa );
628 ret = drmDMA( fd, &dma );
629
630 if ( ret != 0 ) {
631 UNLOCK_HARDWARE( rmesa );
632 fprintf( stderr, "Error: Could not get dma buffer... exiting\n" );
633 exit( -1 );
634 }
635 }
636
637 UNLOCK_HARDWARE(rmesa);
638
639 if (RADEON_DEBUG & DEBUG_DMA)
640 fprintf(stderr, "Allocated buffer %d\n", index);
641
642 dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
643 dmabuf->buf = &rmesa->radeonScreen->buffers->list[index];
644 dmabuf->refcount = 1;
645
646 rmesa->dma.current.buf = dmabuf;
647 rmesa->dma.current.address = dmabuf->buf->address;
648 rmesa->dma.current.end = dmabuf->buf->total;
649 rmesa->dma.current.start = 0;
650 rmesa->dma.current.ptr = 0;
651
652 rmesa->c_vertexBuffers++;
653 }
654
655 void radeonReleaseDmaRegion( radeonContextPtr rmesa,
656 struct radeon_dma_region *region,
657 const char *caller )
658 {
659 if (RADEON_DEBUG & DEBUG_IOCTL)
660 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
661
662 if (!region->buf)
663 return;
664
665 if (rmesa->dma.flush)
666 rmesa->dma.flush( rmesa );
667
668 if (--region->buf->refcount == 0) {
669 drm_radeon_cmd_header_t *cmd;
670
671 if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
672 fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
673 region->buf->buf->idx);
674
675 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sizeof(*cmd),
676 __FUNCTION__ );
677 cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
678 cmd->dma.buf_idx = region->buf->buf->idx;
679 FREE(region->buf);
680 rmesa->dma.nr_released_bufs++;
681 }
682
683 region->buf = 0;
684 region->start = 0;
685 }
686
687 /* Allocates a region from rmesa->dma.current. If there isn't enough
688 * space in current, grab a new buffer (and discard what was left of current)
689 */
690 void radeonAllocDmaRegion( radeonContextPtr rmesa,
691 struct radeon_dma_region *region,
692 int bytes,
693 int alignment )
694 {
695 if (RADEON_DEBUG & DEBUG_IOCTL)
696 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
697
698 if (rmesa->dma.flush)
699 rmesa->dma.flush( rmesa );
700
701 if (region->buf)
702 radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ );
703
704 alignment--;
705 rmesa->dma.current.start = rmesa->dma.current.ptr =
706 (rmesa->dma.current.ptr + alignment) & ~alignment;
707
708 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
709 radeonRefillCurrentDmaRegion( rmesa );
710
711 region->start = rmesa->dma.current.start;
712 region->ptr = rmesa->dma.current.start;
713 region->end = rmesa->dma.current.start + bytes;
714 region->address = rmesa->dma.current.address;
715 region->buf = rmesa->dma.current.buf;
716 region->buf->refcount++;
717
718 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
719 rmesa->dma.current.start =
720 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
721 }
722
723 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa,
724 struct radeon_dma_region *region,
725 int numverts,
726 int vertsize,
727 int alignment )
728 {
729 radeonAllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
730 }
731
732 /* ================================================================
733 * SwapBuffers with client-side throttling
734 */
735
736 static uint32_t radeonGetLastFrame (radeonContextPtr rmesa)
737 {
738 unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
739 int ret;
740 uint32_t frame;
741
742 if (rmesa->dri.screen->drmMinor >= 4) {
743 drm_radeon_getparam_t gp;
744
745 gp.param = RADEON_PARAM_LAST_FRAME;
746 gp.value = (int *)&frame;
747 ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
748 &gp, sizeof(gp) );
749 }
750 else
751 ret = -EINVAL;
752
753 #ifndef __alpha__
754 if ( ret == -EINVAL ) {
755 frame = INREG( RADEON_LAST_FRAME_REG );
756 ret = 0;
757 }
758 #endif
759 if ( ret ) {
760 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
761 exit(1);
762 }
763
764 return frame;
765 }
766
767 static void radeonEmitIrqLocked( radeonContextPtr rmesa )
768 {
769 drm_radeon_irq_emit_t ie;
770 int ret;
771
772 ie.irq_seq = &rmesa->iw.irq_seq;
773 ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT,
774 &ie, sizeof(ie) );
775 if ( ret ) {
776 fprintf( stderr, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__, ret );
777 exit(1);
778 }
779 }
780
781
782 static void radeonWaitIrq( radeonContextPtr rmesa )
783 {
784 int ret;
785
786 do {
787 ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
788 &rmesa->iw, sizeof(rmesa->iw) );
789 } while (ret && (errno == EINTR || errno == EAGAIN));
790
791 if ( ret ) {
792 fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
793 exit(1);
794 }
795 }
796
797
798 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa )
799 {
800 drm_radeon_sarea_t *sarea = rmesa->sarea;
801
802 if (rmesa->do_irqs) {
803 if (radeonGetLastFrame(rmesa) < sarea->last_frame) {
804 if (!rmesa->irqsEmitted) {
805 while (radeonGetLastFrame (rmesa) < sarea->last_frame)
806 ;
807 }
808 else {
809 UNLOCK_HARDWARE( rmesa );
810 radeonWaitIrq( rmesa );
811 LOCK_HARDWARE( rmesa );
812 }
813 rmesa->irqsEmitted = 10;
814 }
815
816 if (rmesa->irqsEmitted) {
817 radeonEmitIrqLocked( rmesa );
818 rmesa->irqsEmitted--;
819 }
820 }
821 else {
822 while (radeonGetLastFrame (rmesa) < sarea->last_frame) {
823 UNLOCK_HARDWARE( rmesa );
824 if (rmesa->do_usleeps)
825 DO_USLEEP( 1 );
826 LOCK_HARDWARE( rmesa );
827 }
828 }
829 }
830
831 /* Copy the back color buffer to the front color buffer.
832 */
833 void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
834 {
835 radeonContextPtr rmesa;
836 GLint nbox, i, ret;
837 GLboolean missed_target;
838 int64_t ust;
839
840 assert(dPriv);
841 assert(dPriv->driContextPriv);
842 assert(dPriv->driContextPriv->driverPrivate);
843
844 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
845
846 if ( RADEON_DEBUG & DEBUG_IOCTL ) {
847 fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void *) rmesa->glCtx );
848 }
849
850 RADEON_FIREVERTICES( rmesa );
851 LOCK_HARDWARE( rmesa );
852
853 /* Throttle the frame rate -- only allow one pending swap buffers
854 * request at a time.
855 */
856 radeonWaitForFrameCompletion( rmesa );
857 UNLOCK_HARDWARE( rmesa );
858 driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
859 LOCK_HARDWARE( rmesa );
860
861 nbox = dPriv->numClipRects; /* must be in locked region */
862
863 for ( i = 0 ; i < nbox ; ) {
864 GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
865 drm_clip_rect_t *box = dPriv->pClipRects;
866 drm_clip_rect_t *b = rmesa->sarea->boxes;
867 GLint n = 0;
868
869 for ( ; i < nr ; i++ ) {
870 *b++ = box[i];
871 n++;
872 }
873 rmesa->sarea->nbox = n;
874
875 ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
876
877 if ( ret ) {
878 fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret );
879 UNLOCK_HARDWARE( rmesa );
880 exit( 1 );
881 }
882 }
883
884 UNLOCK_HARDWARE( rmesa );
885 rmesa->swap_count++;
886 (*rmesa->get_ust)( & ust );
887 if ( missed_target ) {
888 rmesa->swap_missed_count++;
889 rmesa->swap_missed_ust = ust - rmesa->swap_ust;
890 }
891
892 rmesa->swap_ust = ust;
893 }
894
895 void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
896 {
897 radeonContextPtr rmesa;
898 GLint ret;
899 GLboolean missed_target;
900
901 assert(dPriv);
902 assert(dPriv->driContextPriv);
903 assert(dPriv->driContextPriv->driverPrivate);
904
905 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
906
907 if ( RADEON_DEBUG & DEBUG_IOCTL ) {
908 fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
909 rmesa->sarea->pfCurrentPage);
910 }
911
912 RADEON_FIREVERTICES( rmesa );
913 LOCK_HARDWARE( rmesa );
914
915 /* Need to do this for the perf box placement:
916 */
917 if (dPriv->numClipRects)
918 {
919 drm_clip_rect_t *box = dPriv->pClipRects;
920 drm_clip_rect_t *b = rmesa->sarea->boxes;
921 b[0] = box[0];
922 rmesa->sarea->nbox = 1;
923 }
924
925 /* Throttle the frame rate -- only allow a few pending swap buffers
926 * request at a time.
927 */
928 radeonWaitForFrameCompletion( rmesa );
929 UNLOCK_HARDWARE( rmesa );
930 driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
931 if ( missed_target ) {
932 rmesa->swap_missed_count++;
933 (void) (*rmesa->get_ust)( & rmesa->swap_missed_ust );
934 }
935 LOCK_HARDWARE( rmesa );
936
937 ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
938
939 UNLOCK_HARDWARE( rmesa );
940
941 if ( ret ) {
942 fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
943 exit( 1 );
944 }
945
946 rmesa->swap_count++;
947 (void) (*rmesa->get_ust)( & rmesa->swap_ust );
948
949 if ( rmesa->sarea->pfCurrentPage == 1 ) {
950 rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
951 rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch;
952 } else {
953 rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
954 rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch;
955 }
956
957 RADEON_STATECHANGE( rmesa, ctx );
958 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset
959 + rmesa->radeonScreen->fbLocation;
960 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
961 }
962
963
964 /* ================================================================
965 * Buffer clear
966 */
967 #define RADEON_MAX_CLEARS 256
968
969 static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
970 GLint cx, GLint cy, GLint cw, GLint ch )
971 {
972 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
973 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
974 drm_radeon_sarea_t *sarea = rmesa->sarea;
975 unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
976 uint32_t clear;
977 GLuint flags = 0;
978 GLuint color_mask = 0;
979 GLint ret, i;
980
981 if ( RADEON_DEBUG & DEBUG_IOCTL ) {
982 fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
983 __FUNCTION__, all, cx, cy, cw, ch );
984 }
985
986 radeonEmitState( rmesa );
987
988 /* Need to cope with lostcontext here as kernel relies on
989 * some residual state:
990 */
991 RADEON_FIREVERTICES( rmesa );
992
993 if ( mask & DD_FRONT_LEFT_BIT ) {
994 flags |= RADEON_FRONT;
995 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
996 mask &= ~DD_FRONT_LEFT_BIT;
997 }
998
999 if ( mask & DD_BACK_LEFT_BIT ) {
1000 flags |= RADEON_BACK;
1001 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
1002 mask &= ~DD_BACK_LEFT_BIT;
1003 }
1004
1005 if ( mask & DD_DEPTH_BIT ) {
1006 if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
1007 mask &= ~DD_DEPTH_BIT;
1008 }
1009
1010 if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
1011 flags |= RADEON_STENCIL;
1012 mask &= ~DD_STENCIL_BIT;
1013 }
1014
1015 if ( mask ) {
1016 if (RADEON_DEBUG & DEBUG_FALLBACKS)
1017 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
1018 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
1019 }
1020
1021 if ( !flags )
1022 return;
1023
1024
1025 /* Flip top to bottom */
1026 cx += dPriv->x;
1027 cy = dPriv->y + dPriv->h - cy - ch;
1028
1029 LOCK_HARDWARE( rmesa );
1030
1031 /* Throttle the number of clear ioctls we do.
1032 */
1033 while ( 1 ) {
1034 int ret;
1035
1036 if (rmesa->dri.screen->drmMinor >= 4) {
1037 drm_radeon_getparam_t gp;
1038
1039 gp.param = RADEON_PARAM_LAST_CLEAR;
1040 gp.value = (int *)&clear;
1041 ret = drmCommandWriteRead( rmesa->dri.fd,
1042 DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
1043 } else
1044 ret = -EINVAL;
1045
1046 #ifndef __alpha__
1047 if ( ret == -EINVAL ) {
1048 clear = INREG( RADEON_LAST_CLEAR_REG );
1049 ret = 0;
1050 }
1051 #endif
1052 if ( ret ) {
1053 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret );
1054 exit(1);
1055 }
1056 if ( RADEON_DEBUG & DEBUG_IOCTL ) {
1057 fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)clear );
1058 if ( ret ) fprintf( stderr, " ( RADEON_LAST_CLEAR register read directly )\n" );
1059 }
1060
1061 if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
1062 break;
1063 }
1064
1065 if ( rmesa->do_usleeps ) {
1066 UNLOCK_HARDWARE( rmesa );
1067 DO_USLEEP( 1 );
1068 LOCK_HARDWARE( rmesa );
1069 }
1070 }
1071
1072 for ( i = 0 ; i < dPriv->numClipRects ; ) {
1073 GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
1074 drm_clip_rect_t *box = dPriv->pClipRects;
1075 drm_clip_rect_t *b = rmesa->sarea->boxes;
1076 drm_radeon_clear_t clear;
1077 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
1078 GLint n = 0;
1079
1080 if ( !all ) {
1081 for ( ; i < nr ; i++ ) {
1082 GLint x = box[i].x1;
1083 GLint y = box[i].y1;
1084 GLint w = box[i].x2 - x;
1085 GLint h = box[i].y2 - y;
1086
1087 if ( x < cx ) w -= cx - x, x = cx;
1088 if ( y < cy ) h -= cy - y, y = cy;
1089 if ( x + w > cx + cw ) w = cx + cw - x;
1090 if ( y + h > cy + ch ) h = cy + ch - y;
1091 if ( w <= 0 ) continue;
1092 if ( h <= 0 ) continue;
1093
1094 b->x1 = x;
1095 b->y1 = y;
1096 b->x2 = x + w;
1097 b->y2 = y + h;
1098 b++;
1099 n++;
1100 }
1101 } else {
1102 for ( ; i < nr ; i++ ) {
1103 *b++ = box[i];
1104 n++;
1105 }
1106 }
1107
1108 rmesa->sarea->nbox = n;
1109
1110 clear.flags = flags;
1111 clear.clear_color = rmesa->state.color.clear;
1112 clear.clear_depth = rmesa->state.depth.clear;
1113 clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
1114 clear.depth_mask = rmesa->state.stencil.clear;
1115 clear.depth_boxes = depth_boxes;
1116
1117 n--;
1118 b = rmesa->sarea->boxes;
1119 for ( ; n >= 0 ; n-- ) {
1120 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1;
1121 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1;
1122 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2;
1123 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2;
1124 depth_boxes[n].f[CLEAR_DEPTH] =
1125 (float)rmesa->state.depth.clear;
1126 }
1127
1128 ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
1129 &clear, sizeof(drm_radeon_clear_t));
1130
1131 if ( ret ) {
1132 UNLOCK_HARDWARE( rmesa );
1133 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
1134 exit( 1 );
1135 }
1136 }
1137
1138 UNLOCK_HARDWARE( rmesa );
1139 }
1140
1141
1142 void radeonWaitForIdleLocked( radeonContextPtr rmesa )
1143 {
1144 int fd = rmesa->dri.fd;
1145 int to = 0;
1146 int ret, i = 0;
1147
1148 rmesa->c_drawWaits++;
1149
1150 do {
1151 do {
1152 ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE);
1153 } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY );
1154 } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) );
1155
1156 if ( ret < 0 ) {
1157 UNLOCK_HARDWARE( rmesa );
1158 fprintf( stderr, "Error: Radeon timed out... exiting\n" );
1159 exit( -1 );
1160 }
1161 }
1162
1163
1164 static void radeonWaitForIdle( radeonContextPtr rmesa )
1165 {
1166 LOCK_HARDWARE(rmesa);
1167 radeonWaitForIdleLocked( rmesa );
1168 UNLOCK_HARDWARE(rmesa);
1169 }
1170
1171
1172 void radeonFlush( GLcontext *ctx )
1173 {
1174 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
1175
1176 if (RADEON_DEBUG & DEBUG_IOCTL)
1177 fprintf(stderr, "%s\n", __FUNCTION__);
1178
1179 if (rmesa->dma.flush)
1180 rmesa->dma.flush( rmesa );
1181
1182 if (!is_empty_list(&rmesa->hw.dirty))
1183 radeonEmitState( rmesa );
1184
1185 if (rmesa->store.cmd_used)
1186 radeonFlushCmdBuf( rmesa, __FUNCTION__ );
1187 }
1188
1189 /* Make sure all commands have been sent to the hardware and have
1190 * completed processing.
1191 */
1192 void radeonFinish( GLcontext *ctx )
1193 {
1194 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1195 radeonFlush( ctx );
1196
1197 if (rmesa->do_irqs) {
1198 LOCK_HARDWARE( rmesa );
1199 radeonEmitIrqLocked( rmesa );
1200 UNLOCK_HARDWARE( rmesa );
1201 radeonWaitIrq( rmesa );
1202 }
1203 else
1204 radeonWaitForIdle( rmesa );
1205 }
1206
1207
1208 void radeonInitIoctlFuncs( GLcontext *ctx )
1209 {
1210 ctx->Driver.Clear = radeonClear;
1211 ctx->Driver.Finish = radeonFinish;
1212 ctx->Driver.Flush = radeonFlush;
1213 }
1214