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>
38 #include "main/glheader.h"
39 #include "main/imports.h"
40 #include "main/macros.h"
41 #include "main/context.h"
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 uint32_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( __DRIdrawablePrivate
*dPriv
,
423 const drm_clip_rect_t
*rect
)
425 r200ContextPtr rmesa
;
427 GLboolean missed_target
;
429 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
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
, & 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
)
487 rmesa
->sarea
->nbox
= n
;
492 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
495 fprintf( stderr
, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret
);
496 UNLOCK_HARDWARE( rmesa
);
501 UNLOCK_HARDWARE( rmesa
);
504 rmesa
->hw
.all_dirty
= GL_TRUE
;
507 (*psp
->systemTime
->getUST
)( & ust
);
508 if ( missed_target
) {
509 rmesa
->swap_missed_count
++;
510 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
513 rmesa
->swap_ust
= ust
;
519 void r200PageFlip( __DRIdrawablePrivate
*dPriv
)
521 r200ContextPtr rmesa
;
523 GLboolean missed_target
;
524 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
527 assert(dPriv
->driContextPriv
);
528 assert(dPriv
->driContextPriv
->driverPrivate
);
530 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
532 if ( R200_DEBUG
& DEBUG_IOCTL
) {
533 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
534 rmesa
->sarea
->pfCurrentPage
);
537 R200_FIREVERTICES( rmesa
);
538 LOCK_HARDWARE( rmesa
);
540 if (!dPriv
->numClipRects
) {
541 UNLOCK_HARDWARE( rmesa
);
542 usleep( 10000 ); /* throttle invisible client 10ms */
546 /* Need to do this for the perf box placement:
549 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
550 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
552 rmesa
->sarea
->nbox
= 1;
555 /* Throttle the frame rate -- only allow a few pending swap buffers
558 r200WaitForFrameCompletion( rmesa
);
559 UNLOCK_HARDWARE( rmesa
);
560 driWaitForVBlank( dPriv
, & missed_target
);
561 if ( missed_target
) {
562 rmesa
->swap_missed_count
++;
563 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_missed_ust
);
565 LOCK_HARDWARE( rmesa
);
567 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
569 UNLOCK_HARDWARE( rmesa
);
572 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
577 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_ust
);
580 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
581 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->frontOffset
;
582 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->frontPitch
;
584 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->backOffset
;
585 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->backPitch
;
588 R200_STATECHANGE( rmesa
, ctx
);
589 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
590 + rmesa
->r200Screen
->fbLocation
;
591 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
592 if (rmesa
->sarea
->tiling_enabled
) {
593 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= R200_COLOR_TILE_ENABLE
;
596 /* Get ready for drawing next frame. Update the renderbuffers'
597 * flippedOffset/Pitch fields so we draw into the right place.
599 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
600 rmesa
->sarea
->pfCurrentPage
);
603 r200UpdateDrawBuffer(rmesa
->glCtx
);
608 /* ================================================================
611 static void r200Clear( GLcontext
*ctx
, GLbitfield mask
)
613 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
614 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
616 GLuint color_mask
= 0;
618 GLint cx
, cy
, cw
, ch
;
620 if ( R200_DEBUG
& DEBUG_IOCTL
) {
621 fprintf( stderr
, "r200Clear\n");
625 LOCK_HARDWARE( rmesa
);
626 UNLOCK_HARDWARE( rmesa
);
627 if ( dPriv
->numClipRects
== 0 )
633 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
634 flags
|= RADEON_FRONT
;
635 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
636 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
639 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
640 flags
|= RADEON_BACK
;
641 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
642 mask
&= ~BUFFER_BIT_BACK_LEFT
;
645 if ( mask
& BUFFER_BIT_DEPTH
) {
646 flags
|= RADEON_DEPTH
;
647 mask
&= ~BUFFER_BIT_DEPTH
;
650 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
651 flags
|= RADEON_STENCIL
;
652 mask
&= ~BUFFER_BIT_STENCIL
;
656 if (R200_DEBUG
& DEBUG_FALLBACKS
)
657 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
658 _swrast_Clear( ctx
, mask
);
664 if (rmesa
->using_hyperz
) {
665 flags
|= RADEON_USE_COMP_ZBUF
;
666 /* if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200)
667 flags |= RADEON_USE_HIERZ; */
668 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
669 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
670 ((rmesa
->state
.stencil
.clear
& R200_STENCIL_WRITE_MASK
) == R200_STENCIL_WRITE_MASK
))) {
671 flags
|= RADEON_CLEAR_FASTZ
;
675 LOCK_HARDWARE( rmesa
);
677 /* compute region after locking: */
678 cx
= ctx
->DrawBuffer
->_Xmin
;
679 cy
= ctx
->DrawBuffer
->_Ymin
;
680 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
681 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
683 /* Flip top to bottom */
685 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
687 /* Throttle the number of clear ioctls we do.
690 drm_radeon_getparam_t gp
;
694 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
695 gp
.value
= (int *)&clear
;
696 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
697 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
700 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
704 /* Clear throttling needs more thought.
706 if ( rmesa
->sarea
->last_clear
- clear
<= 25 ) {
710 if (rmesa
->do_usleeps
) {
711 UNLOCK_HARDWARE( rmesa
);
713 LOCK_HARDWARE( rmesa
);
717 /* Send current state to the hardware */
718 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
720 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
721 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
722 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
723 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
724 drm_radeon_clear_t clear
;
725 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
728 if (cw
!= dPriv
->w
|| ch
!= dPriv
->h
) {
729 /* clear subregion */
730 for ( ; i
< nr
; i
++ ) {
733 GLint w
= box
[i
].x2
- x
;
734 GLint h
= box
[i
].y2
- y
;
736 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
737 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
738 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
739 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
740 if ( w
<= 0 ) continue;
741 if ( h
<= 0 ) continue;
751 /* clear whole window */
752 for ( ; i
< nr
; i
++ ) {
758 rmesa
->sarea
->nbox
= n
;
761 clear
.clear_color
= rmesa
->state
.color
.clear
;
762 clear
.clear_depth
= rmesa
->state
.depth
.clear
; /* needed for hyperz */
763 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
764 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
765 clear
.depth_boxes
= depth_boxes
;
768 b
= rmesa
->sarea
->boxes
;
769 for ( ; n
>= 0 ; n
-- ) {
770 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
771 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
772 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
773 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
774 depth_boxes
[n
].f
[CLEAR_DEPTH
] = ctx
->Depth
.Clear
;
777 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
778 &clear
, sizeof(clear
));
782 UNLOCK_HARDWARE( rmesa
);
783 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
788 UNLOCK_HARDWARE( rmesa
);
789 rmesa
->hw
.all_dirty
= GL_TRUE
;
793 void r200WaitForIdleLocked( r200ContextPtr rmesa
)
799 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_CP_IDLE
);
802 } while (ret
&& ++i
< 100);
805 UNLOCK_HARDWARE( rmesa
);
806 fprintf( stderr
, "Error: R200 timed out... exiting\n" );
812 static void r200WaitForIdle( r200ContextPtr rmesa
)
814 LOCK_HARDWARE(rmesa
);
815 r200WaitForIdleLocked( rmesa
);
816 UNLOCK_HARDWARE(rmesa
);
820 void r200Flush( GLcontext
*ctx
)
822 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
824 if (R200_DEBUG
& DEBUG_IOCTL
)
825 fprintf(stderr
, "%s\n", __FUNCTION__
);
827 if (rmesa
->dma
.flush
)
828 rmesa
->dma
.flush( rmesa
);
830 r200EmitState( rmesa
);
832 if (rmesa
->store
.cmd_used
)
833 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
836 /* Make sure all commands have been sent to the hardware and have
837 * completed processing.
839 void r200Finish( GLcontext
*ctx
)
841 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
844 if (rmesa
->do_irqs
) {
845 LOCK_HARDWARE( rmesa
);
846 r200EmitIrqLocked( rmesa
);
847 UNLOCK_HARDWARE( rmesa
);
848 r200WaitIrq( rmesa
);
851 r200WaitForIdle( rmesa
);
855 /* This version of AllocateMemoryMESA allocates only GART memory, and
856 * only does so after the point at which the driver has been
859 * Theoretically a valid context isn't required. However, in this
860 * implementation, it is, as I'm using the hardware lock to protect
861 * the kernel data structures, and the current context to get the
864 void *r200AllocateMemoryMESA(__DRIscreen
*screen
, GLsizei size
,
865 GLfloat readfreq
, GLfloat writefreq
,
868 GET_CURRENT_CONTEXT(ctx
);
869 r200ContextPtr rmesa
;
871 drm_radeon_mem_alloc_t alloc
;
874 if (R200_DEBUG
& DEBUG_IOCTL
)
875 fprintf(stderr
, "%s sz %d %f/%f/%f\n", __FUNCTION__
, size
, readfreq
,
876 writefreq
, priority
);
878 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
)
881 if (getenv("R200_NO_ALLOC"))
884 alloc
.region
= RADEON_MEM_REGION_GART
;
887 alloc
.region_offset
= ®ion_offset
;
889 ret
= drmCommandWriteRead( rmesa
->r200Screen
->driScreen
->fd
,
891 &alloc
, sizeof(alloc
));
894 fprintf(stderr
, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__
, ret
);
899 char *region_start
= (char *)rmesa
->r200Screen
->gartTextures
.map
;
900 return (void *)(region_start
+ region_offset
);
905 /* Called via glXFreeMemoryMESA() */
906 void r200FreeMemoryMESA(__DRIscreen
*screen
, GLvoid
*pointer
)
908 GET_CURRENT_CONTEXT(ctx
);
909 r200ContextPtr rmesa
;
910 ptrdiff_t region_offset
;
911 drm_radeon_mem_free_t memfree
;
914 if (R200_DEBUG
& DEBUG_IOCTL
)
915 fprintf(stderr
, "%s %p\n", __FUNCTION__
, pointer
);
917 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
) {
918 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
922 region_offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
924 if (region_offset
< 0 ||
925 region_offset
> rmesa
->r200Screen
->gartTextures
.size
) {
926 fprintf(stderr
, "offset %d outside range 0..%d\n", region_offset
,
927 rmesa
->r200Screen
->gartTextures
.size
);
931 memfree
.region
= RADEON_MEM_REGION_GART
;
932 memfree
.region_offset
= region_offset
;
934 ret
= drmCommandWrite( rmesa
->r200Screen
->driScreen
->fd
,
936 &memfree
, sizeof(memfree
));
939 fprintf(stderr
, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__
, ret
);
942 /* Called via glXGetMemoryOffsetMESA() */
943 GLuint
r200GetMemoryOffsetMESA(__DRIscreen
*screen
, const GLvoid
*pointer
)
945 GET_CURRENT_CONTEXT(ctx
);
946 r200ContextPtr rmesa
;
949 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) ) {
950 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
954 if (!r200IsGartMemory( rmesa
, pointer
, 0 ))
957 card_offset
= r200GartOffsetFromVirtual( rmesa
, pointer
);
959 return card_offset
- rmesa
->r200Screen
->gart_base
;
962 GLboolean
r200IsGartMemory( r200ContextPtr rmesa
, const GLvoid
*pointer
,
965 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
966 int valid
= (size
>= 0 &&
968 offset
+ size
< rmesa
->r200Screen
->gartTextures
.size
);
970 if (R200_DEBUG
& DEBUG_IOCTL
)
971 fprintf(stderr
, "r200IsGartMemory( %p ) : %d\n", pointer
, valid
);
977 GLuint
r200GartOffsetFromVirtual( r200ContextPtr rmesa
, const GLvoid
*pointer
)
979 ptrdiff_t offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
981 if (offset
< 0 || offset
> rmesa
->r200Screen
->gartTextures
.size
)
984 return rmesa
->r200Screen
->gart_texture_offset
+ offset
;
989 void r200InitIoctlFuncs( struct dd_function_table
*functions
)
991 functions
->Clear
= r200Clear
;
992 functions
->Finish
= r200Finish
;
993 functions
->Flush
= r200Flush
;