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 __DRIdrawablePrivate
*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 __DRIdrawablePrivate
*const drawable
= radeon_get_drawable(radeon
);
173 __DRIdrawablePrivate
*const readable
= radeon_get_readable(radeon
);
174 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
175 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
178 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
179 &radeon
->numClipRects
, &x_off
, &y_off
);
181 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
182 (draw_rfb
->base
.Height
!= drawable
->h
)) {
183 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
184 drawable
->w
, drawable
->h
);
185 draw_rfb
->base
.Initialized
= GL_TRUE
;
188 if (drawable
!= readable
) {
189 if ((read_rfb
->base
.Width
!= readable
->w
) ||
190 (read_rfb
->base
.Height
!= readable
->h
)) {
191 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
192 readable
->w
, readable
->h
);
193 read_rfb
->base
.Initialized
= GL_TRUE
;
197 if (radeon
->state
.scissor
.enabled
)
198 radeonRecalcScissorRects(radeon
);
204 void radeonUpdateScissor( GLcontext
*ctx
)
206 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
207 GLint x
= ctx
->Scissor
.X
, y
= ctx
->Scissor
.Y
;
208 GLsizei w
= ctx
->Scissor
.Width
, h
= ctx
->Scissor
.Height
;
210 int min_x
, min_y
, max_x
, max_y
;
212 if (!ctx
->DrawBuffer
)
215 max_x
= ctx
->DrawBuffer
->Width
- 1;
216 max_y
= ctx
->DrawBuffer
->Height
- 1;
218 if ( !ctx
->DrawBuffer
->Name
) {
220 y1
= ctx
->DrawBuffer
->Height
- (y
+ h
);
230 if (!rmesa
->radeonScreen
->kernel_mm
) {
231 /* Fix scissors for dri 1 */
232 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(rmesa
);
236 max_x
+= dPriv
->x
+ 1;
240 max_y
+= dPriv
->y
+ 1;
243 rmesa
->state
.scissor
.rect
.x1
= CLAMP(x1
, min_x
, max_x
);
244 rmesa
->state
.scissor
.rect
.y1
= CLAMP(y1
, min_y
, max_y
);
245 rmesa
->state
.scissor
.rect
.x2
= CLAMP(x2
, min_x
, max_x
);
246 rmesa
->state
.scissor
.rect
.y2
= CLAMP(y2
, min_y
, max_y
);
248 radeonRecalcScissorRects( rmesa
);
251 /* =============================================================
255 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
257 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
258 if (ctx
->Scissor
.Enabled
) {
259 /* We don't pipeline cliprect changes */
260 radeon_firevertices(radeon
);
261 radeonUpdateScissor(ctx
);
265 /* ================================================================
266 * SwapBuffers with client-side throttling
269 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
271 drm_radeon_getparam_t gp
;
275 gp
.param
= RADEON_PARAM_LAST_FRAME
;
276 gp
.value
= (int *)&frame
;
277 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
280 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
288 uint32_t radeonGetAge(radeonContextPtr radeon
)
290 drm_radeon_getparam_t gp
;
294 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
295 gp
.value
= (int *)&age
;
296 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
299 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
307 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
309 drm_radeon_irq_emit_t ie
;
312 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
313 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
316 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
322 static void radeonWaitIrq(radeonContextPtr radeon
)
327 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
328 &radeon
->iw
, sizeof(radeon
->iw
));
329 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
332 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
338 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
340 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
342 if (radeon
->do_irqs
) {
343 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
344 if (!radeon
->irqsEmitted
) {
345 while (radeonGetLastFrame(radeon
) <
348 UNLOCK_HARDWARE(radeon
);
349 radeonWaitIrq(radeon
);
350 LOCK_HARDWARE(radeon
);
352 radeon
->irqsEmitted
= 10;
355 if (radeon
->irqsEmitted
) {
356 radeonEmitIrqLocked(radeon
);
357 radeon
->irqsEmitted
--;
360 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
361 UNLOCK_HARDWARE(radeon
);
362 if (radeon
->do_usleeps
)
364 LOCK_HARDWARE(radeon
);
370 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
376 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
379 } while (ret
&& ++i
< 100);
382 UNLOCK_HARDWARE(radeon
);
383 fprintf(stderr
, "Error: R300 timed out... exiting\n");
388 static void radeonWaitForIdle(radeonContextPtr radeon
)
390 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
391 LOCK_HARDWARE(radeon
);
392 radeonWaitForIdleLocked(radeon
);
393 UNLOCK_HARDWARE(radeon
);
397 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
399 int current_page
= rfb
->pf_current_page
;
400 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
401 struct gl_renderbuffer
*tmp_rb
;
403 /* Exchange renderbuffers if necessary but make sure their
404 * reference counts are preserved.
406 if (rfb
->color_rb
[current_page
] &&
407 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
408 &rfb
->color_rb
[current_page
]->base
) {
410 _mesa_reference_renderbuffer(&tmp_rb
,
411 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
412 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
413 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
414 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
417 if (rfb
->color_rb
[next_page
] &&
418 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
419 &rfb
->color_rb
[next_page
]->base
) {
421 _mesa_reference_renderbuffer(&tmp_rb
,
422 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
423 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
424 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
425 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
429 /* Copy the back color buffer to the front color buffer.
431 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
432 const drm_clip_rect_t
*rect
)
434 radeonContextPtr rmesa
;
435 struct radeon_framebuffer
*rfb
;
439 assert(dPriv
->driContextPriv
);
440 assert(dPriv
->driContextPriv
->driverPrivate
);
442 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
444 LOCK_HARDWARE(rmesa
);
446 rfb
= dPriv
->driverPrivate
;
448 if ( RADEON_DEBUG
& RADEON_IOCTL
) {
449 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
452 nbox
= dPriv
->numClipRects
; /* must be in locked region */
454 for ( i
= 0 ; i
< nbox
; ) {
455 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
456 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
457 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
460 for ( ; i
< nr
; i
++ ) {
466 if (rect
->x1
> b
->x1
)
468 if (rect
->y1
> b
->y1
)
470 if (rect
->x2
< b
->x2
)
472 if (rect
->y2
< b
->y2
)
475 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
482 rmesa
->sarea
->nbox
= n
;
487 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
490 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
491 UNLOCK_HARDWARE( rmesa
);
496 UNLOCK_HARDWARE( rmesa
);
499 static int radeonScheduleSwap(__DRIdrawablePrivate
*dPriv
, GLboolean
*missed_target
)
501 radeonContextPtr rmesa
;
503 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
504 radeon_firevertices(rmesa
);
506 LOCK_HARDWARE( rmesa
);
508 if (!dPriv
->numClipRects
) {
509 UNLOCK_HARDWARE(rmesa
);
510 usleep(10000); /* throttle invisible client 10ms */
514 radeonWaitForFrameCompletion(rmesa
);
516 UNLOCK_HARDWARE(rmesa
);
517 driWaitForVBlank(dPriv
, missed_target
);
522 static GLboolean
radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
524 radeonContextPtr radeon
;
526 __DRIscreenPrivate
*psp
;
527 struct radeon_renderbuffer
*rrb
;
528 struct radeon_framebuffer
*rfb
;
531 assert(dPriv
->driContextPriv
);
532 assert(dPriv
->driContextPriv
->driverPrivate
);
534 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
535 rfb
= dPriv
->driverPrivate
;
536 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
538 psp
= dPriv
->driScreenPriv
;
540 LOCK_HARDWARE(radeon
);
542 if ( RADEON_DEBUG
& RADEON_IOCTL
) {
543 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
544 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
546 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
547 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
549 radeon
->sarea
->nbox
= 1;
551 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
553 UNLOCK_HARDWARE(radeon
);
556 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
563 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
564 radeon_flip_renderbuffers(rfb
);
565 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
572 * Swap front and back buffer.
574 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
577 __DRIscreenPrivate
*psp
;
579 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
580 radeonContextPtr radeon
;
583 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
586 if (ctx
->Visual
.doubleBufferMode
) {
587 GLboolean missed_target
;
588 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
589 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
591 radeonScheduleSwap(dPriv
, &missed_target
);
593 if (rfb
->pf_active
) {
594 radeonPageFlip(dPriv
);
596 radeonCopyBuffer(dPriv
, NULL
);
599 psp
= dPriv
->driScreenPriv
;
602 (*psp
->systemTime
->getUST
)( & ust
);
603 if ( missed_target
) {
604 rfb
->swap_missed_count
++;
605 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
609 radeon
->hw
.all_dirty
= GL_TRUE
;
612 /* XXX this shouldn't be an error but we can't handle it for now */
613 _mesa_problem(NULL
, "%s: drawable has no context!",
618 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
619 int x
, int y
, int w
, int h
)
621 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
622 radeonContextPtr radeon
;
625 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
628 if (ctx
->Visual
.doubleBufferMode
) {
629 drm_clip_rect_t rect
;
630 rect
.x1
= x
+ dPriv
->x
;
631 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
632 rect
.x2
= rect
.x1
+ w
;
633 rect
.y2
= rect
.y1
+ h
;
634 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
635 radeonCopyBuffer(dPriv
, &rect
);
638 /* XXX this shouldn't be an error but we can't handle it for now */
639 _mesa_problem(NULL
, "%s: drawable has no context!",
644 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
646 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
647 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
653 /* this can happen during the initial context initialization */
657 /* radeons only handle 1 color draw so far */
658 if (fb
->_NumColorDrawBuffers
!= 1) {
659 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
663 /* Do this here, note core Mesa, since this function is called from
664 * many places within the driver.
666 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
667 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
668 _mesa_update_framebuffer(ctx
);
669 /* this updates the DrawBuffer's Width/Height if it's a FBO */
670 _mesa_update_draw_buffer_bounds(ctx
);
673 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
674 /* this may occur when we're called by glBindFrameBuffer() during
675 * the process of someone setting up renderbuffers, etc.
677 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
682 ;/* do something depthy/stencily TODO */
687 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
688 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
689 radeon
->front_cliprects
= GL_TRUE
;
690 radeon
->front_buffer_dirty
= GL_TRUE
;
692 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
693 radeon
->front_cliprects
= GL_FALSE
;
696 /* user FBO in theory */
697 struct radeon_renderbuffer
*rrb
;
698 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
700 offset
= rrb
->draw_offset
;
703 radeon
->constant_cliprect
= GL_TRUE
;
706 if (rrbColor
== NULL
)
707 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
709 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
712 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
713 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
714 if (rrbDepth
&& rrbDepth
->bo
) {
715 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
717 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
720 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
724 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
725 rrbStencil
= radeon_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
726 if (rrbStencil
&& rrbStencil
->bo
) {
727 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
728 /* need to re-compute stencil hw state */
730 rrbDepth
= rrbStencil
;
732 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
735 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
736 if (ctx
->Driver
.Enable
!= NULL
)
737 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
739 ctx
->NewState
|= _NEW_STENCIL
;
742 /* Update culling direction which changes depending on the
743 * orientation of the buffer:
745 if (ctx
->Driver
.FrontFace
)
746 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
748 ctx
->NewState
|= _NEW_POLYGON
;
751 * Update depth test state
753 if (ctx
->Driver
.Enable
) {
754 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
755 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
756 /* Need to update the derived ctx->Stencil._Enabled first */
757 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
758 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
760 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
763 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
764 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
765 radeon
->state
.color
.draw_offset
= offset
;
768 /* update viewport since it depends on window size */
769 if (ctx
->Driver
.Viewport
) {
770 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
771 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
776 ctx
->NewState
|= _NEW_VIEWPORT
;
778 /* Set state we know depends on drawable parameters:
780 radeonUpdateScissor(ctx
);
781 radeon
->NewGLState
|= _NEW_SCISSOR
;
783 if (ctx
->Driver
.DepthRange
)
784 ctx
->Driver
.DepthRange(ctx
,
788 /* Update culling direction which changes depending on the
789 * orientation of the buffer:
791 if (ctx
->Driver
.FrontFace
)
792 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
794 ctx
->NewState
|= _NEW_POLYGON
;
798 * Called via glDrawBuffer.
800 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
802 if (RADEON_DEBUG
& RADEON_DRI
)
803 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
804 _mesa_lookup_enum_by_nr( mode
));
806 if (ctx
->DrawBuffer
->Name
== 0) {
807 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
809 const GLboolean was_front_buffer_rendering
=
810 radeon
->is_front_buffer_rendering
;
812 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
815 /* If we weren't front-buffer rendering before but we are now, make sure
816 * that the front-buffer has actually been allocated.
818 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
819 radeon_update_renderbuffers(radeon
->dri
.context
,
820 radeon
->dri
.context
->driDrawablePriv
);
824 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
827 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
829 if ((ctx
->DrawBuffer
!= NULL
) && (ctx
->DrawBuffer
->Name
== 0)) {
830 struct radeon_context
*const rmesa
= RADEON_CONTEXT(ctx
);
831 const GLboolean was_front_buffer_reading
= rmesa
->is_front_buffer_reading
;
832 rmesa
->is_front_buffer_reading
= (mode
== GL_FRONT_LEFT
)
833 || (mode
== GL_FRONT
);
835 if (!was_front_buffer_reading
&& rmesa
->is_front_buffer_reading
) {
836 radeon_update_renderbuffers(rmesa
->dri
.context
,
837 rmesa
->dri
.context
->driReadablePriv
);
840 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
841 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
842 /* This will update FBO completeness status.
843 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
844 * refers to a missing renderbuffer. Calling glReadBuffer can set
845 * that straight and can make the drawing buffer complete.
847 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
852 /* Turn on/off page flipping according to the flags in the sarea:
854 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
856 struct radeon_framebuffer
*rfb
= radeon_get_drawable(radeon
)->driverPrivate
;
858 rfb
->pf_active
= radeon
->sarea
->pfState
;
859 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
860 rfb
->pf_num_pages
= 2;
861 radeon_flip_renderbuffers(rfb
);
862 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
865 void radeon_window_moved(radeonContextPtr radeon
)
867 /* Cliprects has to be updated before doing anything else */
868 radeonSetCliprects(radeon
);
869 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
870 radeonUpdatePageFlipping(radeon
);
874 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
876 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
877 __DRIcontext
*driContext
= radeon
->dri
.context
;
878 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
879 GLsizei w
, GLsizei h
);
881 if (!driContext
->driScreenPriv
->dri2
.enabled
)
884 if (!radeon
->meta
.internal_viewport_call
&& ctx
->DrawBuffer
->Name
== 0) {
885 if (radeon
->is_front_buffer_rendering
) {
886 ctx
->Driver
.Flush(ctx
);
888 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
889 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
890 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
893 old_viewport
= ctx
->Driver
.Viewport
;
894 ctx
->Driver
.Viewport
= NULL
;
895 radeon_window_moved(radeon
);
896 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
897 ctx
->Driver
.Viewport
= old_viewport
;
900 static void radeon_print_state_atom_prekmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
903 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
904 drm_r300_cmd_header_t cmd
;
906 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
908 if (radeon_is_debug_enabled(RADEON_STATE
, RADEON_TRACE
)) {
909 if (dwords
> state
->cmd_size
)
910 dwords
= state
->cmd_size
;
912 for (i
= 0; i
< dwords
;) {
913 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
914 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
915 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
916 state
->name
, i
, reg
, cmd
.packet0
.count
);
918 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
919 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
920 state
->name
, i
, reg
, state
->cmd
[i
]);
928 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
930 int i
, j
, reg
, count
;
933 if (!radeon_is_debug_enabled(RADEON_STATE
, RADEON_VERBOSE
) )
936 if (!radeon
->radeonScreen
->kernel_mm
) {
937 radeon_print_state_atom_prekmm(radeon
, state
);
941 dwords
= (*state
->check
) (radeon
->glCtx
, state
);
943 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
945 if (radeon_is_debug_enabled(RADEON_STATE
, RADEON_TRACE
)) {
946 if (dwords
> state
->cmd_size
)
947 dwords
= state
->cmd_size
;
948 for (i
= 0; i
< dwords
;) {
949 packet0
= state
->cmd
[i
];
950 reg
= (packet0
& 0x1FFF) << 2;
951 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
952 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
953 state
->name
, i
, reg
, count
);
955 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
956 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
957 state
->name
, i
, reg
, state
->cmd
[i
]);
966 * Count total size for next state emit.
968 GLuint
radeonCountStateEmitSize(radeonContextPtr radeon
)
970 struct radeon_state_atom
*atom
;
972 /* check if we are going to emit full state */
974 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.all_dirty
) {
975 if (!radeon
->hw
.is_dirty
)
977 foreach(atom
, &radeon
->hw
.atomlist
) {
979 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
981 if (RADEON_CMDBUF
&& atom_size
) {
982 radeon_print_state_atom(radeon
, atom
);
987 foreach(atom
, &radeon
->hw
.atomlist
) {
988 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
990 if (RADEON_CMDBUF
&& atom_size
) {
991 radeon_print_state_atom(radeon
, atom
);
997 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s %u\n", __func__
, dwords
);
1001 static INLINE
void radeon_emit_atom(radeonContextPtr radeon
, struct radeon_state_atom
*atom
)
1003 BATCH_LOCALS(radeon
);
1006 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
1009 radeon_print_state_atom(radeon
, atom
);
1012 (*atom
->emit
)(radeon
->glCtx
, atom
);
1014 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
1015 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
1019 radeon_print(RADEON_STATE
, RADEON_VERBOSE
, " skip state %s\n", atom
->name
);
1021 atom
->dirty
= GL_FALSE
;
1025 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean emitAll
)
1027 struct radeon_state_atom
*atom
;
1029 if (radeon
->vtbl
.pre_emit_atoms
)
1030 radeon
->vtbl
.pre_emit_atoms(radeon
);
1032 /* Emit actual atoms */
1033 if (radeon
->hw
.all_dirty
|| emitAll
) {
1034 foreach(atom
, &radeon
->hw
.atomlist
)
1035 radeon_emit_atom( radeon
, atom
);
1037 foreach(atom
, &radeon
->hw
.atomlist
) {
1039 radeon_emit_atom( radeon
, atom
);
1046 static GLboolean
radeon_revalidate_bos(GLcontext
*ctx
)
1048 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1051 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
);
1052 if (ret
== RADEON_CS_SPACE_FLUSH
)
1057 void radeonEmitState(radeonContextPtr radeon
)
1059 radeon_print(RADEON_STATE
, RADEON_NORMAL
, "%s\n", __FUNCTION__
);
1061 if (radeon
->vtbl
.pre_emit_state
)
1062 radeon
->vtbl
.pre_emit_state(radeon
);
1064 /* this code used to return here but now it emits zbs */
1065 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1068 if (!radeon
->cmdbuf
.cs
->cdw
) {
1069 if (RADEON_DEBUG
& RADEON_STATE
)
1070 fprintf(stderr
, "Begin reemit state\n");
1072 radeonEmitAtoms(radeon
, GL_TRUE
);
1075 if (RADEON_DEBUG
& RADEON_STATE
)
1076 fprintf(stderr
, "Begin dirty state\n");
1078 radeonEmitAtoms(radeon
, GL_FALSE
);
1081 radeon
->hw
.is_dirty
= GL_FALSE
;
1082 radeon
->hw
.all_dirty
= GL_FALSE
;
1086 void radeonFlush(GLcontext
*ctx
)
1088 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1089 if (RADEON_DEBUG
& RADEON_IOCTL
)
1090 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1092 /* okay if we have no cmds in the buffer &&
1093 we have no DMA flush &&
1094 we have no DMA buffer allocated.
1095 then no point flushing anything at all.
1097 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& is_empty_list(&radeon
->dma
.reserved
))
1100 if (radeon
->dma
.flush
)
1101 radeon
->dma
.flush( ctx
);
1103 radeonEmitState(radeon
);
1105 if (radeon
->cmdbuf
.cs
->cdw
)
1106 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1108 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1109 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1111 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1112 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1113 __DRIdrawablePrivate
* drawable
= radeon_get_drawable(radeon
);
1114 (*screen
->dri2
.loader
->flushFrontBuffer
)(drawable
, drawable
->loaderPrivate
);
1116 /* Only clear the dirty bit if front-buffer rendering is no longer
1117 * enabled. This is done so that the dirty bit can only be set in
1118 * glDrawBuffer. Otherwise the dirty bit would have to be set at
1119 * each of N places that do rendering. This has worse performances,
1120 * but it is much easier to get correct.
1122 if (!radeon
->is_front_buffer_rendering
) {
1123 radeon
->front_buffer_dirty
= GL_FALSE
;
1128 make_empty_list(&radeon
->query
.not_flushed_head
);
1132 /* Make sure all commands have been sent to the hardware and have
1133 * completed processing.
1135 void radeonFinish(GLcontext
* ctx
)
1137 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1138 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1141 if (ctx
->Driver
.Flush
)
1142 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
1144 if (radeon
->radeonScreen
->kernel_mm
) {
1145 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1146 struct radeon_renderbuffer
*rrb
;
1147 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1149 radeon_bo_wait(rrb
->bo
);
1152 struct radeon_renderbuffer
*rrb
;
1153 rrb
= radeon_get_depthbuffer(radeon
);
1155 radeon_bo_wait(rrb
->bo
);
1157 } else if (radeon
->do_irqs
) {
1158 LOCK_HARDWARE(radeon
);
1159 radeonEmitIrqLocked(radeon
);
1160 UNLOCK_HARDWARE(radeon
);
1161 radeonWaitIrq(radeon
);
1163 radeonWaitForIdle(radeon
);
1169 * Send the current command buffer via ioctl to the hardware.
1171 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1175 if (rmesa
->cmdbuf
.flushing
) {
1176 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1179 rmesa
->cmdbuf
.flushing
= 1;
1181 if (RADEON_DEBUG
& RADEON_IOCTL
) {
1182 fprintf(stderr
, "%s from %s - %i cliprects\n",
1183 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1186 radeonEmitQueryEnd(rmesa
->glCtx
);
1188 if (rmesa
->cmdbuf
.cs
->cdw
) {
1189 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1190 rmesa
->hw
.all_dirty
= GL_TRUE
;
1192 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1193 rmesa
->cmdbuf
.flushing
= 0;
1195 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1196 fprintf(stderr
,"failed to revalidate buffers\n");
1202 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1206 radeonReleaseDmaRegions(rmesa
);
1208 LOCK_HARDWARE(rmesa
);
1209 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1210 UNLOCK_HARDWARE(rmesa
);
1213 fprintf(stderr
, "drmRadeonCmdBuffer: %d. Kernel failed to "
1214 "parse or rejected command stream. See dmesg "
1215 "for more info.\n", ret
);
1223 * Make sure that enough space is available in the command buffer
1224 * by flushing if necessary.
1226 * \param dwords The number of dwords we need to be free on the command buffer
1228 GLboolean
rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1230 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
1231 || radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1232 /* If we try to flush empty buffer there is too big rendering operation. */
1233 assert(rmesa
->cmdbuf
.cs
->cdw
);
1234 rcommonFlushCmdBuf(rmesa
, caller
);
1240 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1243 /* Initialize command buffer */
1244 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1245 "command_buffer_size");
1246 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1247 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1249 if (size
> 64 * 256)
1252 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1253 "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t
));
1254 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1255 "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t
));
1256 radeon_print(RADEON_CS
, RADEON_VERBOSE
,
1257 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1258 size
* 4, rmesa
->hw
.max_state_size
* 4);
1260 if (rmesa
->radeonScreen
->kernel_mm
) {
1261 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1262 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1264 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1266 if (rmesa
->cmdbuf
.csm
== NULL
) {
1267 /* FIXME: fatal error */
1270 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1271 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1272 rmesa
->cmdbuf
.size
= size
;
1274 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
1275 (void (*)(void *))rmesa
->glCtx
->Driver
.Flush
, rmesa
->glCtx
);
1277 if (!rmesa
->radeonScreen
->kernel_mm
) {
1278 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1279 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1281 struct drm_radeon_gem_info mminfo
= { 0 };
1283 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1285 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1286 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1292 * Destroy the command buffer
1294 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1296 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1297 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1298 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1300 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1304 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1307 const char *function
,
1310 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1311 radeon_print(RADEON_STATE
, RADEON_NORMAL
,
1312 "Reemit state after flush (from %s)\n", function
);
1313 radeonEmitState(rmesa
);
1315 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1317 radeon_print(RADEON_CS
, RADEON_VERBOSE
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1318 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1322 void radeonUserClear(GLcontext
*ctx
, GLuint mask
)
1324 _mesa_meta_clear(ctx
, mask
);