2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
42 #include "swrast/swrast.h"
44 #include "r200_context.h"
45 #include "r200_state.h"
46 #include "r200_ioctl.h"
48 #include "r200_sanity.h"
49 #include "radeon_reg.h"
51 #include "drirenderbuffer.h"
54 #define R200_TIMEOUT 512
55 #define R200_IDLE_RETRY 16
58 static void r200WaitForIdle( r200ContextPtr rmesa
);
61 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
62 * we need to unwire our current cmdbuf, hook the one with the saved state in
63 * it, flush it, and then put the current one back. This is so commands at the
64 * start of a cmdbuf can rely on the state being kept from the previous one.
66 static void r200BackUpAndEmitLostStateLocked( r200ContextPtr rmesa
)
68 GLuint nr_released_bufs
;
69 struct r200_store saved_store
;
71 if (rmesa
->backup_store
.cmd_used
== 0)
74 if (R200_DEBUG
& DEBUG_STATE
)
75 fprintf(stderr
, "Emitting backup state on lost context\n");
77 rmesa
->lost_context
= GL_FALSE
;
79 nr_released_bufs
= rmesa
->dma
.nr_released_bufs
;
80 saved_store
= rmesa
->store
;
81 rmesa
->dma
.nr_released_bufs
= 0;
82 rmesa
->store
= rmesa
->backup_store
;
83 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
84 rmesa
->dma
.nr_released_bufs
= nr_released_bufs
;
85 rmesa
->store
= saved_store
;
88 int r200FlushCmdBufLocked( r200ContextPtr rmesa
, const char * caller
)
91 drm_radeon_cmd_buffer_t cmd
;
93 if (rmesa
->lost_context
)
94 r200BackUpAndEmitLostStateLocked( rmesa
);
96 if (R200_DEBUG
& DEBUG_IOCTL
) {
97 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
99 if (0 & R200_DEBUG
& DEBUG_VERBOSE
)
100 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
101 fprintf(stderr
, "%d: %x\n", i
/4,
102 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
105 if (R200_DEBUG
& DEBUG_DMA
)
106 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
107 rmesa
->dma
.nr_released_bufs
);
110 if (R200_DEBUG
& DEBUG_SANITY
) {
111 if (rmesa
->state
.scissor
.enabled
)
112 ret
= r200SanityCmdBuffer( rmesa
,
113 rmesa
->state
.scissor
.numClipRects
,
114 rmesa
->state
.scissor
.pClipRects
);
116 ret
= r200SanityCmdBuffer( rmesa
,
120 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
126 if (R200_DEBUG
& DEBUG_MEMORY
) {
127 if (! driValidateTextureHeaps( rmesa
->texture_heaps
, rmesa
->nr_heaps
,
128 & rmesa
->swapped
) ) {
129 fprintf( stderr
, "%s: texture memory is inconsistent - expect "
130 "mangled textures\n", __FUNCTION__
);
135 cmd
.bufsz
= rmesa
->store
.cmd_used
;
136 cmd
.buf
= rmesa
->store
.cmd_buf
;
138 if (rmesa
->state
.scissor
.enabled
) {
139 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
140 cmd
.boxes
= (drm_clip_rect_t
*)rmesa
->state
.scissor
.pClipRects
;
142 cmd
.nbox
= rmesa
->numClipRects
;
143 cmd
.boxes
= (drm_clip_rect_t
*)rmesa
->pClipRects
;
146 ret
= drmCommandWrite( rmesa
->dri
.fd
,
151 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
153 if (R200_DEBUG
& DEBUG_SYNC
) {
154 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
155 r200WaitForIdleLocked( rmesa
);
160 rmesa
->store
.primnr
= 0;
161 rmesa
->store
.statenr
= 0;
162 rmesa
->store
.cmd_used
= 0;
163 rmesa
->dma
.nr_released_bufs
= 0;
164 rmesa
->save_on_next_emit
= 1;
170 /* Note: does not emit any commands to avoid recursion on
173 void r200FlushCmdBuf( r200ContextPtr rmesa
, const char *caller
)
177 LOCK_HARDWARE( rmesa
);
179 ret
= r200FlushCmdBufLocked( rmesa
, caller
);
181 UNLOCK_HARDWARE( rmesa
);
184 fprintf(stderr
, "drmRadeonCmdBuffer: %d (exiting)\n", ret
);
190 /* =============================================================
191 * Hardware vertex buffer handling
195 void r200RefillCurrentDmaRegion( r200ContextPtr rmesa
)
197 struct r200_dma_buffer
*dmabuf
;
198 int fd
= rmesa
->dri
.fd
;
204 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
205 fprintf(stderr
, "%s\n", __FUNCTION__
);
207 if (rmesa
->dma
.flush
) {
208 rmesa
->dma
.flush( rmesa
);
211 if (rmesa
->dma
.current
.buf
)
212 r200ReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
214 if (rmesa
->dma
.nr_released_bufs
> 4)
215 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
217 dma
.context
= rmesa
->dri
.hwContext
;
219 dma
.send_list
= NULL
;
220 dma
.send_sizes
= NULL
;
222 dma
.request_count
= 1;
223 dma
.request_size
= RADEON_BUFFER_SIZE
;
224 dma
.request_list
= &index
;
225 dma
.request_sizes
= &size
;
226 dma
.granted_count
= 0;
228 LOCK_HARDWARE(rmesa
); /* no need to validate */
231 ret
= drmDMA( fd
, &dma
);
235 if (rmesa
->dma
.nr_released_bufs
) {
236 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
239 if (rmesa
->do_usleeps
) {
240 UNLOCK_HARDWARE( rmesa
);
242 LOCK_HARDWARE( rmesa
);
246 UNLOCK_HARDWARE(rmesa
);
248 if (R200_DEBUG
& DEBUG_DMA
)
249 fprintf(stderr
, "Allocated buffer %d\n", index
);
251 dmabuf
= CALLOC_STRUCT( r200_dma_buffer
);
252 dmabuf
->buf
= &rmesa
->r200Screen
->buffers
->list
[index
];
253 dmabuf
->refcount
= 1;
255 rmesa
->dma
.current
.buf
= dmabuf
;
256 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
257 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
258 rmesa
->dma
.current
.start
= 0;
259 rmesa
->dma
.current
.ptr
= 0;
262 void r200ReleaseDmaRegion( r200ContextPtr rmesa
,
263 struct r200_dma_region
*region
,
266 if (R200_DEBUG
& DEBUG_IOCTL
)
267 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
272 if (rmesa
->dma
.flush
)
273 rmesa
->dma
.flush( rmesa
);
275 if (--region
->buf
->refcount
== 0) {
276 drm_radeon_cmd_header_t
*cmd
;
278 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
279 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
280 region
->buf
->buf
->idx
);
282 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sizeof(*cmd
),
284 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
285 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
287 rmesa
->dma
.nr_released_bufs
++;
294 /* Allocates a region from rmesa->dma.current. If there isn't enough
295 * space in current, grab a new buffer (and discard what was left of current)
297 void r200AllocDmaRegion( r200ContextPtr rmesa
,
298 struct r200_dma_region
*region
,
302 if (R200_DEBUG
& DEBUG_IOCTL
)
303 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
305 if (rmesa
->dma
.flush
)
306 rmesa
->dma
.flush( rmesa
);
309 r200ReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
312 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
313 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
315 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
316 r200RefillCurrentDmaRegion( rmesa
);
318 region
->start
= rmesa
->dma
.current
.start
;
319 region
->ptr
= rmesa
->dma
.current
.start
;
320 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
321 region
->address
= rmesa
->dma
.current
.address
;
322 region
->buf
= rmesa
->dma
.current
.buf
;
323 region
->buf
->refcount
++;
325 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
326 rmesa
->dma
.current
.start
=
327 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
329 assert( rmesa
->dma
.current
.ptr
<= rmesa
->dma
.current
.end
);
332 /* ================================================================
333 * SwapBuffers with client-side throttling
336 static u_int32_t
r200GetLastFrame(r200ContextPtr rmesa
)
338 drm_radeon_getparam_t gp
;
342 gp
.param
= RADEON_PARAM_LAST_FRAME
;
343 gp
.value
= (int *)&frame
;
344 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
347 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
354 static void r200EmitIrqLocked( r200ContextPtr rmesa
)
356 drm_radeon_irq_emit_t ie
;
359 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
360 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
363 fprintf( stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
, ret
);
369 static void r200WaitIrq( r200ContextPtr rmesa
)
374 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
375 &rmesa
->iw
, sizeof(rmesa
->iw
) );
376 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
379 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
385 static void r200WaitForFrameCompletion( r200ContextPtr rmesa
)
387 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
389 if (rmesa
->do_irqs
) {
390 if (r200GetLastFrame(rmesa
) < sarea
->last_frame
) {
391 if (!rmesa
->irqsEmitted
) {
392 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
)
396 UNLOCK_HARDWARE( rmesa
);
397 r200WaitIrq( rmesa
);
398 LOCK_HARDWARE( rmesa
);
400 rmesa
->irqsEmitted
= 10;
403 if (rmesa
->irqsEmitted
) {
404 r200EmitIrqLocked( rmesa
);
405 rmesa
->irqsEmitted
--;
409 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
) {
410 UNLOCK_HARDWARE( rmesa
);
411 if (rmesa
->do_usleeps
)
413 LOCK_HARDWARE( rmesa
);
420 /* Copy the back color buffer to the front color buffer.
422 void r200CopyBuffer( const __DRIdrawablePrivate
*dPriv
,
423 const drm_clip_rect_t
*rect
)
425 r200ContextPtr rmesa
;
427 GLboolean missed_target
;
431 assert(dPriv
->driContextPriv
);
432 assert(dPriv
->driContextPriv
->driverPrivate
);
434 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
436 if ( R200_DEBUG
& DEBUG_IOCTL
) {
437 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *)rmesa
->glCtx
);
440 R200_FIREVERTICES( rmesa
);
442 LOCK_HARDWARE( rmesa
);
445 /* Throttle the frame rate -- only allow one pending swap buffers
448 r200WaitForFrameCompletion( rmesa
);
451 UNLOCK_HARDWARE( rmesa
);
452 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
453 LOCK_HARDWARE( rmesa
);
456 nbox
= dPriv
->numClipRects
; /* must be in locked region */
458 for ( i
= 0 ; i
< nbox
; ) {
459 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
460 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
461 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
464 for ( ; i
< nr
; i
++ ) {
470 if (rect
->x1
> b
->x1
)
472 if (rect
->y1
> b
->y1
)
474 if (rect
->x2
< b
->x2
)
476 if (rect
->y2
< b
->y2
)
479 if (b
->x1
< b
->x2
&& b
->y1
< b
->y2
)
487 rmesa
->sarea
->nbox
= n
;
489 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
492 fprintf( stderr
, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret
);
493 UNLOCK_HARDWARE( rmesa
);
498 UNLOCK_HARDWARE( rmesa
);
501 rmesa
->hw
.all_dirty
= GL_TRUE
;
504 (*dri_interface
->getUST
)( & ust
);
505 if ( missed_target
) {
506 rmesa
->swap_missed_count
++;
507 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
510 rmesa
->swap_ust
= ust
;
516 void r200PageFlip( const __DRIdrawablePrivate
*dPriv
)
518 r200ContextPtr rmesa
;
520 GLboolean missed_target
;
523 assert(dPriv
->driContextPriv
);
524 assert(dPriv
->driContextPriv
->driverPrivate
);
526 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
528 if ( R200_DEBUG
& DEBUG_IOCTL
) {
529 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
530 rmesa
->sarea
->pfCurrentPage
);
533 R200_FIREVERTICES( rmesa
);
534 LOCK_HARDWARE( rmesa
);
536 if (!dPriv
->numClipRects
) {
537 UNLOCK_HARDWARE( rmesa
);
538 usleep( 10000 ); /* throttle invisible client 10ms */
542 /* Need to do this for the perf box placement:
545 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
546 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
548 rmesa
->sarea
->nbox
= 1;
551 /* Throttle the frame rate -- only allow a few pending swap buffers
554 r200WaitForFrameCompletion( rmesa
);
555 UNLOCK_HARDWARE( rmesa
);
556 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
557 if ( missed_target
) {
558 rmesa
->swap_missed_count
++;
559 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
561 LOCK_HARDWARE( rmesa
);
563 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
565 UNLOCK_HARDWARE( rmesa
);
568 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
573 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
576 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
577 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->frontOffset
;
578 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->frontPitch
;
580 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->backOffset
;
581 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->backPitch
;
584 R200_STATECHANGE( rmesa
, ctx
);
585 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
586 + rmesa
->r200Screen
->fbLocation
;
587 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
588 if (rmesa
->sarea
->tiling_enabled
) {
589 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
592 /* Get ready for drawing next frame. Update the renderbuffers'
593 * flippedOffset/Pitch fields so we draw into the right place.
595 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
596 rmesa
->sarea
->pfCurrentPage
);
599 r200UpdateDrawBuffer(rmesa
->glCtx
);
604 /* ================================================================
607 static void r200Clear( GLcontext
*ctx
, GLbitfield mask
)
609 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
610 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
612 GLuint color_mask
= 0;
614 GLint cx
, cy
, cw
, ch
;
616 if ( R200_DEBUG
& DEBUG_IOCTL
) {
617 fprintf( stderr
, "r200Clear\n");
621 LOCK_HARDWARE( rmesa
);
622 UNLOCK_HARDWARE( rmesa
);
623 if ( dPriv
->numClipRects
== 0 )
629 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
630 flags
|= RADEON_FRONT
;
631 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
632 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
635 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
636 flags
|= RADEON_BACK
;
637 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
638 mask
&= ~BUFFER_BIT_BACK_LEFT
;
641 if ( mask
& BUFFER_BIT_DEPTH
) {
642 flags
|= RADEON_DEPTH
;
643 mask
&= ~BUFFER_BIT_DEPTH
;
646 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
647 flags
|= RADEON_STENCIL
;
648 mask
&= ~BUFFER_BIT_STENCIL
;
652 if (R200_DEBUG
& DEBUG_FALLBACKS
)
653 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
654 _swrast_Clear( ctx
, mask
);
660 if (rmesa
->using_hyperz
) {
661 flags
|= RADEON_USE_COMP_ZBUF
;
662 /* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200)
663 flags |= RADEON_USE_HIERZ; */
664 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
665 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
666 ((rmesa
->state
.stencil
.clear
& R200_STENCIL_WRITE_MASK
) == R200_STENCIL_WRITE_MASK
))) {
667 flags
|= RADEON_CLEAR_FASTZ
;
671 LOCK_HARDWARE( rmesa
);
673 /* compute region after locking: */
674 cx
= ctx
->DrawBuffer
->_Xmin
;
675 cy
= ctx
->DrawBuffer
->_Ymin
;
676 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
677 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
679 /* Flip top to bottom */
681 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
683 /* Throttle the number of clear ioctls we do.
686 drm_radeon_getparam_t gp
;
690 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
691 gp
.value
= (int *)&clear
;
692 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
693 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
696 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
700 /* Clear throttling needs more thought.
702 if ( rmesa
->sarea
->last_clear
- clear
<= 25 ) {
706 if (rmesa
->do_usleeps
) {
707 UNLOCK_HARDWARE( rmesa
);
709 LOCK_HARDWARE( rmesa
);
713 /* Send current state to the hardware */
714 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
716 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
717 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
718 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
719 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
720 drm_radeon_clear_t clear
;
721 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
724 if (cw
!= dPriv
->w
|| ch
!= dPriv
->h
) {
725 /* clear subregion */
726 for ( ; i
< nr
; i
++ ) {
729 GLint w
= box
[i
].x2
- x
;
730 GLint h
= box
[i
].y2
- y
;
732 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
733 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
734 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
735 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
736 if ( w
<= 0 ) continue;
737 if ( h
<= 0 ) continue;
747 /* clear whole window */
748 for ( ; i
< nr
; i
++ ) {
754 rmesa
->sarea
->nbox
= n
;
757 clear
.clear_color
= rmesa
->state
.color
.clear
;
758 clear
.clear_depth
= rmesa
->state
.depth
.clear
; /* needed for hyperz */
759 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
760 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
761 clear
.depth_boxes
= depth_boxes
;
764 b
= rmesa
->sarea
->boxes
;
765 for ( ; n
>= 0 ; n
-- ) {
766 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
767 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
768 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
769 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
770 depth_boxes
[n
].f
[CLEAR_DEPTH
] = ctx
->Depth
.Clear
;
773 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
774 &clear
, sizeof(clear
));
778 UNLOCK_HARDWARE( rmesa
);
779 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
784 UNLOCK_HARDWARE( rmesa
);
785 rmesa
->hw
.all_dirty
= GL_TRUE
;
789 void r200WaitForIdleLocked( r200ContextPtr rmesa
)
795 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_CP_IDLE
);
798 } while (ret
&& ++i
< 100);
801 UNLOCK_HARDWARE( rmesa
);
802 fprintf( stderr
, "Error: R200 timed out... exiting\n" );
808 static void r200WaitForIdle( r200ContextPtr rmesa
)
810 LOCK_HARDWARE(rmesa
);
811 r200WaitForIdleLocked( rmesa
);
812 UNLOCK_HARDWARE(rmesa
);
816 void r200Flush( GLcontext
*ctx
)
818 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
820 if (R200_DEBUG
& DEBUG_IOCTL
)
821 fprintf(stderr
, "%s\n", __FUNCTION__
);
823 if (rmesa
->dma
.flush
)
824 rmesa
->dma
.flush( rmesa
);
826 r200EmitState( rmesa
);
828 if (rmesa
->store
.cmd_used
)
829 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
832 /* Make sure all commands have been sent to the hardware and have
833 * completed processing.
835 void r200Finish( GLcontext
*ctx
)
837 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
840 if (rmesa
->do_irqs
) {
841 LOCK_HARDWARE( rmesa
);
842 r200EmitIrqLocked( rmesa
);
843 UNLOCK_HARDWARE( rmesa
);
844 r200WaitIrq( rmesa
);
847 r200WaitForIdle( rmesa
);
851 /* This version of AllocateMemoryMESA allocates only GART memory, and
852 * only does so after the point at which the driver has been
855 * Theoretically a valid context isn't required. However, in this
856 * implementation, it is, as I'm using the hardware lock to protect
857 * the kernel data structures, and the current context to get the
860 void *r200AllocateMemoryMESA(__DRIscreen
*screen
, GLsizei size
,
861 GLfloat readfreq
, GLfloat writefreq
,
864 GET_CURRENT_CONTEXT(ctx
);
865 r200ContextPtr rmesa
;
867 drm_radeon_mem_alloc_t alloc
;
870 if (R200_DEBUG
& DEBUG_IOCTL
)
871 fprintf(stderr
, "%s sz %d %f/%f/%f\n", __FUNCTION__
, size
, readfreq
,
872 writefreq
, priority
);
874 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
)
877 if (getenv("R200_NO_ALLOC"))
880 alloc
.region
= RADEON_MEM_REGION_GART
;
883 alloc
.region_offset
= ®ion_offset
;
885 ret
= drmCommandWriteRead( rmesa
->r200Screen
->driScreen
->fd
,
887 &alloc
, sizeof(alloc
));
890 fprintf(stderr
, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__
, ret
);
895 char *region_start
= (char *)rmesa
->r200Screen
->gartTextures
.map
;
896 return (void *)(region_start
+ region_offset
);
901 /* Called via glXFreeMemoryMESA() */
902 void r200FreeMemoryMESA(__DRIscreen
*screen
, GLvoid
*pointer
)
904 GET_CURRENT_CONTEXT(ctx
);
905 r200ContextPtr rmesa
;
906 ptrdiff_t region_offset
;
907 drm_radeon_mem_free_t memfree
;
910 if (R200_DEBUG
& DEBUG_IOCTL
)
911 fprintf(stderr
, "%s %p\n", __FUNCTION__
, pointer
);
913 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
) {
914 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
918 region_offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
920 if (region_offset
< 0 ||
921 region_offset
> rmesa
->r200Screen
->gartTextures
.size
) {
922 fprintf(stderr
, "offset %d outside range 0..%d\n", region_offset
,
923 rmesa
->r200Screen
->gartTextures
.size
);
927 memfree
.region
= RADEON_MEM_REGION_GART
;
928 memfree
.region_offset
= region_offset
;
930 ret
= drmCommandWrite( rmesa
->r200Screen
->driScreen
->fd
,
932 &memfree
, sizeof(memfree
));
935 fprintf(stderr
, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__
, ret
);
938 /* Called via glXGetMemoryOffsetMESA() */
939 GLuint
r200GetMemoryOffsetMESA(__DRIscreen
*screen
, const GLvoid
*pointer
)
941 GET_CURRENT_CONTEXT(ctx
);
942 r200ContextPtr rmesa
;
945 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) ) {
946 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
950 if (!r200IsGartMemory( rmesa
, pointer
, 0 ))
953 card_offset
= r200GartOffsetFromVirtual( rmesa
, pointer
);
955 return card_offset
- rmesa
->r200Screen
->gart_base
;
958 GLboolean
r200IsGartMemory( r200ContextPtr rmesa
, const GLvoid
*pointer
,
961 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
962 int valid
= (size
>= 0 &&
964 offset
+ size
< rmesa
->r200Screen
->gartTextures
.size
);
966 if (R200_DEBUG
& DEBUG_IOCTL
)
967 fprintf(stderr
, "r200IsGartMemory( %p ) : %d\n", pointer
, valid
);
973 GLuint
r200GartOffsetFromVirtual( r200ContextPtr rmesa
, const GLvoid
*pointer
)
975 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
977 if (offset
< 0 || offset
> rmesa
->r200Screen
->gartTextures
.size
)
980 return rmesa
->r200Screen
->gart_texture_offset
+ offset
;
985 void r200InitIoctlFuncs( struct dd_function_table
*functions
)
987 functions
->Clear
= r200Clear
;
988 functions
->Finish
= r200Finish
;
989 functions
->Flush
= r200Flush
;