radeon_present.c revision 0d16fef4
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); 1720d16fef4Smrg if (!drm_queue_seq) { 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/* 2280d16fef4Smrg * Test to see if page flipping is possible on the target crtc 2290d16fef4Smrg */ 2300d16fef4Smrgstatic Bool 2310d16fef4Smrgradeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 2320d16fef4Smrg Bool sync_flip) 2330d16fef4Smrg{ 2340d16fef4Smrg ScreenPtr screen = window->drawable.pScreen; 2350d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2360d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 2370d16fef4Smrg PixmapPtr screen_pixmap; 2380d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2390d16fef4Smrg int num_crtcs_on; 2400d16fef4Smrg int i; 2410d16fef4Smrg 2420d16fef4Smrg if (!scrn->vtSema) 2430d16fef4Smrg return FALSE; 2440d16fef4Smrg 2450d16fef4Smrg if (!info->allowPageFlip) 2460d16fef4Smrg return FALSE; 2470d16fef4Smrg 2480d16fef4Smrg if (info->hwcursor_disabled) 2490d16fef4Smrg return FALSE; 2500d16fef4Smrg 2510d16fef4Smrg if (!sync_flip) 2520d16fef4Smrg return FALSE; 2530d16fef4Smrg 2540d16fef4Smrg if (info->drmmode.dri2_flipping) 2550d16fef4Smrg return FALSE; 2560d16fef4Smrg 2570d16fef4Smrg /* The kernel driver doesn't handle flipping between BOs with different 2580d16fef4Smrg * tiling parameters correctly yet 2590d16fef4Smrg */ 2600d16fef4Smrg screen_pixmap = screen->GetScreenPixmap(screen); 2610d16fef4Smrg if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != 2620d16fef4Smrg radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) 2630d16fef4Smrg return FALSE; 2640d16fef4Smrg 2650d16fef4Smrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2660d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private; 2670d16fef4Smrg 2680d16fef4Smrg if (!config->crtc[i]->enabled) 2690d16fef4Smrg continue; 2700d16fef4Smrg 2710d16fef4Smrg if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL) 2720d16fef4Smrg return FALSE; 2730d16fef4Smrg 2740d16fef4Smrg if (drmmode_crtc->dpms_mode == DPMSModeOn) 2750d16fef4Smrg num_crtcs_on++; 2760d16fef4Smrg } 2770d16fef4Smrg 2780d16fef4Smrg return num_crtcs_on > 0; 2790d16fef4Smrg} 2800d16fef4Smrg 2810d16fef4Smrg/* 2820d16fef4Smrg * Once the flip has been completed on all CRTCs, notify the 2830d16fef4Smrg * extension code telling it when that happened 2840d16fef4Smrg */ 2850d16fef4Smrgstatic void 2860d16fef4Smrgradeon_present_flip_event(xf86CrtcPtr crtc, uint32_t msc, uint64_t ust, void *pageflip_data) 2870d16fef4Smrg{ 2880d16fef4Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 2890d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 2900d16fef4Smrg 2910d16fef4Smrg if (event->unflip) 2920d16fef4Smrg info->drmmode.present_flipping = FALSE; 2930d16fef4Smrg 2940d16fef4Smrg present_event_notify(event->event_id, ust, msc); 2950d16fef4Smrg free(event); 2960d16fef4Smrg} 2970d16fef4Smrg 2980d16fef4Smrg/* 2990d16fef4Smrg * The flip has been aborted, free the structure 3000d16fef4Smrg */ 3010d16fef4Smrgstatic void 3020d16fef4Smrgradeon_present_flip_abort(xf86CrtcPtr crtc, void *pageflip_data) 3030d16fef4Smrg{ 3040d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3050d16fef4Smrg 3060d16fef4Smrg free(event); 3070d16fef4Smrg} 3080d16fef4Smrg 3090d16fef4Smrg/* 3100d16fef4Smrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 3110d16fef4Smrg * then wait for vblank. Otherwise, flip immediately 3120d16fef4Smrg */ 3130d16fef4Smrgstatic Bool 3140d16fef4Smrgradeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, 3150d16fef4Smrg PixmapPtr pixmap, Bool sync_flip) 3160d16fef4Smrg{ 3170d16fef4Smrg ScreenPtr screen = crtc->pScreen; 3180d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3190d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3200d16fef4Smrg struct radeon_present_vblank_event *event; 3210d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 3220d16fef4Smrg int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1; 3230d16fef4Smrg uint32_t handle; 3240d16fef4Smrg Bool ret; 3250d16fef4Smrg 3260d16fef4Smrg if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) 3270d16fef4Smrg return FALSE; 3280d16fef4Smrg 3290d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) 3300d16fef4Smrg return FALSE; 3310d16fef4Smrg 3320d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3330d16fef4Smrg if (!event) 3340d16fef4Smrg return FALSE; 3350d16fef4Smrg 3360d16fef4Smrg event->event_id = event_id; 3370d16fef4Smrg 3380d16fef4Smrg ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 3390d16fef4Smrg event_id, event, crtc_id, 3400d16fef4Smrg radeon_present_flip_event, 3410d16fef4Smrg radeon_present_flip_abort); 3420d16fef4Smrg if (!ret) 3430d16fef4Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); 3440d16fef4Smrg else 3450d16fef4Smrg info->drmmode.present_flipping = TRUE; 3460d16fef4Smrg 3470d16fef4Smrg return ret; 3480d16fef4Smrg} 3490d16fef4Smrg 3500d16fef4Smrg/* 3510d16fef4Smrg * Queue a flip back to the normal frame buffer 3520d16fef4Smrg */ 3530d16fef4Smrgstatic void 3540d16fef4Smrgradeon_present_unflip(ScreenPtr screen, uint64_t event_id) 3550d16fef4Smrg{ 3560d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3570d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3580d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3590d16fef4Smrg struct radeon_present_vblank_event *event; 3600d16fef4Smrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 3610d16fef4Smrg uint32_t handle; 3620d16fef4Smrg int i; 3630d16fef4Smrg 3640d16fef4Smrg if (!radeon_present_check_flip(NULL, screen->root, pixmap, TRUE)) 3650d16fef4Smrg goto modeset; 3660d16fef4Smrg 3670d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) { 3680d16fef4Smrg ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n", 3690d16fef4Smrg __func__); 3700d16fef4Smrg goto modeset; 3710d16fef4Smrg } 3720d16fef4Smrg 3730d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3740d16fef4Smrg if (!event) { 3750d16fef4Smrg ErrorF("%s: calloc failed, display might freeze\n", __func__); 3760d16fef4Smrg goto modeset; 3770d16fef4Smrg } 3780d16fef4Smrg 3790d16fef4Smrg event->event_id = event_id; 3800d16fef4Smrg event->unflip = TRUE; 3810d16fef4Smrg 3820d16fef4Smrg if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 3830d16fef4Smrg event_id, event, -1, radeon_present_flip_event, 3840d16fef4Smrg radeon_present_flip_abort)) 3850d16fef4Smrg return; 3860d16fef4Smrg 3870d16fef4Smrgmodeset: 3880d16fef4Smrg /* info->drmmode.fb_id still points to the FB for the last flipped BO. 3890d16fef4Smrg * Clear it, drmmode_set_mode_major will re-create it 3900d16fef4Smrg */ 3910d16fef4Smrg drmModeRmFB(info->drmmode.fd, info->drmmode.fb_id); 3920d16fef4Smrg info->drmmode.fb_id = 0; 3930d16fef4Smrg 3940d16fef4Smrg for (i = 0; i < config->num_crtc; i++) { 3950d16fef4Smrg xf86CrtcPtr crtc = config->crtc[i]; 3960d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 3970d16fef4Smrg 3980d16fef4Smrg if (!crtc->enabled) 3990d16fef4Smrg continue; 4000d16fef4Smrg 4010d16fef4Smrg if (drmmode_crtc->dpms_mode == DPMSModeOn) 4020d16fef4Smrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 4030d16fef4Smrg crtc->x, crtc->y); 4040d16fef4Smrg else 4050d16fef4Smrg drmmode_crtc->need_modeset = TRUE; 4060d16fef4Smrg } 4070d16fef4Smrg 4080d16fef4Smrg present_event_notify(event_id, 0, 0); 4090d16fef4Smrg 4100d16fef4Smrg info->drmmode.present_flipping = FALSE; 4110d16fef4Smrg} 4120d16fef4Smrg 4130d16fef4Smrgstatic present_screen_info_rec radeon_present_screen_info = { 4140d16fef4Smrg .version = 0, 4150d16fef4Smrg 4160d16fef4Smrg .get_crtc = radeon_present_get_crtc, 4170d16fef4Smrg .get_ust_msc = radeon_present_get_ust_msc, 4180d16fef4Smrg .queue_vblank = radeon_present_queue_vblank, 4190d16fef4Smrg .abort_vblank = radeon_present_abort_vblank, 4200d16fef4Smrg .flush = radeon_present_flush, 4210d16fef4Smrg 4220d16fef4Smrg .capabilities = PresentCapabilityNone, 4230d16fef4Smrg .check_flip = radeon_present_check_flip, 4240d16fef4Smrg .flip = radeon_present_flip, 4250d16fef4Smrg .unflip = radeon_present_unflip, 4260d16fef4Smrg}; 4270d16fef4Smrg 4280d16fef4Smrgstatic Bool 4290d16fef4Smrgradeon_present_has_async_flip(ScreenPtr screen) 4300d16fef4Smrg{ 4310d16fef4Smrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 4320d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 4330d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 4340d16fef4Smrg int ret; 4350d16fef4Smrg uint64_t value; 4360d16fef4Smrg 4370d16fef4Smrg ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4380d16fef4Smrg if (ret == 0) 4390d16fef4Smrg return value == 1; 4400d16fef4Smrg#endif 4410d16fef4Smrg return FALSE; 4420d16fef4Smrg} 4430d16fef4Smrg 4440d16fef4SmrgBool 4450d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4460d16fef4Smrg{ 4470d16fef4Smrg if (radeon_present_has_async_flip(screen)) 4480d16fef4Smrg radeon_present_screen_info.capabilities |= PresentCapabilityAsync; 4490d16fef4Smrg 4500d16fef4Smrg if (!present_screen_init(screen, &radeon_present_screen_info)) { 4510d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING, 4520d16fef4Smrg "Present extension disabled because present_screen_init failed\n"); 4530d16fef4Smrg return FALSE; 4540d16fef4Smrg } 4550d16fef4Smrg 4560d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4570d16fef4Smrg "Present extension enabled\n"); 4580d16fef4Smrg 4590d16fef4Smrg return TRUE; 4600d16fef4Smrg} 4610d16fef4Smrg 4620d16fef4Smrg#else /* !HAVE_PRESENT_H */ 4630d16fef4Smrg 4640d16fef4SmrgBool 4650d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4660d16fef4Smrg{ 4670d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4680d16fef4Smrg "Present extension disabled because present.h not available at " 4690d16fef4Smrg "build time\n"); 4700d16fef4Smrg 4710d16fef4Smrg return FALSE; 4720d16fef4Smrg} 4730d16fef4Smrg 4740d16fef4Smrg#endif 475