1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_ioctl.c,v 1.4 2002/12/17 00:32:56 dawes Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
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:
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.
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.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
43 #include "swrast/swrast.h"
45 #include "r200_context.h"
46 #include "r200_state.h"
47 #include "r200_ioctl.h"
49 #include "r200_sanity.h"
50 #include "radeon_reg.h"
52 #include "drirenderbuffer.h"
55 #define R200_TIMEOUT 512
56 #define R200_IDLE_RETRY 16
59 static void r200WaitForIdle( r200ContextPtr rmesa
);
62 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
63 * we need to unwire our current cmdbuf, hook the one with the saved state in
64 * it, flush it, and then put the current one back. This is so commands at the
65 * start of a cmdbuf can rely on the state being kept from the previous one.
67 static void r200BackUpAndEmitLostStateLocked( r200ContextPtr rmesa
)
69 GLuint nr_released_bufs
;
70 struct r200_store saved_store
;
72 if (rmesa
->backup_store
.cmd_used
== 0)
75 if (R200_DEBUG
& DEBUG_STATE
)
76 fprintf(stderr
, "Emitting backup state on lost context\n");
78 rmesa
->lost_context
= GL_FALSE
;
80 nr_released_bufs
= rmesa
->dma
.nr_released_bufs
;
81 saved_store
= rmesa
->store
;
82 rmesa
->dma
.nr_released_bufs
= 0;
83 rmesa
->store
= rmesa
->backup_store
;
84 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
85 rmesa
->dma
.nr_released_bufs
= nr_released_bufs
;
86 rmesa
->store
= saved_store
;
89 int r200FlushCmdBufLocked( r200ContextPtr rmesa
, const char * caller
)
92 drm_radeon_cmd_buffer_t cmd
;
94 if (rmesa
->lost_context
)
95 r200BackUpAndEmitLostStateLocked( rmesa
);
97 if (R200_DEBUG
& DEBUG_IOCTL
) {
98 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
100 if (0 & R200_DEBUG
& DEBUG_VERBOSE
)
101 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
102 fprintf(stderr
, "%d: %x\n", i
/4,
103 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
106 if (R200_DEBUG
& DEBUG_DMA
)
107 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
108 rmesa
->dma
.nr_released_bufs
);
111 if (R200_DEBUG
& DEBUG_SANITY
) {
112 if (rmesa
->state
.scissor
.enabled
)
113 ret
= r200SanityCmdBuffer( rmesa
,
114 rmesa
->state
.scissor
.numClipRects
,
115 rmesa
->state
.scissor
.pClipRects
);
117 ret
= r200SanityCmdBuffer( rmesa
,
121 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
127 if (R200_DEBUG
& DEBUG_MEMORY
) {
128 if (! driValidateTextureHeaps( rmesa
->texture_heaps
, rmesa
->nr_heaps
,
129 & rmesa
->swapped
) ) {
130 fprintf( stderr
, "%s: texture memory is inconsistent - expect "
131 "mangled textures\n", __FUNCTION__
);
136 cmd
.bufsz
= rmesa
->store
.cmd_used
;
137 cmd
.buf
= rmesa
->store
.cmd_buf
;
139 if (rmesa
->state
.scissor
.enabled
) {
140 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
141 cmd
.boxes
= (drm_clip_rect_t
*)rmesa
->state
.scissor
.pClipRects
;
143 cmd
.nbox
= rmesa
->numClipRects
;
144 cmd
.boxes
= (drm_clip_rect_t
*)rmesa
->pClipRects
;
147 ret
= drmCommandWrite( rmesa
->dri
.fd
,
152 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
154 if (R200_DEBUG
& DEBUG_SYNC
) {
155 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
156 r200WaitForIdleLocked( rmesa
);
161 rmesa
->store
.primnr
= 0;
162 rmesa
->store
.statenr
= 0;
163 rmesa
->store
.cmd_used
= 0;
164 rmesa
->dma
.nr_released_bufs
= 0;
165 rmesa
->save_on_next_emit
= 1;
171 /* Note: does not emit any commands to avoid recursion on
174 void r200FlushCmdBuf( r200ContextPtr rmesa
, const char *caller
)
178 LOCK_HARDWARE( rmesa
);
180 ret
= r200FlushCmdBufLocked( rmesa
, caller
);
182 UNLOCK_HARDWARE( rmesa
);
185 fprintf(stderr
, "drmRadeonCmdBuffer: %d (exiting)\n", ret
);
191 /* =============================================================
192 * Hardware vertex buffer handling
196 void r200RefillCurrentDmaRegion( r200ContextPtr rmesa
)
198 struct r200_dma_buffer
*dmabuf
;
199 int fd
= rmesa
->dri
.fd
;
205 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
206 fprintf(stderr
, "%s\n", __FUNCTION__
);
208 if (rmesa
->dma
.flush
) {
209 rmesa
->dma
.flush( rmesa
);
212 if (rmesa
->dma
.current
.buf
)
213 r200ReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
215 if (rmesa
->dma
.nr_released_bufs
> 4)
216 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
218 dma
.context
= rmesa
->dri
.hwContext
;
220 dma
.send_list
= NULL
;
221 dma
.send_sizes
= NULL
;
223 dma
.request_count
= 1;
224 dma
.request_size
= RADEON_BUFFER_SIZE
;
225 dma
.request_list
= &index
;
226 dma
.request_sizes
= &size
;
227 dma
.granted_count
= 0;
229 LOCK_HARDWARE(rmesa
); /* no need to validate */
232 ret
= drmDMA( fd
, &dma
);
236 if (rmesa
->dma
.nr_released_bufs
) {
237 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
240 if (rmesa
->do_usleeps
) {
241 UNLOCK_HARDWARE( rmesa
);
243 LOCK_HARDWARE( rmesa
);
247 UNLOCK_HARDWARE(rmesa
);
249 if (R200_DEBUG
& DEBUG_DMA
)
250 fprintf(stderr
, "Allocated buffer %d\n", index
);
252 dmabuf
= CALLOC_STRUCT( r200_dma_buffer
);
253 dmabuf
->buf
= &rmesa
->r200Screen
->buffers
->list
[index
];
254 dmabuf
->refcount
= 1;
256 rmesa
->dma
.current
.buf
= dmabuf
;
257 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
258 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
259 rmesa
->dma
.current
.start
= 0;
260 rmesa
->dma
.current
.ptr
= 0;
263 void r200ReleaseDmaRegion( r200ContextPtr rmesa
,
264 struct r200_dma_region
*region
,
267 if (R200_DEBUG
& DEBUG_IOCTL
)
268 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
273 if (rmesa
->dma
.flush
)
274 rmesa
->dma
.flush( rmesa
);
276 if (--region
->buf
->refcount
== 0) {
277 drm_radeon_cmd_header_t
*cmd
;
279 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
280 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
281 region
->buf
->buf
->idx
);
283 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sizeof(*cmd
),
285 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
286 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
288 rmesa
->dma
.nr_released_bufs
++;
295 /* Allocates a region from rmesa->dma.current. If there isn't enough
296 * space in current, grab a new buffer (and discard what was left of current)
298 void r200AllocDmaRegion( r200ContextPtr rmesa
,
299 struct r200_dma_region
*region
,
303 if (R200_DEBUG
& DEBUG_IOCTL
)
304 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
306 if (rmesa
->dma
.flush
)
307 rmesa
->dma
.flush( rmesa
);
310 r200ReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
313 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
314 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
316 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
317 r200RefillCurrentDmaRegion( rmesa
);
319 region
->start
= rmesa
->dma
.current
.start
;
320 region
->ptr
= rmesa
->dma
.current
.start
;
321 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
322 region
->address
= rmesa
->dma
.current
.address
;
323 region
->buf
= rmesa
->dma
.current
.buf
;
324 region
->buf
->refcount
++;
326 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
327 rmesa
->dma
.current
.start
=
328 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
330 assert( rmesa
->dma
.current
.ptr
<= rmesa
->dma
.current
.end
);
333 /* ================================================================
334 * SwapBuffers with client-side throttling
337 static u_int32_t
r200GetLastFrame(r200ContextPtr rmesa
)
339 drm_radeon_getparam_t gp
;
343 gp
.param
= RADEON_PARAM_LAST_FRAME
;
344 gp
.value
= (int *)&frame
;
345 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
348 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
355 static void r200EmitIrqLocked( r200ContextPtr rmesa
)
357 drm_radeon_irq_emit_t ie
;
360 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
361 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
364 fprintf( stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
, ret
);
370 static void r200WaitIrq( r200ContextPtr rmesa
)
375 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
376 &rmesa
->iw
, sizeof(rmesa
->iw
) );
377 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
380 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
386 static void r200WaitForFrameCompletion( r200ContextPtr rmesa
)
388 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
390 if (rmesa
->do_irqs
) {
391 if (r200GetLastFrame(rmesa
) < sarea
->last_frame
) {
392 if (!rmesa
->irqsEmitted
) {
393 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
)
397 UNLOCK_HARDWARE( rmesa
);
398 r200WaitIrq( rmesa
);
399 LOCK_HARDWARE( rmesa
);
401 rmesa
->irqsEmitted
= 10;
404 if (rmesa
->irqsEmitted
) {
405 r200EmitIrqLocked( rmesa
);
406 rmesa
->irqsEmitted
--;
410 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
) {
411 UNLOCK_HARDWARE( rmesa
);
412 if (rmesa
->do_usleeps
)
414 LOCK_HARDWARE( rmesa
);
421 /* Copy the back color buffer to the front color buffer.
423 void r200CopyBuffer( const __DRIdrawablePrivate
*dPriv
,
424 const drm_clip_rect_t
*rect
)
426 r200ContextPtr rmesa
;
428 GLboolean missed_target
;
432 assert(dPriv
->driContextPriv
);
433 assert(dPriv
->driContextPriv
->driverPrivate
);
435 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
437 if ( R200_DEBUG
& DEBUG_IOCTL
) {
438 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *)rmesa
->glCtx
);
441 R200_FIREVERTICES( rmesa
);
443 LOCK_HARDWARE( rmesa
);
446 /* Throttle the frame rate -- only allow one pending swap buffers
449 r200WaitForFrameCompletion( rmesa
);
452 UNLOCK_HARDWARE( rmesa
);
453 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
454 LOCK_HARDWARE( rmesa
);
457 nbox
= dPriv
->numClipRects
; /* must be in locked region */
459 for ( i
= 0 ; i
< nbox
; ) {
460 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
461 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
462 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
465 for ( ; i
< nr
; i
++ ) {
471 if (rect
->x1
> b
->x1
)
473 if (rect
->y1
> b
->y1
)
475 if (rect
->x2
< b
->x2
)
477 if (rect
->y2
< b
->y2
)
480 if (b
->x1
< b
->x2
&& b
->y1
< b
->y2
)
488 rmesa
->sarea
->nbox
= n
;
490 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
493 fprintf( stderr
, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret
);
494 UNLOCK_HARDWARE( rmesa
);
499 UNLOCK_HARDWARE( rmesa
);
502 rmesa
->hw
.all_dirty
= GL_TRUE
;
505 (*dri_interface
->getUST
)( & ust
);
506 if ( missed_target
) {
507 rmesa
->swap_missed_count
++;
508 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
511 rmesa
->swap_ust
= ust
;
517 void r200PageFlip( const __DRIdrawablePrivate
*dPriv
)
519 r200ContextPtr rmesa
;
521 GLboolean missed_target
;
524 assert(dPriv
->driContextPriv
);
525 assert(dPriv
->driContextPriv
->driverPrivate
);
527 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
529 if ( R200_DEBUG
& DEBUG_IOCTL
) {
530 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
531 rmesa
->sarea
->pfCurrentPage
);
534 R200_FIREVERTICES( rmesa
);
535 LOCK_HARDWARE( rmesa
);
537 if (!dPriv
->numClipRects
) {
538 UNLOCK_HARDWARE( rmesa
);
539 usleep( 10000 ); /* throttle invisible client 10ms */
543 /* Need to do this for the perf box placement:
546 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
547 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
549 rmesa
->sarea
->nbox
= 1;
552 /* Throttle the frame rate -- only allow a few pending swap buffers
555 r200WaitForFrameCompletion( rmesa
);
556 UNLOCK_HARDWARE( rmesa
);
557 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
558 if ( missed_target
) {
559 rmesa
->swap_missed_count
++;
560 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
562 LOCK_HARDWARE( rmesa
);
564 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
566 UNLOCK_HARDWARE( rmesa
);
569 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
574 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
577 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
578 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->frontOffset
;
579 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->frontPitch
;
581 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->backOffset
;
582 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->backPitch
;
585 R200_STATECHANGE( rmesa
, ctx
);
586 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
587 + rmesa
->r200Screen
->fbLocation
;
588 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
589 if (rmesa
->sarea
->tiling_enabled
) {
590 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
593 /* Get ready for drawing next frame. Update the renderbuffers'
594 * flippedOffset/Pitch fields so we draw into the right place.
596 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
597 rmesa
->sarea
->pfCurrentPage
);
600 r200UpdateDrawBuffer(rmesa
->glCtx
);
605 /* ================================================================
608 static void r200Clear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
609 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
611 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
612 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
614 GLuint color_mask
= 0;
617 if ( R200_DEBUG
& DEBUG_IOCTL
) {
618 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
619 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
623 LOCK_HARDWARE( rmesa
);
624 UNLOCK_HARDWARE( rmesa
);
625 if ( dPriv
->numClipRects
== 0 )
631 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
632 flags
|= RADEON_FRONT
;
633 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
634 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
637 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
638 flags
|= RADEON_BACK
;
639 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
640 mask
&= ~BUFFER_BIT_BACK_LEFT
;
643 if ( mask
& BUFFER_BIT_DEPTH
) {
644 flags
|= RADEON_DEPTH
;
645 mask
&= ~BUFFER_BIT_DEPTH
;
648 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
649 flags
|= RADEON_STENCIL
;
650 mask
&= ~BUFFER_BIT_STENCIL
;
654 if (R200_DEBUG
& DEBUG_FALLBACKS
)
655 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
656 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
662 if (rmesa
->using_hyperz
) {
663 flags
|= RADEON_USE_COMP_ZBUF
;
664 /* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200)
665 flags |= RADEON_USE_HIERZ; */
666 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
667 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
668 ((rmesa
->state
.stencil
.clear
& R200_STENCIL_WRITE_MASK
) == R200_STENCIL_WRITE_MASK
))) {
669 flags
|= RADEON_CLEAR_FASTZ
;
673 /* Flip top to bottom */
675 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
677 LOCK_HARDWARE( rmesa
);
679 /* Throttle the number of clear ioctls we do.
682 drm_radeon_getparam_t gp
;
686 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
687 gp
.value
= (int *)&clear
;
688 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
689 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
692 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
696 /* Clear throttling needs more thought.
698 if ( rmesa
->sarea
->last_clear
- clear
<= 25 ) {
702 if (rmesa
->do_usleeps
) {
703 UNLOCK_HARDWARE( rmesa
);
705 LOCK_HARDWARE( rmesa
);
709 /* Send current state to the hardware */
710 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
712 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
713 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
714 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
715 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
716 drm_radeon_clear_t clear
;
717 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
721 for ( ; i
< nr
; i
++ ) {
724 GLint w
= box
[i
].x2
- x
;
725 GLint h
= box
[i
].y2
- y
;
727 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
728 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
729 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
730 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
731 if ( w
<= 0 ) continue;
732 if ( h
<= 0 ) continue;
742 for ( ; i
< nr
; i
++ ) {
748 rmesa
->sarea
->nbox
= n
;
751 clear
.clear_color
= rmesa
->state
.color
.clear
;
752 clear
.clear_depth
= rmesa
->state
.depth
.clear
; /* needed for hyperz */
753 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
754 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
755 clear
.depth_boxes
= depth_boxes
;
758 b
= rmesa
->sarea
->boxes
;
759 for ( ; n
>= 0 ; n
-- ) {
760 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
761 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
762 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
763 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
764 depth_boxes
[n
].f
[CLEAR_DEPTH
] = ctx
->Depth
.Clear
;
767 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
768 &clear
, sizeof(clear
));
772 UNLOCK_HARDWARE( rmesa
);
773 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
778 UNLOCK_HARDWARE( rmesa
);
779 rmesa
->hw
.all_dirty
= GL_TRUE
;
783 void r200WaitForIdleLocked( r200ContextPtr rmesa
)
789 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_CP_IDLE
);
792 } while (ret
&& ++i
< 100);
795 UNLOCK_HARDWARE( rmesa
);
796 fprintf( stderr
, "Error: R200 timed out... exiting\n" );
802 static void r200WaitForIdle( r200ContextPtr rmesa
)
804 LOCK_HARDWARE(rmesa
);
805 r200WaitForIdleLocked( rmesa
);
806 UNLOCK_HARDWARE(rmesa
);
810 void r200Flush( GLcontext
*ctx
)
812 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
814 if (R200_DEBUG
& DEBUG_IOCTL
)
815 fprintf(stderr
, "%s\n", __FUNCTION__
);
817 if (rmesa
->dma
.flush
)
818 rmesa
->dma
.flush( rmesa
);
820 r200EmitState( rmesa
);
822 if (rmesa
->store
.cmd_used
)
823 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
826 /* Make sure all commands have been sent to the hardware and have
827 * completed processing.
829 void r200Finish( GLcontext
*ctx
)
831 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
834 if (rmesa
->do_irqs
) {
835 LOCK_HARDWARE( rmesa
);
836 r200EmitIrqLocked( rmesa
);
837 UNLOCK_HARDWARE( rmesa
);
838 r200WaitIrq( rmesa
);
841 r200WaitForIdle( rmesa
);
845 /* This version of AllocateMemoryMESA allocates only GART memory, and
846 * only does so after the point at which the driver has been
849 * Theoretically a valid context isn't required. However, in this
850 * implementation, it is, as I'm using the hardware lock to protect
851 * the kernel data structures, and the current context to get the
854 void *r200AllocateMemoryMESA(__DRInativeDisplay
*dpy
, int scrn
, GLsizei size
,
855 GLfloat readfreq
, GLfloat writefreq
,
858 GET_CURRENT_CONTEXT(ctx
);
859 r200ContextPtr rmesa
;
861 drm_radeon_mem_alloc_t alloc
;
864 if (R200_DEBUG
& DEBUG_IOCTL
)
865 fprintf(stderr
, "%s sz %d %f/%f/%f\n", __FUNCTION__
, size
, readfreq
,
866 writefreq
, priority
);
868 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
)
871 if (getenv("R200_NO_ALLOC"))
874 alloc
.region
= RADEON_MEM_REGION_GART
;
877 alloc
.region_offset
= ®ion_offset
;
879 ret
= drmCommandWriteRead( rmesa
->r200Screen
->driScreen
->fd
,
881 &alloc
, sizeof(alloc
));
884 fprintf(stderr
, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__
, ret
);
889 char *region_start
= (char *)rmesa
->r200Screen
->gartTextures
.map
;
890 return (void *)(region_start
+ region_offset
);
895 /* Called via glXFreeMemoryMESA() */
896 void r200FreeMemoryMESA(__DRInativeDisplay
*dpy
, int scrn
, GLvoid
*pointer
)
898 GET_CURRENT_CONTEXT(ctx
);
899 r200ContextPtr rmesa
;
900 ptrdiff_t region_offset
;
901 drm_radeon_mem_free_t memfree
;
904 if (R200_DEBUG
& DEBUG_IOCTL
)
905 fprintf(stderr
, "%s %p\n", __FUNCTION__
, pointer
);
907 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
) {
908 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
912 region_offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
914 if (region_offset
< 0 ||
915 region_offset
> rmesa
->r200Screen
->gartTextures
.size
) {
916 fprintf(stderr
, "offset %d outside range 0..%d\n", region_offset
,
917 rmesa
->r200Screen
->gartTextures
.size
);
921 memfree
.region
= RADEON_MEM_REGION_GART
;
922 memfree
.region_offset
= region_offset
;
924 ret
= drmCommandWrite( rmesa
->r200Screen
->driScreen
->fd
,
926 &memfree
, sizeof(memfree
));
929 fprintf(stderr
, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__
, ret
);
932 /* Called via glXGetMemoryOffsetMESA() */
933 GLuint
r200GetMemoryOffsetMESA(__DRInativeDisplay
*dpy
, int scrn
, const GLvoid
*pointer
)
935 GET_CURRENT_CONTEXT(ctx
);
936 r200ContextPtr rmesa
;
939 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) ) {
940 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
944 if (!r200IsGartMemory( rmesa
, pointer
, 0 ))
947 card_offset
= r200GartOffsetFromVirtual( rmesa
, pointer
);
949 return card_offset
- rmesa
->r200Screen
->gart_base
;
952 GLboolean
r200IsGartMemory( r200ContextPtr rmesa
, const GLvoid
*pointer
,
955 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
956 int valid
= (size
>= 0 &&
958 offset
+ size
< rmesa
->r200Screen
->gartTextures
.size
);
960 if (R200_DEBUG
& DEBUG_IOCTL
)
961 fprintf(stderr
, "r200IsGartMemory( %p ) : %d\n", pointer
, valid
);
967 GLuint
r200GartOffsetFromVirtual( r200ContextPtr rmesa
, const GLvoid
*pointer
)
969 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
971 if (offset
< 0 || offset
> rmesa
->r200Screen
->gartTextures
.size
)
974 return rmesa
->r200Screen
->gart_texture_offset
+ offset
;
979 void r200InitIoctlFuncs( struct dd_function_table
*functions
)
981 functions
->Clear
= r200Clear
;
982 functions
->Finish
= r200Finish
;
983 functions
->Flush
= r200Flush
;