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