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/arrayobj.h"
49 #include "main/api_arrayelt.h"
50 #include "main/enums.h"
51 #include "main/colormac.h"
52 #include "main/light.h"
53 #include "main/framebuffer.h"
54 #include "main/simple_list.h"
55 #include "main/renderbuffer.h"
56 #include "swrast/swrast.h"
59 #include "tnl/t_pipeline.h"
60 #include "swrast_setup/swrast_setup.h"
62 #include "main/blend.h"
63 #include "main/bufferobj.h"
64 #include "main/buffers.h"
65 #include "main/depth.h"
66 #include "main/polygon.h"
67 #include "main/shaders.h"
68 #include "main/texstate.h"
69 #include "main/varray.h"
70 #include "glapi/dispatch.h"
71 #include "swrast/swrast.h"
72 #include "main/stencil.h"
73 #include "main/matrix.h"
74 #include "main/attrib.h"
75 #include "main/enable.h"
76 #include "main/viewport.h"
81 #include "radeon_common.h"
82 #include "radeon_bocs_wrapper.h"
83 #include "radeon_lock.h"
84 #include "radeon_drm.h"
85 #include "radeon_mipmap_tree.h"
86 #include "radeon_queryobj.h"
88 #define DEBUG_CMDBUF 0
90 /* =============================================================
94 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
95 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
106 if (out
->x1
>= out
->x2
)
108 if (out
->y1
>= out
->y2
)
113 void radeonRecalcScissorRects(radeonContextPtr radeon
)
115 drm_clip_rect_t
*out
;
118 /* Grow cliprect store?
120 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
121 while (radeon
->state
.scissor
.numAllocedClipRects
<
122 radeon
->numClipRects
) {
123 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
124 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
127 if (radeon
->state
.scissor
.pClipRects
)
128 FREE(radeon
->state
.scissor
.pClipRects
);
130 radeon
->state
.scissor
.pClipRects
=
131 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
132 sizeof(drm_clip_rect_t
));
134 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
135 radeon
->state
.scissor
.numAllocedClipRects
= 0;
140 out
= radeon
->state
.scissor
.pClipRects
;
141 radeon
->state
.scissor
.numClipRects
= 0;
143 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
144 if (intersect_rect(out
,
145 &radeon
->pClipRects
[i
],
146 &radeon
->state
.scissor
.rect
)) {
147 radeon
->state
.scissor
.numClipRects
++;
153 void radeon_get_cliprects(radeonContextPtr radeon
,
154 struct drm_clip_rect
**cliprects
,
155 unsigned int *num_cliprects
,
156 int *x_off
, int *y_off
)
158 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(radeon
);
159 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
161 if (radeon
->constant_cliprect
) {
162 radeon
->fboRect
.x1
= 0;
163 radeon
->fboRect
.y1
= 0;
164 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
165 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
167 *cliprects
= &radeon
->fboRect
;
171 } else if (radeon
->front_cliprects
||
172 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
173 *cliprects
= dPriv
->pClipRects
;
174 *num_cliprects
= dPriv
->numClipRects
;
178 *num_cliprects
= dPriv
->numBackClipRects
;
179 *cliprects
= dPriv
->pBackClipRects
;
180 *x_off
= dPriv
->backX
;
181 *y_off
= dPriv
->backY
;
186 * Update cliprects and scissors.
188 void radeonSetCliprects(radeonContextPtr radeon
)
190 __DRIdrawablePrivate
*const drawable
= radeon_get_drawable(radeon
);
191 __DRIdrawablePrivate
*const readable
= radeon_get_readable(radeon
);
192 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
193 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
196 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
197 &radeon
->numClipRects
, &x_off
, &y_off
);
199 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
200 (draw_rfb
->base
.Height
!= drawable
->h
)) {
201 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
202 drawable
->w
, drawable
->h
);
203 draw_rfb
->base
.Initialized
= GL_TRUE
;
206 if (drawable
!= readable
) {
207 if ((read_rfb
->base
.Width
!= readable
->w
) ||
208 (read_rfb
->base
.Height
!= readable
->h
)) {
209 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
210 readable
->w
, readable
->h
);
211 read_rfb
->base
.Initialized
= GL_TRUE
;
215 if (radeon
->state
.scissor
.enabled
)
216 radeonRecalcScissorRects(radeon
);
222 void radeonUpdateScissor( GLcontext
*ctx
)
224 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
226 if ( !ctx
->DrawBuffer
->Name
) {
227 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(rmesa
);
229 int x
= ctx
->Scissor
.X
;
230 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
231 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
232 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
234 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
235 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
236 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
237 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
239 rmesa
->state
.scissor
.rect
.x1
= ctx
->Scissor
.X
;
240 rmesa
->state
.scissor
.rect
.y1
= ctx
->Scissor
.Y
;
241 rmesa
->state
.scissor
.rect
.x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
;
242 rmesa
->state
.scissor
.rect
.y2
= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
;
245 radeonRecalcScissorRects( rmesa
);
248 /* =============================================================
252 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
254 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
255 if (ctx
->Scissor
.Enabled
) {
256 /* We don't pipeline cliprect changes */
257 radeon_firevertices(radeon
);
258 radeonUpdateScissor(ctx
);
263 /* ================================================================
264 * SwapBuffers with client-side throttling
267 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
269 drm_radeon_getparam_t gp
;
273 gp
.param
= RADEON_PARAM_LAST_FRAME
;
274 gp
.value
= (int *)&frame
;
275 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
278 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
286 uint32_t radeonGetAge(radeonContextPtr radeon
)
288 drm_radeon_getparam_t gp
;
292 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
293 gp
.value
= (int *)&age
;
294 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
297 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
305 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
307 drm_radeon_irq_emit_t ie
;
310 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
311 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
314 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
320 static void radeonWaitIrq(radeonContextPtr radeon
)
325 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
326 &radeon
->iw
, sizeof(radeon
->iw
));
327 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
330 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
336 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
338 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
340 if (radeon
->do_irqs
) {
341 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
342 if (!radeon
->irqsEmitted
) {
343 while (radeonGetLastFrame(radeon
) <
346 UNLOCK_HARDWARE(radeon
);
347 radeonWaitIrq(radeon
);
348 LOCK_HARDWARE(radeon
);
350 radeon
->irqsEmitted
= 10;
353 if (radeon
->irqsEmitted
) {
354 radeonEmitIrqLocked(radeon
);
355 radeon
->irqsEmitted
--;
358 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
359 UNLOCK_HARDWARE(radeon
);
360 if (radeon
->do_usleeps
)
362 LOCK_HARDWARE(radeon
);
368 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
374 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
377 } while (ret
&& ++i
< 100);
380 UNLOCK_HARDWARE(radeon
);
381 fprintf(stderr
, "Error: R300 timed out... exiting\n");
386 static void radeonWaitForIdle(radeonContextPtr radeon
)
388 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
389 LOCK_HARDWARE(radeon
);
390 radeonWaitForIdleLocked(radeon
);
391 UNLOCK_HARDWARE(radeon
);
395 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
397 int current_page
= rfb
->pf_current_page
;
398 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
399 struct gl_renderbuffer
*tmp_rb
;
401 /* Exchange renderbuffers if necessary but make sure their
402 * reference counts are preserved.
404 if (rfb
->color_rb
[current_page
] &&
405 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
406 &rfb
->color_rb
[current_page
]->base
) {
408 _mesa_reference_renderbuffer(&tmp_rb
,
409 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
410 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
411 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
412 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
415 if (rfb
->color_rb
[next_page
] &&
416 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
417 &rfb
->color_rb
[next_page
]->base
) {
419 _mesa_reference_renderbuffer(&tmp_rb
,
420 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
421 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
422 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
423 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
427 /* Copy the back color buffer to the front color buffer.
429 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
430 const drm_clip_rect_t
*rect
)
432 radeonContextPtr rmesa
;
433 struct radeon_framebuffer
*rfb
;
437 assert(dPriv
->driContextPriv
);
438 assert(dPriv
->driContextPriv
->driverPrivate
);
440 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
442 LOCK_HARDWARE(rmesa
);
444 rfb
= dPriv
->driverPrivate
;
446 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
447 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
450 nbox
= dPriv
->numClipRects
; /* must be in locked region */
452 for ( i
= 0 ; i
< nbox
; ) {
453 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
454 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
455 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
458 for ( ; i
< nr
; i
++ ) {
464 if (rect
->x1
> b
->x1
)
466 if (rect
->y1
> b
->y1
)
468 if (rect
->x2
< b
->x2
)
470 if (rect
->y2
< b
->y2
)
473 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
480 rmesa
->sarea
->nbox
= n
;
485 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
488 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
489 UNLOCK_HARDWARE( rmesa
);
494 UNLOCK_HARDWARE( rmesa
);
497 static int radeonScheduleSwap(__DRIdrawablePrivate
*dPriv
, GLboolean
*missed_target
)
499 radeonContextPtr rmesa
;
501 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
502 radeon_firevertices(rmesa
);
504 LOCK_HARDWARE( rmesa
);
506 if (!dPriv
->numClipRects
) {
507 UNLOCK_HARDWARE(rmesa
);
508 usleep(10000); /* throttle invisible client 10ms */
512 radeonWaitForFrameCompletion(rmesa
);
514 UNLOCK_HARDWARE(rmesa
);
515 driWaitForVBlank(dPriv
, missed_target
);
520 static GLboolean
radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
522 radeonContextPtr radeon
;
524 __DRIscreenPrivate
*psp
;
525 struct radeon_renderbuffer
*rrb
;
526 struct radeon_framebuffer
*rfb
;
529 assert(dPriv
->driContextPriv
);
530 assert(dPriv
->driContextPriv
->driverPrivate
);
532 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
533 rfb
= dPriv
->driverPrivate
;
534 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
536 psp
= dPriv
->driScreenPriv
;
538 LOCK_HARDWARE(radeon
);
540 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
541 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
542 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
544 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
545 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
547 radeon
->sarea
->nbox
= 1;
549 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
551 UNLOCK_HARDWARE(radeon
);
554 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
561 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
562 radeon_flip_renderbuffers(rfb
);
563 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
570 * Swap front and back buffer.
572 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
575 __DRIscreenPrivate
*psp
;
577 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
578 radeonContextPtr radeon
;
581 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
584 if (ctx
->Visual
.doubleBufferMode
) {
585 GLboolean missed_target
;
586 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
587 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
589 radeonScheduleSwap(dPriv
, &missed_target
);
591 if (rfb
->pf_active
) {
592 radeonPageFlip(dPriv
);
594 radeonCopyBuffer(dPriv
, NULL
);
597 psp
= dPriv
->driScreenPriv
;
600 (*psp
->systemTime
->getUST
)( & ust
);
601 if ( missed_target
) {
602 rfb
->swap_missed_count
++;
603 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
607 radeon
->hw
.all_dirty
= GL_TRUE
;
610 /* XXX this shouldn't be an error but we can't handle it for now */
611 _mesa_problem(NULL
, "%s: drawable has no context!",
616 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
617 int x
, int y
, int w
, int h
)
619 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
620 radeonContextPtr radeon
;
623 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
626 if (ctx
->Visual
.doubleBufferMode
) {
627 drm_clip_rect_t rect
;
628 rect
.x1
= x
+ dPriv
->x
;
629 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
630 rect
.x2
= rect
.x1
+ w
;
631 rect
.y2
= rect
.y1
+ h
;
632 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
633 radeonCopyBuffer(dPriv
, &rect
);
636 /* XXX this shouldn't be an error but we can't handle it for now */
637 _mesa_problem(NULL
, "%s: drawable has no context!",
642 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
644 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
645 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
651 /* this can happen during the initial context initialization */
655 /* radeons only handle 1 color draw so far */
656 if (fb
->_NumColorDrawBuffers
!= 1) {
657 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
661 /* Do this here, note core Mesa, since this function is called from
662 * many places within the driver.
664 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
665 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
666 _mesa_update_framebuffer(ctx
);
667 /* this updates the DrawBuffer's Width/Height if it's a FBO */
668 _mesa_update_draw_buffer_bounds(ctx
);
671 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
672 /* this may occur when we're called by glBindFrameBuffer() during
673 * the process of someone setting up renderbuffers, etc.
675 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
680 ;/* do something depthy/stencily TODO */
685 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
686 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
687 radeon
->front_cliprects
= GL_TRUE
;
688 radeon
->front_buffer_dirty
= GL_TRUE
;
690 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
691 radeon
->front_cliprects
= GL_FALSE
;
694 /* user FBO in theory */
695 struct radeon_renderbuffer
*rrb
;
696 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
698 offset
= rrb
->draw_offset
;
701 radeon
->constant_cliprect
= GL_TRUE
;
704 if (rrbColor
== NULL
)
705 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
707 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
710 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
711 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
712 if (rrbDepth
&& rrbDepth
->bo
) {
713 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
715 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
718 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
722 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
723 rrbStencil
= radeon_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
724 if (rrbStencil
&& rrbStencil
->bo
) {
725 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
726 /* need to re-compute stencil hw state */
728 rrbDepth
= rrbStencil
;
730 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
733 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
734 if (ctx
->Driver
.Enable
!= NULL
)
735 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
737 ctx
->NewState
|= _NEW_STENCIL
;
740 /* Update culling direction which changes depending on the
741 * orientation of the buffer:
743 if (ctx
->Driver
.FrontFace
)
744 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
746 ctx
->NewState
|= _NEW_POLYGON
;
749 * Update depth test state
751 if (ctx
->Driver
.Enable
) {
752 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
753 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
754 /* Need to update the derived ctx->Stencil._Enabled first */
755 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
756 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
758 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
761 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
762 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
763 radeon
->state
.color
.draw_offset
= offset
;
766 /* update viewport since it depends on window size */
767 if (ctx
->Driver
.Viewport
) {
768 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
769 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
774 ctx
->NewState
|= _NEW_VIEWPORT
;
776 /* Set state we know depends on drawable parameters:
778 radeonUpdateScissor(ctx
);
779 radeon
->NewGLState
|= _NEW_SCISSOR
;
781 if (ctx
->Driver
.DepthRange
)
782 ctx
->Driver
.DepthRange(ctx
,
786 /* Update culling direction which changes depending on the
787 * orientation of the buffer:
789 if (ctx
->Driver
.FrontFace
)
790 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
792 ctx
->NewState
|= _NEW_POLYGON
;
796 * Called via glDrawBuffer.
798 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
800 if (RADEON_DEBUG
& DEBUG_DRI
)
801 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
802 _mesa_lookup_enum_by_nr( mode
));
804 if (ctx
->DrawBuffer
->Name
== 0) {
805 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
807 const GLboolean was_front_buffer_rendering
=
808 radeon
->is_front_buffer_rendering
;
810 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
813 /* If we weren't front-buffer rendering before but we are now, make sure
814 * that the front-buffer has actually been allocated.
816 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
817 radeon_update_renderbuffers(radeon
->dri
.context
,
818 radeon
->dri
.context
->driDrawablePriv
);
822 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
825 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
827 if ((ctx
->DrawBuffer
!= NULL
) && (ctx
->DrawBuffer
->Name
== 0)) {
828 struct radeon_context
*const rmesa
= RADEON_CONTEXT(ctx
);
829 const GLboolean was_front_buffer_reading
= rmesa
->is_front_buffer_reading
;
830 rmesa
->is_front_buffer_reading
= (mode
== GL_FRONT_LEFT
)
831 || (mode
== GL_FRONT
);
833 if (!was_front_buffer_reading
&& rmesa
->is_front_buffer_reading
) {
834 radeon_update_renderbuffers(rmesa
->dri
.context
,
835 rmesa
->dri
.context
->driReadablePriv
);
838 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
839 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
840 /* This will update FBO completeness status.
841 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
842 * refers to a missing renderbuffer. Calling glReadBuffer can set
843 * that straight and can make the drawing buffer complete.
845 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
850 /* Turn on/off page flipping according to the flags in the sarea:
852 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
854 struct radeon_framebuffer
*rfb
= radeon_get_drawable(radeon
)->driverPrivate
;
856 rfb
->pf_active
= radeon
->sarea
->pfState
;
857 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
858 rfb
->pf_num_pages
= 2;
859 radeon_flip_renderbuffers(rfb
);
860 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
863 void radeon_window_moved(radeonContextPtr radeon
)
865 /* Cliprects has to be updated before doing anything else */
866 radeonSetCliprects(radeon
);
867 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
868 radeonUpdatePageFlipping(radeon
);
872 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
874 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
875 __DRIcontext
*driContext
= radeon
->dri
.context
;
876 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
877 GLsizei w
, GLsizei h
);
879 if (!driContext
->driScreenPriv
->dri2
.enabled
)
882 if (!radeon
->meta
.internal_viewport_call
&& ctx
->DrawBuffer
->Name
== 0) {
883 if (radeon
->is_front_buffer_rendering
) {
884 ctx
->Driver
.Flush(ctx
);
886 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
887 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
888 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
891 old_viewport
= ctx
->Driver
.Viewport
;
892 ctx
->Driver
.Viewport
= NULL
;
893 radeon_window_moved(radeon
);
894 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
895 ctx
->Driver
.Viewport
= old_viewport
;
898 static void radeon_print_state_atom_prekmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
901 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
902 drm_r300_cmd_header_t cmd
;
904 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
906 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
907 if (dwords
> state
->cmd_size
)
908 dwords
= state
->cmd_size
;
910 for (i
= 0; i
< dwords
;) {
911 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
912 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
913 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
914 state
->name
, i
, reg
, cmd
.packet0
.count
);
916 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
917 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
918 state
->name
, i
, reg
, state
->cmd
[i
]);
926 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
928 int i
, j
, reg
, count
;
931 if (! (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) )
934 if (!radeon
->radeonScreen
->kernel_mm
) {
935 radeon_print_state_atom_prekmm(radeon
, state
);
939 dwords
= (*state
->check
) (radeon
->glCtx
, state
);
941 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
943 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
944 if (dwords
> state
->cmd_size
)
945 dwords
= state
->cmd_size
;
946 for (i
= 0; i
< state
->cmd_size
;) {
947 packet0
= state
->cmd
[i
];
948 reg
= (packet0
& 0x1FFF) << 2;
949 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
950 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
951 state
->name
, i
, reg
, count
);
953 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
954 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
955 state
->name
, i
, reg
, state
->cmd
[i
]);
964 * Count total size for next state emit.
966 GLuint
radeonCountStateEmitSize(radeonContextPtr radeon
)
968 struct radeon_state_atom
*atom
;
970 /* check if we are going to emit full state */
971 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_VERBOSE
)
972 fprintf(stderr
, "%s\n", __func__
);
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 (DEBUG_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 (DEBUG_CMDBUF
&& atom_size
) {
991 radeon_print_state_atom(radeon
, atom
);
999 static INLINE
void radeon_emit_atom(radeonContextPtr radeon
, struct radeon_state_atom
*atom
)
1001 BATCH_LOCALS(radeon
);
1004 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
1007 radeon_print_state_atom(radeon
, atom
);
1010 (*atom
->emit
)(radeon
->glCtx
, atom
);
1012 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
1013 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
1017 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
1018 fprintf(stderr
, " skip state %s\n",
1022 atom
->dirty
= GL_FALSE
;
1026 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean emitAll
)
1028 struct radeon_state_atom
*atom
;
1030 if (radeon
->vtbl
.pre_emit_atoms
)
1031 radeon
->vtbl
.pre_emit_atoms(radeon
);
1033 /* Emit actual atoms */
1034 if (radeon
->hw
.all_dirty
|| emitAll
) {
1035 foreach(atom
, &radeon
->hw
.atomlist
)
1036 radeon_emit_atom( radeon
, atom
);
1038 foreach(atom
, &radeon
->hw
.atomlist
) {
1040 radeon_emit_atom( radeon
, atom
);
1047 static GLboolean
radeon_revalidate_bos(GLcontext
*ctx
)
1049 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1052 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
);
1053 if (ret
== RADEON_CS_SPACE_FLUSH
)
1058 void radeonEmitState(radeonContextPtr radeon
)
1060 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
1061 fprintf(stderr
, "%s\n", __FUNCTION__
);
1063 if (radeon
->vtbl
.pre_emit_state
)
1064 radeon
->vtbl
.pre_emit_state(radeon
);
1066 /* this code used to return here but now it emits zbs */
1067 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1070 if (!radeon
->cmdbuf
.cs
->cdw
) {
1071 if (RADEON_DEBUG
& DEBUG_STATE
)
1072 fprintf(stderr
, "Begin reemit state\n");
1074 radeonEmitAtoms(radeon
, GL_TRUE
);
1077 if (RADEON_DEBUG
& DEBUG_STATE
)
1078 fprintf(stderr
, "Begin dirty state\n");
1080 radeonEmitAtoms(radeon
, GL_FALSE
);
1083 radeon
->hw
.is_dirty
= GL_FALSE
;
1084 radeon
->hw
.all_dirty
= GL_FALSE
;
1088 void radeonFlush(GLcontext
*ctx
)
1090 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1091 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1092 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1094 /* okay if we have no cmds in the buffer &&
1095 we have no DMA flush &&
1096 we have no DMA buffer allocated.
1097 then no point flushing anything at all.
1099 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& is_empty_list(&radeon
->dma
.reserved
))
1102 if (radeon
->dma
.flush
)
1103 radeon
->dma
.flush( ctx
);
1105 radeonEmitState(radeon
);
1107 if (radeon
->cmdbuf
.cs
->cdw
)
1108 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1110 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1111 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1113 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1114 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1115 __DRIdrawablePrivate
* drawable
= radeon_get_drawable(radeon
);
1116 (*screen
->dri2
.loader
->flushFrontBuffer
)(drawable
, drawable
->loaderPrivate
);
1118 /* Only clear the dirty bit if front-buffer rendering is no longer
1119 * enabled. This is done so that the dirty bit can only be set in
1120 * glDrawBuffer. Otherwise the dirty bit would have to be set at
1121 * each of N places that do rendering. This has worse performances,
1122 * but it is much easier to get correct.
1124 if (!radeon
->is_front_buffer_rendering
) {
1125 radeon
->front_buffer_dirty
= GL_FALSE
;
1130 make_empty_list(&radeon
->query
.not_flushed_head
);
1134 /* Make sure all commands have been sent to the hardware and have
1135 * completed processing.
1137 void radeonFinish(GLcontext
* ctx
)
1139 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1140 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1143 if (ctx
->Driver
.Flush
)
1144 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
1146 if (radeon
->radeonScreen
->kernel_mm
) {
1147 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1148 struct radeon_renderbuffer
*rrb
;
1149 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1151 radeon_bo_wait(rrb
->bo
);
1154 struct radeon_renderbuffer
*rrb
;
1155 rrb
= radeon_get_depthbuffer(radeon
);
1157 radeon_bo_wait(rrb
->bo
);
1159 } else if (radeon
->do_irqs
) {
1160 LOCK_HARDWARE(radeon
);
1161 radeonEmitIrqLocked(radeon
);
1162 UNLOCK_HARDWARE(radeon
);
1163 radeonWaitIrq(radeon
);
1165 radeonWaitForIdle(radeon
);
1171 * Send the current command buffer via ioctl to the hardware.
1173 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1177 if (rmesa
->cmdbuf
.flushing
) {
1178 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1181 rmesa
->cmdbuf
.flushing
= 1;
1183 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
1184 fprintf(stderr
, "%s from %s - %i cliprects\n",
1185 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1188 radeonEmitQueryEnd(rmesa
->glCtx
);
1190 if (rmesa
->cmdbuf
.cs
->cdw
) {
1191 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1192 rmesa
->hw
.all_dirty
= GL_TRUE
;
1194 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1195 rmesa
->cmdbuf
.flushing
= 0;
1197 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1198 fprintf(stderr
,"failed to revalidate buffers\n");
1204 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1208 radeonReleaseDmaRegions(rmesa
);
1210 LOCK_HARDWARE(rmesa
);
1211 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1212 UNLOCK_HARDWARE(rmesa
);
1215 fprintf(stderr
, "drmRadeonCmdBuffer: %d\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 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
1253 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
1254 sizeof(drm_r300_cmd_header_t
));
1255 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
1256 sizeof(drm_radeon_cmd_buffer_t
));
1258 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1259 size
* 4, rmesa
->hw
.max_state_size
* 4);
1262 if (rmesa
->radeonScreen
->kernel_mm
) {
1263 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1264 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1266 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1268 if (rmesa
->cmdbuf
.csm
== NULL
) {
1269 /* FIXME: fatal error */
1272 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1273 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1274 rmesa
->cmdbuf
.size
= size
;
1276 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
1277 (void (*)(void *))rmesa
->glCtx
->Driver
.Flush
, rmesa
->glCtx
);
1279 if (!rmesa
->radeonScreen
->kernel_mm
) {
1280 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1281 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1283 struct drm_radeon_gem_info mminfo
= { 0 };
1285 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1287 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1288 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1294 * Destroy the command buffer
1296 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1298 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1299 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1300 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1302 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1306 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1309 const char *function
,
1312 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1313 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1314 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
1315 radeonEmitState(rmesa
);
1317 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1319 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_IOCTL
)
1320 fprintf(stderr
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1321 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1325 void radeonUserClear(GLcontext
*ctx
, GLuint mask
)
1327 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1328 meta_clear_tris(&rmesa
->meta
, mask
);