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"
64 #include "radeon_common.h"
65 #include "radeon_bocs_wrapper.h"
66 #include "radeon_lock.h"
67 #include "radeon_drm.h"
68 #include "radeon_mipmap_tree.h"
70 #define DEBUG_CMDBUF 0
72 /* =============================================================
76 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
77 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
88 if (out
->x1
>= out
->x2
)
90 if (out
->y1
>= out
->y2
)
95 void radeonRecalcScissorRects(radeonContextPtr radeon
)
100 /* Grow cliprect store?
102 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
103 while (radeon
->state
.scissor
.numAllocedClipRects
<
104 radeon
->numClipRects
) {
105 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
106 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
109 if (radeon
->state
.scissor
.pClipRects
)
110 FREE(radeon
->state
.scissor
.pClipRects
);
112 radeon
->state
.scissor
.pClipRects
=
113 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
114 sizeof(drm_clip_rect_t
));
116 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
117 radeon
->state
.scissor
.numAllocedClipRects
= 0;
122 out
= radeon
->state
.scissor
.pClipRects
;
123 radeon
->state
.scissor
.numClipRects
= 0;
125 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
126 if (intersect_rect(out
,
127 &radeon
->pClipRects
[i
],
128 &radeon
->state
.scissor
.rect
)) {
129 radeon
->state
.scissor
.numClipRects
++;
136 * Update cliprects and scissors.
138 void radeonSetCliprects(radeonContextPtr radeon
)
140 __DRIdrawablePrivate
*const drawable
= radeon
->dri
.drawable
;
141 __DRIdrawablePrivate
*const readable
= radeon
->dri
.readable
;
142 GLframebuffer
*const draw_fb
= (GLframebuffer
*)drawable
->driverPrivate
;
143 GLframebuffer
*const read_fb
= (GLframebuffer
*)readable
->driverPrivate
;
145 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
146 if (draw_fb
->_ColorDrawBufferIndexes
[0] == BUFFER_BACK_LEFT
) {
147 /* Can't ignore 2d windows if we are page flipping. */
148 if (drawable
->numBackClipRects
== 0 || radeon
->doPageFlip
||
149 radeon
->sarea
->pfCurrentPage
== 1) {
150 radeon
->numClipRects
= drawable
->numClipRects
;
151 radeon
->pClipRects
= drawable
->pClipRects
;
153 radeon
->numClipRects
= drawable
->numBackClipRects
;
154 radeon
->pClipRects
= drawable
->pBackClipRects
;
157 /* front buffer (or none, or multiple buffers */
158 radeon
->numClipRects
= drawable
->numClipRects
;
159 radeon
->pClipRects
= drawable
->pClipRects
;
163 if ((draw_fb
->Width
!= drawable
->w
) ||
164 (draw_fb
->Height
!= drawable
->h
)) {
165 _mesa_resize_framebuffer(radeon
->glCtx
, draw_fb
,
166 drawable
->w
, drawable
->h
);
167 draw_fb
->Initialized
= GL_TRUE
;
170 if (drawable
!= readable
) {
171 if ((read_fb
->Width
!= readable
->w
) ||
172 (read_fb
->Height
!= readable
->h
)) {
173 _mesa_resize_framebuffer(radeon
->glCtx
, read_fb
,
174 readable
->w
, readable
->h
);
175 read_fb
->Initialized
= GL_TRUE
;
179 if (radeon
->state
.scissor
.enabled
)
180 radeonRecalcScissorRects(radeon
);
182 radeon
->lastStamp
= drawable
->lastStamp
;
185 void radeonUpdateScissor( GLcontext
*ctx
)
187 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
189 if ( rmesa
->dri
.drawable
) {
190 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
192 int x
= ctx
->Scissor
.X
;
193 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
194 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
195 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
197 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
198 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
199 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
200 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
202 radeonRecalcScissorRects( rmesa
);
206 /* =============================================================
210 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
212 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
213 if (ctx
->Scissor
.Enabled
) {
214 /* We don't pipeline cliprect changes */
215 radeon_firevertices(radeon
);
216 radeonUpdateScissor(ctx
);
221 /* ================================================================
222 * SwapBuffers with client-side throttling
225 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
227 drm_radeon_getparam_t gp
;
231 gp
.param
= RADEON_PARAM_LAST_FRAME
;
232 gp
.value
= (int *)&frame
;
233 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
236 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
244 uint32_t radeonGetAge(radeonContextPtr radeon
)
246 drm_radeon_getparam_t gp
;
250 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
251 gp
.value
= (int *)&age
;
252 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
255 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
263 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
265 drm_radeon_irq_emit_t ie
;
268 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
269 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
272 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
278 static void radeonWaitIrq(radeonContextPtr radeon
)
283 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
284 &radeon
->iw
, sizeof(radeon
->iw
));
285 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
288 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
294 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
296 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
298 if (radeon
->do_irqs
) {
299 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
300 if (!radeon
->irqsEmitted
) {
301 while (radeonGetLastFrame(radeon
) <
304 UNLOCK_HARDWARE(radeon
);
305 radeonWaitIrq(radeon
);
306 LOCK_HARDWARE(radeon
);
308 radeon
->irqsEmitted
= 10;
311 if (radeon
->irqsEmitted
) {
312 radeonEmitIrqLocked(radeon
);
313 radeon
->irqsEmitted
--;
316 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
317 UNLOCK_HARDWARE(radeon
);
318 if (radeon
->do_usleeps
)
320 LOCK_HARDWARE(radeon
);
326 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
332 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
335 } while (ret
&& ++i
< 100);
338 UNLOCK_HARDWARE(radeon
);
339 fprintf(stderr
, "Error: R300 timed out... exiting\n");
344 static void radeonWaitForIdle(radeonContextPtr radeon
)
346 LOCK_HARDWARE(radeon
);
347 radeonWaitForIdleLocked(radeon
);
348 UNLOCK_HARDWARE(radeon
);
352 /* Copy the back color buffer to the front color buffer.
354 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
355 const drm_clip_rect_t
*rect
)
357 radeonContextPtr rmesa
;
359 GLboolean missed_target
;
361 __DRIscreenPrivate
*psp
;
364 assert(dPriv
->driContextPriv
);
365 assert(dPriv
->driContextPriv
->driverPrivate
);
367 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
369 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
370 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
373 radeon_firevertices(rmesa
);
374 LOCK_HARDWARE( rmesa
);
376 /* Throttle the frame rate -- only allow one pending swap buffers
379 radeonWaitForFrameCompletion( rmesa
);
382 UNLOCK_HARDWARE( rmesa
);
383 driWaitForVBlank( dPriv
, & missed_target
);
384 LOCK_HARDWARE( rmesa
);
387 nbox
= dPriv
->numClipRects
; /* must be in locked region */
389 for ( i
= 0 ; i
< nbox
; ) {
390 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
391 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
392 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
395 for ( ; i
< nr
; i
++ ) {
401 if (rect
->x1
> b
->x1
)
403 if (rect
->y1
> b
->y1
)
405 if (rect
->x2
< b
->x2
)
407 if (rect
->y2
< b
->y2
)
410 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
417 rmesa
->sarea
->nbox
= n
;
422 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
425 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
426 UNLOCK_HARDWARE( rmesa
);
431 UNLOCK_HARDWARE( rmesa
);
434 psp
= dPriv
->driScreenPriv
;
436 (*psp
->systemTime
->getUST
)( & ust
);
437 if ( missed_target
) {
438 rmesa
->swap_missed_count
++;
439 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
442 rmesa
->swap_ust
= ust
;
443 rmesa
->hw
.all_dirty
= GL_TRUE
;
448 void radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
450 radeonContextPtr rmesa
;
452 GLboolean missed_target
;
453 __DRIscreenPrivate
*psp
;
454 struct radeon_renderbuffer
*rrb
;
455 GLframebuffer
*fb
= dPriv
->driverPrivate
;
458 assert(dPriv
->driContextPriv
);
459 assert(dPriv
->driContextPriv
->driverPrivate
);
461 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
462 rrb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
464 psp
= dPriv
->driScreenPriv
;
466 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
467 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
468 rmesa
->sarea
->pfCurrentPage
);
471 radeon_firevertices(rmesa
);
473 LOCK_HARDWARE( rmesa
);
475 if (!dPriv
->numClipRects
) {
476 UNLOCK_HARDWARE(rmesa
);
477 usleep(10000); /* throttle invisible client 10ms */
481 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
482 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
484 rmesa
->sarea
->nbox
= 1;
486 /* Throttle the frame rate -- only allow a few pending swap buffers
489 radeonWaitForFrameCompletion( rmesa
);
490 UNLOCK_HARDWARE( rmesa
);
491 driWaitForVBlank( dPriv
, & missed_target
);
492 if ( missed_target
) {
493 rmesa
->swap_missed_count
++;
494 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_missed_ust
);
496 LOCK_HARDWARE( rmesa
);
498 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
500 UNLOCK_HARDWARE( rmesa
);
503 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
508 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_ust
);
510 /* Get ready for drawing next frame. Update the renderbuffers'
511 * flippedOffset/Pitch fields so we draw into the right place.
513 // driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
514 // rmesa->sarea->pfCurrentPage);
516 rmesa
->state
.color
.rrb
= rrb
;
518 if (rmesa
->vtbl
.update_draw_buffer
)
519 rmesa
->vtbl
.update_draw_buffer(rmesa
->glCtx
);
524 * Swap front and back buffer.
526 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
528 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
529 radeonContextPtr radeon
;
532 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
535 if (ctx
->Visual
.doubleBufferMode
) {
536 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
537 if (radeon
->doPageFlip
) {
538 radeonPageFlip(dPriv
);
540 radeonCopyBuffer(dPriv
, NULL
);
544 /* XXX this shouldn't be an error but we can't handle it for now */
545 _mesa_problem(NULL
, "%s: drawable has no context!",
550 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
551 int x
, int y
, int w
, int h
)
553 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
554 radeonContextPtr radeon
;
557 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
560 if (ctx
->Visual
.doubleBufferMode
) {
561 drm_clip_rect_t rect
;
562 rect
.x1
= x
+ dPriv
->x
;
563 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
564 rect
.x2
= rect
.x1
+ w
;
565 rect
.y2
= rect
.y1
+ h
;
566 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
567 radeonCopyBuffer(dPriv
, &rect
);
570 /* XXX this shouldn't be an error but we can't handle it for now */
571 _mesa_problem(NULL
, "%s: drawable has no context!",
577 static void radeon_print_state_atom( struct radeon_state_atom
*state
)
581 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
583 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
584 for (i
= 0 ; i
< state
->cmd_size
; i
++)
585 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
589 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean dirty
)
591 BATCH_LOCALS(radeon
);
592 struct radeon_state_atom
*atom
;
595 if (radeon
->vtbl
.pre_emit_atoms
)
596 radeon
->vtbl
.pre_emit_atoms(radeon
);
598 /* Emit actual atoms */
599 foreach(atom
, &radeon
->hw
.atomlist
) {
600 if ((atom
->dirty
|| radeon
->hw
.all_dirty
) == dirty
) {
601 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
603 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
604 radeon_print_state_atom(atom
);
607 (*atom
->emit
)(radeon
->glCtx
, atom
);
609 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
610 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
613 atom
->dirty
= GL_FALSE
;
615 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
616 fprintf(stderr
, " skip state %s\n",
626 void radeonEmitState(radeonContextPtr radeon
)
628 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
629 fprintf(stderr
, "%s\n", __FUNCTION__
);
631 if (radeon
->vtbl
.pre_emit_state
)
632 radeon
->vtbl
.pre_emit_state(radeon
);
634 /* this code used to return here but now it emits zbs */
635 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
638 /* To avoid going across the entire set of states multiple times, just check
639 * for enough space for the case of emitting all state, and inline the
640 * radeonAllocCmdBuf code here without all the checks.
642 rcommonEnsureCmdBufSpace(radeon
, radeon
->hw
.max_state_size
, __FUNCTION__
);
644 if (!radeon
->cmdbuf
.cs
->cdw
) {
645 if (RADEON_DEBUG
& DEBUG_STATE
)
646 fprintf(stderr
, "Begin reemit state\n");
648 radeonEmitAtoms(radeon
, GL_FALSE
);
651 if (RADEON_DEBUG
& DEBUG_STATE
)
652 fprintf(stderr
, "Begin dirty state\n");
654 radeonEmitAtoms(radeon
, GL_TRUE
);
655 radeon
->hw
.is_dirty
= GL_FALSE
;
656 radeon
->hw
.all_dirty
= GL_FALSE
;
661 void radeonFlush(GLcontext
*ctx
)
663 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
664 if (RADEON_DEBUG
& DEBUG_IOCTL
)
665 fprintf(stderr
, "%s\n", __FUNCTION__
);
667 if (radeon
->dma
.flush
)
668 radeon
->dma
.flush( ctx
);
670 radeonEmitState(radeon
);
672 if (radeon
->cmdbuf
.cs
->cdw
)
673 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
676 /* Make sure all commands have been sent to the hardware and have
677 * completed processing.
679 void radeonFinish(GLcontext
* ctx
)
681 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
682 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
687 if (radeon
->radeonScreen
->kernel_mm
) {
688 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
689 struct radeon_renderbuffer
*rrb
;
690 rrb
= (struct radeon_renderbuffer
*)fb
->_ColorDrawBuffers
[i
];
692 radeon_bo_wait(rrb
->bo
);
694 } else if (radeon
->do_irqs
) {
695 LOCK_HARDWARE(radeon
);
696 radeonEmitIrqLocked(radeon
);
697 UNLOCK_HARDWARE(radeon
);
698 radeonWaitIrq(radeon
);
700 radeonWaitForIdle(radeon
);
706 * Send the current command buffer via ioctl to the hardware.
708 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
712 if (rmesa
->cmdbuf
.flushing
) {
713 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
716 rmesa
->cmdbuf
.flushing
= 1;
717 if (rmesa
->cmdbuf
.cs
->cdw
) {
718 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
719 rmesa
->hw
.all_dirty
= GL_TRUE
;
721 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
722 rmesa
->cmdbuf
.flushing
= 0;
726 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
730 radeonReleaseDmaRegion(rmesa
);
732 LOCK_HARDWARE(rmesa
);
733 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
734 UNLOCK_HARDWARE(rmesa
);
737 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
745 * Make sure that enough space is available in the command buffer
746 * by flushing if necessary.
748 * \param dwords The number of dwords we need to be free on the command buffer
750 void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
752 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
||
753 radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
754 rcommonFlushCmdBuf(rmesa
, caller
);
758 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
761 /* Initialize command buffer */
762 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
763 "command_buffer_size");
764 if (size
< 2 * rmesa
->hw
.max_state_size
) {
765 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
770 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
771 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
772 sizeof(drm_r300_cmd_header_t
));
773 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
774 sizeof(drm_radeon_cmd_buffer_t
));
776 "Allocating %d bytes command buffer (max state is %d bytes)\n",
777 size
* 4, rmesa
->hw
.max_state_size
* 4);
780 if (rmesa
->radeonScreen
->kernel_mm
) {
781 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
782 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
784 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
786 if (rmesa
->cmdbuf
.csm
== NULL
) {
787 /* FIXME: fatal error */
790 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
791 assert(rmesa
->cmdbuf
.cs
!= NULL
);
792 rmesa
->cmdbuf
.size
= size
;
794 if (!rmesa
->radeonScreen
->kernel_mm
) {
795 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
796 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
798 struct drm_radeon_gem_info mminfo
;
800 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
802 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_size
);
803 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
809 * Destroy the command buffer
811 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
813 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
814 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
815 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
817 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
821 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
824 const char *function
,
827 rcommonEnsureCmdBufSpace(rmesa
, n
, function
);
828 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
829 if (RADEON_DEBUG
& DEBUG_IOCTL
)
830 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
831 radeonEmitState(rmesa
);
833 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);