radeon_present.c revision 39413783
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 513ed65abbSmrgstatic present_screen_info_rec radeon_present_screen_info; 523ed65abbSmrg 530d16fef4Smrgstruct radeon_present_vblank_event { 540d16fef4Smrg uint64_t event_id; 550d16fef4Smrg Bool unflip; 560d16fef4Smrg}; 570d16fef4Smrg 580d16fef4Smrgstatic RRCrtcPtr 590d16fef4Smrgradeon_present_get_crtc(WindowPtr window) 600d16fef4Smrg{ 610d16fef4Smrg ScreenPtr screen = window->drawable.pScreen; 620d16fef4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 630d16fef4Smrg xf86CrtcPtr crtc; 640d16fef4Smrg RRCrtcPtr randr_crtc = NULL; 650d16fef4Smrg 660d16fef4Smrg crtc = radeon_pick_best_crtc(pScrn, FALSE, 670d16fef4Smrg window->drawable.x, 680d16fef4Smrg window->drawable.x + window->drawable.width, 690d16fef4Smrg window->drawable.y, 700d16fef4Smrg window->drawable.y + window->drawable.height); 710d16fef4Smrg 720d16fef4Smrg if (crtc) 730d16fef4Smrg randr_crtc = crtc->randr_crtc; 740d16fef4Smrg 750d16fef4Smrg return randr_crtc; 760d16fef4Smrg} 770d16fef4Smrg 780d16fef4Smrgstatic int 790d16fef4Smrgradeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) 800d16fef4Smrg{ 810d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 820d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 830d16fef4Smrg 840d16fef4Smrg if (drmmode_crtc->dpms_mode != DPMSModeOn) 850d16fef4Smrg return BadAlloc; 860d16fef4Smrg 870d16fef4Smrg return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc); 880d16fef4Smrg} 890d16fef4Smrg 900d16fef4Smrg/* 910d16fef4Smrg * Flush the DRM event queue when full; this 920d16fef4Smrg * makes space for new requests 930d16fef4Smrg */ 940d16fef4Smrgstatic Bool 950d16fef4Smrgradeon_present_flush_drm_events(ScreenPtr screen) 960d16fef4Smrg{ 970d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 988bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 990d16fef4Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1000d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; 1010d16fef4Smrg drmmode_ptr drmmode = drmmode_crtc->drmmode; 1028bf5c682Smrg struct pollfd p = { .fd = pRADEONEnt->fd, .events = POLLIN }; 1030d16fef4Smrg int r; 1040d16fef4Smrg 1050d16fef4Smrg do { 1060d16fef4Smrg r = poll(&p, 1, 0); 1070d16fef4Smrg } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 1080d16fef4Smrg 1090d16fef4Smrg if (r <= 0) 1100d16fef4Smrg return 0; 1110d16fef4Smrg 11239413783Smrg return radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context) >= 0; 1130d16fef4Smrg} 1140d16fef4Smrg 1150d16fef4Smrg/* 1160d16fef4Smrg * Called when the queued vblank event has occurred 1170d16fef4Smrg */ 1180d16fef4Smrgstatic void 1190d16fef4Smrgradeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc, 1200d16fef4Smrg uint64_t usec, void *data) 1210d16fef4Smrg{ 1220d16fef4Smrg struct radeon_present_vblank_event *event = data; 1230d16fef4Smrg 12439413783Smrg present_event_notify(event->event_id, usec, msc); 1250d16fef4Smrg free(event); 1260d16fef4Smrg} 1270d16fef4Smrg 1280d16fef4Smrg/* 1290d16fef4Smrg * Called when the queued vblank is aborted 1300d16fef4Smrg */ 1310d16fef4Smrgstatic void 1320d16fef4Smrgradeon_present_vblank_abort(xf86CrtcPtr crtc, void *data) 1330d16fef4Smrg{ 1340d16fef4Smrg struct radeon_present_vblank_event *event = data; 1350d16fef4Smrg 1360d16fef4Smrg free(event); 1370d16fef4Smrg} 1380d16fef4Smrg 1390d16fef4Smrg/* 1400d16fef4Smrg * Queue an event to report back to the Present extension when the specified 1410d16fef4Smrg * MSC has past 1420d16fef4Smrg */ 1430d16fef4Smrgstatic int 1440d16fef4Smrgradeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1450d16fef4Smrg{ 1460d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 1470d16fef4Smrg ScreenPtr screen = crtc->pScreen; 1480d16fef4Smrg struct radeon_present_vblank_event *event; 1490d16fef4Smrg uintptr_t drm_queue_seq; 1500d16fef4Smrg 1510d16fef4Smrg event = calloc(sizeof(struct radeon_present_vblank_event), 1); 1520d16fef4Smrg if (!event) 1530d16fef4Smrg return BadAlloc; 1540d16fef4Smrg event->event_id = event_id; 1558bf5c682Smrg 1560d16fef4Smrg drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, 1570d16fef4Smrg RADEON_DRM_QUEUE_CLIENT_DEFAULT, 1580d16fef4Smrg event_id, event, 1590d16fef4Smrg radeon_present_vblank_handler, 1600d16fef4Smrg radeon_present_vblank_abort); 1617314432eSmrg if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 1620d16fef4Smrg free(event); 1630d16fef4Smrg return BadAlloc; 1640d16fef4Smrg } 1650d16fef4Smrg 1660d16fef4Smrg for (;;) { 1678bf5c682Smrg if (drmmode_wait_vblank(xf86_crtc, 1688bf5c682Smrg DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc, 1698bf5c682Smrg drm_queue_seq, NULL, NULL)) 1700d16fef4Smrg break; 1710d16fef4Smrg if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { 1720d16fef4Smrg radeon_drm_abort_entry(drm_queue_seq); 1730d16fef4Smrg return BadAlloc; 1740d16fef4Smrg } 1750d16fef4Smrg } 1760d16fef4Smrg 1770d16fef4Smrg return Success; 1780d16fef4Smrg} 1790d16fef4Smrg 1800d16fef4Smrg/* 1810d16fef4Smrg * Remove a pending vblank event from the DRM queue so that it is not reported 1820d16fef4Smrg * to the extension 1830d16fef4Smrg */ 1840d16fef4Smrgstatic void 1850d16fef4Smrgradeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1860d16fef4Smrg{ 1870d16fef4Smrg radeon_drm_abort_id(event_id); 1880d16fef4Smrg} 1890d16fef4Smrg 1900d16fef4Smrg/* 1910d16fef4Smrg * Flush our batch buffer when requested by the Present extension. 1920d16fef4Smrg */ 1930d16fef4Smrgstatic void 1940d16fef4Smrgradeon_present_flush(WindowPtr window) 1950d16fef4Smrg{ 1960d16fef4Smrg radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen)); 1970d16fef4Smrg} 1980d16fef4Smrg 1990d16fef4Smrgstatic uint32_t 2000d16fef4Smrgradeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap) 2010d16fef4Smrg{ 2020d16fef4Smrg uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap); 2030d16fef4Smrg 2040d16fef4Smrg /* Micro tiling is always enabled with macro tiling on >= R600, so we 2050d16fef4Smrg * can ignore the micro tiling bit in that case 2060d16fef4Smrg */ 2070d16fef4Smrg if ((tiling_flags & RADEON_TILING_MACRO) && 2080d16fef4Smrg info->ChipFamily >= CHIP_FAMILY_R600) 2090d16fef4Smrg tiling_flags &= ~RADEON_TILING_MICRO; 2100d16fef4Smrg 2110d16fef4Smrg return tiling_flags; 2120d16fef4Smrg} 2130d16fef4Smrg 2140d16fef4Smrg/* 2157314432eSmrg * Test to see if unflipping is possible 2167314432eSmrg * 2177314432eSmrg * These tests have to pass for flips as well 2180d16fef4Smrg */ 2190d16fef4Smrgstatic Bool 2207314432eSmrgradeon_present_check_unflip(ScrnInfoPtr scrn) 2210d16fef4Smrg{ 2220d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2230d16fef4Smrg int num_crtcs_on; 2240d16fef4Smrg int i; 2250d16fef4Smrg 2260d16fef4Smrg if (!scrn->vtSema) 2270d16fef4Smrg return FALSE; 2280d16fef4Smrg 2297314432eSmrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2308bf5c682Smrg xf86CrtcPtr crtc = config->crtc[i]; 2317314432eSmrg 2328bf5c682Smrg if (drmmode_crtc_can_flip(crtc)) { 2338bf5c682Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2347314432eSmrg 2358bf5c682Smrg if (drmmode_crtc->flip_pending) 2368bf5c682Smrg return FALSE; 2377314432eSmrg 2388bf5c682Smrg if (!drmmode_crtc->tear_free) 2398bf5c682Smrg num_crtcs_on++; 2408bf5c682Smrg } 2417314432eSmrg } 2427314432eSmrg 2437314432eSmrg return num_crtcs_on > 0; 2447314432eSmrg} 2457314432eSmrg 2467314432eSmrg/* 2477314432eSmrg * Test to see if page flipping is possible on the target crtc 2487314432eSmrg */ 2497314432eSmrgstatic Bool 2507314432eSmrgradeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 2517314432eSmrg Bool sync_flip) 2527314432eSmrg{ 2538bf5c682Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 2547314432eSmrg ScreenPtr screen = window->drawable.pScreen; 2558bf5c682Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 2568bf5c682Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2577314432eSmrg RADEONInfoPtr info = RADEONPTR(scrn); 2587314432eSmrg PixmapPtr screen_pixmap; 2598bf5c682Smrg int num_crtcs_on; 2608bf5c682Smrg int i; 2618bf5c682Smrg 2628bf5c682Smrg if (!scrn->vtSema) 2638bf5c682Smrg return FALSE; 2647314432eSmrg 2650d16fef4Smrg if (!info->allowPageFlip) 2660d16fef4Smrg return FALSE; 2670d16fef4Smrg 2688bf5c682Smrg if (info->sprites_visible > 0) 2690d16fef4Smrg return FALSE; 2700d16fef4Smrg 2710d16fef4Smrg if (info->drmmode.dri2_flipping) 2720d16fef4Smrg return FALSE; 2730d16fef4Smrg 2740d16fef4Smrg /* The kernel driver doesn't handle flipping between BOs with different 2750d16fef4Smrg * tiling parameters correctly yet 2760d16fef4Smrg */ 2770d16fef4Smrg screen_pixmap = screen->GetScreenPixmap(screen); 2780d16fef4Smrg if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != 2790d16fef4Smrg radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) 2800d16fef4Smrg return FALSE; 2810d16fef4Smrg 2828bf5c682Smrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2838bf5c682Smrg if (drmmode_crtc_can_flip(config->crtc[i])) 2848bf5c682Smrg num_crtcs_on++; 2858bf5c682Smrg else if (config->crtc[i] == crtc->devPrivate) 2868bf5c682Smrg return FALSE; 2878bf5c682Smrg } 2888bf5c682Smrg 2898bf5c682Smrg if (num_crtcs_on == 0) 2908bf5c682Smrg return FALSE; 2918bf5c682Smrg 2928bf5c682Smrg return TRUE; 2930d16fef4Smrg} 2940d16fef4Smrg 2950d16fef4Smrg/* 2960d16fef4Smrg * Once the flip has been completed on all CRTCs, notify the 2970d16fef4Smrg * extension code telling it when that happened 2980d16fef4Smrg */ 2990d16fef4Smrgstatic void 3000d16fef4Smrgradeon_present_flip_event(xf86CrtcPtr crtc, uint32_t msc, uint64_t ust, void *pageflip_data) 3010d16fef4Smrg{ 3020d16fef4Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 3030d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3040d16fef4Smrg 3050d16fef4Smrg if (event->unflip) 3060d16fef4Smrg info->drmmode.present_flipping = FALSE; 3070d16fef4Smrg 3080d16fef4Smrg present_event_notify(event->event_id, ust, msc); 3090d16fef4Smrg free(event); 3100d16fef4Smrg} 3110d16fef4Smrg 3120d16fef4Smrg/* 3130d16fef4Smrg * The flip has been aborted, free the structure 3140d16fef4Smrg */ 3150d16fef4Smrgstatic void 3160d16fef4Smrgradeon_present_flip_abort(xf86CrtcPtr crtc, void *pageflip_data) 3170d16fef4Smrg{ 3180d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3190d16fef4Smrg 3200d16fef4Smrg free(event); 3210d16fef4Smrg} 3220d16fef4Smrg 3230d16fef4Smrg/* 3240d16fef4Smrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 3250d16fef4Smrg * then wait for vblank. Otherwise, flip immediately 3260d16fef4Smrg */ 3270d16fef4Smrgstatic Bool 3280d16fef4Smrgradeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, 3290d16fef4Smrg PixmapPtr pixmap, Bool sync_flip) 3300d16fef4Smrg{ 3318bf5c682Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 3320d16fef4Smrg ScreenPtr screen = crtc->pScreen; 3338bf5c682Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 3340d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3350d16fef4Smrg struct radeon_present_vblank_event *event; 3368bf5c682Smrg Bool ret = FALSE; 3370d16fef4Smrg 3380d16fef4Smrg if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) 33939413783Smrg return ret; 3400d16fef4Smrg 3410d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3420d16fef4Smrg if (!event) 34339413783Smrg return ret; 3440d16fef4Smrg 3450d16fef4Smrg event->event_id = event_id; 3460d16fef4Smrg 3473ed65abbSmrg radeon_cs_flush_indirect(scrn); 3483ed65abbSmrg 3498bf5c682Smrg ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, 3508bf5c682Smrg event_id, event, crtc->devPrivate, 3510d16fef4Smrg radeon_present_flip_event, 3527314432eSmrg radeon_present_flip_abort, 3533ed65abbSmrg sync_flip ? FLIP_VSYNC : FLIP_ASYNC, 3543ed65abbSmrg target_msc); 3550d16fef4Smrg if (!ret) 3560d16fef4Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); 3570d16fef4Smrg else 3580d16fef4Smrg info->drmmode.present_flipping = TRUE; 3590d16fef4Smrg 3600d16fef4Smrg return ret; 3610d16fef4Smrg} 3620d16fef4Smrg 3630d16fef4Smrg/* 3640d16fef4Smrg * Queue a flip back to the normal frame buffer 3650d16fef4Smrg */ 3660d16fef4Smrgstatic void 3670d16fef4Smrgradeon_present_unflip(ScreenPtr screen, uint64_t event_id) 3680d16fef4Smrg{ 3690d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3700d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3710d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3720d16fef4Smrg struct radeon_present_vblank_event *event; 3730d16fef4Smrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 3743ed65abbSmrg enum drmmode_flip_sync flip_sync = 3753ed65abbSmrg (radeon_present_screen_info.capabilities & PresentCapabilityAsync) ? 3763ed65abbSmrg FLIP_ASYNC : FLIP_VSYNC; 3770d16fef4Smrg int i; 3780d16fef4Smrg 3797314432eSmrg if (!radeon_present_check_unflip(scrn)) 3800d16fef4Smrg goto modeset; 3810d16fef4Smrg 3820d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3830d16fef4Smrg if (!event) { 3840d16fef4Smrg ErrorF("%s: calloc failed, display might freeze\n", __func__); 3850d16fef4Smrg goto modeset; 3860d16fef4Smrg } 3870d16fef4Smrg 3880d16fef4Smrg event->event_id = event_id; 3890d16fef4Smrg event->unflip = TRUE; 3900d16fef4Smrg 3918bf5c682Smrg if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, 3928bf5c682Smrg event_id, event, NULL, radeon_present_flip_event, 3933ed65abbSmrg radeon_present_flip_abort, flip_sync, 0)) 3940d16fef4Smrg return; 3950d16fef4Smrg 3960d16fef4Smrgmodeset: 39739413783Smrg radeon_finish(scrn, info->front_buffer); 3980d16fef4Smrg for (i = 0; i < config->num_crtc; i++) { 3990d16fef4Smrg xf86CrtcPtr crtc = config->crtc[i]; 4000d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 4010d16fef4Smrg 4028bf5c682Smrg if (!crtc->enabled || drmmode_crtc->tear_free) 4030d16fef4Smrg continue; 4040d16fef4Smrg 4058bf5c682Smrg if (drmmode_crtc->dpms_mode == DPMSModeOn) 4060d16fef4Smrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 4070d16fef4Smrg crtc->x, crtc->y); 4080d16fef4Smrg else 4090d16fef4Smrg drmmode_crtc->need_modeset = TRUE; 4100d16fef4Smrg } 4110d16fef4Smrg 4120d16fef4Smrg present_event_notify(event_id, 0, 0); 4130d16fef4Smrg 4140d16fef4Smrg info->drmmode.present_flipping = FALSE; 4150d16fef4Smrg} 4160d16fef4Smrg 4170d16fef4Smrgstatic present_screen_info_rec radeon_present_screen_info = { 4180d16fef4Smrg .version = 0, 4190d16fef4Smrg 4200d16fef4Smrg .get_crtc = radeon_present_get_crtc, 4210d16fef4Smrg .get_ust_msc = radeon_present_get_ust_msc, 4220d16fef4Smrg .queue_vblank = radeon_present_queue_vblank, 4230d16fef4Smrg .abort_vblank = radeon_present_abort_vblank, 4240d16fef4Smrg .flush = radeon_present_flush, 4250d16fef4Smrg 4260d16fef4Smrg .capabilities = PresentCapabilityNone, 4270d16fef4Smrg .check_flip = radeon_present_check_flip, 4280d16fef4Smrg .flip = radeon_present_flip, 4290d16fef4Smrg .unflip = radeon_present_unflip, 4300d16fef4Smrg}; 4310d16fef4Smrg 4320d16fef4Smrgstatic Bool 4330d16fef4Smrgradeon_present_has_async_flip(ScreenPtr screen) 4340d16fef4Smrg{ 4350d16fef4Smrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 4360d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 4378bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 4380d16fef4Smrg int ret; 4390d16fef4Smrg uint64_t value; 4400d16fef4Smrg 4418bf5c682Smrg ret = drmGetCap(pRADEONEnt->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4420d16fef4Smrg if (ret == 0) 4430d16fef4Smrg return value == 1; 4440d16fef4Smrg#endif 4450d16fef4Smrg return FALSE; 4460d16fef4Smrg} 4470d16fef4Smrg 4480d16fef4SmrgBool 4490d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4500d16fef4Smrg{ 4510d16fef4Smrg if (radeon_present_has_async_flip(screen)) 4520d16fef4Smrg radeon_present_screen_info.capabilities |= PresentCapabilityAsync; 4530d16fef4Smrg 4540d16fef4Smrg if (!present_screen_init(screen, &radeon_present_screen_info)) { 4550d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING, 4560d16fef4Smrg "Present extension disabled because present_screen_init failed\n"); 4570d16fef4Smrg return FALSE; 4580d16fef4Smrg } 4590d16fef4Smrg 4600d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4610d16fef4Smrg "Present extension enabled\n"); 4620d16fef4Smrg 4630d16fef4Smrg return TRUE; 4640d16fef4Smrg} 4650d16fef4Smrg 4660d16fef4Smrg#else /* !HAVE_PRESENT_H */ 4670d16fef4Smrg 4680d16fef4SmrgBool 4690d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4700d16fef4Smrg{ 4710d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4720d16fef4Smrg "Present extension disabled because present.h not available at " 4730d16fef4Smrg "build time\n"); 4740d16fef4Smrg 4750d16fef4Smrg return FALSE; 4760d16fef4Smrg} 4770d16fef4Smrg 4780d16fef4Smrg#endif 479