radeon_present.c revision 7314432e
10d16fef4Smrg/* 20d16fef4Smrg * Copyright © 2014 Intel Corporation 30d16fef4Smrg * Copyright © 2015 Advanced Micro Devices, Inc. 40d16fef4Smrg * 50d16fef4Smrg * Permission to use, copy, modify, distribute, and sell this software and its 60d16fef4Smrg * documentation for any purpose is hereby granted without fee, provided that 70d16fef4Smrg * the above copyright notice appear in all copies and that both that copyright 80d16fef4Smrg * notice and this permission notice appear in supporting documentation, and 90d16fef4Smrg * that the name of the copyright holders not be used in advertising or 100d16fef4Smrg * publicity pertaining to distribution of the software without specific, 110d16fef4Smrg * written prior permission. The copyright holders make no representations 120d16fef4Smrg * about the suitability of this software for any purpose. It is provided "as 130d16fef4Smrg * is" without express or implied warranty. 140d16fef4Smrg * 150d16fef4Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 160d16fef4Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 170d16fef4Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 180d16fef4Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 190d16fef4Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 200d16fef4Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 210d16fef4Smrg * OF THIS SOFTWARE. 220d16fef4Smrg */ 230d16fef4Smrg 240d16fef4Smrg#ifdef HAVE_CONFIG_H 250d16fef4Smrg#include "config.h" 260d16fef4Smrg#endif 270d16fef4Smrg 280d16fef4Smrg#include "radeon.h" 290d16fef4Smrg 300d16fef4Smrg#ifdef HAVE_PRESENT_H 310d16fef4Smrg 320d16fef4Smrg#include <stdio.h> 330d16fef4Smrg#include <string.h> 340d16fef4Smrg#include <assert.h> 350d16fef4Smrg#include <sys/types.h> 360d16fef4Smrg#include <sys/stat.h> 370d16fef4Smrg#include <sys/ioctl.h> 380d16fef4Smrg#include <unistd.h> 390d16fef4Smrg#include <fcntl.h> 400d16fef4Smrg#include <poll.h> 410d16fef4Smrg#include <sys/time.h> 420d16fef4Smrg#include <time.h> 430d16fef4Smrg#include <errno.h> 440d16fef4Smrg 450d16fef4Smrg#include "radeon_bo_helper.h" 460d16fef4Smrg#include "radeon_glamor.h" 470d16fef4Smrg#include "radeon_video.h" 480d16fef4Smrg 490d16fef4Smrg#include "present.h" 500d16fef4Smrg 510d16fef4Smrgstruct radeon_present_vblank_event { 520d16fef4Smrg uint64_t event_id; 530d16fef4Smrg Bool unflip; 540d16fef4Smrg}; 550d16fef4Smrg 560d16fef4Smrgstatic uint32_t crtc_select(int crtc_id) 570d16fef4Smrg{ 580d16fef4Smrg if (crtc_id > 1) 590d16fef4Smrg return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT; 600d16fef4Smrg else if (crtc_id > 0) 610d16fef4Smrg return DRM_VBLANK_SECONDARY; 620d16fef4Smrg else 630d16fef4Smrg return 0; 640d16fef4Smrg} 650d16fef4Smrg 660d16fef4Smrgstatic RRCrtcPtr 670d16fef4Smrgradeon_present_get_crtc(WindowPtr window) 680d16fef4Smrg{ 690d16fef4Smrg ScreenPtr screen = window->drawable.pScreen; 700d16fef4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 710d16fef4Smrg xf86CrtcPtr crtc; 720d16fef4Smrg RRCrtcPtr randr_crtc = NULL; 730d16fef4Smrg 740d16fef4Smrg crtc = radeon_pick_best_crtc(pScrn, FALSE, 750d16fef4Smrg window->drawable.x, 760d16fef4Smrg window->drawable.x + window->drawable.width, 770d16fef4Smrg window->drawable.y, 780d16fef4Smrg window->drawable.y + window->drawable.height); 790d16fef4Smrg 800d16fef4Smrg if (crtc) 810d16fef4Smrg randr_crtc = crtc->randr_crtc; 820d16fef4Smrg 830d16fef4Smrg return randr_crtc; 840d16fef4Smrg} 850d16fef4Smrg 860d16fef4Smrgstatic int 870d16fef4Smrgradeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) 880d16fef4Smrg{ 890d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 900d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 910d16fef4Smrg 920d16fef4Smrg if (drmmode_crtc->dpms_mode != DPMSModeOn) 930d16fef4Smrg return BadAlloc; 940d16fef4Smrg 950d16fef4Smrg return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc); 960d16fef4Smrg} 970d16fef4Smrg 980d16fef4Smrg/* 990d16fef4Smrg * Flush the DRM event queue when full; this 1000d16fef4Smrg * makes space for new requests 1010d16fef4Smrg */ 1020d16fef4Smrgstatic Bool 1030d16fef4Smrgradeon_present_flush_drm_events(ScreenPtr screen) 1040d16fef4Smrg{ 1050d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1060d16fef4Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1070d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; 1080d16fef4Smrg drmmode_ptr drmmode = drmmode_crtc->drmmode; 1090d16fef4Smrg struct pollfd p = { .fd = drmmode->fd, .events = POLLIN }; 1100d16fef4Smrg int r; 1110d16fef4Smrg 1120d16fef4Smrg do { 1130d16fef4Smrg r = poll(&p, 1, 0); 1140d16fef4Smrg } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 1150d16fef4Smrg 1160d16fef4Smrg if (r <= 0) 1170d16fef4Smrg return 0; 1180d16fef4Smrg 1190d16fef4Smrg return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0; 1200d16fef4Smrg} 1210d16fef4Smrg 1220d16fef4Smrg/* 1230d16fef4Smrg * Called when the queued vblank event has occurred 1240d16fef4Smrg */ 1250d16fef4Smrgstatic void 1260d16fef4Smrgradeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc, 1270d16fef4Smrg uint64_t usec, void *data) 1280d16fef4Smrg{ 1290d16fef4Smrg struct radeon_present_vblank_event *event = data; 1300d16fef4Smrg 1310d16fef4Smrg present_event_notify(event->event_id, usec, msc); 1320d16fef4Smrg free(event); 1330d16fef4Smrg} 1340d16fef4Smrg 1350d16fef4Smrg/* 1360d16fef4Smrg * Called when the queued vblank is aborted 1370d16fef4Smrg */ 1380d16fef4Smrgstatic void 1390d16fef4Smrgradeon_present_vblank_abort(xf86CrtcPtr crtc, void *data) 1400d16fef4Smrg{ 1410d16fef4Smrg struct radeon_present_vblank_event *event = data; 1420d16fef4Smrg 1430d16fef4Smrg free(event); 1440d16fef4Smrg} 1450d16fef4Smrg 1460d16fef4Smrg/* 1470d16fef4Smrg * Queue an event to report back to the Present extension when the specified 1480d16fef4Smrg * MSC has past 1490d16fef4Smrg */ 1500d16fef4Smrgstatic int 1510d16fef4Smrgradeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1520d16fef4Smrg{ 1530d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 1540d16fef4Smrg ScreenPtr screen = crtc->pScreen; 1550d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1560d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 1570d16fef4Smrg int crtc_id = drmmode_get_crtc_id(xf86_crtc); 1580d16fef4Smrg struct radeon_present_vblank_event *event; 1590d16fef4Smrg uintptr_t drm_queue_seq; 1600d16fef4Smrg drmVBlank vbl; 1610d16fef4Smrg int ret; 1620d16fef4Smrg 1630d16fef4Smrg event = calloc(sizeof(struct radeon_present_vblank_event), 1); 1640d16fef4Smrg if (!event) 1650d16fef4Smrg return BadAlloc; 1660d16fef4Smrg event->event_id = event_id; 1670d16fef4Smrg drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, 1680d16fef4Smrg RADEON_DRM_QUEUE_CLIENT_DEFAULT, 1690d16fef4Smrg event_id, event, 1700d16fef4Smrg radeon_present_vblank_handler, 1710d16fef4Smrg radeon_present_vblank_abort); 1727314432eSmrg if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 1730d16fef4Smrg free(event); 1740d16fef4Smrg return BadAlloc; 1750d16fef4Smrg } 1760d16fef4Smrg 1770d16fef4Smrg vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id); 1780d16fef4Smrg vbl.request.sequence = msc; 1790d16fef4Smrg vbl.request.signal = drm_queue_seq; 1800d16fef4Smrg for (;;) { 1810d16fef4Smrg ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1820d16fef4Smrg if (!ret) 1830d16fef4Smrg break; 1840d16fef4Smrg if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { 1850d16fef4Smrg radeon_drm_abort_entry(drm_queue_seq); 1860d16fef4Smrg return BadAlloc; 1870d16fef4Smrg } 1880d16fef4Smrg } 1890d16fef4Smrg 1900d16fef4Smrg return Success; 1910d16fef4Smrg} 1920d16fef4Smrg 1930d16fef4Smrg/* 1940d16fef4Smrg * Remove a pending vblank event from the DRM queue so that it is not reported 1950d16fef4Smrg * to the extension 1960d16fef4Smrg */ 1970d16fef4Smrgstatic void 1980d16fef4Smrgradeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1990d16fef4Smrg{ 2000d16fef4Smrg radeon_drm_abort_id(event_id); 2010d16fef4Smrg} 2020d16fef4Smrg 2030d16fef4Smrg/* 2040d16fef4Smrg * Flush our batch buffer when requested by the Present extension. 2050d16fef4Smrg */ 2060d16fef4Smrgstatic void 2070d16fef4Smrgradeon_present_flush(WindowPtr window) 2080d16fef4Smrg{ 2090d16fef4Smrg radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen)); 2100d16fef4Smrg} 2110d16fef4Smrg 2120d16fef4Smrgstatic uint32_t 2130d16fef4Smrgradeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap) 2140d16fef4Smrg{ 2150d16fef4Smrg uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap); 2160d16fef4Smrg 2170d16fef4Smrg /* Micro tiling is always enabled with macro tiling on >= R600, so we 2180d16fef4Smrg * can ignore the micro tiling bit in that case 2190d16fef4Smrg */ 2200d16fef4Smrg if ((tiling_flags & RADEON_TILING_MACRO) && 2210d16fef4Smrg info->ChipFamily >= CHIP_FAMILY_R600) 2220d16fef4Smrg tiling_flags &= ~RADEON_TILING_MICRO; 2230d16fef4Smrg 2240d16fef4Smrg return tiling_flags; 2250d16fef4Smrg} 2260d16fef4Smrg 2270d16fef4Smrg/* 2287314432eSmrg * Test to see if unflipping is possible 2297314432eSmrg * 2307314432eSmrg * These tests have to pass for flips as well 2310d16fef4Smrg */ 2320d16fef4Smrgstatic Bool 2337314432eSmrgradeon_present_check_unflip(ScrnInfoPtr scrn) 2340d16fef4Smrg{ 2350d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2360d16fef4Smrg int num_crtcs_on; 2370d16fef4Smrg int i; 2380d16fef4Smrg 2390d16fef4Smrg if (!scrn->vtSema) 2400d16fef4Smrg return FALSE; 2410d16fef4Smrg 2427314432eSmrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2437314432eSmrg drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private; 2447314432eSmrg 2457314432eSmrg if (!config->crtc[i]->enabled) 2467314432eSmrg continue; 2477314432eSmrg 2487314432eSmrg if (!drmmode_crtc || drmmode_crtc->rotate.bo || 2497314432eSmrg drmmode_crtc->scanout[0].bo) 2507314432eSmrg return FALSE; 2517314432eSmrg 2527314432eSmrg if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) 2537314432eSmrg num_crtcs_on++; 2547314432eSmrg } 2557314432eSmrg 2567314432eSmrg return num_crtcs_on > 0; 2577314432eSmrg} 2587314432eSmrg 2597314432eSmrg/* 2607314432eSmrg * Test to see if page flipping is possible on the target crtc 2617314432eSmrg */ 2627314432eSmrgstatic Bool 2637314432eSmrgradeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 2647314432eSmrg Bool sync_flip) 2657314432eSmrg{ 2667314432eSmrg ScreenPtr screen = window->drawable.pScreen; 2677314432eSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2687314432eSmrg RADEONInfoPtr info = RADEONPTR(scrn); 2697314432eSmrg PixmapPtr screen_pixmap; 2707314432eSmrg 2710d16fef4Smrg if (!info->allowPageFlip) 2720d16fef4Smrg return FALSE; 2730d16fef4Smrg 2740d16fef4Smrg if (info->hwcursor_disabled) 2750d16fef4Smrg return FALSE; 2760d16fef4Smrg 2770d16fef4Smrg if (info->drmmode.dri2_flipping) 2780d16fef4Smrg return FALSE; 2790d16fef4Smrg 2800d16fef4Smrg /* The kernel driver doesn't handle flipping between BOs with different 2810d16fef4Smrg * tiling parameters correctly yet 2820d16fef4Smrg */ 2830d16fef4Smrg screen_pixmap = screen->GetScreenPixmap(screen); 2840d16fef4Smrg if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != 2850d16fef4Smrg radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) 2860d16fef4Smrg return FALSE; 2870d16fef4Smrg 2887314432eSmrg return radeon_present_check_unflip(scrn); 2890d16fef4Smrg} 2900d16fef4Smrg 2910d16fef4Smrg/* 2920d16fef4Smrg * Once the flip has been completed on all CRTCs, notify the 2930d16fef4Smrg * extension code telling it when that happened 2940d16fef4Smrg */ 2950d16fef4Smrgstatic void 2960d16fef4Smrgradeon_present_flip_event(xf86CrtcPtr crtc, uint32_t msc, uint64_t ust, void *pageflip_data) 2970d16fef4Smrg{ 2980d16fef4Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 2990d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3000d16fef4Smrg 3010d16fef4Smrg if (event->unflip) 3020d16fef4Smrg info->drmmode.present_flipping = FALSE; 3030d16fef4Smrg 3040d16fef4Smrg present_event_notify(event->event_id, ust, msc); 3050d16fef4Smrg free(event); 3060d16fef4Smrg} 3070d16fef4Smrg 3080d16fef4Smrg/* 3090d16fef4Smrg * The flip has been aborted, free the structure 3100d16fef4Smrg */ 3110d16fef4Smrgstatic void 3120d16fef4Smrgradeon_present_flip_abort(xf86CrtcPtr crtc, void *pageflip_data) 3130d16fef4Smrg{ 3140d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3150d16fef4Smrg 3160d16fef4Smrg free(event); 3170d16fef4Smrg} 3180d16fef4Smrg 3190d16fef4Smrg/* 3200d16fef4Smrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 3210d16fef4Smrg * then wait for vblank. Otherwise, flip immediately 3220d16fef4Smrg */ 3230d16fef4Smrgstatic Bool 3240d16fef4Smrgradeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, 3250d16fef4Smrg PixmapPtr pixmap, Bool sync_flip) 3260d16fef4Smrg{ 3270d16fef4Smrg ScreenPtr screen = crtc->pScreen; 3280d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3290d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3300d16fef4Smrg struct radeon_present_vblank_event *event; 3310d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 3320d16fef4Smrg int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1; 3330d16fef4Smrg uint32_t handle; 3340d16fef4Smrg Bool ret; 3350d16fef4Smrg 3360d16fef4Smrg if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) 3370d16fef4Smrg return FALSE; 3380d16fef4Smrg 3390d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) 3400d16fef4Smrg return FALSE; 3410d16fef4Smrg 3420d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3430d16fef4Smrg if (!event) 3440d16fef4Smrg return FALSE; 3450d16fef4Smrg 3460d16fef4Smrg event->event_id = event_id; 3470d16fef4Smrg 3480d16fef4Smrg ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 3490d16fef4Smrg event_id, event, crtc_id, 3500d16fef4Smrg radeon_present_flip_event, 3517314432eSmrg radeon_present_flip_abort, 3527314432eSmrg sync_flip ? FLIP_VSYNC : FLIP_ASYNC); 3530d16fef4Smrg if (!ret) 3540d16fef4Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); 3550d16fef4Smrg else 3560d16fef4Smrg info->drmmode.present_flipping = TRUE; 3570d16fef4Smrg 3580d16fef4Smrg return ret; 3590d16fef4Smrg} 3600d16fef4Smrg 3610d16fef4Smrg/* 3620d16fef4Smrg * Queue a flip back to the normal frame buffer 3630d16fef4Smrg */ 3640d16fef4Smrgstatic void 3650d16fef4Smrgradeon_present_unflip(ScreenPtr screen, uint64_t event_id) 3660d16fef4Smrg{ 3670d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3680d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3690d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3700d16fef4Smrg struct radeon_present_vblank_event *event; 3710d16fef4Smrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 3720d16fef4Smrg uint32_t handle; 3730d16fef4Smrg int i; 3740d16fef4Smrg 3757314432eSmrg if (!radeon_present_check_unflip(scrn)) 3760d16fef4Smrg goto modeset; 3770d16fef4Smrg 3780d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) { 3790d16fef4Smrg ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n", 3800d16fef4Smrg __func__); 3810d16fef4Smrg goto modeset; 3820d16fef4Smrg } 3830d16fef4Smrg 3840d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3850d16fef4Smrg if (!event) { 3860d16fef4Smrg ErrorF("%s: calloc failed, display might freeze\n", __func__); 3870d16fef4Smrg goto modeset; 3880d16fef4Smrg } 3890d16fef4Smrg 3900d16fef4Smrg event->event_id = event_id; 3910d16fef4Smrg event->unflip = TRUE; 3920d16fef4Smrg 3930d16fef4Smrg if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 3940d16fef4Smrg event_id, event, -1, radeon_present_flip_event, 3957314432eSmrg radeon_present_flip_abort, FLIP_VSYNC)) 3960d16fef4Smrg return; 3970d16fef4Smrg 3980d16fef4Smrgmodeset: 3990d16fef4Smrg /* info->drmmode.fb_id still points to the FB for the last flipped BO. 4000d16fef4Smrg * Clear it, drmmode_set_mode_major will re-create it 4010d16fef4Smrg */ 4020d16fef4Smrg drmModeRmFB(info->drmmode.fd, info->drmmode.fb_id); 4030d16fef4Smrg info->drmmode.fb_id = 0; 4040d16fef4Smrg 4050d16fef4Smrg for (i = 0; i < config->num_crtc; i++) { 4060d16fef4Smrg xf86CrtcPtr crtc = config->crtc[i]; 4070d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 4080d16fef4Smrg 4090d16fef4Smrg if (!crtc->enabled) 4100d16fef4Smrg continue; 4110d16fef4Smrg 4127314432eSmrg if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) 4130d16fef4Smrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 4140d16fef4Smrg crtc->x, crtc->y); 4150d16fef4Smrg else 4160d16fef4Smrg drmmode_crtc->need_modeset = TRUE; 4170d16fef4Smrg } 4180d16fef4Smrg 4190d16fef4Smrg present_event_notify(event_id, 0, 0); 4200d16fef4Smrg 4210d16fef4Smrg info->drmmode.present_flipping = FALSE; 4220d16fef4Smrg} 4230d16fef4Smrg 4240d16fef4Smrgstatic present_screen_info_rec radeon_present_screen_info = { 4250d16fef4Smrg .version = 0, 4260d16fef4Smrg 4270d16fef4Smrg .get_crtc = radeon_present_get_crtc, 4280d16fef4Smrg .get_ust_msc = radeon_present_get_ust_msc, 4290d16fef4Smrg .queue_vblank = radeon_present_queue_vblank, 4300d16fef4Smrg .abort_vblank = radeon_present_abort_vblank, 4310d16fef4Smrg .flush = radeon_present_flush, 4320d16fef4Smrg 4330d16fef4Smrg .capabilities = PresentCapabilityNone, 4340d16fef4Smrg .check_flip = radeon_present_check_flip, 4350d16fef4Smrg .flip = radeon_present_flip, 4360d16fef4Smrg .unflip = radeon_present_unflip, 4370d16fef4Smrg}; 4380d16fef4Smrg 4390d16fef4Smrgstatic Bool 4400d16fef4Smrgradeon_present_has_async_flip(ScreenPtr screen) 4410d16fef4Smrg{ 4420d16fef4Smrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 4430d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 4440d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 4450d16fef4Smrg int ret; 4460d16fef4Smrg uint64_t value; 4470d16fef4Smrg 4480d16fef4Smrg ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4490d16fef4Smrg if (ret == 0) 4500d16fef4Smrg return value == 1; 4510d16fef4Smrg#endif 4520d16fef4Smrg return FALSE; 4530d16fef4Smrg} 4540d16fef4Smrg 4550d16fef4SmrgBool 4560d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4570d16fef4Smrg{ 4580d16fef4Smrg if (radeon_present_has_async_flip(screen)) 4590d16fef4Smrg radeon_present_screen_info.capabilities |= PresentCapabilityAsync; 4600d16fef4Smrg 4610d16fef4Smrg if (!present_screen_init(screen, &radeon_present_screen_info)) { 4620d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING, 4630d16fef4Smrg "Present extension disabled because present_screen_init failed\n"); 4640d16fef4Smrg return FALSE; 4650d16fef4Smrg } 4660d16fef4Smrg 4670d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4680d16fef4Smrg "Present extension enabled\n"); 4690d16fef4Smrg 4700d16fef4Smrg return TRUE; 4710d16fef4Smrg} 4720d16fef4Smrg 4730d16fef4Smrg#else /* !HAVE_PRESENT_H */ 4740d16fef4Smrg 4750d16fef4SmrgBool 4760d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4770d16fef4Smrg{ 4780d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4790d16fef4Smrg "Present extension disabled because present.h not available at " 4800d16fef4Smrg "build time\n"); 4810d16fef4Smrg 4820d16fef4Smrg return FALSE; 4830d16fef4Smrg} 4840d16fef4Smrg 4850d16fef4Smrg#endif 486