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, 160446f62d6Smrg radeon_present_vblank_abort, 161446f62d6Smrg FALSE); 1627314432eSmrg if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 1630d16fef4Smrg free(event); 1640d16fef4Smrg return BadAlloc; 1650d16fef4Smrg } 1660d16fef4Smrg 1670d16fef4Smrg for (;;) { 1688bf5c682Smrg if (drmmode_wait_vblank(xf86_crtc, 1698bf5c682Smrg DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc, 1708bf5c682Smrg drm_queue_seq, NULL, NULL)) 1710d16fef4Smrg break; 1720d16fef4Smrg if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { 1730d16fef4Smrg radeon_drm_abort_entry(drm_queue_seq); 1740d16fef4Smrg return BadAlloc; 1750d16fef4Smrg } 1760d16fef4Smrg } 1770d16fef4Smrg 1780d16fef4Smrg return Success; 1790d16fef4Smrg} 1800d16fef4Smrg 1810d16fef4Smrg/* 1820d16fef4Smrg * Remove a pending vblank event from the DRM queue so that it is not reported 1830d16fef4Smrg * to the extension 1840d16fef4Smrg */ 1850d16fef4Smrgstatic void 1860d16fef4Smrgradeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1870d16fef4Smrg{ 1880d16fef4Smrg radeon_drm_abort_id(event_id); 1890d16fef4Smrg} 1900d16fef4Smrg 1910d16fef4Smrg/* 1920d16fef4Smrg * Flush our batch buffer when requested by the Present extension. 1930d16fef4Smrg */ 1940d16fef4Smrgstatic void 1950d16fef4Smrgradeon_present_flush(WindowPtr window) 1960d16fef4Smrg{ 1970d16fef4Smrg radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen)); 1980d16fef4Smrg} 1990d16fef4Smrg 2000d16fef4Smrgstatic uint32_t 2010d16fef4Smrgradeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap) 2020d16fef4Smrg{ 2030d16fef4Smrg uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap); 2040d16fef4Smrg 2050d16fef4Smrg /* Micro tiling is always enabled with macro tiling on >= R600, so we 2060d16fef4Smrg * can ignore the micro tiling bit in that case 2070d16fef4Smrg */ 2080d16fef4Smrg if ((tiling_flags & RADEON_TILING_MACRO) && 2090d16fef4Smrg info->ChipFamily >= CHIP_FAMILY_R600) 2100d16fef4Smrg tiling_flags &= ~RADEON_TILING_MICRO; 2110d16fef4Smrg 2120d16fef4Smrg return tiling_flags; 2130d16fef4Smrg} 2140d16fef4Smrg 2150d16fef4Smrg/* 2167314432eSmrg * Test to see if unflipping is possible 2177314432eSmrg * 2187314432eSmrg * These tests have to pass for flips as well 2190d16fef4Smrg */ 2200d16fef4Smrgstatic Bool 2217314432eSmrgradeon_present_check_unflip(ScrnInfoPtr scrn) 2220d16fef4Smrg{ 2230d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2240d16fef4Smrg int num_crtcs_on; 2250d16fef4Smrg int i; 2260d16fef4Smrg 2270d16fef4Smrg if (!scrn->vtSema) 2280d16fef4Smrg return FALSE; 2290d16fef4Smrg 2307314432eSmrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2318bf5c682Smrg xf86CrtcPtr crtc = config->crtc[i]; 2327314432eSmrg 2338bf5c682Smrg if (drmmode_crtc_can_flip(crtc)) { 2348bf5c682Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 2357314432eSmrg 2368bf5c682Smrg if (drmmode_crtc->flip_pending) 2378bf5c682Smrg return FALSE; 2387314432eSmrg 2398bf5c682Smrg if (!drmmode_crtc->tear_free) 2408bf5c682Smrg num_crtcs_on++; 2418bf5c682Smrg } 2427314432eSmrg } 2437314432eSmrg 2447314432eSmrg return num_crtcs_on > 0; 2457314432eSmrg} 2467314432eSmrg 2477314432eSmrg/* 2487314432eSmrg * Test to see if page flipping is possible on the target crtc 2497314432eSmrg */ 2507314432eSmrgstatic Bool 2517314432eSmrgradeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 2527314432eSmrg Bool sync_flip) 2537314432eSmrg{ 2548bf5c682Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 2557314432eSmrg ScreenPtr screen = window->drawable.pScreen; 2568bf5c682Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 2570a1d3ae0Smrg#ifdef USE_GLAMOR 2580d2a5547Smrg struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); 2590a1d3ae0Smrg#endif 2608bf5c682Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2617314432eSmrg RADEONInfoPtr info = RADEONPTR(scrn); 262446f62d6Smrg PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); 2638bf5c682Smrg int num_crtcs_on; 2648bf5c682Smrg int i; 2658bf5c682Smrg 2668bf5c682Smrg if (!scrn->vtSema) 2678bf5c682Smrg return FALSE; 2687314432eSmrg 2690d16fef4Smrg if (!info->allowPageFlip) 2700d16fef4Smrg return FALSE; 2710d16fef4Smrg 2728bf5c682Smrg if (info->sprites_visible > 0) 2730d16fef4Smrg return FALSE; 2740d16fef4Smrg 2750d16fef4Smrg if (info->drmmode.dri2_flipping) 2760d16fef4Smrg return FALSE; 2770d16fef4Smrg 278446f62d6Smrg#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(1, 20, 99, 1, 0) 279446f62d6Smrg if (pixmap->devKind != screen_pixmap->devKind) 280446f62d6Smrg return FALSE; 281446f62d6Smrg#endif 282446f62d6Smrg 2830a1d3ae0Smrg#ifdef USE_GLAMOR 2840d2a5547Smrg if (priv && priv->fb_failed) 2850d2a5547Smrg return FALSE; 2860a1d3ae0Smrg#endif 2870d2a5547Smrg 2880d2a5547Smrg if (!radeon_pixmap_get_fb(pixmap)) { 2890a1d3ae0Smrg#ifdef USE_GLAMOR 2900d2a5547Smrg if (!priv) 2910d2a5547Smrg priv = radeon_get_pixmap_private(pixmap); 2920d2a5547Smrg 2930d2a5547Smrg if (priv && !priv->fb_failed) { 2940d2a5547Smrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 2950d2a5547Smrg "Cannot get FB for Present flip (may be " 2960d2a5547Smrg "normal if using PRIME render offloading)\n"); 2970d2a5547Smrg priv->fb_failed = TRUE; 2980d2a5547Smrg } 2990a1d3ae0Smrg#endif 3000d2a5547Smrg 3010d2a5547Smrg return FALSE; 3020d2a5547Smrg } 3030d2a5547Smrg 3040d16fef4Smrg /* The kernel driver doesn't handle flipping between BOs with different 3050d16fef4Smrg * tiling parameters correctly yet 3060d16fef4Smrg */ 3070d16fef4Smrg if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != 3080d16fef4Smrg radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) 3090d16fef4Smrg return FALSE; 3100d16fef4Smrg 3118bf5c682Smrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 3128bf5c682Smrg if (drmmode_crtc_can_flip(config->crtc[i])) 3138bf5c682Smrg num_crtcs_on++; 3148bf5c682Smrg else if (config->crtc[i] == crtc->devPrivate) 3158bf5c682Smrg return FALSE; 3168bf5c682Smrg } 3178bf5c682Smrg 3188bf5c682Smrg if (num_crtcs_on == 0) 3198bf5c682Smrg return FALSE; 3208bf5c682Smrg 3218bf5c682Smrg return TRUE; 3220d16fef4Smrg} 3230d16fef4Smrg 3240d16fef4Smrg/* 3250d16fef4Smrg * Once the flip has been completed on all CRTCs, notify the 3260d16fef4Smrg * extension code telling it when that happened 3270d16fef4Smrg */ 3280d16fef4Smrgstatic void 3290d16fef4Smrgradeon_present_flip_event(xf86CrtcPtr crtc, uint32_t msc, uint64_t ust, void *pageflip_data) 3300d16fef4Smrg{ 3310d16fef4Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 3320d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3330d16fef4Smrg 3340d16fef4Smrg if (event->unflip) 3350d16fef4Smrg info->drmmode.present_flipping = FALSE; 3360d16fef4Smrg 3370d16fef4Smrg present_event_notify(event->event_id, ust, msc); 3380d16fef4Smrg free(event); 3390d16fef4Smrg} 3400d16fef4Smrg 3410d16fef4Smrg/* 3420d16fef4Smrg * The flip has been aborted, free the structure 3430d16fef4Smrg */ 3440d16fef4Smrgstatic void 3450d16fef4Smrgradeon_present_flip_abort(xf86CrtcPtr crtc, void *pageflip_data) 3460d16fef4Smrg{ 3470d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3480d16fef4Smrg 3490d16fef4Smrg free(event); 3500d16fef4Smrg} 3510d16fef4Smrg 3520d16fef4Smrg/* 3530d16fef4Smrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 3540d16fef4Smrg * then wait for vblank. Otherwise, flip immediately 3550d16fef4Smrg */ 3560d16fef4Smrgstatic Bool 3570d16fef4Smrgradeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, 3580d16fef4Smrg PixmapPtr pixmap, Bool sync_flip) 3590d16fef4Smrg{ 3608bf5c682Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 3610d16fef4Smrg ScreenPtr screen = crtc->pScreen; 3628bf5c682Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 3630d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3640d16fef4Smrg struct radeon_present_vblank_event *event; 3658bf5c682Smrg Bool ret = FALSE; 3660d16fef4Smrg 3670d16fef4Smrg if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) 36839413783Smrg return ret; 3690d16fef4Smrg 3700d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3710d16fef4Smrg if (!event) 37239413783Smrg return ret; 3730d16fef4Smrg 3740d16fef4Smrg event->event_id = event_id; 3750d16fef4Smrg 3763ed65abbSmrg radeon_cs_flush_indirect(scrn); 3773ed65abbSmrg 3788bf5c682Smrg ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, 3798bf5c682Smrg event_id, event, crtc->devPrivate, 3800d16fef4Smrg radeon_present_flip_event, 3817314432eSmrg radeon_present_flip_abort, 3823ed65abbSmrg sync_flip ? FLIP_VSYNC : FLIP_ASYNC, 3833ed65abbSmrg target_msc); 3840d16fef4Smrg if (!ret) 3850d16fef4Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); 3860d16fef4Smrg else 3870d16fef4Smrg info->drmmode.present_flipping = TRUE; 3880d16fef4Smrg 3890d16fef4Smrg return ret; 3900d16fef4Smrg} 3910d16fef4Smrg 3920d16fef4Smrg/* 3930d16fef4Smrg * Queue a flip back to the normal frame buffer 3940d16fef4Smrg */ 3950d16fef4Smrgstatic void 3960d16fef4Smrgradeon_present_unflip(ScreenPtr screen, uint64_t event_id) 3970d16fef4Smrg{ 3980d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3990d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 4000d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 4010d16fef4Smrg struct radeon_present_vblank_event *event; 4020d16fef4Smrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 4033ed65abbSmrg enum drmmode_flip_sync flip_sync = 4043ed65abbSmrg (radeon_present_screen_info.capabilities & PresentCapabilityAsync) ? 4053ed65abbSmrg FLIP_ASYNC : FLIP_VSYNC; 4060d16fef4Smrg int i; 4070d16fef4Smrg 4087314432eSmrg if (!radeon_present_check_unflip(scrn)) 4090d16fef4Smrg goto modeset; 4100d16fef4Smrg 4110d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 4120d16fef4Smrg if (!event) { 4130d16fef4Smrg ErrorF("%s: calloc failed, display might freeze\n", __func__); 4140d16fef4Smrg goto modeset; 4150d16fef4Smrg } 4160d16fef4Smrg 4170d16fef4Smrg event->event_id = event_id; 4180d16fef4Smrg event->unflip = TRUE; 4190d16fef4Smrg 4208bf5c682Smrg if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap, 4218bf5c682Smrg event_id, event, NULL, radeon_present_flip_event, 4223ed65abbSmrg radeon_present_flip_abort, flip_sync, 0)) 4230d16fef4Smrg return; 4240d16fef4Smrg 4250d16fef4Smrgmodeset: 42639413783Smrg radeon_finish(scrn, info->front_buffer); 4270d16fef4Smrg for (i = 0; i < config->num_crtc; i++) { 4280d16fef4Smrg xf86CrtcPtr crtc = config->crtc[i]; 4290d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 4300d16fef4Smrg 4318bf5c682Smrg if (!crtc->enabled || drmmode_crtc->tear_free) 4320d16fef4Smrg continue; 4330d16fef4Smrg 4348bf5c682Smrg if (drmmode_crtc->dpms_mode == DPMSModeOn) 4350d16fef4Smrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 4360d16fef4Smrg crtc->x, crtc->y); 4370d16fef4Smrg else 4380d16fef4Smrg drmmode_crtc->need_modeset = TRUE; 4390d16fef4Smrg } 4400d16fef4Smrg 4410d16fef4Smrg present_event_notify(event_id, 0, 0); 4420d16fef4Smrg 4430d16fef4Smrg info->drmmode.present_flipping = FALSE; 4440d16fef4Smrg} 4450d16fef4Smrg 4460d16fef4Smrgstatic present_screen_info_rec radeon_present_screen_info = { 4470d16fef4Smrg .version = 0, 4480d16fef4Smrg 4490d16fef4Smrg .get_crtc = radeon_present_get_crtc, 4500d16fef4Smrg .get_ust_msc = radeon_present_get_ust_msc, 4510d16fef4Smrg .queue_vblank = radeon_present_queue_vblank, 4520d16fef4Smrg .abort_vblank = radeon_present_abort_vblank, 4530d16fef4Smrg .flush = radeon_present_flush, 4540d16fef4Smrg 4550d16fef4Smrg .capabilities = PresentCapabilityNone, 4560d16fef4Smrg .check_flip = radeon_present_check_flip, 4570d16fef4Smrg .flip = radeon_present_flip, 4580d16fef4Smrg .unflip = radeon_present_unflip, 4590d16fef4Smrg}; 4600d16fef4Smrg 4610d16fef4Smrgstatic Bool 4620d16fef4Smrgradeon_present_has_async_flip(ScreenPtr screen) 4630d16fef4Smrg{ 4640d16fef4Smrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 4650d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 4668bf5c682Smrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); 4670d16fef4Smrg int ret; 4680d16fef4Smrg uint64_t value; 4690d16fef4Smrg 4708bf5c682Smrg ret = drmGetCap(pRADEONEnt->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4710d16fef4Smrg if (ret == 0) 4720d16fef4Smrg return value == 1; 4730d16fef4Smrg#endif 4740d16fef4Smrg return FALSE; 4750d16fef4Smrg} 4760d16fef4Smrg 4770d16fef4SmrgBool 4780d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4790d16fef4Smrg{ 4800d16fef4Smrg if (radeon_present_has_async_flip(screen)) 4810d16fef4Smrg radeon_present_screen_info.capabilities |= PresentCapabilityAsync; 4820d16fef4Smrg 4830d16fef4Smrg if (!present_screen_init(screen, &radeon_present_screen_info)) { 4840d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING, 4850d16fef4Smrg "Present extension disabled because present_screen_init failed\n"); 4860d16fef4Smrg return FALSE; 4870d16fef4Smrg } 4880d16fef4Smrg 4890d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4900d16fef4Smrg "Present extension enabled\n"); 4910d16fef4Smrg 4920d16fef4Smrg return TRUE; 4930d16fef4Smrg} 4940d16fef4Smrg 4950d16fef4Smrg#else /* !HAVE_PRESENT_H */ 4960d16fef4Smrg 4970d16fef4SmrgBool 4980d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4990d16fef4Smrg{ 5000d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 5010d16fef4Smrg "Present extension disabled because present.h not available at " 5020d16fef4Smrg "build time\n"); 5030d16fef4Smrg 5040d16fef4Smrg return FALSE; 5050d16fef4Smrg} 5060d16fef4Smrg 5070d16fef4Smrg#endif 508