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"
43 #include "r300_context.h"
44 #include "radeon_ioctl.h"
45 #include "r300_ioctl.h"
46 #include "r300_state.h"
47 #include "radeon_reg.h"
49 #include "drirenderbuffer.h"
52 static void radeonWaitForIdle(radeonContextPtr radeon
);
54 /* ================================================================
55 * SwapBuffers with client-side throttling
58 static uint32_t radeonGetLastFrame(radeonContextPtr radeon
)
60 drm_radeon_getparam_t gp
;
64 gp
.param
= RADEON_PARAM_LAST_FRAME
;
65 gp
.value
= (int *)&frame
;
66 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
69 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
77 uint32_t radeonGetAge(radeonContextPtr radeon
)
79 drm_radeon_getparam_t gp
;
83 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
84 gp
.value
= (int *)&age
;
85 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_GETPARAM
,
88 fprintf(stderr
, "%s: drmRadeonGetParam: %d\n", __FUNCTION__
,
96 static void radeonEmitIrqLocked(radeonContextPtr radeon
)
98 drm_radeon_irq_emit_t ie
;
101 ie
.irq_seq
= &radeon
->iw
.irq_seq
;
102 ret
= drmCommandWriteRead(radeon
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
105 fprintf(stderr
, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__
,
111 static void radeonWaitIrq(radeonContextPtr radeon
)
116 ret
= drmCommandWrite(radeon
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
117 &radeon
->iw
, sizeof(radeon
->iw
));
118 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
121 fprintf(stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
,
127 static void radeonWaitForFrameCompletion(radeonContextPtr radeon
)
129 drm_radeon_sarea_t
*sarea
= radeon
->sarea
;
131 if (radeon
->do_irqs
) {
132 if (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
133 if (!radeon
->irqsEmitted
) {
134 while (radeonGetLastFrame(radeon
) <
137 UNLOCK_HARDWARE(radeon
);
138 radeonWaitIrq(radeon
);
139 LOCK_HARDWARE(radeon
);
141 radeon
->irqsEmitted
= 10;
144 if (radeon
->irqsEmitted
) {
145 radeonEmitIrqLocked(radeon
);
146 radeon
->irqsEmitted
--;
149 while (radeonGetLastFrame(radeon
) < sarea
->last_frame
) {
150 UNLOCK_HARDWARE(radeon
);
151 if (radeon
->do_usleeps
)
153 LOCK_HARDWARE(radeon
);
158 /* Copy the back color buffer to the front color buffer.
160 void radeonCopyBuffer(const __DRIdrawablePrivate
* dPriv
,
161 const drm_clip_rect_t
* rect
)
163 radeonContextPtr radeon
;
165 GLboolean missed_target
;
169 assert(dPriv
->driContextPriv
);
170 assert(dPriv
->driContextPriv
->driverPrivate
);
172 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
174 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
175 fprintf(stderr
, "\n%s( %p )\n\n", __FUNCTION__
,
176 (void *)radeon
->glCtx
);
179 r300Flush(radeon
->glCtx
);
181 LOCK_HARDWARE(radeon
);
183 /* Throttle the frame rate -- only allow one pending swap buffers
186 radeonWaitForFrameCompletion(radeon
);
189 UNLOCK_HARDWARE(radeon
);
190 driWaitForVBlank(dPriv
, &radeon
->vbl_seq
, radeon
->vblank_flags
,
192 LOCK_HARDWARE(radeon
);
195 nbox
= dPriv
->numClipRects
; /* must be in locked region */
197 for (i
= 0; i
< nbox
;) {
198 GLint nr
= MIN2(i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
199 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
200 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
203 for ( ; i
< nr
; i
++ ) {
209 if (rect
->x1
> b
->x1
)
211 if (rect
->y1
> b
->y1
)
213 if (rect
->x2
< b
->x2
)
215 if (rect
->y2
< b
->y2
)
218 if (b
->x1
< b
->x2
&& b
->y1
< b
->y2
)
226 radeon
->sarea
->nbox
= n
;
228 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_SWAP
);
231 fprintf(stderr
, "DRM_RADEON_SWAP: return = %d\n",
233 UNLOCK_HARDWARE(radeon
);
238 UNLOCK_HARDWARE(radeon
);
241 ((r300ContextPtr
)radeon
)->hw
.all_dirty
= GL_TRUE
;
243 radeon
->swap_count
++;
244 (*dri_interface
->getUST
) (&ust
);
246 radeon
->swap_missed_count
++;
247 radeon
->swap_missed_ust
= ust
- radeon
->swap_ust
;
250 radeon
->swap_ust
= ust
;
256 void radeonPageFlip(const __DRIdrawablePrivate
* dPriv
)
258 radeonContextPtr radeon
;
260 GLboolean missed_target
;
263 assert(dPriv
->driContextPriv
);
264 assert(dPriv
->driContextPriv
->driverPrivate
);
266 radeon
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
268 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
269 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
270 radeon
->sarea
->pfCurrentPage
);
273 r300Flush(radeon
->glCtx
);
274 LOCK_HARDWARE(radeon
);
276 if (!dPriv
->numClipRects
) {
277 UNLOCK_HARDWARE(radeon
);
278 usleep(10000); /* throttle invisible client 10ms */
282 /* Need to do this for the perf box placement:
285 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
286 drm_clip_rect_t
*b
= radeon
->sarea
->boxes
;
288 radeon
->sarea
->nbox
= 1;
291 /* Throttle the frame rate -- only allow a few pending swap buffers
294 radeonWaitForFrameCompletion(radeon
);
295 UNLOCK_HARDWARE(radeon
);
296 driWaitForVBlank(dPriv
, &radeon
->vbl_seq
, radeon
->vblank_flags
,
299 radeon
->swap_missed_count
++;
300 (void)(*dri_interface
->getUST
) (&radeon
->swap_missed_ust
);
302 LOCK_HARDWARE(radeon
);
304 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_FLIP
);
306 UNLOCK_HARDWARE(radeon
);
309 fprintf(stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
313 radeon
->swap_count
++;
314 (void)(*dri_interface
->getUST
) (&radeon
->swap_ust
);
316 driFlipRenderbuffers(radeon
->glCtx
->WinSysDrawBuffer
,
317 radeon
->sarea
->pfCurrentPage
);
319 if (radeon
->sarea
->pfCurrentPage
== 1) {
320 radeon
->state
.color
.drawOffset
= radeon
->radeonScreen
->frontOffset
;
321 radeon
->state
.color
.drawPitch
= radeon
->radeonScreen
->frontPitch
;
323 radeon
->state
.color
.drawOffset
= radeon
->radeonScreen
->backOffset
;
324 radeon
->state
.color
.drawPitch
= radeon
->radeonScreen
->backPitch
;
327 if (IS_R300_CLASS(radeon
->radeonScreen
)) {
328 r300ContextPtr r300
= (r300ContextPtr
)radeon
;
329 R300_STATECHANGE(r300
, cb
);
330 r300
->hw
.cb
.cmd
[R300_CB_OFFSET
] = r300
->radeon
.state
.color
.drawOffset
+
331 r300
->radeon
.radeonScreen
->fbLocation
;
332 r300
->hw
.cb
.cmd
[R300_CB_PITCH
] = r300
->radeon
.state
.color
.drawPitch
;
334 if (r300
->radeon
.radeonScreen
->cpp
== 4)
335 r300
->hw
.cb
.cmd
[R300_CB_PITCH
] |= R300_COLOR_FORMAT_ARGB8888
;
337 r300
->hw
.cb
.cmd
[R300_CB_PITCH
] |= R300_COLOR_FORMAT_RGB565
;
339 if (r300
->radeon
.sarea
->tiling_enabled
)
340 r300
->hw
.cb
.cmd
[R300_CB_PITCH
] |= R300_COLOR_TILE_ENABLE
;
344 void radeonWaitForIdleLocked(radeonContextPtr radeon
)
350 ret
= drmCommandNone(radeon
->dri
.fd
, DRM_RADEON_CP_IDLE
);
353 } while (ret
&& ++i
< 100);
356 UNLOCK_HARDWARE(radeon
);
357 fprintf(stderr
, "Error: R300 timed out... exiting\n");
362 static void radeonWaitForIdle(radeonContextPtr radeon
)
364 LOCK_HARDWARE(radeon
);
365 radeonWaitForIdleLocked(radeon
);
366 UNLOCK_HARDWARE(radeon
);
369 void radeonFlush(GLcontext
* ctx
)
371 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
373 if (IS_R300_CLASS(radeon
->radeonScreen
))
378 /* Make sure all commands have been sent to the hardware and have
379 * completed processing.
381 void radeonFinish(GLcontext
* ctx
)
383 radeonContextPtr radeon
= RADEON_CONTEXT(ctx
);
387 if (radeon
->do_irqs
) {
388 LOCK_HARDWARE(radeon
);
389 radeonEmitIrqLocked(radeon
);
390 UNLOCK_HARDWARE(radeon
);
391 radeonWaitIrq(radeon
);
393 radeonWaitForIdle(radeon
);