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 drm_radeon_cmd_buffer_t 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
= (drm_clip_rect_t
*)rmesa
->state
.scissor
.pClipRects
;
113 cmd
.nbox
= rmesa
->numClipRects
;
114 cmd
.boxes
= (drm_clip_rect_t
*)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 drm_radeon_cmd_header_t
*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
= (drm_radeon_cmd_header_t
*)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 uint32_t r200GetLastFrame(r200ContextPtr rmesa
)
317 drm_radeon_getparam_t 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
)
335 drm_radeon_irq_emit_t ie
;
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 drm_radeon_sarea_t
*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 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
436 drm_clip_rect_t
*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 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
499 drm_clip_rect_t
*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 drm_radeon_getparam_t 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 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
645 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
646 drm_radeon_clear_t clear
;
647 drm_radeon_clear_rect_t 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
[CLEAR_X1
] = (float)b
[n
].x1
;
691 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
692 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
693 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
694 depth_boxes
[n
].f
[CLEAR_DEPTH
] = ctx
->Depth
.Clear
;
697 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
698 &clear
, sizeof(clear
));
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
786 void *r200AllocateMemoryMESA(Display
*dpy
, int scrn
, GLsizei size
,
787 GLfloat readfreq
, GLfloat writefreq
,
790 GET_CURRENT_CONTEXT(ctx
);
791 r200ContextPtr rmesa
;
793 drm_radeon_mem_alloc_t alloc
;
796 if (R200_DEBUG
& DEBUG_IOCTL
)
797 fprintf(stderr
, "%s sz %d %f/%f/%f\n", __FUNCTION__
, size
, readfreq
,
798 writefreq
, priority
);
800 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
)
803 if (getenv("R200_NO_ALLOC"))
806 if (rmesa
->dri
.drmMinor
< 6)
809 alloc
.region
= RADEON_MEM_REGION_GART
;
812 alloc
.region_offset
= ®ion_offset
;
814 ret
= drmCommandWriteRead( rmesa
->r200Screen
->driScreen
->fd
,
816 &alloc
, sizeof(alloc
));
819 fprintf(stderr
, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__
, ret
);
824 char *region_start
= (char *)rmesa
->r200Screen
->gartTextures
.map
;
825 return (void *)(region_start
+ region_offset
);
830 /* Called via glXFreeMemoryMESA() */
831 void r200FreeMemoryMESA(Display
*dpy
, int scrn
, GLvoid
*pointer
)
833 GET_CURRENT_CONTEXT(ctx
);
834 r200ContextPtr rmesa
;
836 drm_radeon_mem_free_t memfree
;
839 if (R200_DEBUG
& DEBUG_IOCTL
)
840 fprintf(stderr
, "%s %p\n", __FUNCTION__
, pointer
);
842 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) || !rmesa
->r200Screen
->gartTextures
.map
) {
843 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
847 if (rmesa
->dri
.drmMinor
< 6)
850 region_offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
852 if (region_offset
< 0 ||
853 region_offset
> rmesa
->r200Screen
->gartTextures
.size
) {
854 fprintf(stderr
, "offset %d outside range 0..%d\n", region_offset
,
855 rmesa
->r200Screen
->gartTextures
.size
);
859 memfree
.region
= RADEON_MEM_REGION_GART
;
860 memfree
.region_offset
= region_offset
;
862 ret
= drmCommandWrite( rmesa
->r200Screen
->driScreen
->fd
,
864 &memfree
, sizeof(memfree
));
867 fprintf(stderr
, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__
, ret
);
870 /* Called via glXGetMemoryOffsetMESA() */
871 GLuint
r200GetMemoryOffsetMESA(Display
*dpy
, int scrn
, const GLvoid
*pointer
)
873 GET_CURRENT_CONTEXT(ctx
);
874 r200ContextPtr rmesa
;
877 if (!ctx
|| !(rmesa
= R200_CONTEXT(ctx
)) ) {
878 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
882 if (!r200IsGartMemory( rmesa
, pointer
, 0 ))
885 if (rmesa
->dri
.drmMinor
< 6)
888 card_offset
= r200GartOffsetFromVirtual( rmesa
, pointer
);
890 return card_offset
- rmesa
->r200Screen
->gart_base
;
894 GLboolean
r200IsGartMemory( r200ContextPtr rmesa
, const GLvoid
*pointer
,
897 int offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
898 int valid
= (size
>= 0 &&
900 offset
+ size
< rmesa
->r200Screen
->gartTextures
.size
);
902 if (R200_DEBUG
& DEBUG_IOCTL
)
903 fprintf(stderr
, "r200IsGartMemory( %p ) : %d\n", pointer
, valid
);
909 GLuint
r200GartOffsetFromVirtual( r200ContextPtr rmesa
, const GLvoid
*pointer
)
911 int offset
= (char *)pointer
- (char *)rmesa
->r200Screen
->gartTextures
.map
;
913 if (offset
< 0 || offset
> rmesa
->r200Screen
->gartTextures
.size
)
916 return rmesa
->r200Screen
->gart_texture_offset
+ offset
;
921 void r200InitIoctlFuncs( struct dd_function_table
*functions
)
923 functions
->Clear
= r200Clear
;
924 functions
->Finish
= r200Finish
;
925 functions
->Flush
= r200Flush
;