1 /**************************************************************************
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>
37 - Scissor implementation
38 - buffer swap/copy ioctls
41 - cmdbuffer management
45 #include "main/glheader.h"
46 #include "main/imports.h"
47 #include "main/context.h"
48 #include "main/api_arrayelt.h"
49 #include "main/enums.h"
50 #include "main/colormac.h"
51 #include "main/light.h"
52 #include "main/framebuffer.h"
53 #include "main/simple_list.h"
55 #include "swrast/swrast.h"
58 #include "tnl/t_pipeline.h"
59 #include "swrast_setup/swrast_setup.h"
62 #include "drirenderbuffer.h"
65 #include "radeon_common.h"
66 #include "radeon_common.h"
67 #include "radeon_bo.h"
68 #include "radeon_cs.h"
69 #include "radeon_bo_legacy.h"
70 #include "radeon_cs_legacy.h"
71 #include "radeon_bo_gem.h"
72 #include "radeon_cs_gem.h"
73 #include "radeon_drm.h"
74 #include "radeon_mipmap_tree.h"
76 #define DEBUG_CMDBUF 0
78 /* =============================================================
82 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
83 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
94 if (out
->x1
>= out
->x2
)
96 if (out
->y1
>= out
->y2
)
101 void radeonRecalcScissorRects(radeonContextPtr radeon
)
103 drm_clip_rect_t
*out
;
106 /* Grow cliprect store?
108 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
109 while (radeon
->state
.scissor
.numAllocedClipRects
<
110 radeon
->numClipRects
) {
111 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
112 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
115 if (radeon
->state
.scissor
.pClipRects
)
116 FREE(radeon
->state
.scissor
.pClipRects
);
118 radeon
->state
.scissor
.pClipRects
=
119 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
120 sizeof(drm_clip_rect_t
));
122 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
123 radeon
->state
.scissor
.numAllocedClipRects
= 0;
128 out
= radeon
->state
.scissor
.pClipRects
;
129 radeon
->state
.scissor
.numClipRects
= 0;
131 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
132 if (intersect_rect(out
,
133 &radeon
->pClipRects
[i
],
134 &radeon
->state
.scissor
.rect
)) {
135 radeon
->state
.scissor
.numClipRects
++;
142 * Update cliprects and scissors.
144 void radeonSetCliprects(radeonContextPtr radeon
)
146 __DRIdrawablePrivate
*const drawable
= radeon
->dri
.drawable
;
147 __DRIdrawablePrivate
*const readable
= radeon
->dri
.readable
;
148 GLframebuffer
*const draw_fb
= (GLframebuffer
*)drawable
->driverPrivate
;
149 GLframebuffer
*const read_fb
= (GLframebuffer
*)readable
->driverPrivate
;
151 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
152 if (draw_fb
->_ColorDrawBufferIndexes
[0] == BUFFER_BACK_LEFT
) {
153 /* Can't ignore 2d windows if we are page flipping. */
154 if (drawable
->numBackClipRects
== 0 || radeon
->doPageFlip
||
155 radeon
->sarea
->pfCurrentPage
== 1) {
156 radeon
->numClipRects
= drawable
->numClipRects
;
157 radeon
->pClipRects
= drawable
->pClipRects
;
159 radeon
->numClipRects
= drawable
->numBackClipRects
;
160 radeon
->pClipRects
= drawable
->pBackClipRects
;
163 /* front buffer (or none, or multiple buffers */
164 radeon
->numClipRects
= drawable
->numClipRects
;
165 radeon
->pClipRects
= drawable
->pClipRects
;
169 if ((draw_fb
->Width
!= drawable
->w
) ||
170 (draw_fb
->Height
!= drawable
->h
)) {
171 _mesa_resize_framebuffer(radeon
->glCtx
, draw_fb
,
172 drawable
->w
, drawable
->h
);
173 draw_fb
->Initialized
= GL_TRUE
;
176 if (drawable
!= readable
) {
177 if ((read_fb
->Width
!= readable
->w
) ||
178 (read_fb
->Height
!= readable
->h
)) {
179 _mesa_resize_framebuffer(radeon
->glCtx
, read_fb
,
180 readable
->w
, readable
->h
);
181 read_fb
->Initialized
= GL_TRUE
;
185 if (radeon
->state
.scissor
.enabled
)
186 radeonRecalcScissorRects(radeon
);
188 radeon
->lastStamp
= drawable
->lastStamp
;
191 void radeonUpdateScissor( GLcontext
*ctx
)
193 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
195 if ( rmesa
->dri
.drawable
) {
196 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
198 int x
= ctx
->Scissor
.X
;
199 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
200 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
201 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
203 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
204 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
205 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
206 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
208 radeonRecalcScissorRects( rmesa
);
212 /* =============================================================
216 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
218 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
219 if (ctx
->Scissor
.Enabled
) {
220 /* We don't pipeline cliprect changes */
221 radeon_firevertices(radeon
);
222 radeonUpdateScissor(ctx
);
227 /* ================================================================
228 * SwapBuffers with client-side throttling
231 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
233 drm_radeon_getparam_t gp
;
237 gp
.param
= RADEON_PARAM_LAST_FRAME
;
238 gp
.value
= (int *)&frame
;
239 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
242 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
250 uint32_t radeonGetAge(radeonContextPtr radeon
)
252 drm_radeon_getparam_t gp
;
256 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
257 gp
.value
= (int *)&age
;
258 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
261 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
269 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
271 drm_radeon_irq_emit_t ie
;
274 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
275 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
278 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
284 static void radeonWaitIrq(radeonContextPtr radeon
)
289 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
290 &radeon
->iw
, sizeof(radeon
->iw
));
291 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
294 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
300 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
302 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
304 if (radeon
->do_irqs
) {
305 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
306 if (!radeon
->irqsEmitted
) {
307 while (radeonGetLastFrame(radeon
) <
310 UNLOCK_HARDWARE(radeon
);
311 radeonWaitIrq(radeon
);
312 LOCK_HARDWARE(radeon
);
314 radeon
->irqsEmitted
= 10;
317 if (radeon
->irqsEmitted
) {
318 radeonEmitIrqLocked(radeon
);
319 radeon
->irqsEmitted
--;
322 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
323 UNLOCK_HARDWARE(radeon
);
324 if (radeon
->do_usleeps
)
326 LOCK_HARDWARE(radeon
);
332 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
338 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
341 } while (ret
&& ++i
< 100);
344 UNLOCK_HARDWARE(radeon
);
345 fprintf(stderr
, "Error: R300 timed out... exiting\n");
350 static void radeonWaitForIdle(radeonContextPtr radeon
)
352 LOCK_HARDWARE(radeon
);
353 radeonWaitForIdleLocked(radeon
);
354 UNLOCK_HARDWARE(radeon
);
358 /* Copy the back color buffer to the front color buffer.
360 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
361 const drm_clip_rect_t
*rect
)
363 radeonContextPtr rmesa
;
365 GLboolean missed_target
;
367 __DRIscreenPrivate
*psp
;
370 assert(dPriv
->driContextPriv
);
371 assert(dPriv
->driContextPriv
->driverPrivate
);
373 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
375 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
376 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
379 radeon_firevertices(rmesa
);
380 LOCK_HARDWARE( rmesa
);
382 /* Throttle the frame rate -- only allow one pending swap buffers
385 radeonWaitForFrameCompletion( rmesa
);
388 UNLOCK_HARDWARE( rmesa
);
389 driWaitForVBlank( dPriv
, & missed_target
);
390 LOCK_HARDWARE( rmesa
);
393 nbox
= dPriv
->numClipRects
; /* must be in locked region */
395 for ( i
= 0 ; i
< nbox
; ) {
396 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
397 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
398 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
401 for ( ; i
< nr
; i
++ ) {
407 if (rect
->x1
> b
->x1
)
409 if (rect
->y1
> b
->y1
)
411 if (rect
->x2
< b
->x2
)
413 if (rect
->y2
< b
->y2
)
416 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
423 rmesa
->sarea
->nbox
= n
;
428 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
431 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
432 UNLOCK_HARDWARE( rmesa
);
437 UNLOCK_HARDWARE( rmesa
);
440 psp
= dPriv
->driScreenPriv
;
442 (*psp
->systemTime
->getUST
)( & ust
);
443 if ( missed_target
) {
444 rmesa
->swap_missed_count
++;
445 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
448 rmesa
->swap_ust
= ust
;
449 rmesa
->hw
.all_dirty
= GL_TRUE
;
454 void radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
456 radeonContextPtr rmesa
;
458 GLboolean missed_target
;
459 __DRIscreenPrivate
*psp
;
460 struct radeon_renderbuffer
*rrb
;
461 GLframebuffer
*fb
= dPriv
->driverPrivate
;
464 assert(dPriv
->driContextPriv
);
465 assert(dPriv
->driContextPriv
->driverPrivate
);
467 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
468 rrb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
470 psp
= dPriv
->driScreenPriv
;
472 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
473 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
474 rmesa
->sarea
->pfCurrentPage
);
477 radeon_firevertices(rmesa
);
479 LOCK_HARDWARE( rmesa
);
481 if (!dPriv
->numClipRects
) {
482 UNLOCK_HARDWARE(rmesa
);
483 usleep(10000); /* throttle invisible client 10ms */
487 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
488 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
490 rmesa
->sarea
->nbox
= 1;
492 /* Throttle the frame rate -- only allow a few pending swap buffers
495 radeonWaitForFrameCompletion( rmesa
);
496 UNLOCK_HARDWARE( rmesa
);
497 driWaitForVBlank( dPriv
, & missed_target
);
498 if ( missed_target
) {
499 rmesa
->swap_missed_count
++;
500 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_missed_ust
);
502 LOCK_HARDWARE( rmesa
);
504 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
506 UNLOCK_HARDWARE( rmesa
);
509 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
514 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_ust
);
516 /* Get ready for drawing next frame. Update the renderbuffers'
517 * flippedOffset/Pitch fields so we draw into the right place.
519 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
520 rmesa
->sarea
->pfCurrentPage
);
522 rmesa
->state
.color
.rrb
= rrb
;
524 if (rmesa
->vtbl
.update_draw_buffer
)
525 rmesa
->vtbl
.update_draw_buffer(rmesa
->glCtx
);
530 * Swap front and back buffer.
532 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
534 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
535 radeonContextPtr radeon
;
538 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
541 if (ctx
->Visual
.doubleBufferMode
) {
542 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
543 if (radeon
->doPageFlip
) {
544 radeonPageFlip(dPriv
);
546 radeonCopyBuffer(dPriv
, NULL
);
550 /* XXX this shouldn't be an error but we can't handle it for now */
551 _mesa_problem(NULL
, "%s: drawable has no context!",
556 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
557 int x
, int y
, int w
, int h
)
559 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
560 radeonContextPtr radeon
;
563 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
566 if (ctx
->Visual
.doubleBufferMode
) {
567 drm_clip_rect_t rect
;
568 rect
.x1
= x
+ dPriv
->x
;
569 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
570 rect
.x2
= rect
.x1
+ w
;
571 rect
.y2
= rect
.y1
+ h
;
572 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
573 radeonCopyBuffer(dPriv
, &rect
);
576 /* XXX this shouldn't be an error but we can't handle it for now */
577 _mesa_problem(NULL
, "%s: drawable has no context!",
583 static void radeon_print_state_atom( struct radeon_state_atom
*state
)
587 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
589 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
590 for (i
= 0 ; i
< state
->cmd_size
; i
++)
591 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
595 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean dirty
)
597 BATCH_LOCALS(radeon
);
598 struct radeon_state_atom
*atom
;
601 if (radeon
->vtbl
.pre_emit_atoms
)
602 radeon
->vtbl
.pre_emit_atoms(radeon
);
604 /* Emit actual atoms */
605 foreach(atom
, &radeon
->hw
.atomlist
) {
606 if ((atom
->dirty
|| radeon
->hw
.all_dirty
) == dirty
) {
607 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
609 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
610 radeon_print_state_atom(atom
);
613 (*atom
->emit
)(radeon
->glCtx
, atom
);
615 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
616 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
619 atom
->dirty
= GL_FALSE
;
621 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
622 fprintf(stderr
, " skip state %s\n",
632 void radeonEmitState(radeonContextPtr radeon
)
634 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
635 fprintf(stderr
, "%s\n", __FUNCTION__
);
637 if (radeon
->vtbl
.pre_emit_state
)
638 radeon
->vtbl
.pre_emit_state(radeon
);
640 /* this code used to return here but now it emits zbs */
641 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
644 /* To avoid going across the entire set of states multiple times, just check
645 * for enough space for the case of emitting all state, and inline the
646 * radeonAllocCmdBuf code here without all the checks.
648 rcommonEnsureCmdBufSpace(radeon
, radeon
->hw
.max_state_size
, __FUNCTION__
);
650 if (!radeon
->cmdbuf
.cs
->cdw
) {
651 if (RADEON_DEBUG
& DEBUG_STATE
)
652 fprintf(stderr
, "Begin reemit state\n");
654 radeonEmitAtoms(radeon
, GL_FALSE
);
657 if (RADEON_DEBUG
& DEBUG_STATE
)
658 fprintf(stderr
, "Begin dirty state\n");
660 radeonEmitAtoms(radeon
, GL_TRUE
);
661 radeon
->hw
.is_dirty
= GL_FALSE
;
662 radeon
->hw
.all_dirty
= GL_FALSE
;
667 void radeonFlush(GLcontext
*ctx
)
669 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
670 if (RADEON_DEBUG
& DEBUG_IOCTL
)
671 fprintf(stderr
, "%s\n", __FUNCTION__
);
673 if (radeon
->dma
.flush
)
674 radeon
->dma
.flush( ctx
);
676 radeonEmitState(radeon
);
678 if (radeon
->cmdbuf
.cs
->cdw
)
679 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
682 /* Make sure all commands have been sent to the hardware and have
683 * completed processing.
685 void radeonFinish(GLcontext
* ctx
)
687 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
688 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
693 if (radeon
->radeonScreen
->kernel_mm
) {
694 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
695 struct radeon_renderbuffer
*rrb
;
696 rrb
= (struct radeon_renderbuffer
*)fb
->_ColorDrawBuffers
[i
];
698 radeon_bo_wait(rrb
->bo
);
700 } else if (radeon
->do_irqs
) {
701 LOCK_HARDWARE(radeon
);
702 radeonEmitIrqLocked(radeon
);
703 UNLOCK_HARDWARE(radeon
);
704 radeonWaitIrq(radeon
);
706 radeonWaitForIdle(radeon
);
712 * Send the current command buffer via ioctl to the hardware.
714 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
718 if (rmesa
->cmdbuf
.flushing
) {
719 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
722 rmesa
->cmdbuf
.flushing
= 1;
723 if (rmesa
->cmdbuf
.cs
->cdw
) {
724 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
725 rmesa
->hw
.all_dirty
= GL_TRUE
;
727 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
728 rmesa
->cmdbuf
.flushing
= 0;
732 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
736 radeonReleaseDmaRegion(rmesa
);
738 LOCK_HARDWARE(rmesa
);
739 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
740 UNLOCK_HARDWARE(rmesa
);
743 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
751 * Make sure that enough space is available in the command buffer
752 * by flushing if necessary.
754 * \param dwords The number of dwords we need to be free on the command buffer
756 void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
758 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
||
759 radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
760 rcommonFlushCmdBuf(rmesa
, caller
);
764 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
767 /* Initialize command buffer */
768 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
769 "command_buffer_size");
770 if (size
< 2 * rmesa
->hw
.max_state_size
) {
771 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
776 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
777 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
778 sizeof(drm_r300_cmd_header_t
));
779 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
780 sizeof(drm_radeon_cmd_buffer_t
));
782 "Allocating %d bytes command buffer (max state is %d bytes)\n",
783 size
* 4, rmesa
->hw
.max_state_size
* 4);
786 if (rmesa
->radeonScreen
->kernel_mm
) {
787 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
788 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
790 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
792 if (rmesa
->cmdbuf
.csm
== NULL
) {
793 /* FIXME: fatal error */
796 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
797 assert(rmesa
->cmdbuf
.cs
!= NULL
);
798 rmesa
->cmdbuf
.size
= size
;
800 if (!rmesa
->radeonScreen
->kernel_mm
) {
801 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
802 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
804 struct drm_radeon_gem_info mminfo
;
806 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
808 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_size
);
809 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
815 * Destroy the command buffer
817 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
819 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
820 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
821 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
823 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
827 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
830 const char *function
,
833 rcommonEnsureCmdBufSpace(rmesa
, n
, function
);
834 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
835 if (RADEON_DEBUG
& DEBUG_IOCTL
)
836 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
837 radeonEmitState(rmesa
);
839 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);