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>
42 #include "swrast/swrast.h"
44 #include "r200_context.h"
45 #include "r200_state.h"
46 #include "radeon_ioctl.h"
47 #include "r200_ioctl.h"
48 #include "r300_ioctl.h"
50 #include "r200_sanity.h"
51 #include "radeon_reg.h"
55 static void radeonWaitForIdle(radeonContextPtr radeon
);
57 /* ================================================================
58 * SwapBuffers with client-side throttling
61 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
63 drm_radeon_getparam_t gp
;
67 gp
.param
= RADEON_PARAM_LAST_FRAME
;
68 gp
.value
= (int *)&frame
;
69 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
72 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
80 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
82 drm_radeon_irq_emit_t ie
;
85 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
86 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
89 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
95 static void radeonWaitIrq(radeonContextPtr radeon
)
100 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
101 &radeon
->iw
, sizeof(radeon
->iw
));
102 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
105 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
111 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
113 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
115 if (radeon
->do_irqs
) {
116 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
117 if (!radeon
->irqsEmitted
) {
118 while (radeonGetLastFrame(radeon
) <
121 UNLOCK_HARDWARE(radeon
);
122 radeonWaitIrq(radeon
);
123 LOCK_HARDWARE(radeon
);
125 radeon
->irqsEmitted
= 10;
128 if (radeon
->irqsEmitted
) {
129 radeonEmitIrqLocked(radeon
);
130 radeon
->irqsEmitted
--;
133 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
134 UNLOCK_HARDWARE(radeon
);
135 if (radeon
->do_usleeps
)
137 LOCK_HARDWARE(radeon
);
142 /* Copy the back color buffer to the front color buffer.
144 void radeonCopyBuffer(const __DRIdrawablePrivate
* dPriv
)
146 radeonContextPtr radeon
;
148 GLboolean missed_target
;
152 assert(dPriv
->driContextPriv
);
153 assert(dPriv
->driContextPriv
->driverPrivate
);
155 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
157 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
158 fprintf(stderr
, "\n%s( %p )\n\n", __FUNCTION__
,
159 (void *)radeon
->glCtx
);
162 if (IS_FAMILY_R200(radeon
))
163 R200_FIREVERTICES((r200ContextPtr
)radeon
);
165 LOCK_HARDWARE(radeon
);
167 /* Throttle the frame rate -- only allow one pending swap buffers
170 radeonWaitForFrameCompletion(radeon
);
171 UNLOCK_HARDWARE(radeon
);
172 driWaitForVBlank(dPriv
, &radeon
->vbl_seq
, radeon
->vblank_flags
,
174 LOCK_HARDWARE(radeon
);
176 nbox
= dPriv
->numClipRects
; /* must be in locked region */
178 for (i
= 0; i
< nbox
;) {
179 GLint nr
= MIN2(i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
180 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
181 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
184 for (; i
< nr
; i
++) {
188 radeon
->sarea
->nbox
= n
;
190 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_SWAP
);
193 fprintf(stderr
, "DRM_R200_SWAP_BUFFERS: return = %d\n",
195 UNLOCK_HARDWARE(radeon
);
200 UNLOCK_HARDWARE(radeon
);
202 if (IS_FAMILY_R200(radeon
))
203 ((r200ContextPtr
)radeon
)->hw
.all_dirty
= GL_TRUE
;
205 radeon
->swap_count
++;
206 (*radeon
->get_ust
) (&ust
);
208 radeon
->swap_missed_count
++;
209 radeon
->swap_missed_ust
= ust
- radeon
->swap_ust
;
212 radeon
->swap_ust
= ust
;
217 void radeonPageFlip(const __DRIdrawablePrivate
* dPriv
)
219 radeonContextPtr radeon
;
221 GLboolean missed_target
;
224 assert(dPriv
->driContextPriv
);
225 assert(dPriv
->driContextPriv
->driverPrivate
);
227 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
229 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
230 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
231 radeon
->sarea
->pfCurrentPage
);
234 if (IS_FAMILY_R200(radeon
))
235 R200_FIREVERTICES((r200ContextPtr
)radeon
);
236 LOCK_HARDWARE(radeon
);
238 if (!dPriv
->numClipRects
) {
239 UNLOCK_HARDWARE(radeon
);
240 usleep(10000); /* throttle invisible client 10ms */
244 /* Need to do this for the perf box placement:
247 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
248 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
250 radeon
->sarea
->nbox
= 1;
253 /* Throttle the frame rate -- only allow a few pending swap buffers
256 radeonWaitForFrameCompletion(radeon
);
257 UNLOCK_HARDWARE(radeon
);
258 driWaitForVBlank(dPriv
, &radeon
->vbl_seq
, radeon
->vblank_flags
,
261 radeon
->swap_missed_count
++;
262 (void)(*radeon
->get_ust
) (&radeon
->swap_missed_ust
);
264 LOCK_HARDWARE(radeon
);
266 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_FLIP
);
268 UNLOCK_HARDWARE(radeon
);
271 fprintf(stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
275 radeon
->swap_count
++;
276 (void)(*radeon
->get_ust
) (&radeon
->swap_ust
);
278 if (radeon
->sarea
->pfCurrentPage
== 1) {
279 radeon
->state
.color
.drawOffset
= radeon
->radeonScreen
->frontOffset
;
280 radeon
->state
.color
.drawPitch
= radeon
->radeonScreen
->frontPitch
;
282 radeon
->state
.color
.drawOffset
= radeon
->radeonScreen
->backOffset
;
283 radeon
->state
.color
.drawPitch
= radeon
->radeonScreen
->backPitch
;
286 if (IS_FAMILY_R200(radeon
)) {
287 r200ContextPtr r200
= (r200ContextPtr
)radeon
;
289 R200_STATECHANGE(r200
, ctx
);
290 r200
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = radeon
->state
.color
.drawOffset
291 + radeon
->radeonScreen
->fbLocation
;
292 r200
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = radeon
->state
.color
.drawPitch
;
296 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
302 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
305 } while (ret
&& ++i
< 100);
308 UNLOCK_HARDWARE(radeon
);
309 fprintf(stderr
, "Error: R200 timed out... exiting\n");
314 static void radeonWaitForIdle(radeonContextPtr radeon
)
316 LOCK_HARDWARE(radeon
);
317 radeonWaitForIdleLocked(radeon
);
318 UNLOCK_HARDWARE(radeon
);
321 void radeonFlush(GLcontext
* ctx
)
323 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
325 if (IS_FAMILY_R300(radeon
))
332 /* Make sure all commands have been sent to the hardware and have
333 * completed processing.
335 void radeonFinish(GLcontext
* ctx
)
337 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
341 if (radeon
->do_irqs
) {
342 LOCK_HARDWARE(radeon
);
343 radeonEmitIrqLocked(radeon
);
344 UNLOCK_HARDWARE(radeon
);
345 radeonWaitIrq(radeon
);
347 radeonWaitForIdle(radeon
);