2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
38 #include "main/glheader.h"
39 #include "main/imports.h"
40 #include "main/macros.h"
41 #include "main/context.h"
42 #include "swrast/swrast.h"
43 #include "r300_context.h"
44 #include "radeon_ioctl.h"
45 #include "radeon_buffer.h"
46 #include "r300_ioctl.h"
47 #include "r300_state.h"
48 #include "radeon_reg.h"
50 #include "drirenderbuffer.h"
53 static void radeonWaitForIdle(radeonContextPtr radeon
);
55 /* ================================================================
56 * SwapBuffers with client-side throttling
59 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
61 drm_radeon_getparam_t gp
;
65 gp
.param
= RADEON_PARAM_LAST_FRAME
;
66 gp
.value
= (int *)&frame
;
67 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
70 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
78 uint32_t radeonGetAge(radeonContextPtr radeon
)
80 drm_radeon_getparam_t gp
;
84 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
85 gp
.value
= (int *)&age
;
86 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
89 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
97 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
99 drm_radeon_irq_emit_t ie
;
102 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
103 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
106 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
112 static void radeonWaitIrq(radeonContextPtr radeon
)
117 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
118 &radeon
->iw
, sizeof(radeon
->iw
));
119 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
122 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
128 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
130 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
132 if (radeon
->do_irqs
) {
133 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
134 if (!radeon
->irqsEmitted
) {
135 while (radeonGetLastFrame(radeon
) <
138 UNLOCK_HARDWARE(radeon
);
139 radeonWaitIrq(radeon
);
140 LOCK_HARDWARE(radeon
);
142 radeon
->irqsEmitted
= 10;
145 if (radeon
->irqsEmitted
) {
146 radeonEmitIrqLocked(radeon
);
147 radeon
->irqsEmitted
--;
150 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
151 UNLOCK_HARDWARE(radeon
);
152 if (radeon
->do_usleeps
)
154 LOCK_HARDWARE(radeon
);
159 /* Copy the back color buffer to the front color buffer.
161 void radeonCopyBuffer(__DRIdrawablePrivate
* dPriv
,
162 const drm_clip_rect_t
* rect
)
164 radeonContextPtr radeon
;
166 GLboolean missed_target
;
168 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
171 assert(dPriv
->driContextPriv
);
172 assert(dPriv
->driContextPriv
->driverPrivate
);
174 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
176 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
177 fprintf(stderr
, "\n%s( %p )\n\n", __FUNCTION__
,
178 (void *)radeon
->glCtx
);
181 r300Flush(radeon
->glCtx
);
183 LOCK_HARDWARE(radeon
);
185 /* Throttle the frame rate -- only allow one pending swap buffers
188 radeonWaitForFrameCompletion(radeon
);
191 UNLOCK_HARDWARE(radeon
);
192 driWaitForVBlank(dPriv
, &missed_target
);
193 LOCK_HARDWARE(radeon
);
196 nbox
= dPriv
->numClipRects
; /* must be in locked region */
198 for (i
= 0; i
< nbox
;) {
199 GLint nr
= MIN2(i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
200 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
201 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
204 for ( ; i
< nr
; i
++ ) {
210 if (rect
->x1
> b
->x1
)
212 if (rect
->y1
> b
->y1
)
214 if (rect
->x2
< b
->x2
)
216 if (rect
->y2
< b
->y2
)
219 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
226 radeon
->sarea
->nbox
= n
;
231 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_SWAP
);
234 fprintf(stderr
, "DRM_RADEON_SWAP: return = %d\n",
236 UNLOCK_HARDWARE(radeon
);
241 UNLOCK_HARDWARE(radeon
);
244 ((r300ContextPtr
)radeon
)->hw
.all_dirty
= GL_TRUE
;
246 radeon
->swap_count
++;
247 (*psp
->systemTime
->getUST
) (&ust
);
249 radeon
->swap_missed_count
++;
250 radeon
->swap_missed_ust
= ust
- radeon
->swap_ust
;
253 radeon
->swap_ust
= ust
;
259 void radeonPageFlip(__DRIdrawablePrivate
* dPriv
)
261 radeonContextPtr radeon
;
263 GLboolean missed_target
;
264 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
265 GLframebuffer
*fb
= dPriv
->driverPrivate
;
266 struct radeon_renderbuffer
*rrb
;
269 assert(dPriv
->driContextPriv
);
270 assert(dPriv
->driContextPriv
->driverPrivate
);
272 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
274 rrb
= (void *)fb
->Attachment
[BUFFER_FRONT_LEFT
].Renderbuffer
;
276 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
277 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
278 radeon
->sarea
->pfCurrentPage
);
281 r300Flush(radeon
->glCtx
);
282 LOCK_HARDWARE(radeon
);
284 if (!dPriv
->numClipRects
) {
285 UNLOCK_HARDWARE(radeon
);
286 usleep(10000); /* throttle invisible client 10ms */
290 /* Need to do this for the perf box placement:
293 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
294 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
296 radeon
->sarea
->nbox
= 1;
299 /* Throttle the frame rate -- only allow a few pending swap buffers
302 radeonWaitForFrameCompletion(radeon
);
303 UNLOCK_HARDWARE(radeon
);
304 driWaitForVBlank(dPriv
, &missed_target
);
306 radeon
->swap_missed_count
++;
307 (void)(*psp
->systemTime
->getUST
) (&radeon
->swap_missed_ust
);
309 LOCK_HARDWARE(radeon
);
311 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_FLIP
);
313 UNLOCK_HARDWARE(radeon
);
316 fprintf(stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
320 radeon
->swap_count
++;
321 (void)(*psp
->systemTime
->getUST
) (&radeon
->swap_ust
);
323 driFlipRenderbuffers(radeon
->glCtx
->WinSysDrawBuffer
,
324 radeon
->sarea
->pfCurrentPage
);
326 radeon
->state
.color
.rrb
= rrb
;
329 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
335 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
338 } while (ret
&& ++i
< 100);
341 UNLOCK_HARDWARE(radeon
);
342 fprintf(stderr
, "Error: R300 timed out... exiting\n");
347 static void radeonWaitForIdle(radeonContextPtr radeon
)
349 LOCK_HARDWARE(radeon
);
350 radeonWaitForIdleLocked(radeon
);
351 UNLOCK_HARDWARE(radeon
);
354 void radeonFlush(GLcontext
* ctx
)
356 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
358 if (IS_R300_CLASS(radeon
->radeonScreen
))
363 /* Make sure all commands have been sent to the hardware and have
364 * completed processing.
366 void radeonFinish(GLcontext
* ctx
)
368 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
372 if (radeon
->do_irqs
) {
373 LOCK_HARDWARE(radeon
);
374 radeonEmitIrqLocked(radeon
);
375 UNLOCK_HARDWARE(radeon
);
376 radeonWaitIrq(radeon
);
378 radeonWaitForIdle(radeon
);