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"
61 #include "main/blend.h"
62 #include "main/bufferobj.h"
63 #include "main/buffers.h"
64 #include "main/depth.h"
65 #include "main/polygon.h"
66 #include "main/shaders.h"
67 #include "main/texstate.h"
68 #include "main/varray.h"
69 #include "glapi/dispatch.h"
70 #include "swrast/swrast.h"
71 #include "main/stencil.h"
72 #include "main/matrix.h"
73 #include "main/attrib.h"
74 #include "main/enable.h"
75 #include "main/viewport.h"
80 #include "radeon_common.h"
81 #include "radeon_bocs_wrapper.h"
82 #include "radeon_lock.h"
83 #include "radeon_drm.h"
84 #include "radeon_mipmap_tree.h"
86 #define DEBUG_CMDBUF 0
88 /* =============================================================
92 static GLboolean
intersect_rect(drm_clip_rect_t
* out
,
93 drm_clip_rect_t
* a
, drm_clip_rect_t
* b
)
104 if (out
->x1
>= out
->x2
)
106 if (out
->y1
>= out
->y2
)
111 void radeonRecalcScissorRects(radeonContextPtr radeon
)
113 drm_clip_rect_t
*out
;
116 /* Grow cliprect store?
118 if (radeon
->state
.scissor
.numAllocedClipRects
< radeon
->numClipRects
) {
119 while (radeon
->state
.scissor
.numAllocedClipRects
<
120 radeon
->numClipRects
) {
121 radeon
->state
.scissor
.numAllocedClipRects
+= 1; /* zero case */
122 radeon
->state
.scissor
.numAllocedClipRects
*= 2;
125 if (radeon
->state
.scissor
.pClipRects
)
126 FREE(radeon
->state
.scissor
.pClipRects
);
128 radeon
->state
.scissor
.pClipRects
=
129 MALLOC(radeon
->state
.scissor
.numAllocedClipRects
*
130 sizeof(drm_clip_rect_t
));
132 if (radeon
->state
.scissor
.pClipRects
== NULL
) {
133 radeon
->state
.scissor
.numAllocedClipRects
= 0;
138 out
= radeon
->state
.scissor
.pClipRects
;
139 radeon
->state
.scissor
.numClipRects
= 0;
141 for (i
= 0; i
< radeon
->numClipRects
; i
++) {
142 if (intersect_rect(out
,
143 &radeon
->pClipRects
[i
],
144 &radeon
->state
.scissor
.rect
)) {
145 radeon
->state
.scissor
.numClipRects
++;
151 void radeon_get_cliprects(radeonContextPtr radeon
,
152 struct drm_clip_rect
**cliprects
,
153 unsigned int *num_cliprects
,
154 int *x_off
, int *y_off
)
156 __DRIdrawablePrivate
*dPriv
= radeon
->dri
.drawable
;
157 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
159 if (radeon
->constant_cliprect
) {
160 radeon
->fboRect
.x1
= 0;
161 radeon
->fboRect
.y1
= 0;
162 radeon
->fboRect
.x2
= radeon
->glCtx
->DrawBuffer
->Width
;
163 radeon
->fboRect
.y2
= radeon
->glCtx
->DrawBuffer
->Height
;
165 *cliprects
= &radeon
->fboRect
;
169 } else if (radeon
->front_cliprects
||
170 rfb
->pf_active
|| dPriv
->numBackClipRects
== 0) {
171 *cliprects
= dPriv
->pClipRects
;
172 *num_cliprects
= dPriv
->numClipRects
;
176 *num_cliprects
= dPriv
->numBackClipRects
;
177 *cliprects
= dPriv
->pBackClipRects
;
178 *x_off
= dPriv
->backX
;
179 *y_off
= dPriv
->backY
;
184 * Update cliprects and scissors.
186 void radeonSetCliprects(radeonContextPtr radeon
)
188 __DRIdrawablePrivate
*const drawable
= radeon
->dri
.drawable
;
189 __DRIdrawablePrivate
*const readable
= radeon
->dri
.readable
;
190 struct radeon_framebuffer
*const draw_rfb
= drawable
->driverPrivate
;
191 struct radeon_framebuffer
*const read_rfb
= readable
->driverPrivate
;
194 radeon_get_cliprects(radeon
, &radeon
->pClipRects
,
195 &radeon
->numClipRects
, &x_off
, &y_off
);
197 if ((draw_rfb
->base
.Width
!= drawable
->w
) ||
198 (draw_rfb
->base
.Height
!= drawable
->h
)) {
199 _mesa_resize_framebuffer(radeon
->glCtx
, &draw_rfb
->base
,
200 drawable
->w
, drawable
->h
);
201 draw_rfb
->base
.Initialized
= GL_TRUE
;
204 if (drawable
!= readable
) {
205 if ((read_rfb
->base
.Width
!= readable
->w
) ||
206 (read_rfb
->base
.Height
!= readable
->h
)) {
207 _mesa_resize_framebuffer(radeon
->glCtx
, &read_rfb
->base
,
208 readable
->w
, readable
->h
);
209 read_rfb
->base
.Initialized
= GL_TRUE
;
213 if (radeon
->state
.scissor
.enabled
)
214 radeonRecalcScissorRects(radeon
);
220 void radeonUpdateScissor( GLcontext
*ctx
)
222 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
224 if ( rmesa
->dri
.drawable
) {
225 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
227 int x
= ctx
->Scissor
.X
;
228 int y
= dPriv
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
229 int w
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
230 int h
= dPriv
->h
- ctx
->Scissor
.Y
- 1;
232 rmesa
->state
.scissor
.rect
.x1
= x
+ dPriv
->x
;
233 rmesa
->state
.scissor
.rect
.y1
= y
+ dPriv
->y
;
234 rmesa
->state
.scissor
.rect
.x2
= w
+ dPriv
->x
+ 1;
235 rmesa
->state
.scissor
.rect
.y2
= h
+ dPriv
->y
+ 1;
237 radeonRecalcScissorRects( rmesa
);
241 /* =============================================================
245 void radeonScissor(GLcontext
* ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
247 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
248 if (ctx
->Scissor
.Enabled
) {
249 /* We don't pipeline cliprect changes */
250 radeon_firevertices(radeon
);
251 radeonUpdateScissor(ctx
);
256 /* ================================================================
257 * SwapBuffers with client-side throttling
260 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
262 drm_radeon_getparam_t gp
;
266 gp
.param
= RADEON_PARAM_LAST_FRAME
;
267 gp
.value
= (int *)&frame
;
268 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
271 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
279 uint32_t radeonGetAge(radeonContextPtr radeon
)
281 drm_radeon_getparam_t gp
;
285 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
286 gp
.value
= (int *)&age
;
287 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
290 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
298 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
300 drm_radeon_irq_emit_t ie
;
303 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
304 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
307 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
313 static void radeonWaitIrq(radeonContextPtr radeon
)
318 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
319 &radeon
->iw
, sizeof(radeon
->iw
));
320 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
323 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
329 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
331 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
333 if (radeon
->do_irqs
) {
334 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
335 if (!radeon
->irqsEmitted
) {
336 while (radeonGetLastFrame(radeon
) <
339 UNLOCK_HARDWARE(radeon
);
340 radeonWaitIrq(radeon
);
341 LOCK_HARDWARE(radeon
);
343 radeon
->irqsEmitted
= 10;
346 if (radeon
->irqsEmitted
) {
347 radeonEmitIrqLocked(radeon
);
348 radeon
->irqsEmitted
--;
351 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
352 UNLOCK_HARDWARE(radeon
);
353 if (radeon
->do_usleeps
)
355 LOCK_HARDWARE(radeon
);
361 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
367 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
370 } while (ret
&& ++i
< 100);
373 UNLOCK_HARDWARE(radeon
);
374 fprintf(stderr
, "Error: R300 timed out... exiting\n");
379 static void radeonWaitForIdle(radeonContextPtr radeon
)
381 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
382 LOCK_HARDWARE(radeon
);
383 radeonWaitForIdleLocked(radeon
);
384 UNLOCK_HARDWARE(radeon
);
388 static void radeon_flip_renderbuffers(struct radeon_framebuffer
*rfb
)
390 int current_page
= rfb
->pf_current_page
;
391 int next_page
= (current_page
+ 1) % rfb
->pf_num_pages
;
392 struct gl_renderbuffer
*tmp_rb
;
394 /* Exchange renderbuffers if necessary but make sure their
395 * reference counts are preserved.
397 if (rfb
->color_rb
[current_page
] &&
398 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
!=
399 &rfb
->color_rb
[current_page
]->base
) {
401 _mesa_reference_renderbuffer(&tmp_rb
,
402 rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
403 tmp_rb
= &rfb
->color_rb
[current_page
]->base
;
404 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
, tmp_rb
);
405 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
408 if (rfb
->color_rb
[next_page
] &&
409 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
!=
410 &rfb
->color_rb
[next_page
]->base
) {
412 _mesa_reference_renderbuffer(&tmp_rb
,
413 rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
414 tmp_rb
= &rfb
->color_rb
[next_page
]->base
;
415 _mesa_reference_renderbuffer(&rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
, tmp_rb
);
416 _mesa_reference_renderbuffer(&tmp_rb
, NULL
);
420 /* Copy the back color buffer to the front color buffer.
422 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
423 const drm_clip_rect_t
*rect
)
425 radeonContextPtr rmesa
;
426 struct radeon_framebuffer
*rfb
;
430 assert(dPriv
->driContextPriv
);
431 assert(dPriv
->driContextPriv
->driverPrivate
);
433 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
435 LOCK_HARDWARE(rmesa
);
437 rfb
= dPriv
->driverPrivate
;
439 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
440 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
443 nbox
= dPriv
->numClipRects
; /* must be in locked region */
445 for ( i
= 0 ; i
< nbox
; ) {
446 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
447 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
448 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
451 for ( ; i
< nr
; i
++ ) {
457 if (rect
->x1
> b
->x1
)
459 if (rect
->y1
> b
->y1
)
461 if (rect
->x2
< b
->x2
)
463 if (rect
->y2
< b
->y2
)
466 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
473 rmesa
->sarea
->nbox
= n
;
478 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
481 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
482 UNLOCK_HARDWARE( rmesa
);
487 UNLOCK_HARDWARE( rmesa
);
490 static int radeonScheduleSwap(__DRIdrawablePrivate
*dPriv
, GLboolean
*missed_target
)
492 radeonContextPtr rmesa
;
494 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
495 radeon_firevertices(rmesa
);
497 LOCK_HARDWARE( rmesa
);
499 if (!dPriv
->numClipRects
) {
500 UNLOCK_HARDWARE(rmesa
);
501 usleep(10000); /* throttle invisible client 10ms */
505 radeonWaitForFrameCompletion(rmesa
);
507 UNLOCK_HARDWARE(rmesa
);
508 driWaitForVBlank(dPriv
, missed_target
);
513 static GLboolean
radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
515 radeonContextPtr radeon
;
517 __DRIscreenPrivate
*psp
;
518 struct radeon_renderbuffer
*rrb
;
519 struct radeon_framebuffer
*rfb
;
522 assert(dPriv
->driContextPriv
);
523 assert(dPriv
->driContextPriv
->driverPrivate
);
525 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
526 rfb
= dPriv
->driverPrivate
;
527 rrb
= (void *)rfb
->base
.Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
529 psp
= dPriv
->driScreenPriv
;
531 LOCK_HARDWARE(radeon
);
533 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
534 fprintf(stderr
, "%s: pfCurrentPage: %d %d\n", __FUNCTION__
,
535 radeon
->sarea
->pfCurrentPage
, radeon
->sarea
->pfState
);
537 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
538 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
540 radeon
->sarea
->nbox
= 1;
542 ret
= drmCommandNone( radeon
->dri
.fd
, DRM_RADEON_FLIP
);
544 UNLOCK_HARDWARE(radeon
);
547 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
554 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
555 radeon_flip_renderbuffers(rfb
);
556 radeon_draw_buffer(radeon
->glCtx
, &rfb
->base
);
563 * Swap front and back buffer.
565 void radeonSwapBuffers(__DRIdrawablePrivate
* dPriv
)
568 __DRIscreenPrivate
*psp
;
570 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
571 radeonContextPtr radeon
;
574 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
577 if (ctx
->Visual
.doubleBufferMode
) {
578 GLboolean missed_target
;
579 struct radeon_framebuffer
*rfb
= dPriv
->driverPrivate
;
580 _mesa_notifySwapBuffers(ctx
);/* flush pending rendering comands */
582 radeonScheduleSwap(dPriv
, &missed_target
);
584 if (rfb
->pf_active
) {
585 radeonPageFlip(dPriv
);
587 radeonCopyBuffer(dPriv
, NULL
);
590 psp
= dPriv
->driScreenPriv
;
593 (*psp
->systemTime
->getUST
)( & ust
);
594 if ( missed_target
) {
595 rfb
->swap_missed_count
++;
596 rfb
->swap_missed_ust
= ust
- rfb
->swap_ust
;
600 radeon
->hw
.all_dirty
= GL_TRUE
;
603 /* XXX this shouldn't be an error but we can't handle it for now */
604 _mesa_problem(NULL
, "%s: drawable has no context!",
609 void radeonCopySubBuffer(__DRIdrawablePrivate
* dPriv
,
610 int x
, int y
, int w
, int h
)
612 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
613 radeonContextPtr radeon
;
616 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
619 if (ctx
->Visual
.doubleBufferMode
) {
620 drm_clip_rect_t rect
;
621 rect
.x1
= x
+ dPriv
->x
;
622 rect
.y1
= (dPriv
->h
- y
- h
) + dPriv
->y
;
623 rect
.x2
= rect
.x1
+ w
;
624 rect
.y2
= rect
.y1
+ h
;
625 _mesa_notifySwapBuffers(ctx
); /* flush pending rendering comands */
626 radeonCopyBuffer(dPriv
, &rect
);
629 /* XXX this shouldn't be an error but we can't handle it for now */
630 _mesa_problem(NULL
, "%s: drawable has no context!",
635 void radeon_draw_buffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
637 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
638 struct radeon_renderbuffer
*rrbDepth
= NULL
, *rrbStencil
= NULL
,
644 /* this can happen during the initial context initialization */
648 /* radeons only handle 1 color draw so far */
649 if (fb
->_NumColorDrawBuffers
!= 1) {
650 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
654 /* Do this here, note core Mesa, since this function is called from
655 * many places within the driver.
657 if (ctx
->NewState
& (_NEW_BUFFERS
| _NEW_COLOR
| _NEW_PIXEL
)) {
658 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
659 _mesa_update_framebuffer(ctx
);
660 /* this updates the DrawBuffer's Width/Height if it's a FBO */
661 _mesa_update_draw_buffer_bounds(ctx
);
664 if (fb
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
665 /* this may occur when we're called by glBindFrameBuffer() during
666 * the process of someone setting up renderbuffers, etc.
668 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
673 ;/* do something depthy/stencily TODO */
678 if (fb
->_ColorDrawBufferIndexes
[0] == BUFFER_FRONT_LEFT
) {
679 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
);
680 radeon
->front_cliprects
= GL_TRUE
;
681 radeon
->front_buffer_dirty
= GL_TRUE
;
683 rrbColor
= radeon_renderbuffer(fb
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
);
684 radeon
->front_cliprects
= GL_FALSE
;
687 /* user FBO in theory */
688 struct radeon_renderbuffer
*rrb
;
689 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[0]);
691 offset
= rrb
->draw_offset
;
694 radeon
->constant_cliprect
= GL_TRUE
;
697 if (rrbColor
== NULL
)
698 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
700 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
703 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
) {
704 rrbDepth
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
705 if (rrbDepth
&& rrbDepth
->bo
) {
706 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
708 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_TRUE
);
711 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_DEPTH_BUFFER
, GL_FALSE
);
715 if (fb
->_StencilBuffer
&& fb
->_StencilBuffer
->Wrapped
) {
716 rrbStencil
= radeon_renderbuffer(fb
->_DepthBuffer
->Wrapped
);
717 if (rrbStencil
&& rrbStencil
->bo
) {
718 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
719 /* need to re-compute stencil hw state */
721 rrbDepth
= rrbStencil
;
723 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_TRUE
);
726 radeon
->vtbl
.fallback(ctx
, RADEON_FALLBACK_STENCIL_BUFFER
, GL_FALSE
);
727 if (ctx
->Driver
.Enable
!= NULL
)
728 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
, ctx
->Stencil
.Enabled
);
730 ctx
->NewState
|= _NEW_STENCIL
;
733 /* Update culling direction which changes depending on the
734 * orientation of the buffer:
736 if (ctx
->Driver
.FrontFace
)
737 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
739 ctx
->NewState
|= _NEW_POLYGON
;
742 * Update depth test state
744 if (ctx
->Driver
.Enable
) {
745 ctx
->Driver
.Enable(ctx
, GL_DEPTH_TEST
,
746 (ctx
->Depth
.Test
&& fb
->Visual
.depthBits
> 0));
747 /* Need to update the derived ctx->Stencil._Enabled first */
748 _mesa_update_stencil(ctx
);
749 ctx
->Driver
.Enable(ctx
, GL_STENCIL_TEST
,
750 (ctx
->Stencil
._Enabled
&& fb
->Visual
.stencilBits
> 0));
752 ctx
->NewState
|= (_NEW_DEPTH
| _NEW_STENCIL
);
755 _mesa_reference_renderbuffer(&radeon
->state
.depth
.rb
, &rrbDepth
->base
);
756 _mesa_reference_renderbuffer(&radeon
->state
.color
.rb
, &rrbColor
->base
);
757 radeon
->state
.color
.draw_offset
= offset
;
760 /* update viewport since it depends on window size */
761 if (ctx
->Driver
.Viewport
) {
762 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
763 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
768 ctx
->NewState
|= _NEW_VIEWPORT
;
770 /* Set state we know depends on drawable parameters:
772 if (ctx
->Driver
.Scissor
)
773 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
774 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
775 radeon
->NewGLState
|= _NEW_SCISSOR
;
777 if (ctx
->Driver
.DepthRange
)
778 ctx
->Driver
.DepthRange(ctx
,
782 /* Update culling direction which changes depending on the
783 * orientation of the buffer:
785 if (ctx
->Driver
.FrontFace
)
786 ctx
->Driver
.FrontFace(ctx
, ctx
->Polygon
.FrontFace
);
788 ctx
->NewState
|= _NEW_POLYGON
;
792 * Called via glDrawBuffer.
794 void radeonDrawBuffer( GLcontext
*ctx
, GLenum mode
)
796 if (RADEON_DEBUG
& DEBUG_DRI
)
797 fprintf(stderr
, "%s %s\n", __FUNCTION__
,
798 _mesa_lookup_enum_by_nr( mode
));
800 if (ctx
->DrawBuffer
->Name
== 0) {
801 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
803 const GLboolean was_front_buffer_rendering
=
804 radeon
->is_front_buffer_rendering
;
806 radeon
->is_front_buffer_rendering
= (mode
== GL_FRONT_LEFT
) ||
809 /* If we weren't front-buffer rendering before but we are now, make sure
810 * that the front-buffer has actually been allocated.
812 if (!was_front_buffer_rendering
&& radeon
->is_front_buffer_rendering
) {
813 radeon_update_renderbuffers(radeon
->dri
.context
,
814 radeon
->dri
.context
->driDrawablePriv
);
818 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
821 void radeonReadBuffer( GLcontext
*ctx
, GLenum mode
)
823 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
824 if (ctx
->ReadBuffer
== ctx
->DrawBuffer
) {
825 /* This will update FBO completeness status.
826 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
827 * refers to a missing renderbuffer. Calling glReadBuffer can set
828 * that straight and can make the drawing buffer complete.
830 radeon_draw_buffer(ctx
, ctx
->DrawBuffer
);
835 /* Turn on/off page flipping according to the flags in the sarea:
837 void radeonUpdatePageFlipping(radeonContextPtr radeon
)
839 struct radeon_framebuffer
*rfb
= radeon
->dri
.drawable
->driverPrivate
;
841 rfb
->pf_active
= radeon
->sarea
->pfState
;
842 rfb
->pf_current_page
= radeon
->sarea
->pfCurrentPage
;
843 rfb
->pf_num_pages
= 2;
844 radeon_flip_renderbuffers(rfb
);
845 radeon_draw_buffer(radeon
->glCtx
, radeon
->glCtx
->DrawBuffer
);
848 void radeon_window_moved(radeonContextPtr radeon
)
850 if (!radeon
->radeonScreen
->driScreen
->dri2
.enabled
) {
851 radeonUpdatePageFlipping(radeon
);
853 radeonSetCliprects(radeon
);
856 void radeon_viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei width
, GLsizei height
)
858 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
859 __DRIcontext
*driContext
= radeon
->dri
.context
;
860 void (*old_viewport
)(GLcontext
*ctx
, GLint x
, GLint y
,
861 GLsizei w
, GLsizei h
);
863 if (!driContext
->driScreenPriv
->dri2
.enabled
)
866 radeon_update_renderbuffers(driContext
, driContext
->driDrawablePriv
);
867 if (driContext
->driDrawablePriv
!= driContext
->driReadablePriv
)
868 radeon_update_renderbuffers(driContext
, driContext
->driReadablePriv
);
870 old_viewport
= ctx
->Driver
.Viewport
;
871 ctx
->Driver
.Viewport
= NULL
;
872 radeon
->dri
.drawable
= driContext
->driDrawablePriv
;
873 radeon_window_moved(radeon
);
874 radeon_draw_buffer(ctx
, radeon
->glCtx
->DrawBuffer
);
875 ctx
->Driver
.Viewport
= old_viewport
;
878 static void radeon_print_state_atom(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
881 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
882 drm_r300_cmd_header_t cmd
;
884 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
886 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
887 for (i
= 0; i
< dwords
;) {
888 cmd
= *((drm_r300_cmd_header_t
*) &state
->cmd
[i
]);
889 reg
= (cmd
.packet0
.reghi
<< 8) | cmd
.packet0
.reglo
;
890 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
891 state
->name
, i
, reg
, cmd
.packet0
.count
);
893 for (j
= 0; j
< cmd
.packet0
.count
&& i
< dwords
; j
++) {
894 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
895 state
->name
, i
, reg
, state
->cmd
[i
]);
903 static void radeon_print_state_atom_kmm(radeonContextPtr radeon
, struct radeon_state_atom
*state
)
905 int i
, j
, reg
, count
;
906 int dwords
= (*state
->check
) (radeon
->glCtx
, state
);
909 fprintf(stderr
, " emit %s %d/%d\n", state
->name
, dwords
, state
->cmd_size
);
911 if (RADEON_DEBUG
& DEBUG_VERBOSE
) {
912 for (i
= 0; i
< dwords
;) {
913 packet0
= state
->cmd
[i
];
914 reg
= (packet0
& 0x1FFF) << 2;
915 count
= ((packet0
& 0x3FFF0000) >> 16) + 1;
916 fprintf(stderr
, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
917 state
->name
, i
, reg
, count
);
919 for (j
= 0; j
< count
&& i
< dwords
; j
++) {
920 fprintf(stderr
, " %s[%d]: 0x%04x = %08x\n",
921 state
->name
, i
, reg
, state
->cmd
[i
]);
929 static INLINE
void radeonEmitAtoms(radeonContextPtr radeon
, GLboolean dirty
)
931 BATCH_LOCALS(radeon
);
932 struct radeon_state_atom
*atom
;
935 if (radeon
->vtbl
.pre_emit_atoms
)
936 radeon
->vtbl
.pre_emit_atoms(radeon
);
938 /* Emit actual atoms */
939 foreach(atom
, &radeon
->hw
.atomlist
) {
940 if ((atom
->dirty
|| radeon
->hw
.all_dirty
) == dirty
) {
941 dwords
= (*atom
->check
) (radeon
->glCtx
, atom
);
943 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
944 if (radeon
->radeonScreen
->kernel_mm
)
945 radeon_print_state_atom_kmm(radeon
, atom
);
947 radeon_print_state_atom(radeon
, atom
);
950 (*atom
->emit
)(radeon
->glCtx
, atom
);
952 BEGIN_BATCH_NO_AUTOSTATE(dwords
);
953 OUT_BATCH_TABLE(atom
->cmd
, dwords
);
956 atom
->dirty
= GL_FALSE
;
958 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_STATE
) {
959 fprintf(stderr
, " skip state %s\n",
969 GLboolean
radeon_revalidate_bos(GLcontext
*ctx
)
971 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
975 ret
= radeon_cs_space_check(radeon
->cmdbuf
.cs
, radeon
->state
.bos
, radeon
->state
.validated_bo_count
);
976 if (ret
== RADEON_CS_SPACE_OP_TO_BIG
)
978 if (ret
== RADEON_CS_SPACE_FLUSH
) {
988 void radeon_validate_reset_bos(radeonContextPtr radeon
)
992 for (i
= 0; i
< radeon
->state
.validated_bo_count
; i
++) {
993 radeon_bo_unref(radeon
->state
.bos
[i
].bo
);
994 radeon
->state
.bos
[i
].bo
= NULL
;
995 radeon
->state
.bos
[i
].read_domains
= 0;
996 radeon
->state
.bos
[i
].write_domain
= 0;
997 radeon
->state
.bos
[i
].new_accounted
= 0;
999 radeon
->state
.validated_bo_count
= 0;
1002 void radeon_validate_bo(radeonContextPtr radeon
, struct radeon_bo
*bo
, uint32_t read_domains
, uint32_t write_domain
)
1005 radeon
->state
.bos
[radeon
->state
.validated_bo_count
].bo
= bo
;
1006 radeon
->state
.bos
[radeon
->state
.validated_bo_count
].read_domains
= read_domains
;
1007 radeon
->state
.bos
[radeon
->state
.validated_bo_count
].write_domain
= write_domain
;
1008 radeon
->state
.bos
[radeon
->state
.validated_bo_count
].new_accounted
= 0;
1009 radeon
->state
.validated_bo_count
++;
1011 assert(radeon
->state
.validated_bo_count
< RADEON_MAX_BOS
);
1014 void radeonEmitState(radeonContextPtr radeon
)
1016 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
1017 fprintf(stderr
, "%s\n", __FUNCTION__
);
1019 if (radeon
->vtbl
.pre_emit_state
)
1020 radeon
->vtbl
.pre_emit_state(radeon
);
1022 /* this code used to return here but now it emits zbs */
1023 if (radeon
->cmdbuf
.cs
->cdw
&& !radeon
->hw
.is_dirty
&& !radeon
->hw
.all_dirty
)
1026 /* To avoid going across the entire set of states multiple times, just check
1027 * for enough space for the case of emitting all state, and inline the
1028 * radeonAllocCmdBuf code here without all the checks.
1030 rcommonEnsureCmdBufSpace(radeon
, radeon
->hw
.max_state_size
, __FUNCTION__
);
1032 if (!radeon
->cmdbuf
.cs
->cdw
) {
1033 if (RADEON_DEBUG
& DEBUG_STATE
)
1034 fprintf(stderr
, "Begin reemit state\n");
1036 radeonEmitAtoms(radeon
, GL_FALSE
);
1039 if (RADEON_DEBUG
& DEBUG_STATE
)
1040 fprintf(stderr
, "Begin dirty state\n");
1042 radeonEmitAtoms(radeon
, GL_TRUE
);
1043 radeon
->hw
.is_dirty
= GL_FALSE
;
1044 radeon
->hw
.all_dirty
= GL_FALSE
;
1049 void radeonFlush(GLcontext
*ctx
)
1051 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1052 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1053 fprintf(stderr
, "%s %d\n", __FUNCTION__
, radeon
->cmdbuf
.cs
->cdw
);
1055 /* okay if we have no cmds in the buffer &&
1056 we have no DMA flush &&
1057 we have no DMA buffer allocated.
1058 then no point flushing anything at all.
1060 if (!radeon
->dma
.flush
&& !radeon
->cmdbuf
.cs
->cdw
&& !radeon
->dma
.current
)
1063 if (radeon
->dma
.flush
)
1064 radeon
->dma
.flush( ctx
);
1066 radeonEmitState(radeon
);
1068 if (radeon
->cmdbuf
.cs
->cdw
)
1069 rcommonFlushCmdBuf(radeon
, __FUNCTION__
);
1071 if ((ctx
->DrawBuffer
->Name
== 0) && radeon
->front_buffer_dirty
) {
1072 __DRIscreen
*const screen
= radeon
->radeonScreen
->driScreen
;
1074 if (screen
->dri2
.loader
&& (screen
->dri2
.loader
->base
.version
>= 2)
1075 && (screen
->dri2
.loader
->flushFrontBuffer
!= NULL
)) {
1076 (*screen
->dri2
.loader
->flushFrontBuffer
)(radeon
->dri
.drawable
,
1077 radeon
->dri
.drawable
->loaderPrivate
);
1079 /* Only clear the dirty bit if front-buffer rendering is no longer
1080 * enabled. This is done so that the dirty bit can only be set in
1081 * glDrawBuffer. Otherwise the dirty bit would have to be set at
1082 * each of N places that do rendering. This has worse performances,
1083 * but it is much easier to get correct.
1085 if (radeon
->is_front_buffer_rendering
) {
1086 radeon
->front_buffer_dirty
= GL_FALSE
;
1092 /* Make sure all commands have been sent to the hardware and have
1093 * completed processing.
1095 void radeonFinish(GLcontext
* ctx
)
1097 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
1098 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1103 if (radeon
->radeonScreen
->kernel_mm
) {
1104 for (i
= 0; i
< fb
->_NumColorDrawBuffers
; i
++) {
1105 struct radeon_renderbuffer
*rrb
;
1106 rrb
= radeon_renderbuffer(fb
->_ColorDrawBuffers
[i
]);
1108 radeon_bo_wait(rrb
->bo
);
1111 struct radeon_renderbuffer
*rrb
;
1112 rrb
= radeon_get_depthbuffer(radeon
);
1114 radeon_bo_wait(rrb
->bo
);
1116 } else if (radeon
->do_irqs
) {
1117 LOCK_HARDWARE(radeon
);
1118 radeonEmitIrqLocked(radeon
);
1119 UNLOCK_HARDWARE(radeon
);
1120 radeonWaitIrq(radeon
);
1122 radeonWaitForIdle(radeon
);
1128 * Send the current command buffer via ioctl to the hardware.
1130 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa
, const char *caller
)
1134 if (rmesa
->cmdbuf
.flushing
) {
1135 fprintf(stderr
, "Recursive call into r300FlushCmdBufLocked!\n");
1138 rmesa
->cmdbuf
.flushing
= 1;
1140 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
1141 fprintf(stderr
, "%s from %s - %i cliprects\n",
1142 __FUNCTION__
, caller
, rmesa
->numClipRects
);
1145 if (rmesa
->cmdbuf
.cs
->cdw
) {
1146 ret
= radeon_cs_emit(rmesa
->cmdbuf
.cs
);
1147 rmesa
->hw
.all_dirty
= GL_TRUE
;
1149 radeon_cs_erase(rmesa
->cmdbuf
.cs
);
1150 rmesa
->cmdbuf
.flushing
= 0;
1152 if (radeon_revalidate_bos(rmesa
->glCtx
) == GL_FALSE
) {
1153 fprintf(stderr
,"failed to revalidate buffers\n");
1159 int rcommonFlushCmdBuf(radeonContextPtr rmesa
, const char *caller
)
1163 radeonReleaseDmaRegion(rmesa
);
1165 LOCK_HARDWARE(rmesa
);
1166 ret
= rcommonFlushCmdBufLocked(rmesa
, caller
);
1167 UNLOCK_HARDWARE(rmesa
);
1170 fprintf(stderr
, "drmRadeonCmdBuffer: %d\n", ret
);
1178 * Make sure that enough space is available in the command buffer
1179 * by flushing if necessary.
1181 * \param dwords The number of dwords we need to be free on the command buffer
1183 void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa
, int dwords
, const char *caller
)
1185 if ((rmesa
->cmdbuf
.cs
->cdw
+ dwords
+ 128) > rmesa
->cmdbuf
.size
||
1186 radeon_cs_need_flush(rmesa
->cmdbuf
.cs
)) {
1187 rcommonFlushCmdBuf(rmesa
, caller
);
1191 void rcommonInitCmdBuf(radeonContextPtr rmesa
)
1194 /* Initialize command buffer */
1195 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
1196 "command_buffer_size");
1197 if (size
< 2 * rmesa
->hw
.max_state_size
) {
1198 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
1200 if (size
> 64 * 256)
1203 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
)) {
1204 fprintf(stderr
, "sizeof(drm_r300_cmd_header_t)=%zd\n",
1205 sizeof(drm_r300_cmd_header_t
));
1206 fprintf(stderr
, "sizeof(drm_radeon_cmd_buffer_t)=%zd\n",
1207 sizeof(drm_radeon_cmd_buffer_t
));
1209 "Allocating %d bytes command buffer (max state is %d bytes)\n",
1210 size
* 4, rmesa
->hw
.max_state_size
* 4);
1213 if (rmesa
->radeonScreen
->kernel_mm
) {
1214 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
1215 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
1217 rmesa
->cmdbuf
.csm
= radeon_cs_manager_legacy_ctor(rmesa
);
1219 if (rmesa
->cmdbuf
.csm
== NULL
) {
1220 /* FIXME: fatal error */
1223 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
1224 assert(rmesa
->cmdbuf
.cs
!= NULL
);
1225 rmesa
->cmdbuf
.size
= size
;
1227 if (!rmesa
->radeonScreen
->kernel_mm
) {
1228 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
1229 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
1231 struct drm_radeon_gem_info mminfo
= { 0 };
1233 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
1235 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
1236 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);
1242 * Destroy the command buffer
1244 void rcommonDestroyCmdBuf(radeonContextPtr rmesa
)
1246 radeon_cs_destroy(rmesa
->cmdbuf
.cs
);
1247 if (rmesa
->radeonScreen
->driScreen
->dri2
.enabled
|| rmesa
->radeonScreen
->kernel_mm
) {
1248 radeon_cs_manager_gem_dtor(rmesa
->cmdbuf
.csm
);
1250 radeon_cs_manager_legacy_dtor(rmesa
->cmdbuf
.csm
);
1254 void rcommonBeginBatch(radeonContextPtr rmesa
, int n
,
1257 const char *function
,
1260 rcommonEnsureCmdBufSpace(rmesa
, n
, function
);
1261 if (!rmesa
->cmdbuf
.cs
->cdw
&& dostate
) {
1262 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1263 fprintf(stderr
, "Reemit state after flush (from %s)\n", function
);
1264 radeonEmitState(rmesa
);
1266 radeon_cs_begin(rmesa
->cmdbuf
.cs
, n
, file
, function
, line
);
1268 if (DEBUG_CMDBUF
&& RADEON_DEBUG
& DEBUG_IOCTL
)
1269 fprintf(stderr
, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
1270 n
, rmesa
->cmdbuf
.cs
->cdw
, function
, line
);
1277 radeon_meta_set_passthrough_transform(radeonContextPtr radeon
)
1279 GLcontext
*ctx
= radeon
->glCtx
;
1281 radeon
->meta
.saved_vp_x
= ctx
->Viewport
.X
;
1282 radeon
->meta
.saved_vp_y
= ctx
->Viewport
.Y
;
1283 radeon
->meta
.saved_vp_width
= ctx
->Viewport
.Width
;
1284 radeon
->meta
.saved_vp_height
= ctx
->Viewport
.Height
;
1285 radeon
->meta
.saved_matrix_mode
= ctx
->Transform
.MatrixMode
;
1287 _mesa_Viewport(0, 0, ctx
->DrawBuffer
->Width
, ctx
->DrawBuffer
->Height
);
1289 _mesa_MatrixMode(GL_PROJECTION
);
1291 _mesa_LoadIdentity();
1292 _mesa_Ortho(0, ctx
->DrawBuffer
->Width
, 0, ctx
->DrawBuffer
->Height
, 1, -1);
1294 _mesa_MatrixMode(GL_MODELVIEW
);
1296 _mesa_LoadIdentity();
1300 radeon_meta_restore_transform(radeonContextPtr radeon
)
1302 _mesa_MatrixMode(GL_PROJECTION
);
1304 _mesa_MatrixMode(GL_MODELVIEW
);
1307 _mesa_MatrixMode(radeon
->meta
.saved_matrix_mode
);
1309 _mesa_Viewport(radeon
->meta
.saved_vp_x
, radeon
->meta
.saved_vp_y
,
1310 radeon
->meta
.saved_vp_width
, radeon
->meta
.saved_vp_height
);
1315 * Perform glClear where mask contains only color, depth, and/or stencil.
1317 * The implementation is based on calling into Mesa to set GL state and
1318 * performing normal triangle rendering. The intent of this path is to
1319 * have as generic a path as possible, so that any driver could make use of
1324 void radeon_clear_tris(GLcontext
*ctx
, GLbitfield mask
)
1326 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1327 GLfloat vertices
[4][3];
1328 GLfloat color
[4][4];
1330 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1332 GLboolean saved_fp_enable
= GL_FALSE
, saved_vp_enable
= GL_FALSE
;
1333 GLboolean saved_shader_program
= 0;
1334 unsigned int saved_active_texture
;
1336 assert((mask
& ~(TRI_CLEAR_COLOR_BITS
| BUFFER_BIT_DEPTH
|
1337 BUFFER_BIT_STENCIL
)) == 0);
1339 _mesa_PushAttrib(GL_COLOR_BUFFER_BIT
|
1341 GL_DEPTH_BUFFER_BIT
|
1344 GL_STENCIL_BUFFER_BIT
|
1347 _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT
);
1348 saved_active_texture
= ctx
->Texture
.CurrentUnit
;
1350 /* Disable existing GL state we don't want to apply to a clear. */
1351 _mesa_Disable(GL_ALPHA_TEST
);
1352 _mesa_Disable(GL_BLEND
);
1353 _mesa_Disable(GL_CULL_FACE
);
1354 _mesa_Disable(GL_FOG
);
1355 _mesa_Disable(GL_POLYGON_SMOOTH
);
1356 _mesa_Disable(GL_POLYGON_STIPPLE
);
1357 _mesa_Disable(GL_POLYGON_OFFSET_FILL
);
1358 _mesa_Disable(GL_LIGHTING
);
1359 _mesa_Disable(GL_CLIP_PLANE0
);
1360 _mesa_Disable(GL_CLIP_PLANE1
);
1361 _mesa_Disable(GL_CLIP_PLANE2
);
1362 _mesa_Disable(GL_CLIP_PLANE3
);
1363 _mesa_Disable(GL_CLIP_PLANE4
);
1364 _mesa_Disable(GL_CLIP_PLANE5
);
1365 _mesa_PolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
1366 if (ctx
->Extensions
.ARB_fragment_program
&& ctx
->FragmentProgram
.Enabled
) {
1367 saved_fp_enable
= GL_TRUE
;
1368 _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB
);
1370 if (ctx
->Extensions
.ARB_vertex_program
&& ctx
->VertexProgram
.Enabled
) {
1371 saved_vp_enable
= GL_TRUE
;
1372 _mesa_Disable(GL_VERTEX_PROGRAM_ARB
);
1374 if (ctx
->Extensions
.ARB_shader_objects
&& ctx
->Shader
.CurrentProgram
) {
1375 saved_shader_program
= ctx
->Shader
.CurrentProgram
->Name
;
1376 _mesa_UseProgramObjectARB(0);
1379 if (ctx
->Texture
._EnabledUnits
!= 0) {
1382 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1383 _mesa_ActiveTextureARB(GL_TEXTURE0
+ i
);
1384 _mesa_Disable(GL_TEXTURE_1D
);
1385 _mesa_Disable(GL_TEXTURE_2D
);
1386 _mesa_Disable(GL_TEXTURE_3D
);
1387 if (ctx
->Extensions
.ARB_texture_cube_map
)
1388 _mesa_Disable(GL_TEXTURE_CUBE_MAP_ARB
);
1389 if (ctx
->Extensions
.NV_texture_rectangle
)
1390 _mesa_Disable(GL_TEXTURE_RECTANGLE_NV
);
1391 if (ctx
->Extensions
.MESA_texture_array
) {
1392 _mesa_Disable(GL_TEXTURE_1D_ARRAY_EXT
);
1393 _mesa_Disable(GL_TEXTURE_2D_ARRAY_EXT
);
1398 #if FEATURE_ARB_vertex_buffer_object
1399 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
1400 _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
1403 radeon_meta_set_passthrough_transform(rmesa
);
1405 for (i
= 0; i
< 4; i
++) {
1406 color
[i
][0] = ctx
->Color
.ClearColor
[0];
1407 color
[i
][1] = ctx
->Color
.ClearColor
[1];
1408 color
[i
][2] = ctx
->Color
.ClearColor
[2];
1409 color
[i
][3] = ctx
->Color
.ClearColor
[3];
1412 /* convert clear Z from [0,1] to NDC coord in [-1,1] */
1414 dst_z
= -1.0 + 2.0 * ctx
->Depth
.Clear
;
1415 /* Prepare the vertices, which are the same regardless of which buffer we're
1418 vertices
[0][0] = fb
->_Xmin
;
1419 vertices
[0][1] = fb
->_Ymin
;
1420 vertices
[0][2] = dst_z
;
1421 vertices
[1][0] = fb
->_Xmax
;
1422 vertices
[1][1] = fb
->_Ymin
;
1423 vertices
[1][2] = dst_z
;
1424 vertices
[2][0] = fb
->_Xmax
;
1425 vertices
[2][1] = fb
->_Ymax
;
1426 vertices
[2][2] = dst_z
;
1427 vertices
[3][0] = fb
->_Xmin
;
1428 vertices
[3][1] = fb
->_Ymax
;
1429 vertices
[3][2] = dst_z
;
1431 _mesa_ColorPointer(4, GL_FLOAT
, 4 * sizeof(GLfloat
), &color
);
1432 _mesa_VertexPointer(3, GL_FLOAT
, 3 * sizeof(GLfloat
), &vertices
);
1433 _mesa_Enable(GL_COLOR_ARRAY
);
1434 _mesa_Enable(GL_VERTEX_ARRAY
);
1437 GLuint this_mask
= 0;
1440 color_bit
= _mesa_ffs(mask
& TRI_CLEAR_COLOR_BITS
);
1442 this_mask
|= (1 << (color_bit
- 1));
1444 /* Clear depth/stencil in the same pass as color. */
1445 this_mask
|= (mask
& (BUFFER_BIT_DEPTH
| BUFFER_BIT_STENCIL
));
1447 /* Select the current color buffer and use the color write mask if
1448 * we have one, otherwise don't write any color channels.
1450 if (this_mask
& BUFFER_BIT_FRONT_LEFT
)
1451 _mesa_DrawBuffer(GL_FRONT_LEFT
);
1452 else if (this_mask
& BUFFER_BIT_BACK_LEFT
)
1453 _mesa_DrawBuffer(GL_BACK_LEFT
);
1454 else if (color_bit
!= 0)
1455 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0
+
1456 (color_bit
- BUFFER_COLOR0
- 1));
1458 _mesa_ColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
1460 /* Control writing of the depth clear value to depth. */
1461 if (this_mask
& BUFFER_BIT_DEPTH
) {
1462 _mesa_DepthFunc(GL_ALWAYS
);
1463 _mesa_DepthMask(GL_TRUE
);
1464 _mesa_Enable(GL_DEPTH_TEST
);
1466 _mesa_Disable(GL_DEPTH_TEST
);
1467 _mesa_DepthMask(GL_FALSE
);
1470 /* Control writing of the stencil clear value to stencil. */
1471 if (this_mask
& BUFFER_BIT_STENCIL
) {
1472 _mesa_Enable(GL_STENCIL_TEST
);
1473 _mesa_StencilOp(GL_REPLACE
, GL_REPLACE
, GL_REPLACE
);
1474 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK
, GL_ALWAYS
, ctx
->Stencil
.Clear
,
1475 ctx
->Stencil
.WriteMask
[0]);
1477 _mesa_Disable(GL_STENCIL_TEST
);
1480 CALL_DrawArrays(ctx
->Exec
, (GL_TRIANGLE_FAN
, 0, 4));
1485 radeon_meta_restore_transform(rmesa
);
1487 _mesa_ActiveTextureARB(GL_TEXTURE0
+ saved_active_texture
);
1488 if (saved_fp_enable
)
1489 _mesa_Enable(GL_FRAGMENT_PROGRAM_ARB
);
1490 if (saved_vp_enable
)
1491 _mesa_Enable(GL_VERTEX_PROGRAM_ARB
);
1493 if (saved_shader_program
)
1494 _mesa_UseProgramObjectARB(saved_shader_program
);
1496 _mesa_PopClientAttrib();