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
++;
152 if (radeon
->vtbl
.update_scissor
)
153 radeon
->vtbl
.update_scissor(radeon
->glCtx
);
156 void radeon_get_cliprects(radeonContextPtr radeon
,
157 struct drm_clip_rect
**cliprects
,
158 unsigned int *num_cliprects
,
159 int *x_off
, int *y_off
)
161 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(radeon
);
162 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
164 if (radeon
->constant_cliprect
) {
165 radeon
->fboRect
.x1
= 0;
166 radeon
->fboRect
.y1
= 0;
167 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
168 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
170 *cliprects
= &radeon
->fboRect
;
174 } else if (radeon
->front_cliprects
||
175 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
176 *cliprects
= dPriv
->pClipRects
;
177 *num_cliprects
= dPriv
->numClipRects
;
181 *num_cliprects
= dPriv
->numBackClipRects
;
182 *cliprects
= dPriv
->pBackClipRects
;
183 *x_off
= dPriv
->backX
;
184 *y_off
= dPriv
->backY
;
189 * Update cliprects and scissors.
191 void radeonSetCliprects(radeonContextPtr radeon
)
193 __DRIdrawablePrivate
*const drawable
= radeon_get_drawable(radeon
);
194 __DRIdrawablePrivate
*const readable
= radeon_get_readable(radeon
);
195 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
196 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
199 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
200 &radeon
->numClipRects
, &x_off
, &y_off
);
202 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
203 (draw_rfb
->base
.Height
!= drawable
->h
)) {
204 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
205 drawable
->w
, drawable
->h
);
206 draw_rfb
->base
.Initialized
= GL_TRUE
;
209 if (drawable
!= readable
) {
210 if ((read_rfb
->base
.Width
!= readable
->w
) ||
211 (read_rfb
->base
.Height
!= readable
->h
)) {
212 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
213 readable
->w
, readable
->h
);
214 read_rfb
->base
.Initialized
= GL_TRUE
;
218 if (radeon
->state
.scissor
.enabled
)
219 radeonRecalcScissorRects(radeon
);
225 void radeonUpdateScissor( GLcontext
*ctx
)
227 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
229 if ( !ctx
->DrawBuffer
->Name
) {
230 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(rmesa
);
232 int x
= ctx
->Scissor
.X
;
233 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
234 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
235 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
237 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
238 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
239 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
240 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
242 rmesa
->state
.scissor
.rect
.x1
= ctx
->Scissor
.X
;
243 rmesa
->state
.scissor
.rect
.y1
= ctx
->Scissor
.Y
;
244 rmesa
->state
.scissor
.rect
.x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
;
245 rmesa
->state
.scissor
.rect
.y2
= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
;
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
);
266 /* ================================================================
267 * SwapBuffers with client-side throttling
270 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
272 drm_radeon_getparam_t gp
;
276 gp
.param
= RADEON_PARAM_LAST_FRAME
;
277 gp
.value
= (int *)&frame
;
278 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
281 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
289 uint32_t radeonGetAge(radeonContextPtr radeon
)
291 drm_radeon_getparam_t gp
;
295 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
296 gp
.value
= (int *)&age
;
297 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
300 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
308 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
310 drm_radeon_irq_emit_t ie
;
313 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
314 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
317 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
323 static void radeonWaitIrq(radeonContextPtr radeon
)
328 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
329 &radeon
->iw
, sizeof(radeon
->iw
));
330 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
333 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
339 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
341 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
343 if (radeon
->do_irqs
) {
344 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
345 if (!radeon
->irqsEmitted
) {
346 while (radeonGetLastFrame(radeon
) <
349 UNLOCK_HARDWARE(radeon
);
350 radeonWaitIrq(radeon
);
351 LOCK_HARDWARE(radeon
);
353 radeon
->irqsEmitted
= 10;
356 if (radeon
->irqsEmitted
) {
357 radeonEmitIrqLocked(radeon
);
358 radeon
->irqsEmitted
--;
361 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
362 UNLOCK_HARDWARE(radeon
);
363 if (radeon
->do_usleeps
)
365 LOCK_HARDWARE(radeon
);
371 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
377 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
380 } while (ret
&& ++i
< 100);
383 UNLOCK_HARDWARE(radeon
);
384 fprintf(stderr
, "Error: R300 timed out... exiting\n");
389 static void radeonWaitForIdle(radeonContextPtr radeon
)
391 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
392 LOCK_HARDWARE(radeon
);
393 radeonWaitForIdleLocked(radeon
);
394 UNLOCK_HARDWARE(radeon
);
398 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
400 int current_page
= rfb
->pf_current_page
;
401 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
402 struct gl_renderbuffer
*tmp_rb
;
404 /* Exchange renderbuffers if necessary but make sure their
405 * reference counts are preserved.
407 if (rfb
->color_rb
[current_page
] &&
408 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
409 &rfb
->color_rb
[current_page
]->base
) {
411 _mesa_reference_renderbuffer(&tmp_rb
,
412 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
413 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
414 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
415 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
418 if (rfb
->color_rb
[next_page
] &&
419 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
420 &rfb
->color_rb
[next_page
]->base
) {
422 _mesa_reference_renderbuffer(&tmp_rb
,
423 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
424 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
425 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
426 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
430 /* Copy the back color buffer to the front color buffer.
432 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
433 const drm_clip_rect_t
*rect
)
435 radeonContextPtr rmesa
;
436 struct radeon_framebuffer
*rfb
;
440 assert(dPriv
->driContextPriv
);
441 assert(dPriv
->driContextPriv
->driverPrivate
);
443 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
445 LOCK_HARDWARE(rmesa
);
447 rfb
= dPriv
->driverPrivate
;
449 if ( RADEON_DEBUG
& DEBUG_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(__DRIdrawablePrivate
*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( __DRIdrawablePrivate
*dPriv
)
525 radeonContextPtr radeon
;
527 __DRIscreenPrivate
*psp
;
528 struct radeon_renderbuffer
*rrb
;
529 struct radeon_framebuffer
*rfb
;
532 assert(dPriv
->driContextPriv
);
533 assert(dPriv
->driContextPriv
->driverPrivate
);
535 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
536 rfb
= dPriv
->driverPrivate
;
537 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
539 psp
= dPriv
->driScreenPriv
;
541 LOCK_HARDWARE(radeon
);
543 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
544 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
545 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
547 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
548 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
550 radeon
->sarea
->nbox
= 1;
552 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
554 UNLOCK_HARDWARE(radeon
);
557 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
564 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
565 radeon_flip_renderbuffers(rfb
);
566 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
573 * Swap front and back buffer.
575 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
578 __DRIscreenPrivate
*psp
;
580 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
581 radeonContextPtr radeon
;
584 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
587 if (ctx
->Visual
.doubleBufferMode
) {
588 GLboolean missed_target
;
589 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
590 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
592 radeonScheduleSwap(dPriv
, &missed_target
);
594 if (rfb
->pf_active
) {
595 radeonPageFlip(dPriv
);
597 radeonCopyBuffer(dPriv
, NULL
);
600 psp
= dPriv
->driScreenPriv
;
603 (*psp
->systemTime
->getUST
)( & ust
);
604 if ( missed_target
) {
605 rfb
->swap_missed_count
++;
606 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
610 radeon
->hw
.all_dirty
= GL_TRUE
;
613 /* XXX this shouldn't be an error but we can't handle it for now */
614 _mesa_problem(NULL
, "%s: drawable has no context!",
619 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
620 int x
, int y
, int w
, int h
)
622 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
623 radeonContextPtr radeon
;
626 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
629 if (ctx
->Visual
.doubleBufferMode
) {
630 drm_clip_rect_t rect
;
631 rect
.x1
= x
+ dPriv
->x
;
632 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
633 rect
.x2
= rect
.x1
+ w
;
634 rect
.y2
= rect
.y1
+ h
;
635 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
636 radeonCopyBuffer(dPriv
, &rect
);
639 /* XXX this shouldn't be an error but we can't handle it for now */
640 _mesa_problem(NULL
, "%s: drawable has no context!",
645 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
647 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
648 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
654 /* this can happen during the initial context initialization */
658 /* radeons only handle 1 color draw so far */
659 if (fb
->_NumColorDrawBuffers
!= 1) {
660 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
664 /* Do this here, note core Mesa, since this function is called from
665 * many places within the driver.
667 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
668 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
669 _mesa_update_framebuffer(ctx
);
670 /* this updates the DrawBuffer's Width/Height if it's a FBO */
671 _mesa_update_draw_buffer_bounds(ctx
);
674 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
675 /* this may occur when we're called by glBindFrameBuffer() during
676 * the process of someone setting up renderbuffers, etc.
678 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
683 ;/* do something depthy/stencily TODO */
688 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
689 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
690 radeon
->front_cliprects
= GL_TRUE
;
691 radeon
->front_buffer_dirty
= GL_TRUE
;
693 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
694 radeon
->front_cliprects
= GL_FALSE
;
697 /* user FBO in theory */
698 struct radeon_renderbuffer
*rrb
;
699 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
701 offset
= rrb
->draw_offset
;
704 radeon
->constant_cliprect
= GL_TRUE
;
707 if (rrbColor
== NULL
)
708 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
710 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
713 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
714 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
715 if (rrbDepth
&& rrbDepth
->bo
) {
716 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
718 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
721 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
725 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
726 rrbStencil
= radeon_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
727 if (rrbStencil
&& rrbStencil
->bo
) {
728 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
729 /* need to re-compute stencil hw state */
731 rrbDepth
= rrbStencil
;
733 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
736 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
737 if (ctx
->Driver
.Enable
!= NULL
)
738 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
740 ctx
->NewState
|= _NEW_STENCIL
;
743 /* Update culling direction which changes depending on the
744 * orientation of the buffer:
746 if (ctx
->Driver
.FrontFace
)
747 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
749 ctx
->NewState
|= _NEW_POLYGON
;
752 * Update depth test state
754 if (ctx
->Driver
.Enable
) {
755 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
756 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
757 /* Need to update the derived ctx->Stencil._Enabled first */
758 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
759 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
761 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
764 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
765 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
766 radeon
->state
.color
.draw_offset
= offset
;
769 /* update viewport since it depends on window size */
770 if (ctx
->Driver
.Viewport
) {
771 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
772 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
777 ctx
->NewState
|= _NEW_VIEWPORT
;
779 /* Set state we know depends on drawable parameters:
781 radeonUpdateScissor(ctx
);
782 radeon
->NewGLState
|= _NEW_SCISSOR
;
784 if (ctx
->Driver
.DepthRange
)
785 ctx
->Driver
.DepthRange(ctx
,
789 /* Update culling direction which changes depending on the
790 * orientation of the buffer:
792 if (ctx
->Driver
.FrontFace
)
793 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
795 ctx
->NewState
|= _NEW_POLYGON
;
799 * Called via glDrawBuffer.
801 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
803 if (RADEON_DEBUG
& DEBUG_DRI
)
804 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
805 _mesa_lookup_enum_by_nr( mode
));
807 if (ctx
->DrawBuffer
->Name
== 0) {
808 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
810 const GLboolean was_front_buffer_rendering
=
811 radeon
->is_front_buffer_rendering
;
813 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
816 /* If we weren't front-buffer rendering before but we are now, make sure
817 * that the front-buffer has actually been allocated.
819 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
820 radeon_update_renderbuffers(radeon
->dri
.context
,
821 radeon
->dri
.context
->driDrawablePriv
);
825 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
828 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
830 if ((ctx
->DrawBuffer
!= NULL
) && (ctx
->DrawBuffer
->Name
== 0)) {
831 struct radeon_context
*const rmesa
= RADEON_CONTEXT(ctx
);
832 const GLboolean was_front_buffer_reading
= rmesa
->is_front_buffer_reading
;
833 rmesa
->is_front_buffer_reading
= (mode
== GL_FRONT_LEFT
)
834 || (mode
== GL_FRONT
);
836 if (!was_front_buffer_reading
&& rmesa
->is_front_buffer_reading
) {
837 radeon_update_renderbuffers(rmesa
->dri
.context
,
838 rmesa
->dri
.context
->driReadablePriv
);
841 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
842 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
843 /* This will update FBO completeness status.
844 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
845 * refers to a missing renderbuffer. Calling glReadBuffer can set
846 * that straight and can make the drawing buffer complete.
848 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
853 /* Turn on/off page flipping according to the flags in the sarea:
855 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
857 struct radeon_framebuffer
*rfb
= radeon_get_drawable(radeon
)->driverPrivate
;
859 rfb
->pf_active
= radeon
->sarea
->pfState
;
860 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
861 rfb
->pf_num_pages
= 2;
862 radeon_flip_renderbuffers(rfb
);
863 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
866 void radeon_window_moved(radeonContextPtr radeon
)
868 /* Cliprects has to be updated before doing anything else */
869 radeonSetCliprects(radeon
);
870 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
871 radeonUpdatePageFlipping(radeon
);
875 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
877 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
878 __DRIcontext
*driContext
= radeon
->dri
.context
;
879 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
880 GLsizei w
, GLsizei h
);
882 if (!driContext
->driScreenPriv
->dri2
.enabled
)
885 if (!radeon
->meta
.internal_viewport_call
&& ctx
->DrawBuffer
->Name
== 0) {
886 if (radeon
->is_front_buffer_rendering
) {
887 ctx
->Driver
.Flush(ctx
);
889 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
890 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
891 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
894 old_viewport
= ctx
->Driver
.Viewport
;
895 ctx
->Driver
.Viewport
= NULL
;
896 radeon_window_moved(radeon
);
897 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
898 ctx
->Driver
.Viewport
= old_viewport
;
901 static void radeon_print_state_atom_prekmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
904 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
905 drm_r300_cmd_header_t cmd
;
907 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
909 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
910 if (dwords
> state
->cmd_size
)
911 dwords
= state
->cmd_size
;
913 for (i
= 0; i
< dwords
;) {
914 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
915 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
916 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
917 state
->name
, i
, reg
, cmd
.packet0
.count
);
919 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
920 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
921 state
->name
, i
, reg
, state
->cmd
[i
]);
929 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
931 int i
, j
, reg
, count
;
934 if (! (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) )
937 if (!radeon
->radeonScreen
->kernel_mm
) {
938 radeon_print_state_atom_prekmm(radeon
, state
);
942 dwords
= (*state
->check
) (radeon
->glCtx
, state
);
944 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
946 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
947 if (dwords
> state
->cmd_size
)
948 dwords
= state
->cmd_size
;
949 for (i
= 0; i
< state
->cmd_size
;) {
950 packet0
= state
->cmd
[i
];
951 reg
= (packet0
& 0x1FFF) << 2;
952 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
953 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
954 state
->name
, i
, reg
, count
);
956 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
957 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
958 state
->name
, i
, reg
, state
->cmd
[i
]);
967 * Count total size for next state emit.
969 GLuint
radeonCountStateEmitSize(radeonContextPtr radeon
)
971 struct radeon_state_atom
*atom
;
973 /* check if we are going to emit full state */
974 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_VERBOSE
)
975 fprintf(stderr
, "%s\n", __func__
);
977 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.all_dirty
) {
978 if (!radeon
->hw
.is_dirty
)
980 foreach(atom
, &radeon
->hw
.atomlist
) {
982 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
984 if (DEBUG_CMDBUF
&& atom_size
) {
985 radeon_print_state_atom(radeon
, atom
);
990 foreach(atom
, &radeon
->hw
.atomlist
) {
991 const GLuint atom_size
= atom
->check(radeon
->glCtx
, atom
);
993 if (DEBUG_CMDBUF
&& atom_size
) {
994 radeon_print_state_atom(radeon
, atom
);
1002 static INLINE
void radeon_emit_atom(radeonContextPtr radeon
, struct radeon_state_atom
*atom
)
1004 BATCH_LOCALS(radeon
);
1007 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
1010 radeon_print_state_atom(radeon
, atom
);
1013 (*atom
->emit
)(radeon
->glCtx
, atom
);
1015 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
1016 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
1020 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
1021 fprintf(stderr
, " skip state %s\n",
1025 atom
->dirty
= GL_FALSE
;
1029 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean emitAll
)
1031 struct radeon_state_atom
*atom
;
1033 if (radeon
->vtbl
.pre_emit_atoms
)
1034 radeon
->vtbl
.pre_emit_atoms(radeon
);
1036 /* Emit actual atoms */
1037 if (radeon
->hw
.all_dirty
|| emitAll
) {
1038 foreach(atom
, &radeon
->hw
.atomlist
)
1039 radeon_emit_atom( radeon
, atom
);
1041 foreach(atom
, &radeon
->hw
.atomlist
) {
1043 radeon_emit_atom( radeon
, atom
);
1050 static GLboolean
radeon_revalidate_bos(GLcontext
*ctx
)
1052 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1055 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
);
1056 if (ret
== RADEON_CS_SPACE_FLUSH
)
1061 void radeonEmitState(radeonContextPtr radeon
)
1063 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
1064 fprintf(stderr
, "%s\n", __FUNCTION__
);
1066 if (radeon
->vtbl
.pre_emit_state
)
1067 radeon
->vtbl
.pre_emit_state(radeon
);
1069 /* this code used to return here but now it emits zbs */
1070 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1073 if (!radeon
->cmdbuf
.cs
->cdw
) {
1074 if (RADEON_DEBUG
& DEBUG_STATE
)
1075 fprintf(stderr
, "Begin reemit state\n");
1077 radeonEmitAtoms(radeon
, GL_TRUE
);
1080 if (RADEON_DEBUG
& DEBUG_STATE
)
1081 fprintf(stderr
, "Begin dirty state\n");
1083 radeonEmitAtoms(radeon
, GL_FALSE
);
1086 radeon
->hw
.is_dirty
= GL_FALSE
;
1087 radeon
->hw
.all_dirty
= GL_FALSE
;
1091 void radeonFlush(GLcontext
*ctx
)
1093 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1094 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1095 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1097 /* okay if we have no cmds in the buffer &&
1098 we have no DMA flush &&
1099 we have no DMA buffer allocated.
1100 then no point flushing anything at all.
1102 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& is_empty_list(&radeon
->dma
.reserved
))
1105 if (radeon
->dma
.flush
)
1106 radeon
->dma
.flush( ctx
);
1108 radeonEmitState(radeon
);
1110 if (radeon
->cmdbuf
.cs
->cdw
)
1111 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1113 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1114 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1116 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1117 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1118 __DRIdrawablePrivate
* drawable
= radeon_get_drawable(radeon
);
1119 (*screen
->dri2
.loader
->flushFrontBuffer
)(drawable
, drawable
->loaderPrivate
);
1121 /* Only clear the dirty bit if front-buffer rendering is no longer
1122 * enabled. This is done so that the dirty bit can only be set in
1123 * glDrawBuffer. Otherwise the dirty bit would have to be set at
1124 * each of N places that do rendering. This has worse performances,
1125 * but it is much easier to get correct.
1127 if (!radeon
->is_front_buffer_rendering
) {
1128 radeon
->front_buffer_dirty
= GL_FALSE
;
1133 make_empty_list(&radeon
->query
.not_flushed_head
);
1137 /* Make sure all commands have been sent to the hardware and have
1138 * completed processing.
1140 void radeonFinish(GLcontext
* ctx
)
1142 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1143 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1146 if (ctx
->Driver
.Flush
)
1147 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
1149 if (radeon
->radeonScreen
->kernel_mm
) {
1150 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1151 struct radeon_renderbuffer
*rrb
;
1152 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1154 radeon_bo_wait(rrb
->bo
);
1157 struct radeon_renderbuffer
*rrb
;
1158 rrb
= radeon_get_depthbuffer(radeon
);
1160 radeon_bo_wait(rrb
->bo
);
1162 } else if (radeon
->do_irqs
) {
1163 LOCK_HARDWARE(radeon
);
1164 radeonEmitIrqLocked(radeon
);
1165 UNLOCK_HARDWARE(radeon
);
1166 radeonWaitIrq(radeon
);
1168 radeonWaitForIdle(radeon
);
1174 * Send the current command buffer via ioctl to the hardware.
1176 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1180 if (rmesa
->cmdbuf
.flushing
) {
1181 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1184 rmesa
->cmdbuf
.flushing
= 1;
1186 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
1187 fprintf(stderr
, "%s from %s - %i cliprects\n",
1188 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1191 radeonEmitQueryEnd(rmesa
->glCtx
);
1193 if (rmesa
->cmdbuf
.cs
->cdw
) {
1194 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1195 rmesa
->hw
.all_dirty
= GL_TRUE
;
1197 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1198 rmesa
->cmdbuf
.flushing
= 0;
1200 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1201 fprintf(stderr
,"failed to revalidate buffers\n");
1207 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1211 radeonReleaseDmaRegions(rmesa
);
1213 LOCK_HARDWARE(rmesa
);
1214 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1215 UNLOCK_HARDWARE(rmesa
);
1218 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
1226 * Make sure that enough space is available in the command buffer
1227 * by flushing if necessary.
1229 * \param dwords The number of dwords we need to be free on the command buffer
1231 GLboolean
rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1233 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
1234 || radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1235 /* If we try to flush empty buffer there is too big rendering operation. */
1236 assert(rmesa
->cmdbuf
.cs
->cdw
);
1237 rcommonFlushCmdBuf(rmesa
, caller
);
1243 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1246 /* Initialize command buffer */
1247 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1248 "command_buffer_size");
1249 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1250 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1252 if (size
> 64 * 256)
1255 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
1256 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
1257 sizeof(drm_r300_cmd_header_t
));
1258 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
1259 sizeof(drm_radeon_cmd_buffer_t
));
1261 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1262 size
* 4, rmesa
->hw
.max_state_size
* 4);
1265 if (rmesa
->radeonScreen
->kernel_mm
) {
1266 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1267 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1269 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1271 if (rmesa
->cmdbuf
.csm
== NULL
) {
1272 /* FIXME: fatal error */
1275 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1276 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1277 rmesa
->cmdbuf
.size
= size
;
1279 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
1280 (void (*)(void *))rmesa
->glCtx
->Driver
.Flush
, rmesa
->glCtx
);
1282 if (!rmesa
->radeonScreen
->kernel_mm
) {
1283 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1284 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1286 struct drm_radeon_gem_info mminfo
= { 0 };
1288 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1290 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1291 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1297 * Destroy the command buffer
1299 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1301 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1302 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1303 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1305 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1309 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1312 const char *function
,
1315 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1316 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1317 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
1318 radeonEmitState(rmesa
);
1320 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1322 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_IOCTL
)
1323 fprintf(stderr
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1324 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1328 void radeonUserClear(GLcontext
*ctx
, GLuint mask
)
1330 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1331 meta_clear_tris(&rmesa
->meta
, mask
);