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/api_arrayelt.h"
49 #include "main/enums.h"
50 #include "main/colormac.h"
51 #include "main/light.h"
52 #include "main/framebuffer.h"
53 #include "main/simple_list.h"
54 #include "main/renderbuffer.h"
55 #include "swrast/swrast.h"
58 #include "tnl/t_pipeline.h"
59 #include "swrast_setup/swrast_setup.h"
64 #include "radeon_common.h"
65 #include "radeon_bocs_wrapper.h"
66 #include "radeon_lock.h"
67 #include "radeon_drm.h"
68 #include "radeon_mipmap_tree.h"
70 #define DEBUG_CMDBUF 0
72 /* =============================================================
76 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
77 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
88 if (out
->x1
>= out
->x2
)
90 if (out
->y1
>= out
->y2
)
95 void radeonRecalcScissorRects(radeonContextPtr radeon
)
100 /* Grow cliprect store?
102 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
103 while (radeon
->state
.scissor
.numAllocedClipRects
<
104 radeon
->numClipRects
) {
105 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
106 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
109 if (radeon
->state
.scissor
.pClipRects
)
110 FREE(radeon
->state
.scissor
.pClipRects
);
112 radeon
->state
.scissor
.pClipRects
=
113 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
114 sizeof(drm_clip_rect_t
));
116 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
117 radeon
->state
.scissor
.numAllocedClipRects
= 0;
122 out
= radeon
->state
.scissor
.pClipRects
;
123 radeon
->state
.scissor
.numClipRects
= 0;
125 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
126 if (intersect_rect(out
,
127 &radeon
->pClipRects
[i
],
128 &radeon
->state
.scissor
.rect
)) {
129 radeon
->state
.scissor
.numClipRects
++;
135 static void radeon_get_cliprects(radeonContextPtr radeon
,
136 struct drm_clip_rect
**cliprects
,
137 unsigned int *num_cliprects
,
138 int *x_off
, int *y_off
)
140 __DRIdrawablePrivate
*dPriv
= radeon
->dri
.drawable
;
141 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
143 if (radeon
->constant_cliprect
) {
144 radeon
->fboRect
.x1
= 0;
145 radeon
->fboRect
.y1
= 0;
146 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
147 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
149 *cliprects
= &radeon
->fboRect
;
153 } else if (radeon
->front_cliprects
||
154 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
155 *cliprects
= dPriv
->pClipRects
;
156 *num_cliprects
= dPriv
->numClipRects
;
160 *num_cliprects
= dPriv
->numBackClipRects
;
161 *cliprects
= dPriv
->pBackClipRects
;
162 *x_off
= dPriv
->backX
;
163 *y_off
= dPriv
->backY
;
168 * Update cliprects and scissors.
170 void radeonSetCliprects(radeonContextPtr radeon
)
172 __DRIdrawablePrivate
*const drawable
= radeon
->dri
.drawable
;
173 __DRIdrawablePrivate
*const readable
= radeon
->dri
.readable
;
174 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
175 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
178 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
179 &radeon
->numClipRects
, &x_off
, &y_off
);
181 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
182 (draw_rfb
->base
.Height
!= drawable
->h
)) {
183 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
184 drawable
->w
, drawable
->h
);
185 draw_rfb
->base
.Initialized
= GL_TRUE
;
188 if (drawable
!= readable
) {
189 if ((read_rfb
->base
.Width
!= readable
->w
) ||
190 (read_rfb
->base
.Height
!= readable
->h
)) {
191 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
192 readable
->w
, readable
->h
);
193 read_rfb
->base
.Initialized
= GL_TRUE
;
197 if (radeon
->state
.scissor
.enabled
)
198 radeonRecalcScissorRects(radeon
);
204 void radeonUpdateScissor( GLcontext
*ctx
)
206 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
208 if ( rmesa
->dri
.drawable
) {
209 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
211 int x
= ctx
->Scissor
.X
;
212 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
213 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
214 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
216 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
217 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
218 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
219 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
221 radeonRecalcScissorRects( rmesa
);
225 /* =============================================================
229 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
231 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
232 if (ctx
->Scissor
.Enabled
) {
233 /* We don't pipeline cliprect changes */
234 radeon_firevertices(radeon
);
235 radeonUpdateScissor(ctx
);
240 /* ================================================================
241 * SwapBuffers with client-side throttling
244 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
246 drm_radeon_getparam_t gp
;
250 gp
.param
= RADEON_PARAM_LAST_FRAME
;
251 gp
.value
= (int *)&frame
;
252 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
255 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
263 uint32_t radeonGetAge(radeonContextPtr radeon
)
265 drm_radeon_getparam_t gp
;
269 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
270 gp
.value
= (int *)&age
;
271 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
274 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
282 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
284 drm_radeon_irq_emit_t ie
;
287 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
288 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
291 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
297 static void radeonWaitIrq(radeonContextPtr radeon
)
302 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
303 &radeon
->iw
, sizeof(radeon
->iw
));
304 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
307 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
313 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
315 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
317 if (radeon
->do_irqs
) {
318 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
319 if (!radeon
->irqsEmitted
) {
320 while (radeonGetLastFrame(radeon
) <
323 UNLOCK_HARDWARE(radeon
);
324 radeonWaitIrq(radeon
);
325 LOCK_HARDWARE(radeon
);
327 radeon
->irqsEmitted
= 10;
330 if (radeon
->irqsEmitted
) {
331 radeonEmitIrqLocked(radeon
);
332 radeon
->irqsEmitted
--;
335 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
336 UNLOCK_HARDWARE(radeon
);
337 if (radeon
->do_usleeps
)
339 LOCK_HARDWARE(radeon
);
345 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
351 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
354 } while (ret
&& ++i
< 100);
357 UNLOCK_HARDWARE(radeon
);
358 fprintf(stderr
, "Error: R300 timed out... exiting\n");
363 static void radeonWaitForIdle(radeonContextPtr radeon
)
365 LOCK_HARDWARE(radeon
);
366 radeonWaitForIdleLocked(radeon
);
367 UNLOCK_HARDWARE(radeon
);
370 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
372 int current_page
= rfb
->pf_current_page
;
373 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
374 struct gl_renderbuffer
*tmp_rb
;
376 /* Exchange renderbuffers if necessary but make sure their
377 * reference counts are preserved.
379 if (rfb
->color_rb
[current_page
] &&
380 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
381 &rfb
->color_rb
[current_page
]->base
) {
383 _mesa_reference_renderbuffer(&tmp_rb
,
384 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
385 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
386 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
387 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
390 if (rfb
->color_rb
[next_page
] &&
391 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
392 &rfb
->color_rb
[next_page
]->base
) {
394 _mesa_reference_renderbuffer(&tmp_rb
,
395 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
396 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
397 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
398 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
402 /* Copy the back color buffer to the front color buffer.
404 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
405 const drm_clip_rect_t
*rect
)
407 radeonContextPtr rmesa
;
408 struct radeon_framebuffer
*rfb
;
412 assert(dPriv
->driContextPriv
);
413 assert(dPriv
->driContextPriv
->driverPrivate
);
415 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
417 rfb
= dPriv
->driverPrivate
;
419 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
420 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
423 nbox
= dPriv
->numClipRects
; /* must be in locked region */
425 for ( i
= 0 ; i
< nbox
; ) {
426 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
427 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
428 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
431 for ( ; i
< nr
; i
++ ) {
437 if (rect
->x1
> b
->x1
)
439 if (rect
->y1
> b
->y1
)
441 if (rect
->x2
< b
->x2
)
443 if (rect
->y2
< b
->y2
)
446 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
453 rmesa
->sarea
->nbox
= n
;
458 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
461 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
462 UNLOCK_HARDWARE( rmesa
);
467 UNLOCK_HARDWARE( rmesa
);
470 static int radeonScheduleSwap(__DRIdrawablePrivate
*dPriv
, GLboolean
*missed_target
)
472 radeonContextPtr rmesa
;
474 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
475 radeon_firevertices(rmesa
);
477 LOCK_HARDWARE( rmesa
);
479 if (!dPriv
->numClipRects
) {
480 UNLOCK_HARDWARE(rmesa
);
481 usleep(10000); /* throttle invisible client 10ms */
485 radeonWaitForFrameCompletion(rmesa
);
487 UNLOCK_HARDWARE(rmesa
);
488 driWaitForVBlank(dPriv
, missed_target
);
489 LOCK_HARDWARE(rmesa
);
494 static GLboolean
radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
496 radeonContextPtr radeon
;
498 __DRIscreenPrivate
*psp
;
499 struct radeon_renderbuffer
*rrb
;
500 struct radeon_framebuffer
*rfb
;
503 assert(dPriv
->driContextPriv
);
504 assert(dPriv
->driContextPriv
->driverPrivate
);
506 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
507 rfb
= dPriv
->driverPrivate
;
508 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
510 psp
= dPriv
->driScreenPriv
;
512 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
513 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
514 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
516 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
517 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
519 radeon
->sarea
->nbox
= 1;
521 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
523 UNLOCK_HARDWARE( radeon
);
526 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
533 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
534 radeon_flip_renderbuffers(rfb
);
535 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
542 * Swap front and back buffer.
544 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
547 __DRIscreenPrivate
*psp
;
549 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
550 radeonContextPtr radeon
;
553 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
556 if (ctx
->Visual
.doubleBufferMode
) {
557 GLboolean missed_target
;
558 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
559 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
561 radeonScheduleSwap(dPriv
, &missed_target
);
563 if (rfb
->pf_active
) {
564 radeonPageFlip(dPriv
);
566 radeonCopyBuffer(dPriv
, NULL
);
569 psp
= dPriv
->driScreenPriv
;
572 (*psp
->systemTime
->getUST
)( & ust
);
573 if ( missed_target
) {
574 rfb
->swap_missed_count
++;
575 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
579 radeon
->hw
.all_dirty
= GL_TRUE
;
582 /* XXX this shouldn't be an error but we can't handle it for now */
583 _mesa_problem(NULL
, "%s: drawable has no context!",
588 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
589 int x
, int y
, int w
, int h
)
591 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
592 radeonContextPtr radeon
;
595 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
598 if (ctx
->Visual
.doubleBufferMode
) {
599 drm_clip_rect_t rect
;
600 rect
.x1
= x
+ dPriv
->x
;
601 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
602 rect
.x2
= rect
.x1
+ w
;
603 rect
.y2
= rect
.y1
+ h
;
604 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
605 radeonCopyBuffer(dPriv
, &rect
);
608 /* XXX this shouldn't be an error but we can't handle it for now */
609 _mesa_problem(NULL
, "%s: drawable has no context!",
614 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
616 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
617 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
622 /* this can happen during the initial context initialization */
626 /* radeons only handle 1 color draw so far */
627 if (fb
->_NumColorDrawBuffers
!= 1) {
628 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
632 /* Do this here, note core Mesa, since this function is called from
633 * many places within the driver.
635 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
636 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
637 _mesa_update_framebuffer(ctx
);
638 /* this updates the DrawBuffer's Width/Height if it's a FBO */
639 _mesa_update_draw_buffer_bounds(ctx
);
642 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
643 /* this may occur when we're called by glBindFrameBuffer() during
644 * the process of someone setting up renderbuffers, etc.
646 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
651 ;/* do something depthy/stencily TODO */
656 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
657 rrbColor
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
658 radeon
->front_cliprects
= GL_TRUE
;
660 rrbColor
= (void *)fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
661 radeon
->front_cliprects
= GL_FALSE
;
664 /* user FBO in theory */
665 struct radeon_renderbuffer
*rrb
;
666 rrb
= (void *)fb
->_ColorDrawBuffers
[0];
668 radeon
->constant_cliprect
= GL_TRUE
;
671 if (rrbColor
== NULL
)
672 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
674 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
678 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
679 rrbDepth
= (struct radeon_renderbuffer
*)fb
->_DepthBuffer
->Wrapped
;
680 if (rrbDepth
&& rrbDepth
->bo
) {
681 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
683 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
686 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
690 /* TODO stencil things */
691 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
692 rrbStencil
= (struct radeon_renderbuffer
*)fb
->_DepthBuffer
->Wrapped
;
693 if (rrbStencil
&& rrbStencil
->bo
) {
694 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
695 /* need to re-compute stencil hw state */
696 if (ctx
->Driver
.Enable
!= NULL
)
697 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
699 ctx
->NewState
|= _NEW_STENCIL
;
701 rrbDepth
= rrbStencil
;
703 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
706 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
707 if (ctx
->Driver
.Enable
!= NULL
)
708 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
710 ctx
->NewState
|= _NEW_STENCIL
;
713 /* Update culling direction which changes depending on the
714 * orientation of the buffer:
716 if (ctx
->Driver
.FrontFace
)
717 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
719 ctx
->NewState
|= _NEW_POLYGON
;
722 * Update depth test state
724 if (ctx
->Driver
.Enable
) {
725 if (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0) {
726 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
, GL_TRUE
);
728 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
, GL_FALSE
);
731 ctx
->NewState
|= _NEW_DEPTH
;
734 radeon
->state
.depth
.rrb
= rrbDepth
;
736 radeon
->state
.color
.rrb
= rrbColor
;
738 /* update viewport since it depends on window size */
739 if (ctx
->Driver
.Viewport
) {
740 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
741 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
743 ctx
->NewState
|= _NEW_VIEWPORT
;
746 /* Set state we know depends on drawable parameters:
748 if (ctx
->Driver
.Scissor
)
749 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
750 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
751 radeon
->NewGLState
|= _NEW_SCISSOR
;
755 * Called via glDrawBuffer.
757 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
759 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
761 if (RADEON_DEBUG
& DEBUG_DRI
)
762 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
763 _mesa_lookup_enum_by_nr( mode
));
765 radeon_firevertices(radeon
); /* don't pipeline cliprect changes */
767 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
770 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
772 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
773 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
774 /* This will update FBO completeness status.
775 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
776 * refers to a missing renderbuffer. Calling glReadBuffer can set
777 * that straight and can make the drawing buffer complete.
779 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
784 /* Turn on/off page flipping according to the flags in the sarea:
786 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
788 struct radeon_framebuffer
*rfb
= radeon
->dri
.drawable
->driverPrivate
;
790 rfb
->pf_active
= radeon
->sarea
->pfState
;
791 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
792 rfb
->pf_num_pages
= 2;
793 radeon_flip_renderbuffers(rfb
);
794 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
797 void radeon_window_moved(radeonContextPtr radeon
)
799 GLcontext
*ctx
= radeon
->glCtx
;
800 __DRIdrawablePrivate
*dPriv
= radeon
->dri
.drawable
;
801 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
803 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
804 radeonUpdatePageFlipping(radeon
);
806 radeonSetCliprects(radeon
);
809 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
811 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
812 __DRIcontext
*driContext
= radeon
->dri
.context
;
813 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
814 GLsizei w
, GLsizei h
);
816 if (!driContext
->driScreenPriv
->dri2
.enabled
)
819 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
820 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
821 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
823 old_viewport
= ctx
->Driver
.Viewport
;
824 ctx
->Driver
.Viewport
= NULL
;
825 radeon
->dri
.drawable
= driContext
->driDrawablePriv
;
826 radeon_window_moved(radeon
);
827 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
828 ctx
->Driver
.Viewport
= old_viewport
;
832 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
835 int dwords
= (*state
->check
)(radeon
->glCtx
, state
);
837 fprintf(stderr
, "emit %s %d/%d\n", state
->name
, state
->cmd_size
, dwords
);
839 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
840 for (i
= 0 ; i
< dwords
; i
++)
841 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
845 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean dirty
)
847 BATCH_LOCALS(radeon
);
848 struct radeon_state_atom
*atom
;
851 if (radeon
->vtbl
.pre_emit_atoms
)
852 radeon
->vtbl
.pre_emit_atoms(radeon
);
854 /* Emit actual atoms */
855 foreach(atom
, &radeon
->hw
.atomlist
) {
856 if ((atom
->dirty
|| radeon
->hw
.all_dirty
) == dirty
) {
857 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
859 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
860 radeon_print_state_atom(radeon
, atom
);
863 (*atom
->emit
)(radeon
->glCtx
, atom
);
865 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
866 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
869 atom
->dirty
= GL_FALSE
;
871 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
872 fprintf(stderr
, " skip state %s\n",
882 void radeonEmitState(radeonContextPtr radeon
)
884 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
885 fprintf(stderr
, "%s\n", __FUNCTION__
);
887 if (radeon
->vtbl
.pre_emit_state
)
888 radeon
->vtbl
.pre_emit_state(radeon
);
890 /* this code used to return here but now it emits zbs */
891 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
894 /* To avoid going across the entire set of states multiple times, just check
895 * for enough space for the case of emitting all state, and inline the
896 * radeonAllocCmdBuf code here without all the checks.
898 rcommonEnsureCmdBufSpace(radeon
, radeon
->hw
.max_state_size
, __FUNCTION__
);
900 if (!radeon
->cmdbuf
.cs
->cdw
) {
901 if (RADEON_DEBUG
& DEBUG_STATE
)
902 fprintf(stderr
, "Begin reemit state\n");
904 radeonEmitAtoms(radeon
, GL_FALSE
);
907 if (RADEON_DEBUG
& DEBUG_STATE
)
908 fprintf(stderr
, "Begin dirty state\n");
910 radeonEmitAtoms(radeon
, GL_TRUE
);
911 radeon
->hw
.is_dirty
= GL_FALSE
;
912 radeon
->hw
.all_dirty
= GL_FALSE
;
917 void radeonFlush(GLcontext
*ctx
)
919 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
920 if (RADEON_DEBUG
& DEBUG_IOCTL
)
921 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
923 if (radeon
->dma
.flush
)
924 radeon
->dma
.flush( ctx
);
926 radeonEmitState(radeon
);
928 if (radeon
->cmdbuf
.cs
->cdw
)
929 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
932 /* Make sure all commands have been sent to the hardware and have
933 * completed processing.
935 void radeonFinish(GLcontext
* ctx
)
937 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
938 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
943 if (radeon
->radeonScreen
->kernel_mm
) {
944 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
945 struct radeon_renderbuffer
*rrb
;
946 rrb
= (struct radeon_renderbuffer
*)fb
->_ColorDrawBuffers
[i
];
948 radeon_bo_wait(rrb
->bo
);
950 } else if (radeon
->do_irqs
) {
951 LOCK_HARDWARE(radeon
);
952 radeonEmitIrqLocked(radeon
);
953 UNLOCK_HARDWARE(radeon
);
954 radeonWaitIrq(radeon
);
956 radeonWaitForIdle(radeon
);
962 * Send the current command buffer via ioctl to the hardware.
964 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
968 if (rmesa
->cmdbuf
.flushing
) {
969 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
972 rmesa
->cmdbuf
.flushing
= 1;
974 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
975 fprintf(stderr
, "%s from %s - %i cliprects\n",
976 __FUNCTION__
, caller
, rmesa
->numClipRects
);
979 if (rmesa
->cmdbuf
.cs
->cdw
) {
980 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
981 rmesa
->hw
.all_dirty
= GL_TRUE
;
983 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
984 rmesa
->cmdbuf
.flushing
= 0;
988 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
992 radeonReleaseDmaRegion(rmesa
);
994 LOCK_HARDWARE(rmesa
);
995 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
996 UNLOCK_HARDWARE(rmesa
);
999 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
1007 * Make sure that enough space is available in the command buffer
1008 * by flushing if necessary.
1010 * \param dwords The number of dwords we need to be free on the command buffer
1012 void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1014 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
||
1015 radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1016 rcommonFlushCmdBuf(rmesa
, caller
);
1020 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1023 /* Initialize command buffer */
1024 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1025 "command_buffer_size");
1026 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1027 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1029 if (size
> 64 * 256)
1032 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
1033 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
1034 sizeof(drm_r300_cmd_header_t
));
1035 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
1036 sizeof(drm_radeon_cmd_buffer_t
));
1038 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1039 size
* 4, rmesa
->hw
.max_state_size
* 4);
1042 if (rmesa
->radeonScreen
->kernel_mm
) {
1043 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1044 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1046 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1048 if (rmesa
->cmdbuf
.csm
== NULL
) {
1049 /* FIXME: fatal error */
1052 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1053 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1054 rmesa
->cmdbuf
.size
= size
;
1056 if (!rmesa
->radeonScreen
->kernel_mm
) {
1057 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1058 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1060 struct drm_radeon_gem_info mminfo
;
1062 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1064 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_size
);
1065 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1071 * Destroy the command buffer
1073 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1075 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1076 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1077 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1079 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1083 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1086 const char *function
,
1089 rcommonEnsureCmdBufSpace(rmesa
, n
, function
);
1090 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1091 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1092 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
1093 radeonEmitState(rmesa
);
1095 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1097 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_IOCTL
)
1098 fprintf(stderr
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1099 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);