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/enums.h"
49 #include "main/framebuffer.h"
50 #include "main/renderbuffer.h"
51 #include "drivers/common/meta.h"
55 #include "radeon_common.h"
56 #include "radeon_bocs_wrapper.h"
57 #include "radeon_lock.h"
58 #include "radeon_drm.h"
59 #include "radeon_queryobj.h"
62 * Enable verbose debug output for emit code.
65 * 2 also print state alues
67 #define RADEON_CMDBUF 0
69 /* =============================================================
73 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
74 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
85 if (out
->x1
>= out
->x2
)
87 if (out
->y1
>= out
->y2
)
92 void radeonRecalcScissorRects(radeonContextPtr radeon
)
97 /* Grow cliprect store?
99 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
100 while (radeon
->state
.scissor
.numAllocedClipRects
<
101 radeon
->numClipRects
) {
102 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
103 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
106 if (radeon
->state
.scissor
.pClipRects
)
107 FREE(radeon
->state
.scissor
.pClipRects
);
109 radeon
->state
.scissor
.pClipRects
=
110 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
111 sizeof(drm_clip_rect_t
));
113 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
114 radeon
->state
.scissor
.numAllocedClipRects
= 0;
119 out
= radeon
->state
.scissor
.pClipRects
;
120 radeon
->state
.scissor
.numClipRects
= 0;
122 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
123 if (intersect_rect(out
,
124 &radeon
->pClipRects
[i
],
125 &radeon
->state
.scissor
.rect
)) {
126 radeon
->state
.scissor
.numClipRects
++;
131 if (radeon
->vtbl
.update_scissor
)
132 radeon
->vtbl
.update_scissor(radeon
->glCtx
);
135 void radeon_get_cliprects(radeonContextPtr radeon
,
136 struct drm_clip_rect
**cliprects
,
137 unsigned int *num_cliprects
,
138 int *x_off
, int *y_off
)
140 __DRIdrawable
*dPriv
= radeon_get_drawable(radeon
);
141 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
143 if (radeon
->constant_cliprect
) {
144 radeon
->fboRect
.x1
= 0;
145 radeon
->fboRect
.y1
= 0;
146 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
147 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
149 *cliprects
= &radeon
->fboRect
;
153 } else if (radeon
->front_cliprects
||
154 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
155 *cliprects
= dPriv
->pClipRects
;
156 *num_cliprects
= dPriv
->numClipRects
;
160 *num_cliprects
= dPriv
->numBackClipRects
;
161 *cliprects
= dPriv
->pBackClipRects
;
162 *x_off
= dPriv
->backX
;
163 *y_off
= dPriv
->backY
;
168 * Update cliprects and scissors.
170 void radeonSetCliprects(radeonContextPtr radeon
)
172 __DRIdrawable
*const drawable
= radeon_get_drawable(radeon
);
173 __DRIdrawable
*const readable
= radeon_get_readable(radeon
);
175 if(drawable
== NULL
&& readable
== NULL
)
178 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
179 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
182 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
183 &radeon
->numClipRects
, &x_off
, &y_off
);
185 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
186 (draw_rfb
->base
.Height
!= drawable
->h
)) {
187 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
188 drawable
->w
, drawable
->h
);
189 draw_rfb
->base
.Initialized
= GL_TRUE
;
192 if (drawable
!= readable
) {
193 if ((read_rfb
->base
.Width
!= readable
->w
) ||
194 (read_rfb
->base
.Height
!= readable
->h
)) {
195 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
196 readable
->w
, readable
->h
);
197 read_rfb
->base
.Initialized
= GL_TRUE
;
201 if (radeon
->state
.scissor
.enabled
)
202 radeonRecalcScissorRects(radeon
);
208 void radeonUpdateScissor( struct gl_context
*ctx
)
210 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
211 GLint x
= ctx
->Scissor
.X
, y
= ctx
->Scissor
.Y
;
212 GLsizei w
= ctx
->Scissor
.Width
, h
= ctx
->Scissor
.Height
;
214 int min_x
, min_y
, max_x
, max_y
;
216 if (!ctx
->DrawBuffer
)
219 max_x
= ctx
->DrawBuffer
->Width
- 1;
220 max_y
= ctx
->DrawBuffer
->Height
- 1;
222 if ( !ctx
->DrawBuffer
->Name
) {
224 y1
= ctx
->DrawBuffer
->Height
- (y
+ h
);
234 if (!rmesa
->radeonScreen
->kernel_mm
) {
235 /* Fix scissors for dri 1 */
236 __DRIdrawable
*dPriv
= radeon_get_drawable(rmesa
);
240 max_x
+= dPriv
->x
+ 1;
244 max_y
+= dPriv
->y
+ 1;
247 rmesa
->state
.scissor
.rect
.x1
= CLAMP(x1
, min_x
, max_x
);
248 rmesa
->state
.scissor
.rect
.y1
= CLAMP(y1
, min_y
, max_y
);
249 rmesa
->state
.scissor
.rect
.x2
= CLAMP(x2
, min_x
, max_x
);
250 rmesa
->state
.scissor
.rect
.y2
= CLAMP(y2
, min_y
, max_y
);
252 radeonRecalcScissorRects( rmesa
);
255 /* =============================================================
259 void radeonScissor(struct gl_context
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
261 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
262 if (ctx
->Scissor
.Enabled
) {
263 /* We don't pipeline cliprect changes */
264 radeon_firevertices(radeon
);
265 radeonUpdateScissor(ctx
);
269 /* ================================================================
270 * SwapBuffers with client-side throttling
273 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
275 drm_radeon_getparam_t gp
;
279 gp
.param
= RADEON_PARAM_LAST_FRAME
;
280 gp
.value
= (int *)&frame
;
281 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
284 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
292 uint32_t radeonGetAge(radeonContextPtr radeon
)
294 drm_radeon_getparam_t gp
;
298 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
299 gp
.value
= (int *)&age
;
300 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
303 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
311 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
313 drm_radeon_irq_emit_t ie
;
316 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
317 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
320 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
326 static void radeonWaitIrq(radeonContextPtr radeon
)
331 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
332 &radeon
->iw
, sizeof(radeon
->iw
));
333 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
336 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
342 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
344 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
346 if (radeon
->do_irqs
) {
347 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
348 if (!radeon
->irqsEmitted
) {
349 while (radeonGetLastFrame(radeon
) <
352 UNLOCK_HARDWARE(radeon
);
353 radeonWaitIrq(radeon
);
354 LOCK_HARDWARE(radeon
);
356 radeon
->irqsEmitted
= 10;
359 if (radeon
->irqsEmitted
) {
360 radeonEmitIrqLocked(radeon
);
361 radeon
->irqsEmitted
--;
364 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
365 UNLOCK_HARDWARE(radeon
);
366 if (radeon
->do_usleeps
)
368 LOCK_HARDWARE(radeon
);
374 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
380 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
383 } while (ret
&& ++i
< 100);
386 UNLOCK_HARDWARE(radeon
);
387 fprintf(stderr
, "Error: R300 timed out... exiting\n");
392 static void radeonWaitForIdle(radeonContextPtr radeon
)
394 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
395 LOCK_HARDWARE(radeon
);
396 radeonWaitForIdleLocked(radeon
);
397 UNLOCK_HARDWARE(radeon
);
401 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
403 int current_page
= rfb
->pf_current_page
;
404 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
405 struct gl_renderbuffer
*tmp_rb
;
407 /* Exchange renderbuffers if necessary but make sure their
408 * reference counts are preserved.
410 if (rfb
->color_rb
[current_page
] &&
411 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
412 &rfb
->color_rb
[current_page
]->base
) {
414 _mesa_reference_renderbuffer(&tmp_rb
,
415 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
416 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
417 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
418 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
421 if (rfb
->color_rb
[next_page
] &&
422 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
423 &rfb
->color_rb
[next_page
]->base
) {
425 _mesa_reference_renderbuffer(&tmp_rb
,
426 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
427 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
428 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
429 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
433 /* Copy the back color buffer to the front color buffer.
435 void radeonCopyBuffer( __DRIdrawable
*dPriv
,
436 const drm_clip_rect_t
*rect
)
438 radeonContextPtr rmesa
;
442 assert(dPriv
->driContextPriv
);
443 assert(dPriv
->driContextPriv
->driverPrivate
);
445 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
447 LOCK_HARDWARE(rmesa
);
449 if ( RADEON_DEBUG
& RADEON_IOCTL
) {
450 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
453 nbox
= dPriv
->numClipRects
; /* must be in locked region */
455 for ( i
= 0 ; i
< nbox
; ) {
456 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
457 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
458 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
461 for ( ; i
< nr
; i
++ ) {
467 if (rect
->x1
> b
->x1
)
469 if (rect
->y1
> b
->y1
)
471 if (rect
->x2
< b
->x2
)
473 if (rect
->y2
< b
->y2
)
476 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
483 rmesa
->sarea
->nbox
= n
;
488 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
491 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
492 UNLOCK_HARDWARE( rmesa
);
497 UNLOCK_HARDWARE( rmesa
);
500 static int radeonScheduleSwap(__DRIdrawable
*dPriv
, GLboolean
*missed_target
)
502 radeonContextPtr rmesa
;
504 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
505 radeon_firevertices(rmesa
);
507 LOCK_HARDWARE( rmesa
);
509 if (!dPriv
->numClipRects
) {
510 UNLOCK_HARDWARE(rmesa
);
511 usleep(10000); /* throttle invisible client 10ms */
515 radeonWaitForFrameCompletion(rmesa
);
517 UNLOCK_HARDWARE(rmesa
);
518 driWaitForVBlank(dPriv
, missed_target
);
523 static GLboolean
radeonPageFlip( __DRIdrawable
*dPriv
)
525 radeonContextPtr radeon
;
527 struct radeon_framebuffer
*rfb
;
530 assert(dPriv
->driContextPriv
);
531 assert(dPriv
->driContextPriv
->driverPrivate
);
533 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
534 rfb
= dPriv
->driverPrivate
;
536 LOCK_HARDWARE(radeon
);
538 if ( RADEON_DEBUG
& RADEON_IOCTL
) {
539 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
540 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
542 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
543 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
545 radeon
->sarea
->nbox
= 1;
547 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
549 UNLOCK_HARDWARE(radeon
);
552 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
559 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
560 radeon_flip_renderbuffers(rfb
);
561 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
568 * Swap front and back buffer.
570 void radeonSwapBuffers(__DRIdrawable
* dPriv
)
575 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
576 radeonContextPtr radeon
;
577 struct gl_context
*ctx
;
579 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
582 if (ctx
->Visual
.doubleBufferMode
) {
583 GLboolean missed_target
;
584 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
585 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
587 radeonScheduleSwap(dPriv
, &missed_target
);
589 if (rfb
->pf_active
) {
590 radeonPageFlip(dPriv
);
592 radeonCopyBuffer(dPriv
, NULL
);
595 psp
= dPriv
->driScreenPriv
;
598 (*psp
->systemTime
->getUST
)( & ust
);
599 if ( missed_target
) {
600 rfb
->swap_missed_count
++;
601 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
605 radeon
->hw
.all_dirty
= GL_TRUE
;
608 /* XXX this shouldn't be an error but we can't handle it for now */
609 _mesa_problem(NULL
, "%s: drawable has no context!",
614 void radeonCopySubBuffer(__DRIdrawable
* dPriv
,
615 int x
, int y
, int w
, int h
)
617 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
618 radeonContextPtr radeon
;
619 struct gl_context
*ctx
;
621 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
624 if (ctx
->Visual
.doubleBufferMode
) {
625 drm_clip_rect_t rect
;
626 rect
.x1
= x
+ dPriv
->x
;
627 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
628 rect
.x2
= rect
.x1
+ w
;
629 rect
.y2
= rect
.y1
+ h
;
630 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
631 radeonCopyBuffer(dPriv
, &rect
);
634 /* XXX this shouldn't be an error but we can't handle it for now */
635 _mesa_problem(NULL
, "%s: drawable has no context!",
641 * Check if we're about to draw into the front color buffer.
642 * If so, set the intel->front_buffer_dirty field to true.
645 radeon_check_front_buffer_rendering(struct gl_context
*ctx
)
647 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
648 const struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
651 /* drawing to window system buffer */
652 if (fb
->_NumColorDrawBuffers
> 0) {
653 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
654 radeon
->front_buffer_dirty
= GL_TRUE
;
661 void radeon_draw_buffer(struct gl_context
*ctx
, struct gl_framebuffer
*fb
)
663 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
664 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
670 /* this can happen during the initial context initialization */
674 /* radeons only handle 1 color draw so far */
675 if (fb
->_NumColorDrawBuffers
!= 1) {
676 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
680 /* Do this here, note core Mesa, since this function is called from
681 * many places within the driver.
683 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
684 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
685 _mesa_update_framebuffer(ctx
);
686 /* this updates the DrawBuffer's Width/Height if it's a FBO */
687 _mesa_update_draw_buffer_bounds(ctx
);
690 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
691 /* this may occur when we're called by glBindFrameBuffer() during
692 * the process of someone setting up renderbuffers, etc.
694 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
699 ;/* do something depthy/stencily TODO */
704 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
705 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
706 radeon
->front_cliprects
= GL_TRUE
;
708 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
709 radeon
->front_cliprects
= GL_FALSE
;
712 /* user FBO in theory */
713 struct radeon_renderbuffer
*rrb
;
714 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
716 offset
= rrb
->draw_offset
;
719 radeon
->constant_cliprect
= GL_TRUE
;
722 if (rrbColor
== NULL
)
723 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
725 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
728 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
729 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
730 if (rrbDepth
&& rrbDepth
->bo
) {
731 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
733 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
736 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
740 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
741 rrbStencil
= radeon_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
742 if (rrbStencil
&& rrbStencil
->bo
) {
743 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
744 /* need to re-compute stencil hw state */
746 rrbDepth
= rrbStencil
;
748 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
751 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
752 if (ctx
->Driver
.Enable
!= NULL
)
753 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
755 ctx
->NewState
|= _NEW_STENCIL
;
758 /* Update culling direction which changes depending on the
759 * orientation of the buffer:
761 if (ctx
->Driver
.FrontFace
)
762 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
764 ctx
->NewState
|= _NEW_POLYGON
;
767 * Update depth test state
769 if (ctx
->Driver
.Enable
) {
770 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
771 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
772 /* Need to update the derived ctx->Stencil._Enabled first */
773 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
774 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
776 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
779 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
780 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
781 radeon
->state
.color
.draw_offset
= offset
;
784 /* update viewport since it depends on window size */
785 if (ctx
->Driver
.Viewport
) {
786 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
787 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
792 ctx
->NewState
|= _NEW_VIEWPORT
;
794 /* Set state we know depends on drawable parameters:
796 radeonUpdateScissor(ctx
);
797 radeon
->NewGLState
|= _NEW_SCISSOR
;
799 if (ctx
->Driver
.DepthRange
)
800 ctx
->Driver
.DepthRange(ctx
,
804 /* Update culling direction which changes depending on the
805 * orientation of the buffer:
807 if (ctx
->Driver
.FrontFace
)
808 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
810 ctx
->NewState
|= _NEW_POLYGON
;
814 * Called via glDrawBuffer.
816 void radeonDrawBuffer( struct gl_context
*ctx
, GLenum mode
)
818 if (RADEON_DEBUG
& RADEON_DRI
)
819 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
820 _mesa_lookup_enum_by_nr( mode
));
822 if (ctx
->DrawBuffer
->Name
== 0) {
823 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
825 const GLboolean was_front_buffer_rendering
=
826 radeon
->is_front_buffer_rendering
;
828 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
831 /* If we weren't front-buffer rendering before but we are now, make sure
832 * that the front-buffer has actually been allocated.
834 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
835 radeon_update_renderbuffers(radeon
->dri
.context
,
836 radeon
->dri
.context
->driDrawablePriv
, GL_FALSE
);
840 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
843 void radeonReadBuffer( struct gl_context
*ctx
, GLenum mode
)
845 if ((ctx
->DrawBuffer
!= NULL
) && (ctx
->DrawBuffer
->Name
== 0)) {
846 struct radeon_context
*const rmesa
= RADEON_CONTEXT(ctx
);
847 const GLboolean was_front_buffer_reading
= rmesa
->is_front_buffer_reading
;
848 rmesa
->is_front_buffer_reading
= (mode
== GL_FRONT_LEFT
)
849 || (mode
== GL_FRONT
);
851 if (!was_front_buffer_reading
&& rmesa
->is_front_buffer_reading
) {
852 radeon_update_renderbuffers(rmesa
->dri
.context
,
853 rmesa
->dri
.context
->driReadablePriv
, GL_FALSE
);
856 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
857 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
858 /* This will update FBO completeness status.
859 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
860 * refers to a missing renderbuffer. Calling glReadBuffer can set
861 * that straight and can make the drawing buffer complete.
863 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
868 /* Turn on/off page flipping according to the flags in the sarea:
870 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
872 struct radeon_framebuffer
*rfb
= radeon_get_drawable(radeon
)->driverPrivate
;
874 rfb
->pf_active
= radeon
->sarea
->pfState
;
875 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
876 rfb
->pf_num_pages
= 2;
877 radeon_flip_renderbuffers(rfb
);
878 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
881 void radeon_window_moved(radeonContextPtr radeon
)
883 /* Cliprects has to be updated before doing anything else */
884 radeonSetCliprects(radeon
);
885 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
886 radeonUpdatePageFlipping(radeon
);
890 void radeon_viewport(struct gl_context
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
892 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
893 __DRIcontext
*driContext
= radeon
->dri
.context
;
894 void (*old_viewport
)(struct gl_context
*ctx
, GLint x
, GLint y
,
895 GLsizei w
, GLsizei h
);
897 if (!driContext
->driScreenPriv
->dri2
.enabled
)
900 if (ctx
->DrawBuffer
->Name
== 0) {
901 if (radeon
->is_front_buffer_rendering
) {
902 ctx
->Driver
.Flush(ctx
);
904 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
, GL_FALSE
);
905 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
906 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
, GL_FALSE
);
909 old_viewport
= ctx
->Driver
.Viewport
;
910 ctx
->Driver
.Viewport
= NULL
;
911 radeon_window_moved(radeon
);
912 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
913 ctx
->Driver
.Viewport
= old_viewport
;
916 static void radeon_print_state_atom_prekmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
919 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
920 drm_r300_cmd_header_t cmd
;
922 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
924 if (radeon_is_debug_enabled(RADEON_STATE
, RADEON_TRACE
)) {
925 if (dwords
> state
->cmd_size
)
926 dwords
= state
->cmd_size
;
928 for (i
= 0; i
< dwords
;) {
929 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
930 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
931 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
932 state
->name
, i
, reg
, cmd
.packet0
.count
);
934 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
935 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
936 state
->name
, i
, reg
, state
->cmd
[i
]);
944 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
946 int i
, j
, reg
, count
;
949 if (!radeon_is_debug_enabled(RADEON_STATE
, RADEON_VERBOSE
) )
952 if (!radeon
->radeonScreen
->kernel_mm
) {
953 radeon_print_state_atom_prekmm(radeon
, state
);
957 dwords
= (*state
->check
) (radeon
->glCtx
, state
);
959 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
961 if (state
->cmd
&& radeon_is_debug_enabled(RADEON_STATE
, RADEON_TRACE
)) {
962 if (dwords
> state
->cmd_size
)
963 dwords
= state
->cmd_size
;
964 for (i
= 0; i
< dwords
;) {
965 packet0
= state
->cmd
[i
];
966 reg
= (packet0
& 0x1FFF) << 2;
967 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
968 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
969 state
->name
, i
, reg
, count
);
971 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
972 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
973 state
->name
, i
, reg
, state
->cmd
[i
]);
982 * Count total size for next state emit.
984 GLuint
radeonCountStateEmitSize(radeonContextPtr radeon
)
986 struct radeon_state_atom
*atom
;
988 /* check if we are going to emit full state */
990 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.all_dirty
) {
991 if (!radeon
->hw
.is_dirty
)
993 foreach(atom
, &radeon
->hw
.atomlist
) {
995 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
997 if (RADEON_CMDBUF
&& atom_size
) {
998 radeon_print_state_atom(radeon
, atom
);
1003 foreach(atom
, &radeon
->hw
.atomlist
) {
1004 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
1005 dwords
+= atom_size
;
1006 if (RADEON_CMDBUF
&& atom_size
) {
1007 radeon_print_state_atom(radeon
, atom
);
1013 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s %u\n", __func__
, dwords
);
1017 static INLINE
void radeon_emit_atom(radeonContextPtr radeon
, struct radeon_state_atom
*atom
)
1019 BATCH_LOCALS(radeon
);
1022 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
1025 radeon_print_state_atom(radeon
, atom
);
1028 (*atom
->emit
)(radeon
->glCtx
, atom
);
1030 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
1031 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
1034 atom
->dirty
= GL_FALSE
;
1037 radeon_print(RADEON_STATE
, RADEON_VERBOSE
, " skip state %s\n", atom
->name
);
1042 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean emitAll
)
1044 struct radeon_state_atom
*atom
;
1046 if (radeon
->vtbl
.pre_emit_atoms
)
1047 radeon
->vtbl
.pre_emit_atoms(radeon
);
1049 /* Emit actual atoms */
1050 if (radeon
->hw
.all_dirty
|| emitAll
) {
1051 foreach(atom
, &radeon
->hw
.atomlist
)
1052 radeon_emit_atom( radeon
, atom
);
1054 foreach(atom
, &radeon
->hw
.atomlist
) {
1056 radeon_emit_atom( radeon
, atom
);
1063 static GLboolean
radeon_revalidate_bos(struct gl_context
*ctx
)
1065 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1068 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
);
1069 if (ret
== RADEON_CS_SPACE_FLUSH
)
1074 void radeonEmitState(radeonContextPtr radeon
)
1076 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s\n", __FUNCTION__
);
1078 if (radeon
->vtbl
.pre_emit_state
)
1079 radeon
->vtbl
.pre_emit_state(radeon
);
1081 /* this code used to return here but now it emits zbs */
1082 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1085 if (!radeon
->cmdbuf
.cs
->cdw
) {
1086 if (RADEON_DEBUG
& RADEON_STATE
)
1087 fprintf(stderr
, "Begin reemit state\n");
1089 radeonEmitAtoms(radeon
, GL_TRUE
);
1092 if (RADEON_DEBUG
& RADEON_STATE
)
1093 fprintf(stderr
, "Begin dirty state\n");
1095 radeonEmitAtoms(radeon
, GL_FALSE
);
1098 radeon
->hw
.is_dirty
= GL_FALSE
;
1099 radeon
->hw
.all_dirty
= GL_FALSE
;
1103 void radeonFlush(struct gl_context
*ctx
)
1105 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1106 if (RADEON_DEBUG
& RADEON_IOCTL
)
1107 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1109 /* okay if we have no cmds in the buffer &&
1110 we have no DMA flush &&
1111 we have no DMA buffer allocated.
1112 then no point flushing anything at all.
1114 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& is_empty_list(&radeon
->dma
.reserved
))
1117 if (radeon
->dma
.flush
)
1118 radeon
->dma
.flush( ctx
);
1120 if (radeon
->cmdbuf
.cs
->cdw
)
1121 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1124 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1125 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1127 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1128 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1129 __DRIdrawable
* drawable
= radeon_get_drawable(radeon
);
1131 /* We set the dirty bit in radeon_prepare_render() if we're
1132 * front buffer rendering once we get there.
1134 radeon
->front_buffer_dirty
= GL_FALSE
;
1136 (*screen
->dri2
.loader
->flushFrontBuffer
)(drawable
, drawable
->loaderPrivate
);
1141 /* Make sure all commands have been sent to the hardware and have
1142 * completed processing.
1144 void radeonFinish(struct gl_context
* ctx
)
1146 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1147 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1150 if (ctx
->Driver
.Flush
)
1151 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
1153 if (radeon
->radeonScreen
->kernel_mm
) {
1154 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1155 struct radeon_renderbuffer
*rrb
;
1156 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1158 radeon_bo_wait(rrb
->bo
);
1161 struct radeon_renderbuffer
*rrb
;
1162 rrb
= radeon_get_depthbuffer(radeon
);
1164 radeon_bo_wait(rrb
->bo
);
1166 } else if (radeon
->do_irqs
) {
1167 LOCK_HARDWARE(radeon
);
1168 radeonEmitIrqLocked(radeon
);
1169 UNLOCK_HARDWARE(radeon
);
1170 radeonWaitIrq(radeon
);
1172 radeonWaitForIdle(radeon
);
1178 * Send the current command buffer via ioctl to the hardware.
1180 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1184 if (rmesa
->cmdbuf
.flushing
) {
1185 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1188 rmesa
->cmdbuf
.flushing
= 1;
1190 if (RADEON_DEBUG
& RADEON_IOCTL
) {
1191 fprintf(stderr
, "%s from %s - %i cliprects\n",
1192 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1195 radeonEmitQueryEnd(rmesa
->glCtx
);
1197 if (rmesa
->cmdbuf
.cs
->cdw
) {
1198 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1199 rmesa
->hw
.all_dirty
= GL_TRUE
;
1201 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1202 rmesa
->cmdbuf
.flushing
= 0;
1204 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1205 fprintf(stderr
,"failed to revalidate buffers\n");
1211 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1215 radeonReleaseDmaRegions(rmesa
);
1217 LOCK_HARDWARE(rmesa
);
1218 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1219 UNLOCK_HARDWARE(rmesa
);
1222 fprintf(stderr
, "drmRadeonCmdBuffer: %d. Kernel failed to "
1223 "parse or rejected command stream. See dmesg "
1224 "for more info.\n", ret
);
1232 * Make sure that enough space is available in the command buffer
1233 * by flushing if necessary.
1235 * \param dwords The number of dwords we need to be free on the command buffer
1237 GLboolean
rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1239 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
1240 || radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1241 /* If we try to flush empty buffer there is too big rendering operation. */
1242 assert(rmesa
->cmdbuf
.cs
->cdw
);
1243 rcommonFlushCmdBuf(rmesa
, caller
);
1249 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1252 /* Initialize command buffer */
1253 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1254 "command_buffer_size");
1255 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1256 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1258 if (size
> 64 * 256)
1261 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1262 "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t
));
1263 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1264 "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t
));
1265 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1266 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1267 size
* 4, rmesa
->hw
.max_state_size
* 4);
1269 if (rmesa
->radeonScreen
->kernel_mm
) {
1270 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1271 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1273 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1275 if (rmesa
->cmdbuf
.csm
== NULL
) {
1276 /* FIXME: fatal error */
1279 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1280 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1281 rmesa
->cmdbuf
.size
= size
;
1283 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
1284 (void (*)(void *))rmesa
->glCtx
->Driver
.Flush
, rmesa
->glCtx
);
1286 if (!rmesa
->radeonScreen
->kernel_mm
) {
1287 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1288 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1290 struct drm_radeon_gem_info mminfo
= { 0 };
1292 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1294 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1295 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1301 * Destroy the command buffer
1303 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1305 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1306 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1307 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1309 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1313 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1316 const char *function
,
1319 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1321 radeon_print(RADEON_CS
, RADEON_VERBOSE
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1322 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1326 void radeonUserClear(struct gl_context
*ctx
, GLuint mask
)
1328 _mesa_meta_Clear(ctx
, mask
);