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"
55 #define R200_TIMEOUT 512
56 #define R200_IDLE_RETRY 16
59 static void r200WaitForIdle( r200ContextPtr rmesa
);
62 int r200FlushCmdBufLocked( r200ContextPtr rmesa
, const char * caller
)
65 drmRadeonCmdBuffer cmd
;
67 if (R200_DEBUG
& DEBUG_IOCTL
) {
68 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
70 if (0 & R200_DEBUG
& DEBUG_VERBOSE
)
71 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
72 fprintf(stderr
, "%d: %x\n", i
/4,
73 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
76 if (R200_DEBUG
& DEBUG_DMA
)
77 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
78 rmesa
->dma
.nr_released_bufs
);
81 if (R200_DEBUG
& DEBUG_SANITY
) {
82 if (rmesa
->state
.scissor
.enabled
)
83 ret
= r200SanityCmdBuffer( rmesa
,
84 rmesa
->state
.scissor
.numClipRects
,
85 rmesa
->state
.scissor
.pClipRects
);
87 ret
= r200SanityCmdBuffer( rmesa
,
91 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
97 if (R200_DEBUG
& DEBUG_MEMORY
) {
98 if (! driValidateTextureHeaps( rmesa
->texture_heaps
, rmesa
->nr_heaps
,
99 & rmesa
->swapped
) ) {
100 fprintf( stderr
, "%s: texture memory is inconsistent - expect "
101 "mangled textures\n", __FUNCTION__
);
106 cmd
.bufsz
= rmesa
->store
.cmd_used
;
107 cmd
.buf
= rmesa
->store
.cmd_buf
;
109 if (rmesa
->state
.scissor
.enabled
) {
110 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
111 cmd
.boxes
= (drmClipRect
*)rmesa
->state
.scissor
.pClipRects
;
113 cmd
.nbox
= rmesa
->numClipRects
;
114 cmd
.boxes
= (drmClipRect
*)rmesa
->pClipRects
;
117 ret
= drmCommandWrite( rmesa
->dri
.fd
,
122 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
124 if (R200_DEBUG
& DEBUG_SYNC
) {
125 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
126 r200WaitForIdleLocked( rmesa
);
131 rmesa
->store
.primnr
= 0;
132 rmesa
->store
.statenr
= 0;
133 rmesa
->store
.cmd_used
= 0;
134 rmesa
->dma
.nr_released_bufs
= 0;
135 rmesa
->lost_context
= 1;
140 /* Note: does not emit any commands to avoid recursion on
143 void r200FlushCmdBuf( r200ContextPtr rmesa
, const char *caller
)
147 LOCK_HARDWARE( rmesa
);
149 ret
= r200FlushCmdBufLocked( rmesa
, caller
);
151 UNLOCK_HARDWARE( rmesa
);
154 fprintf(stderr
, "drmRadeonCmdBuffer: %d (exiting)\n", ret
);
160 /* =============================================================
161 * Hardware vertex buffer handling
165 void r200RefillCurrentDmaRegion( r200ContextPtr rmesa
)
167 struct r200_dma_buffer
*dmabuf
;
168 int fd
= rmesa
->dri
.fd
;
174 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
175 fprintf(stderr
, "%s\n", __FUNCTION__
);
177 if (rmesa
->dma
.flush
) {
178 rmesa
->dma
.flush( rmesa
);
181 if (rmesa
->dma
.current
.buf
)
182 r200ReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
184 if (rmesa
->dma
.nr_released_bufs
> 4)
185 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
187 dma
.context
= rmesa
->dri
.hwContext
;
189 dma
.send_list
= NULL
;
190 dma
.send_sizes
= NULL
;
192 dma
.request_count
= 1;
193 dma
.request_size
= RADEON_BUFFER_SIZE
;
194 dma
.request_list
= &index
;
195 dma
.request_sizes
= &size
;
196 dma
.granted_count
= 0;
198 LOCK_HARDWARE(rmesa
); /* no need to validate */
201 ret
= drmDMA( fd
, &dma
);
205 if (rmesa
->dma
.nr_released_bufs
) {
206 r200FlushCmdBufLocked( rmesa
, __FUNCTION__
);
209 if (rmesa
->do_usleeps
) {
210 UNLOCK_HARDWARE( rmesa
);
212 LOCK_HARDWARE( rmesa
);
216 UNLOCK_HARDWARE(rmesa
);
218 if (R200_DEBUG
& DEBUG_DMA
)
219 fprintf(stderr
, "Allocated buffer %d\n", index
);
221 dmabuf
= CALLOC_STRUCT( r200_dma_buffer
);
222 dmabuf
->buf
= &rmesa
->r200Screen
->buffers
->list
[index
];
223 dmabuf
->refcount
= 1;
225 rmesa
->dma
.current
.buf
= dmabuf
;
226 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
227 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
228 rmesa
->dma
.current
.start
= 0;
229 rmesa
->dma
.current
.ptr
= 0;
232 void r200ReleaseDmaRegion( r200ContextPtr rmesa
,
233 struct r200_dma_region
*region
,
236 if (R200_DEBUG
& DEBUG_IOCTL
)
237 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
242 if (rmesa
->dma
.flush
)
243 rmesa
->dma
.flush( rmesa
);
245 if (--region
->buf
->refcount
== 0) {
246 drmRadeonCmdHeader
*cmd
;
248 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
249 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
250 region
->buf
->buf
->idx
);
252 cmd
= (drmRadeonCmdHeader
*)r200AllocCmdBuf( rmesa
, sizeof(*cmd
),
254 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
255 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
257 rmesa
->dma
.nr_released_bufs
++;
264 /* Allocates a region from rmesa->dma.current. If there isn't enough
265 * space in current, grab a new buffer (and discard what was left of current)
267 void r200AllocDmaRegion( r200ContextPtr rmesa
,
268 struct r200_dma_region
*region
,
272 if (R200_DEBUG
& DEBUG_IOCTL
)
273 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
275 if (rmesa
->dma
.flush
)
276 rmesa
->dma
.flush( rmesa
);
279 r200ReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
282 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
283 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
285 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
286 r200RefillCurrentDmaRegion( rmesa
);
288 region
->start
= rmesa
->dma
.current
.start
;
289 region
->ptr
= rmesa
->dma
.current
.start
;
290 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
291 region
->address
= rmesa
->dma
.current
.address
;
292 region
->buf
= rmesa
->dma
.current
.buf
;
293 region
->buf
->refcount
++;
295 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
296 rmesa
->dma
.current
.start
=
297 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
299 assert( rmesa
->dma
.current
.ptr
<= rmesa
->dma
.current
.end
);
302 void r200AllocDmaRegionVerts( r200ContextPtr rmesa
,
303 struct r200_dma_region
*region
,
308 r200AllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
311 /* ================================================================
312 * SwapBuffers with client-side throttling
315 static CARD32
r200GetLastFrame(r200ContextPtr rmesa
)
317 drmRadeonGetParam gp
;
321 gp
.param
= RADEON_PARAM_LAST_FRAME
;
322 gp
.value
= (int *)&frame
;
323 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
326 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
333 static void r200EmitIrqLocked( r200ContextPtr rmesa
)
338 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
339 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
342 fprintf( stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
, ret
);
348 static void r200WaitIrq( r200ContextPtr rmesa
)
353 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
354 &rmesa
->iw
, sizeof(rmesa
->iw
) );
355 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
358 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
364 static void r200WaitForFrameCompletion( r200ContextPtr rmesa
)
366 RADEONSAREAPrivPtr sarea
= rmesa
->sarea
;
368 if (rmesa
->do_irqs
) {
369 if (r200GetLastFrame(rmesa
) < sarea
->last_frame
) {
370 if (!rmesa
->irqsEmitted
) {
371 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
)
375 UNLOCK_HARDWARE( rmesa
);
376 r200WaitIrq( rmesa
);
377 LOCK_HARDWARE( rmesa
);
379 rmesa
->irqsEmitted
= 10;
382 if (rmesa
->irqsEmitted
) {
383 r200EmitIrqLocked( rmesa
);
384 rmesa
->irqsEmitted
--;
388 while (r200GetLastFrame (rmesa
) < sarea
->last_frame
) {
389 UNLOCK_HARDWARE( rmesa
);
390 if (rmesa
->do_usleeps
)
392 LOCK_HARDWARE( rmesa
);
399 /* Copy the back color buffer to the front color buffer.
401 void r200CopyBuffer( const __DRIdrawablePrivate
*dPriv
)
403 r200ContextPtr rmesa
;
405 GLboolean missed_target
;
409 assert(dPriv
->driContextPriv
);
410 assert(dPriv
->driContextPriv
->driverPrivate
);
412 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
414 if ( R200_DEBUG
& DEBUG_IOCTL
) {
415 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *)rmesa
->glCtx
);
418 R200_FIREVERTICES( rmesa
);
420 LOCK_HARDWARE( rmesa
);
423 /* Throttle the frame rate -- only allow one pending swap buffers
426 r200WaitForFrameCompletion( rmesa
);
427 UNLOCK_HARDWARE( rmesa
);
428 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
429 LOCK_HARDWARE( rmesa
);
431 nbox
= dPriv
->numClipRects
; /* must be in locked region */
433 for ( i
= 0 ; i
< nbox
; ) {
434 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
435 XF86DRIClipRectPtr box
= dPriv
->pClipRects
;
436 XF86DRIClipRectPtr b
= rmesa
->sarea
->boxes
;
439 for ( ; i
< nr
; i
++ ) {
443 rmesa
->sarea
->nbox
= n
;
445 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
448 fprintf( stderr
, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret
);
449 UNLOCK_HARDWARE( rmesa
);
454 UNLOCK_HARDWARE( rmesa
);
455 rmesa
->lost_context
= 1;
458 (*rmesa
->get_ust
)( & ust
);
459 if ( missed_target
) {
460 rmesa
->swap_missed_count
++;
461 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
464 rmesa
->swap_ust
= ust
;
469 void r200PageFlip( const __DRIdrawablePrivate
*dPriv
)
471 r200ContextPtr rmesa
;
473 GLboolean missed_target
;
476 assert(dPriv
->driContextPriv
);
477 assert(dPriv
->driContextPriv
->driverPrivate
);
479 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
481 if ( R200_DEBUG
& DEBUG_IOCTL
) {
482 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
483 rmesa
->sarea
->pfCurrentPage
);
486 R200_FIREVERTICES( rmesa
);
487 LOCK_HARDWARE( rmesa
);
489 if (!dPriv
->numClipRects
) {
490 UNLOCK_HARDWARE( rmesa
);
491 usleep( 10000 ); /* throttle invisible client 10ms */
495 /* Need to do this for the perf box placement:
498 XF86DRIClipRectPtr box
= dPriv
->pClipRects
;
499 XF86DRIClipRectPtr b
= rmesa
->sarea
->boxes
;
501 rmesa
->sarea
->nbox
= 1;
504 /* Throttle the frame rate -- only allow a few pending swap buffers
507 r200WaitForFrameCompletion( rmesa
);
508 UNLOCK_HARDWARE( rmesa
);
509 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
510 if ( missed_target
) {
511 rmesa
->swap_missed_count
++;
512 (void) (*rmesa
->get_ust
)( & rmesa
->swap_missed_ust
);
514 LOCK_HARDWARE( rmesa
);
516 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
518 UNLOCK_HARDWARE( rmesa
);
521 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
526 (void) (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
528 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
529 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->frontOffset
;
530 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->frontPitch
;
532 rmesa
->state
.color
.drawOffset
= rmesa
->r200Screen
->backOffset
;
533 rmesa
->state
.color
.drawPitch
= rmesa
->r200Screen
->backPitch
;
536 R200_STATECHANGE( rmesa
, ctx
);
537 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
538 + rmesa
->r200Screen
->fbLocation
;
539 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
543 /* ================================================================
546 static void r200Clear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
547 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
549 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
550 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
552 GLuint color_mask
= 0;
555 if ( R200_DEBUG
& DEBUG_IOCTL
) {
556 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
557 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
561 LOCK_HARDWARE( rmesa
);
562 UNLOCK_HARDWARE( rmesa
);
563 if ( dPriv
->numClipRects
== 0 )
567 r200EmitState( rmesa
);
569 /* Need to cope with lostcontext here as kernel relies on
570 * some residual state:
572 R200_FIREVERTICES( rmesa
);
574 if ( mask
& DD_FRONT_LEFT_BIT
) {
575 flags
|= RADEON_FRONT
;
576 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
577 mask
&= ~DD_FRONT_LEFT_BIT
;
580 if ( mask
& DD_BACK_LEFT_BIT
) {
581 flags
|= RADEON_BACK
;
582 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
583 mask
&= ~DD_BACK_LEFT_BIT
;
586 if ( mask
& DD_DEPTH_BIT
) {
587 if ( ctx
->Depth
.Mask
) flags
|= RADEON_DEPTH
; /* FIXME: ??? */
588 mask
&= ~DD_DEPTH_BIT
;
591 if ( (mask
& DD_STENCIL_BIT
) && rmesa
->state
.stencil
.hwBuffer
) {
592 flags
|= RADEON_STENCIL
;
593 mask
&= ~DD_STENCIL_BIT
;
597 if (R200_DEBUG
& DEBUG_FALLBACKS
)
598 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
599 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
605 /* Flip top to bottom */
607 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
609 LOCK_HARDWARE( rmesa
);
611 /* Throttle the number of clear ioctls we do.
614 drmRadeonGetParam gp
;
618 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
619 gp
.value
= (int *)&clear
;
620 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
621 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
624 fprintf( stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
, ret
);
628 /* Clear throttling needs more thought.
630 if ( rmesa
->sarea
->last_clear
- clear
<= 25 ) {
634 if (rmesa
->do_usleeps
) {
635 UNLOCK_HARDWARE( rmesa
);
637 LOCK_HARDWARE( rmesa
);
642 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
643 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
644 XF86DRIClipRectPtr box
= dPriv
->pClipRects
;
645 XF86DRIClipRectPtr b
= rmesa
->sarea
->boxes
;
646 drmRadeonClearType clear
;
647 drmRadeonClearRect depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
651 for ( ; i
< nr
; i
++ ) {
654 GLint w
= box
[i
].x2
- x
;
655 GLint h
= box
[i
].y2
- y
;
657 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
658 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
659 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
660 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
661 if ( w
<= 0 ) continue;
662 if ( h
<= 0 ) continue;
672 for ( ; i
< nr
; i
++ ) {
678 rmesa
->sarea
->nbox
= n
;
681 clear
.clear_color
= rmesa
->state
.color
.clear
;
682 clear
.clear_depth
= 0; /* not used */
683 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
684 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
685 clear
.depth_boxes
= depth_boxes
;
688 b
= rmesa
->sarea
->boxes
;
689 for ( ; n
>= 0 ; n
-- ) {
690 depth_boxes
[n
].f
[RADEON_CLEAR_X1
] = (float)b
[n
].x1
;
691 depth_boxes
[n
].f
[RADEON_CLEAR_Y1
] = (float)b
[n
].y1
;
692 depth_boxes
[n
].f
[RADEON_CLEAR_X2
] = (float)b
[n
].x2
;
693 depth_boxes
[n
].f
[RADEON_CLEAR_Y2
] = (float)b
[n
].y2
;
694 depth_boxes
[n
].f
[RADEON_CLEAR_DEPTH
] = ctx
->Depth
.Clear
;
697 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
698 &clear
, sizeof(drmRadeonClearType
));
702 UNLOCK_HARDWARE( rmesa
);
703 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
708 UNLOCK_HARDWARE( rmesa
);
709 rmesa
->lost_context
= 1;
713 void r200WaitForIdleLocked( r200ContextPtr rmesa
)
719 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_CP_IDLE
);
722 } while (ret
&& ++i
< 100);
725 UNLOCK_HARDWARE( rmesa
);
726 fprintf( stderr
, "Error: R200 timed out... exiting\n" );
732 static void r200WaitForIdle( r200ContextPtr rmesa
)
734 LOCK_HARDWARE(rmesa
);
735 r200WaitForIdleLocked( rmesa
);
736 UNLOCK_HARDWARE(rmesa
);
740 void r200Flush( GLcontext
*ctx
)
742 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
744 if (R200_DEBUG
& DEBUG_IOCTL
)
745 fprintf(stderr
, "%s\n", __FUNCTION__
);
747 if (rmesa
->dma
.flush
)
748 rmesa
->dma
.flush( rmesa
);
750 if (!is_empty_list(&rmesa
->hw
.dirty
))
751 r200EmitState( rmesa
);
753 if (rmesa
->store
.cmd_used
)
754 r200FlushCmdBuf( rmesa
, __FUNCTION__
);
757 /* Make sure all commands have been sent to the hardware and have
758 * completed processing.
760 void r200Finish( GLcontext
*ctx
)
762 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
765 if (rmesa
->do_irqs
) {
766 LOCK_HARDWARE( rmesa
);
767 r200EmitIrqLocked( rmesa
);
768 UNLOCK_HARDWARE( rmesa
);
769 r200WaitIrq( rmesa
);
772 r200WaitForIdle( rmesa
);
776 /* This version of AllocateMemoryMESA allocates only GART memory, and
777 * only does so after the point at which the driver has been
780 * Theoretically a valid context isn't required. However, in this
781 * implementation, it is, as I'm using the hardware lock to protect
782 * the kernel data structures, and the current context to get the
785 void *r200AllocateMemoryMESA(GLsizei size
,
786 GLfloat readfreq
, GLfloat writefreq
,
789 GET_CURRENT_CONTEXT(ctx
);
790 r200ContextPtr rmesa
;
792 drmRadeonMemAlloc alloc
;
795 if (R200_DEBUG
& DEBUG_IOCTL
)
796 fprintf(stderr
, "%s sz %d %f/%f/%f\n", __FUNCTION__
, size
, readfreq
,
797 writefreq
, priority
);
799 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
)
802 if (getenv("R200_NO_ALLOC"))
805 if (rmesa
->dri
.drmMinor
< 6)
808 alloc
.region
= RADEON_MEM_REGION_GART
;
811 alloc
.region_offset
= ®ion_offset
;
813 ret
= drmCommandWriteRead( rmesa
->r200Screen
->driScreen
->fd
,
815 &alloc
, sizeof(alloc
));
818 fprintf(stderr
, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__
, ret
);
823 char *region_start
= (char *)rmesa
->r200Screen
->gartTextures
.map
;
824 return (void *)(region_start
+ region_offset
);
829 /* Called via glXFreeMemoryMESA() */
830 void r200FreeMemoryMESA(GLvoid
*pointer
)
832 GET_CURRENT_CONTEXT(ctx
);
833 r200ContextPtr rmesa
;
835 drmRadeonMemFree memfree
;
838 if (R200_DEBUG
& DEBUG_IOCTL
)
839 fprintf(stderr
, "%s %p\n", __FUNCTION__
, pointer
);
841 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
) {
842 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
846 if (rmesa
->dri
.drmMinor
< 6)
849 region_offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
851 if (region_offset
< 0 ||
852 region_offset
> rmesa
->r200Screen
->gartTextures
.size
) {
853 fprintf(stderr
, "offset %d outside range 0..%d\n", region_offset
,
854 rmesa
->r200Screen
->gartTextures
.size
);
858 memfree
.region
= RADEON_MEM_REGION_GART
;
859 memfree
.region_offset
= region_offset
;
861 ret
= drmCommandWrite( rmesa
->r200Screen
->driScreen
->fd
,
863 &memfree
, sizeof(memfree
));
866 fprintf(stderr
, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__
, ret
);
869 /* Called via glXGetMemoryOffsetMESA() */
870 GLuint
r200GetMemoryOffsetMESA(const GLvoid
*pointer
)
872 GET_CURRENT_CONTEXT(ctx
);
873 r200ContextPtr rmesa
;
876 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) ) {
877 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
881 if (!r200IsGartMemory( rmesa
, pointer
, 0 ))
884 if (rmesa
->dri
.drmMinor
< 6)
887 card_offset
= r200GartOffsetFromVirtual( rmesa
, pointer
);
889 return card_offset
- rmesa
->r200Screen
->gart_base
;
893 GLboolean
r200IsGartMemory( r200ContextPtr rmesa
, const GLvoid
*pointer
,
896 int offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
897 int valid
= (size
>= 0 &&
899 offset
+ size
< rmesa
->r200Screen
->gartTextures
.size
);
901 if (R200_DEBUG
& DEBUG_IOCTL
)
902 fprintf(stderr
, "r200IsGartMemory( %p ) : %d\n", pointer
, valid
);
908 GLuint
r200GartOffsetFromVirtual( r200ContextPtr rmesa
, const GLvoid
*pointer
)
910 int offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
912 if (offset
< 0 || offset
> rmesa
->r200Screen
->gartTextures
.size
)
915 return rmesa
->r200Screen
->gart_texture_offset
+ offset
;
920 void r200InitIoctlFuncs( GLcontext
*ctx
)
922 ctx
->Driver
.Clear
= r200Clear
;
923 ctx
->Driver
.Finish
= r200Finish
;
924 ctx
->Driver
.Flush
= r200Flush
;