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"
87 #define DEBUG_CMDBUF 0
89 /* =============================================================
93 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
94 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
105 if (out
->x1
>= out
->x2
)
107 if (out
->y1
>= out
->y2
)
112 void radeonRecalcScissorRects(radeonContextPtr radeon
)
114 drm_clip_rect_t
*out
;
117 /* Grow cliprect store?
119 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
120 while (radeon
->state
.scissor
.numAllocedClipRects
<
121 radeon
->numClipRects
) {
122 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
123 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
126 if (radeon
->state
.scissor
.pClipRects
)
127 FREE(radeon
->state
.scissor
.pClipRects
);
129 radeon
->state
.scissor
.pClipRects
=
130 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
131 sizeof(drm_clip_rect_t
));
133 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
134 radeon
->state
.scissor
.numAllocedClipRects
= 0;
139 out
= radeon
->state
.scissor
.pClipRects
;
140 radeon
->state
.scissor
.numClipRects
= 0;
142 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
143 if (intersect_rect(out
,
144 &radeon
->pClipRects
[i
],
145 &radeon
->state
.scissor
.rect
)) {
146 radeon
->state
.scissor
.numClipRects
++;
152 void radeon_get_cliprects(radeonContextPtr radeon
,
153 struct drm_clip_rect
**cliprects
,
154 unsigned int *num_cliprects
,
155 int *x_off
, int *y_off
)
157 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(radeon
);
158 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
160 if (radeon
->constant_cliprect
) {
161 radeon
->fboRect
.x1
= 0;
162 radeon
->fboRect
.y1
= 0;
163 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
164 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
166 *cliprects
= &radeon
->fboRect
;
170 } else if (radeon
->front_cliprects
||
171 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
172 *cliprects
= dPriv
->pClipRects
;
173 *num_cliprects
= dPriv
->numClipRects
;
177 *num_cliprects
= dPriv
->numBackClipRects
;
178 *cliprects
= dPriv
->pBackClipRects
;
179 *x_off
= dPriv
->backX
;
180 *y_off
= dPriv
->backY
;
185 * Update cliprects and scissors.
187 void radeonSetCliprects(radeonContextPtr radeon
)
189 __DRIdrawablePrivate
*const drawable
= radeon_get_drawable(radeon
);
190 __DRIdrawablePrivate
*const readable
= radeon_get_readable(radeon
);
191 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
192 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
195 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
196 &radeon
->numClipRects
, &x_off
, &y_off
);
198 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
199 (draw_rfb
->base
.Height
!= drawable
->h
)) {
200 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
201 drawable
->w
, drawable
->h
);
202 draw_rfb
->base
.Initialized
= GL_TRUE
;
205 if (drawable
!= readable
) {
206 if ((read_rfb
->base
.Width
!= readable
->w
) ||
207 (read_rfb
->base
.Height
!= readable
->h
)) {
208 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
209 readable
->w
, readable
->h
);
210 read_rfb
->base
.Initialized
= GL_TRUE
;
214 if (radeon
->state
.scissor
.enabled
)
215 radeonRecalcScissorRects(radeon
);
221 void radeonUpdateScissor( GLcontext
*ctx
)
223 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
225 if ( !ctx
->DrawBuffer
->Name
) {
226 __DRIdrawablePrivate
*dPriv
= radeon_get_drawable(rmesa
);
228 int x
= ctx
->Scissor
.X
;
229 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
230 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
231 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
233 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
234 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
235 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
236 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
238 rmesa
->state
.scissor
.rect
.x1
= ctx
->Scissor
.X
;
239 rmesa
->state
.scissor
.rect
.y1
= ctx
->Scissor
.Y
;
240 rmesa
->state
.scissor
.rect
.x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
;
241 rmesa
->state
.scissor
.rect
.y2
= ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
;
244 radeonRecalcScissorRects( rmesa
);
247 /* =============================================================
251 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
253 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
254 if (ctx
->Scissor
.Enabled
) {
255 /* We don't pipeline cliprect changes */
256 radeon_firevertices(radeon
);
257 radeonUpdateScissor(ctx
);
262 /* ================================================================
263 * SwapBuffers with client-side throttling
266 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
268 drm_radeon_getparam_t gp
;
272 gp
.param
= RADEON_PARAM_LAST_FRAME
;
273 gp
.value
= (int *)&frame
;
274 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
277 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
285 uint32_t radeonGetAge(radeonContextPtr radeon
)
287 drm_radeon_getparam_t gp
;
291 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
292 gp
.value
= (int *)&age
;
293 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
296 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
304 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
306 drm_radeon_irq_emit_t ie
;
309 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
310 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
313 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
319 static void radeonWaitIrq(radeonContextPtr radeon
)
324 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
325 &radeon
->iw
, sizeof(radeon
->iw
));
326 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
329 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
335 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
337 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
339 if (radeon
->do_irqs
) {
340 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
341 if (!radeon
->irqsEmitted
) {
342 while (radeonGetLastFrame(radeon
) <
345 UNLOCK_HARDWARE(radeon
);
346 radeonWaitIrq(radeon
);
347 LOCK_HARDWARE(radeon
);
349 radeon
->irqsEmitted
= 10;
352 if (radeon
->irqsEmitted
) {
353 radeonEmitIrqLocked(radeon
);
354 radeon
->irqsEmitted
--;
357 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
358 UNLOCK_HARDWARE(radeon
);
359 if (radeon
->do_usleeps
)
361 LOCK_HARDWARE(radeon
);
367 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
373 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
376 } while (ret
&& ++i
< 100);
379 UNLOCK_HARDWARE(radeon
);
380 fprintf(stderr
, "Error: R300 timed out... exiting\n");
385 static void radeonWaitForIdle(radeonContextPtr radeon
)
387 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
388 LOCK_HARDWARE(radeon
);
389 radeonWaitForIdleLocked(radeon
);
390 UNLOCK_HARDWARE(radeon
);
394 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
396 int current_page
= rfb
->pf_current_page
;
397 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
398 struct gl_renderbuffer
*tmp_rb
;
400 /* Exchange renderbuffers if necessary but make sure their
401 * reference counts are preserved.
403 if (rfb
->color_rb
[current_page
] &&
404 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
405 &rfb
->color_rb
[current_page
]->base
) {
407 _mesa_reference_renderbuffer(&tmp_rb
,
408 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
409 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
410 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
411 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
414 if (rfb
->color_rb
[next_page
] &&
415 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
416 &rfb
->color_rb
[next_page
]->base
) {
418 _mesa_reference_renderbuffer(&tmp_rb
,
419 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
420 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
421 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
422 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
426 /* Copy the back color buffer to the front color buffer.
428 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
429 const drm_clip_rect_t
*rect
)
431 radeonContextPtr rmesa
;
432 struct radeon_framebuffer
*rfb
;
436 assert(dPriv
->driContextPriv
);
437 assert(dPriv
->driContextPriv
->driverPrivate
);
439 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
441 LOCK_HARDWARE(rmesa
);
443 rfb
= dPriv
->driverPrivate
;
445 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
446 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
449 nbox
= dPriv
->numClipRects
; /* must be in locked region */
451 for ( i
= 0 ; i
< nbox
; ) {
452 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
453 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
454 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
457 for ( ; i
< nr
; i
++ ) {
463 if (rect
->x1
> b
->x1
)
465 if (rect
->y1
> b
->y1
)
467 if (rect
->x2
< b
->x2
)
469 if (rect
->y2
< b
->y2
)
472 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
479 rmesa
->sarea
->nbox
= n
;
484 if (IS_R600_CLASS(rmesa
->radeonScreen
)) {
485 int cpp
= rmesa
->radeonScreen
->cpp
;
486 int src_pitch
= rmesa
->radeonScreen
->backPitch
* cpp
;
487 int dst_pitch
= rmesa
->radeonScreen
->frontPitch
* cpp
;
488 char *src
= (char *)rmesa
->radeonScreen
->driScreen
->pFB
+ rmesa
->radeonScreen
->backOffset
;
489 char *dst
= (char *)rmesa
->radeonScreen
->driScreen
->pFB
+ rmesa
->radeonScreen
->frontOffset
;
491 drm_clip_rect_t
*pb
= rmesa
->sarea
->boxes
;
493 for (j
= 0; j
< n
; j
++) {
496 int w
= pb
[j
].x2
- x
;
497 int h
= pb
[j
].y2
- y
;
499 src
+= (y
* src_pitch
) + (x
* cpp
);
500 dst
+= (y
* dst_pitch
) + (x
* cpp
);
503 memcpy(dst
, src
, w
* cpp
);
510 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
513 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
514 UNLOCK_HARDWARE( rmesa
);
519 UNLOCK_HARDWARE( rmesa
);
522 static int radeonScheduleSwap(__DRIdrawablePrivate
*dPriv
, GLboolean
*missed_target
)
524 radeonContextPtr rmesa
;
526 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
527 radeon_firevertices(rmesa
);
529 LOCK_HARDWARE( rmesa
);
531 if (!dPriv
->numClipRects
) {
532 UNLOCK_HARDWARE(rmesa
);
533 usleep(10000); /* throttle invisible client 10ms */
537 radeonWaitForFrameCompletion(rmesa
);
539 UNLOCK_HARDWARE(rmesa
);
540 driWaitForVBlank(dPriv
, missed_target
);
545 static GLboolean
radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
547 radeonContextPtr radeon
;
549 __DRIscreenPrivate
*psp
;
550 struct radeon_renderbuffer
*rrb
;
551 struct radeon_framebuffer
*rfb
;
554 assert(dPriv
->driContextPriv
);
555 assert(dPriv
->driContextPriv
->driverPrivate
);
557 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
558 rfb
= dPriv
->driverPrivate
;
559 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
561 psp
= dPriv
->driScreenPriv
;
563 LOCK_HARDWARE(radeon
);
565 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
566 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
567 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
569 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
570 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
572 radeon
->sarea
->nbox
= 1;
574 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
576 UNLOCK_HARDWARE(radeon
);
579 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
586 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
587 radeon_flip_renderbuffers(rfb
);
588 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
595 * Swap front and back buffer.
597 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
600 __DRIscreenPrivate
*psp
;
602 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
603 radeonContextPtr radeon
;
606 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
609 if (ctx
->Visual
.doubleBufferMode
) {
610 GLboolean missed_target
;
611 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
612 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
614 radeonScheduleSwap(dPriv
, &missed_target
);
616 if (rfb
->pf_active
) {
617 radeonPageFlip(dPriv
);
619 radeonCopyBuffer(dPriv
, NULL
);
622 psp
= dPriv
->driScreenPriv
;
625 (*psp
->systemTime
->getUST
)( & ust
);
626 if ( missed_target
) {
627 rfb
->swap_missed_count
++;
628 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
632 radeon
->hw
.all_dirty
= GL_TRUE
;
635 /* XXX this shouldn't be an error but we can't handle it for now */
636 _mesa_problem(NULL
, "%s: drawable has no context!",
641 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
642 int x
, int y
, int w
, int h
)
644 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
645 radeonContextPtr radeon
;
648 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
651 if (ctx
->Visual
.doubleBufferMode
) {
652 drm_clip_rect_t rect
;
653 rect
.x1
= x
+ dPriv
->x
;
654 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
655 rect
.x2
= rect
.x1
+ w
;
656 rect
.y2
= rect
.y1
+ h
;
657 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
658 radeonCopyBuffer(dPriv
, &rect
);
661 /* XXX this shouldn't be an error but we can't handle it for now */
662 _mesa_problem(NULL
, "%s: drawable has no context!",
667 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
669 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
670 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
676 /* this can happen during the initial context initialization */
680 /* radeons only handle 1 color draw so far */
681 if (fb
->_NumColorDrawBuffers
!= 1) {
682 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
686 /* Do this here, note core Mesa, since this function is called from
687 * many places within the driver.
689 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
690 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
691 _mesa_update_framebuffer(ctx
);
692 /* this updates the DrawBuffer's Width/Height if it's a FBO */
693 _mesa_update_draw_buffer_bounds(ctx
);
696 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
697 /* this may occur when we're called by glBindFrameBuffer() during
698 * the process of someone setting up renderbuffers, etc.
700 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
705 ;/* do something depthy/stencily TODO */
710 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
711 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
712 radeon
->front_cliprects
= GL_TRUE
;
713 radeon
->front_buffer_dirty
= GL_TRUE
;
715 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
716 radeon
->front_cliprects
= GL_FALSE
;
719 /* user FBO in theory */
720 struct radeon_renderbuffer
*rrb
;
721 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
723 offset
= rrb
->draw_offset
;
726 radeon
->constant_cliprect
= GL_TRUE
;
729 if (rrbColor
== NULL
)
730 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
732 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
735 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
736 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
737 if (rrbDepth
&& rrbDepth
->bo
) {
738 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
740 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
743 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
747 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
748 rrbStencil
= radeon_renderbuffer(fb
->_StencilBuffer
->Wrapped
);
749 if (rrbStencil
&& rrbStencil
->bo
) {
750 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
751 /* need to re-compute stencil hw state */
753 rrbDepth
= rrbStencil
;
755 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
758 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
759 if (ctx
->Driver
.Enable
!= NULL
)
760 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
762 ctx
->NewState
|= _NEW_STENCIL
;
765 /* Update culling direction which changes depending on the
766 * orientation of the buffer:
768 if (ctx
->Driver
.FrontFace
)
769 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
771 ctx
->NewState
|= _NEW_POLYGON
;
774 * Update depth test state
776 if (ctx
->Driver
.Enable
) {
777 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
778 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
779 /* Need to update the derived ctx->Stencil._Enabled first */
780 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
781 (ctx
->Stencil
.Enabled
&& fb
->Visual
.stencilBits
> 0));
783 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
786 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
787 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
788 radeon
->state
.color
.draw_offset
= offset
;
791 /* update viewport since it depends on window size */
792 if (ctx
->Driver
.Viewport
) {
793 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
794 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
799 ctx
->NewState
|= _NEW_VIEWPORT
;
801 /* Set state we know depends on drawable parameters:
803 radeonUpdateScissor(ctx
);
804 radeon
->NewGLState
|= _NEW_SCISSOR
;
806 if (ctx
->Driver
.DepthRange
)
807 ctx
->Driver
.DepthRange(ctx
,
811 /* Update culling direction which changes depending on the
812 * orientation of the buffer:
814 if (ctx
->Driver
.FrontFace
)
815 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
817 ctx
->NewState
|= _NEW_POLYGON
;
821 * Called via glDrawBuffer.
823 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
825 if (RADEON_DEBUG
& DEBUG_DRI
)
826 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
827 _mesa_lookup_enum_by_nr( mode
));
829 if (ctx
->DrawBuffer
->Name
== 0) {
830 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
832 const GLboolean was_front_buffer_rendering
=
833 radeon
->is_front_buffer_rendering
;
835 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
838 /* If we weren't front-buffer rendering before but we are now, make sure
839 * that the front-buffer has actually been allocated.
841 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
842 radeon_update_renderbuffers(radeon
->dri
.context
,
843 radeon
->dri
.context
->driDrawablePriv
);
847 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
850 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
852 if ((ctx
->DrawBuffer
!= NULL
) && (ctx
->DrawBuffer
->Name
== 0)) {
853 struct radeon_context
*const rmesa
= RADEON_CONTEXT(ctx
);
854 const GLboolean was_front_buffer_reading
= rmesa
->is_front_buffer_reading
;
855 rmesa
->is_front_buffer_reading
= (mode
== GL_FRONT_LEFT
)
856 || (mode
== GL_FRONT
);
858 if (!was_front_buffer_reading
&& rmesa
->is_front_buffer_reading
) {
859 radeon_update_renderbuffers(rmesa
->dri
.context
,
860 rmesa
->dri
.context
->driReadablePriv
);
863 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
864 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
865 /* This will update FBO completeness status.
866 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
867 * refers to a missing renderbuffer. Calling glReadBuffer can set
868 * that straight and can make the drawing buffer complete.
870 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
875 /* Turn on/off page flipping according to the flags in the sarea:
877 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
879 struct radeon_framebuffer
*rfb
= radeon_get_drawable(radeon
)->driverPrivate
;
881 rfb
->pf_active
= radeon
->sarea
->pfState
;
882 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
883 rfb
->pf_num_pages
= 2;
884 radeon_flip_renderbuffers(rfb
);
885 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
888 void radeon_window_moved(radeonContextPtr radeon
)
890 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
891 radeonUpdatePageFlipping(radeon
);
893 radeonSetCliprects(radeon
);
896 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
898 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
899 __DRIcontext
*driContext
= radeon
->dri
.context
;
900 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
901 GLsizei w
, GLsizei h
);
903 if (!driContext
->driScreenPriv
->dri2
.enabled
)
906 if (!radeon
->meta
.internal_viewport_call
&& ctx
->DrawBuffer
->Name
== 0) {
907 if (radeon
->is_front_buffer_rendering
) {
910 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
911 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
912 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
915 old_viewport
= ctx
->Driver
.Viewport
;
916 ctx
->Driver
.Viewport
= NULL
;
917 radeon_window_moved(radeon
);
918 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
919 ctx
->Driver
.Viewport
= old_viewport
;
922 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
925 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
926 drm_r300_cmd_header_t cmd
;
928 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
930 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
931 for (i
= 0; i
< dwords
;) {
932 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
933 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
934 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
935 state
->name
, i
, reg
, cmd
.packet0
.count
);
937 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
938 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
939 state
->name
, i
, reg
, state
->cmd
[i
]);
947 static void radeon_print_state_atom_kmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
949 int i
, j
, reg
, count
;
950 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
953 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
955 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
956 for (i
= 0; i
< dwords
;) {
957 packet0
= state
->cmd
[i
];
958 reg
= (packet0
& 0x1FFF) << 2;
959 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
960 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
961 state
->name
, i
, reg
, count
);
963 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
964 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
965 state
->name
, i
, reg
, state
->cmd
[i
]);
973 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean dirty
)
975 BATCH_LOCALS(radeon
);
976 struct radeon_state_atom
*atom
;
979 if (radeon
->vtbl
.pre_emit_atoms
)
980 radeon
->vtbl
.pre_emit_atoms(radeon
);
982 /* Emit actual atoms */
983 foreach(atom
, &radeon
->hw
.atomlist
) {
984 if ((atom
->dirty
|| radeon
->hw
.all_dirty
) == dirty
) {
985 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
987 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
988 if (radeon
->radeonScreen
->kernel_mm
)
989 radeon_print_state_atom_kmm(radeon
, atom
);
991 radeon_print_state_atom(radeon
, atom
);
994 (*atom
->emit
)(radeon
->glCtx
, atom
);
996 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
997 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
1000 atom
->dirty
= GL_FALSE
;
1002 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
1003 fprintf(stderr
, " skip state %s\n",
1013 static GLboolean
radeon_revalidate_bos(GLcontext
*ctx
)
1015 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1018 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
);
1019 if (ret
== RADEON_CS_SPACE_FLUSH
)
1024 void radeonEmitState(radeonContextPtr radeon
)
1026 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
1027 fprintf(stderr
, "%s\n", __FUNCTION__
);
1029 if (radeon
->vtbl
.pre_emit_state
)
1030 radeon
->vtbl
.pre_emit_state(radeon
);
1032 /* this code used to return here but now it emits zbs */
1033 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1036 /* To avoid going across the entire set of states multiple times, just check
1037 * for enough space for the case of emitting all state, and inline the
1038 * radeonAllocCmdBuf code here without all the checks.
1040 rcommonEnsureCmdBufSpace(radeon
, radeon
->hw
.max_state_size
, __FUNCTION__
);
1042 if (!radeon
->cmdbuf
.cs
->cdw
) {
1043 if (RADEON_DEBUG
& DEBUG_STATE
)
1044 fprintf(stderr
, "Begin reemit state\n");
1046 radeonEmitAtoms(radeon
, GL_FALSE
);
1049 if (RADEON_DEBUG
& DEBUG_STATE
)
1050 fprintf(stderr
, "Begin dirty state\n");
1052 radeonEmitAtoms(radeon
, GL_TRUE
);
1053 radeon
->hw
.is_dirty
= GL_FALSE
;
1054 radeon
->hw
.all_dirty
= GL_FALSE
;
1059 void radeonFlush(GLcontext
*ctx
)
1061 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1062 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1063 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1065 /* okay if we have no cmds in the buffer &&
1066 we have no DMA flush &&
1067 we have no DMA buffer allocated.
1068 then no point flushing anything at all.
1070 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& !radeon
->dma
.current
)
1073 if (radeon
->dma
.flush
)
1074 radeon
->dma
.flush( ctx
);
1076 radeonEmitState(radeon
);
1078 if (radeon
->cmdbuf
.cs
->cdw
)
1079 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1081 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1082 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1084 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1085 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1086 __DRIdrawablePrivate
* drawable
= radeon_get_drawable(radeon
);
1087 (*screen
->dri2
.loader
->flushFrontBuffer
)(drawable
, drawable
->loaderPrivate
);
1089 /* Only clear the dirty bit if front-buffer rendering is no longer
1090 * enabled. This is done so that the dirty bit can only be set in
1091 * glDrawBuffer. Otherwise the dirty bit would have to be set at
1092 * each of N places that do rendering. This has worse performances,
1093 * but it is much easier to get correct.
1095 if (radeon
->is_front_buffer_rendering
) {
1096 radeon
->front_buffer_dirty
= GL_FALSE
;
1102 /* Make sure all commands have been sent to the hardware and have
1103 * completed processing.
1105 void radeonFinish(GLcontext
* ctx
)
1107 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1108 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1111 if (ctx
->Driver
.Flush
)
1112 ctx
->Driver
.Flush(ctx
); /* +r6/r7 */
1114 if (radeon
->radeonScreen
->kernel_mm
) {
1115 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1116 struct radeon_renderbuffer
*rrb
;
1117 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1119 radeon_bo_wait(rrb
->bo
);
1122 struct radeon_renderbuffer
*rrb
;
1123 rrb
= radeon_get_depthbuffer(radeon
);
1125 radeon_bo_wait(rrb
->bo
);
1127 } else if (radeon
->do_irqs
) {
1128 LOCK_HARDWARE(radeon
);
1129 radeonEmitIrqLocked(radeon
);
1130 UNLOCK_HARDWARE(radeon
);
1131 radeonWaitIrq(radeon
);
1133 radeonWaitForIdle(radeon
);
1139 * Send the current command buffer via ioctl to the hardware.
1141 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1145 if (rmesa
->cmdbuf
.flushing
) {
1146 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1149 rmesa
->cmdbuf
.flushing
= 1;
1151 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
1152 fprintf(stderr
, "%s from %s - %i cliprects\n",
1153 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1156 if (rmesa
->cmdbuf
.cs
->cdw
) {
1157 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1158 rmesa
->hw
.all_dirty
= GL_TRUE
;
1160 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1161 rmesa
->cmdbuf
.flushing
= 0;
1163 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1164 fprintf(stderr
,"failed to revalidate buffers\n");
1170 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1174 radeonReleaseDmaRegion(rmesa
);
1176 LOCK_HARDWARE(rmesa
);
1177 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1178 UNLOCK_HARDWARE(rmesa
);
1181 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
1189 * Make sure that enough space is available in the command buffer
1190 * by flushing if necessary.
1192 * \param dwords The number of dwords we need to be free on the command buffer
1194 void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1196 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
||
1197 radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1198 rcommonFlushCmdBuf(rmesa
, caller
);
1202 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1205 /* Initialize command buffer */
1206 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1207 "command_buffer_size");
1208 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1209 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1211 if (size
> 64 * 256)
1214 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
1215 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
1216 sizeof(drm_r300_cmd_header_t
));
1217 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
1218 sizeof(drm_radeon_cmd_buffer_t
));
1220 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1221 size
* 4, rmesa
->hw
.max_state_size
* 4);
1224 if (rmesa
->radeonScreen
->kernel_mm
) {
1225 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1226 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1228 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1230 if (rmesa
->cmdbuf
.csm
== NULL
) {
1231 /* FIXME: fatal error */
1234 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1235 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1236 rmesa
->cmdbuf
.size
= size
;
1238 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
1239 (void (*)(void *))radeonFlush
, rmesa
->glCtx
);
1241 if (!rmesa
->radeonScreen
->kernel_mm
) {
1242 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1243 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1245 struct drm_radeon_gem_info mminfo
= { 0 };
1247 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1249 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1250 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1256 * Destroy the command buffer
1258 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1260 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1261 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1262 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1264 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1268 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1271 const char *function
,
1274 rcommonEnsureCmdBufSpace(rmesa
, n
, function
);
1275 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1276 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1277 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
1278 radeonEmitState(rmesa
);
1280 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1282 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_IOCTL
)
1283 fprintf(stderr
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1284 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1288 void radeonUserClear(GLcontext
*ctx
, GLuint mask
)
1290 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1291 meta_clear_tris(&rmesa
->meta
, mask
);