radeon_present.c revision 3ed65abb
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 uint32_t crtc_select(int crtc_id) 590d16fef4Smrg{ 600d16fef4Smrg if (crtc_id > 1) 610d16fef4Smrg return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT; 620d16fef4Smrg else if (crtc_id > 0) 630d16fef4Smrg return DRM_VBLANK_SECONDARY; 640d16fef4Smrg else 650d16fef4Smrg return 0; 660d16fef4Smrg} 670d16fef4Smrg 680d16fef4Smrgstatic RRCrtcPtr 690d16fef4Smrgradeon_present_get_crtc(WindowPtr window) 700d16fef4Smrg{ 710d16fef4Smrg ScreenPtr screen = window->drawable.pScreen; 720d16fef4Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 730d16fef4Smrg xf86CrtcPtr crtc; 740d16fef4Smrg RRCrtcPtr randr_crtc = NULL; 750d16fef4Smrg 760d16fef4Smrg crtc = radeon_pick_best_crtc(pScrn, FALSE, 770d16fef4Smrg window->drawable.x, 780d16fef4Smrg window->drawable.x + window->drawable.width, 790d16fef4Smrg window->drawable.y, 800d16fef4Smrg window->drawable.y + window->drawable.height); 810d16fef4Smrg 820d16fef4Smrg if (crtc) 830d16fef4Smrg randr_crtc = crtc->randr_crtc; 840d16fef4Smrg 850d16fef4Smrg return randr_crtc; 860d16fef4Smrg} 870d16fef4Smrg 880d16fef4Smrgstatic int 890d16fef4Smrgradeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) 900d16fef4Smrg{ 910d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 920d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 930d16fef4Smrg 940d16fef4Smrg if (drmmode_crtc->dpms_mode != DPMSModeOn) 950d16fef4Smrg return BadAlloc; 960d16fef4Smrg 970d16fef4Smrg return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc); 980d16fef4Smrg} 990d16fef4Smrg 1000d16fef4Smrg/* 1010d16fef4Smrg * Flush the DRM event queue when full; this 1020d16fef4Smrg * makes space for new requests 1030d16fef4Smrg */ 1040d16fef4Smrgstatic Bool 1050d16fef4Smrgradeon_present_flush_drm_events(ScreenPtr screen) 1060d16fef4Smrg{ 1070d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1080d16fef4Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 1090d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; 1100d16fef4Smrg drmmode_ptr drmmode = drmmode_crtc->drmmode; 1110d16fef4Smrg struct pollfd p = { .fd = drmmode->fd, .events = POLLIN }; 1120d16fef4Smrg int r; 1130d16fef4Smrg 1140d16fef4Smrg do { 1150d16fef4Smrg r = poll(&p, 1, 0); 1160d16fef4Smrg } while (r == -1 && (errno == EINTR || errno == EAGAIN)); 1170d16fef4Smrg 1180d16fef4Smrg if (r <= 0) 1190d16fef4Smrg return 0; 1200d16fef4Smrg 1210d16fef4Smrg return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0; 1220d16fef4Smrg} 1230d16fef4Smrg 1240d16fef4Smrg/* 1250d16fef4Smrg * Called when the queued vblank event has occurred 1260d16fef4Smrg */ 1270d16fef4Smrgstatic void 1280d16fef4Smrgradeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc, 1290d16fef4Smrg uint64_t usec, void *data) 1300d16fef4Smrg{ 1310d16fef4Smrg struct radeon_present_vblank_event *event = data; 1320d16fef4Smrg 1330d16fef4Smrg present_event_notify(event->event_id, usec, msc); 1340d16fef4Smrg free(event); 1350d16fef4Smrg} 1360d16fef4Smrg 1370d16fef4Smrg/* 1380d16fef4Smrg * Called when the queued vblank is aborted 1390d16fef4Smrg */ 1400d16fef4Smrgstatic void 1410d16fef4Smrgradeon_present_vblank_abort(xf86CrtcPtr crtc, void *data) 1420d16fef4Smrg{ 1430d16fef4Smrg struct radeon_present_vblank_event *event = data; 1440d16fef4Smrg 1450d16fef4Smrg free(event); 1460d16fef4Smrg} 1470d16fef4Smrg 1480d16fef4Smrg/* 1490d16fef4Smrg * Queue an event to report back to the Present extension when the specified 1500d16fef4Smrg * MSC has past 1510d16fef4Smrg */ 1520d16fef4Smrgstatic int 1530d16fef4Smrgradeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 1540d16fef4Smrg{ 1550d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 1560d16fef4Smrg ScreenPtr screen = crtc->pScreen; 1570d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1580d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 1590d16fef4Smrg int crtc_id = drmmode_get_crtc_id(xf86_crtc); 1600d16fef4Smrg struct radeon_present_vblank_event *event; 1610d16fef4Smrg uintptr_t drm_queue_seq; 1620d16fef4Smrg drmVBlank vbl; 1630d16fef4Smrg int ret; 1640d16fef4Smrg 1650d16fef4Smrg event = calloc(sizeof(struct radeon_present_vblank_event), 1); 1660d16fef4Smrg if (!event) 1670d16fef4Smrg return BadAlloc; 1680d16fef4Smrg event->event_id = event_id; 1690d16fef4Smrg drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, 1700d16fef4Smrg RADEON_DRM_QUEUE_CLIENT_DEFAULT, 1710d16fef4Smrg event_id, event, 1720d16fef4Smrg radeon_present_vblank_handler, 1730d16fef4Smrg radeon_present_vblank_abort); 1747314432eSmrg if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { 1750d16fef4Smrg free(event); 1760d16fef4Smrg return BadAlloc; 1770d16fef4Smrg } 1780d16fef4Smrg 1790d16fef4Smrg vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id); 1800d16fef4Smrg vbl.request.sequence = msc; 1810d16fef4Smrg vbl.request.signal = drm_queue_seq; 1820d16fef4Smrg for (;;) { 1830d16fef4Smrg ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); 1840d16fef4Smrg if (!ret) 1850d16fef4Smrg break; 1860d16fef4Smrg if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { 1870d16fef4Smrg radeon_drm_abort_entry(drm_queue_seq); 1880d16fef4Smrg return BadAlloc; 1890d16fef4Smrg } 1900d16fef4Smrg } 1910d16fef4Smrg 1920d16fef4Smrg return Success; 1930d16fef4Smrg} 1940d16fef4Smrg 1950d16fef4Smrg/* 1960d16fef4Smrg * Remove a pending vblank event from the DRM queue so that it is not reported 1970d16fef4Smrg * to the extension 1980d16fef4Smrg */ 1990d16fef4Smrgstatic void 2000d16fef4Smrgradeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 2010d16fef4Smrg{ 2020d16fef4Smrg radeon_drm_abort_id(event_id); 2030d16fef4Smrg} 2040d16fef4Smrg 2050d16fef4Smrg/* 2060d16fef4Smrg * Flush our batch buffer when requested by the Present extension. 2070d16fef4Smrg */ 2080d16fef4Smrgstatic void 2090d16fef4Smrgradeon_present_flush(WindowPtr window) 2100d16fef4Smrg{ 2110d16fef4Smrg radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen)); 2120d16fef4Smrg} 2130d16fef4Smrg 2140d16fef4Smrgstatic uint32_t 2150d16fef4Smrgradeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap) 2160d16fef4Smrg{ 2170d16fef4Smrg uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap); 2180d16fef4Smrg 2190d16fef4Smrg /* Micro tiling is always enabled with macro tiling on >= R600, so we 2200d16fef4Smrg * can ignore the micro tiling bit in that case 2210d16fef4Smrg */ 2220d16fef4Smrg if ((tiling_flags & RADEON_TILING_MACRO) && 2230d16fef4Smrg info->ChipFamily >= CHIP_FAMILY_R600) 2240d16fef4Smrg tiling_flags &= ~RADEON_TILING_MICRO; 2250d16fef4Smrg 2260d16fef4Smrg return tiling_flags; 2270d16fef4Smrg} 2280d16fef4Smrg 2290d16fef4Smrg/* 2307314432eSmrg * Test to see if unflipping is possible 2317314432eSmrg * 2327314432eSmrg * These tests have to pass for flips as well 2330d16fef4Smrg */ 2340d16fef4Smrgstatic Bool 2357314432eSmrgradeon_present_check_unflip(ScrnInfoPtr scrn) 2360d16fef4Smrg{ 2370d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 2380d16fef4Smrg int num_crtcs_on; 2390d16fef4Smrg int i; 2400d16fef4Smrg 2410d16fef4Smrg if (!scrn->vtSema) 2420d16fef4Smrg return FALSE; 2430d16fef4Smrg 2447314432eSmrg for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) { 2457314432eSmrg drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private; 2467314432eSmrg 2477314432eSmrg if (!config->crtc[i]->enabled) 2487314432eSmrg continue; 2497314432eSmrg 2507314432eSmrg if (!drmmode_crtc || drmmode_crtc->rotate.bo || 2517314432eSmrg drmmode_crtc->scanout[0].bo) 2527314432eSmrg return FALSE; 2537314432eSmrg 2547314432eSmrg if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) 2557314432eSmrg num_crtcs_on++; 2567314432eSmrg } 2577314432eSmrg 2587314432eSmrg return num_crtcs_on > 0; 2597314432eSmrg} 2607314432eSmrg 2617314432eSmrg/* 2627314432eSmrg * Test to see if page flipping is possible on the target crtc 2637314432eSmrg */ 2647314432eSmrgstatic Bool 2657314432eSmrgradeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, 2667314432eSmrg Bool sync_flip) 2677314432eSmrg{ 2687314432eSmrg ScreenPtr screen = window->drawable.pScreen; 2697314432eSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 2707314432eSmrg RADEONInfoPtr info = RADEONPTR(scrn); 2717314432eSmrg PixmapPtr screen_pixmap; 2727314432eSmrg 2730d16fef4Smrg if (!info->allowPageFlip) 2740d16fef4Smrg return FALSE; 2750d16fef4Smrg 2760d16fef4Smrg if (info->hwcursor_disabled) 2770d16fef4Smrg return FALSE; 2780d16fef4Smrg 2790d16fef4Smrg if (info->drmmode.dri2_flipping) 2800d16fef4Smrg return FALSE; 2810d16fef4Smrg 2820d16fef4Smrg /* The kernel driver doesn't handle flipping between BOs with different 2830d16fef4Smrg * tiling parameters correctly yet 2840d16fef4Smrg */ 2850d16fef4Smrg screen_pixmap = screen->GetScreenPixmap(screen); 2860d16fef4Smrg if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != 2870d16fef4Smrg radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) 2880d16fef4Smrg return FALSE; 2890d16fef4Smrg 2907314432eSmrg return radeon_present_check_unflip(scrn); 2910d16fef4Smrg} 2920d16fef4Smrg 2930d16fef4Smrg/* 2940d16fef4Smrg * Once the flip has been completed on all CRTCs, notify the 2950d16fef4Smrg * extension code telling it when that happened 2960d16fef4Smrg */ 2970d16fef4Smrgstatic void 2980d16fef4Smrgradeon_present_flip_event(xf86CrtcPtr crtc, uint32_t msc, uint64_t ust, void *pageflip_data) 2990d16fef4Smrg{ 3000d16fef4Smrg RADEONInfoPtr info = RADEONPTR(crtc->scrn); 3010d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3020d16fef4Smrg 3030d16fef4Smrg if (event->unflip) 3040d16fef4Smrg info->drmmode.present_flipping = FALSE; 3050d16fef4Smrg 3060d16fef4Smrg present_event_notify(event->event_id, ust, msc); 3070d16fef4Smrg free(event); 3080d16fef4Smrg} 3090d16fef4Smrg 3100d16fef4Smrg/* 3110d16fef4Smrg * The flip has been aborted, free the structure 3120d16fef4Smrg */ 3130d16fef4Smrgstatic void 3140d16fef4Smrgradeon_present_flip_abort(xf86CrtcPtr crtc, void *pageflip_data) 3150d16fef4Smrg{ 3160d16fef4Smrg struct radeon_present_vblank_event *event = pageflip_data; 3170d16fef4Smrg 3180d16fef4Smrg free(event); 3190d16fef4Smrg} 3200d16fef4Smrg 3210d16fef4Smrg/* 3220d16fef4Smrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 3230d16fef4Smrg * then wait for vblank. Otherwise, flip immediately 3240d16fef4Smrg */ 3250d16fef4Smrgstatic Bool 3260d16fef4Smrgradeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, 3270d16fef4Smrg PixmapPtr pixmap, Bool sync_flip) 3280d16fef4Smrg{ 3290d16fef4Smrg ScreenPtr screen = crtc->pScreen; 3300d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3310d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3320d16fef4Smrg struct radeon_present_vblank_event *event; 3330d16fef4Smrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 3340d16fef4Smrg int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1; 3350d16fef4Smrg uint32_t handle; 3360d16fef4Smrg Bool ret; 3370d16fef4Smrg 3380d16fef4Smrg if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) 3390d16fef4Smrg return FALSE; 3400d16fef4Smrg 3410d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) 3420d16fef4Smrg return FALSE; 3430d16fef4Smrg 3440d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3450d16fef4Smrg if (!event) 3460d16fef4Smrg return FALSE; 3470d16fef4Smrg 3480d16fef4Smrg event->event_id = event_id; 3490d16fef4Smrg 3503ed65abbSmrg radeon_cs_flush_indirect(scrn); 3513ed65abbSmrg 3520d16fef4Smrg ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 3530d16fef4Smrg event_id, event, crtc_id, 3540d16fef4Smrg radeon_present_flip_event, 3557314432eSmrg radeon_present_flip_abort, 3563ed65abbSmrg sync_flip ? FLIP_VSYNC : FLIP_ASYNC, 3573ed65abbSmrg target_msc); 3580d16fef4Smrg if (!ret) 3590d16fef4Smrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); 3600d16fef4Smrg else 3610d16fef4Smrg info->drmmode.present_flipping = TRUE; 3620d16fef4Smrg 3630d16fef4Smrg return ret; 3640d16fef4Smrg} 3650d16fef4Smrg 3660d16fef4Smrg/* 3670d16fef4Smrg * Queue a flip back to the normal frame buffer 3680d16fef4Smrg */ 3690d16fef4Smrgstatic void 3700d16fef4Smrgradeon_present_unflip(ScreenPtr screen, uint64_t event_id) 3710d16fef4Smrg{ 3720d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3730d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 3740d16fef4Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 3750d16fef4Smrg struct radeon_present_vblank_event *event; 3760d16fef4Smrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 3773ed65abbSmrg enum drmmode_flip_sync flip_sync = 3783ed65abbSmrg (radeon_present_screen_info.capabilities & PresentCapabilityAsync) ? 3793ed65abbSmrg FLIP_ASYNC : FLIP_VSYNC; 3800d16fef4Smrg uint32_t handle; 3813ed65abbSmrg int old_fb_id; 3820d16fef4Smrg int i; 3830d16fef4Smrg 3843ed65abbSmrg radeon_cs_flush_indirect(scrn); 3853ed65abbSmrg 3867314432eSmrg if (!radeon_present_check_unflip(scrn)) 3870d16fef4Smrg goto modeset; 3880d16fef4Smrg 3890d16fef4Smrg if (!radeon_get_pixmap_handle(pixmap, &handle)) { 3900d16fef4Smrg ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n", 3910d16fef4Smrg __func__); 3920d16fef4Smrg goto modeset; 3930d16fef4Smrg } 3940d16fef4Smrg 3950d16fef4Smrg event = calloc(1, sizeof(struct radeon_present_vblank_event)); 3960d16fef4Smrg if (!event) { 3970d16fef4Smrg ErrorF("%s: calloc failed, display might freeze\n", __func__); 3980d16fef4Smrg goto modeset; 3990d16fef4Smrg } 4000d16fef4Smrg 4010d16fef4Smrg event->event_id = event_id; 4020d16fef4Smrg event->unflip = TRUE; 4030d16fef4Smrg 4040d16fef4Smrg if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, 4050d16fef4Smrg event_id, event, -1, radeon_present_flip_event, 4063ed65abbSmrg radeon_present_flip_abort, flip_sync, 0)) 4070d16fef4Smrg return; 4080d16fef4Smrg 4090d16fef4Smrgmodeset: 4100d16fef4Smrg /* info->drmmode.fb_id still points to the FB for the last flipped BO. 4110d16fef4Smrg * Clear it, drmmode_set_mode_major will re-create it 4120d16fef4Smrg */ 4133ed65abbSmrg old_fb_id = info->drmmode.fb_id; 4140d16fef4Smrg info->drmmode.fb_id = 0; 4150d16fef4Smrg 4163ed65abbSmrg radeon_bo_wait(info->front_bo); 4170d16fef4Smrg for (i = 0; i < config->num_crtc; i++) { 4180d16fef4Smrg xf86CrtcPtr crtc = config->crtc[i]; 4190d16fef4Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 4200d16fef4Smrg 4210d16fef4Smrg if (!crtc->enabled) 4220d16fef4Smrg continue; 4230d16fef4Smrg 4247314432eSmrg if (drmmode_crtc->pending_dpms_mode == DPMSModeOn) 4250d16fef4Smrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 4260d16fef4Smrg crtc->x, crtc->y); 4270d16fef4Smrg else 4280d16fef4Smrg drmmode_crtc->need_modeset = TRUE; 4290d16fef4Smrg } 4300d16fef4Smrg 4313ed65abbSmrg drmModeRmFB(info->drmmode.fd, old_fb_id); 4320d16fef4Smrg present_event_notify(event_id, 0, 0); 4330d16fef4Smrg 4340d16fef4Smrg info->drmmode.present_flipping = FALSE; 4350d16fef4Smrg} 4360d16fef4Smrg 4370d16fef4Smrgstatic present_screen_info_rec radeon_present_screen_info = { 4380d16fef4Smrg .version = 0, 4390d16fef4Smrg 4400d16fef4Smrg .get_crtc = radeon_present_get_crtc, 4410d16fef4Smrg .get_ust_msc = radeon_present_get_ust_msc, 4420d16fef4Smrg .queue_vblank = radeon_present_queue_vblank, 4430d16fef4Smrg .abort_vblank = radeon_present_abort_vblank, 4440d16fef4Smrg .flush = radeon_present_flush, 4450d16fef4Smrg 4460d16fef4Smrg .capabilities = PresentCapabilityNone, 4470d16fef4Smrg .check_flip = radeon_present_check_flip, 4480d16fef4Smrg .flip = radeon_present_flip, 4490d16fef4Smrg .unflip = radeon_present_unflip, 4500d16fef4Smrg}; 4510d16fef4Smrg 4520d16fef4Smrgstatic Bool 4530d16fef4Smrgradeon_present_has_async_flip(ScreenPtr screen) 4540d16fef4Smrg{ 4550d16fef4Smrg#ifdef DRM_CAP_ASYNC_PAGE_FLIP 4560d16fef4Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 4570d16fef4Smrg RADEONInfoPtr info = RADEONPTR(scrn); 4580d16fef4Smrg int ret; 4590d16fef4Smrg uint64_t value; 4600d16fef4Smrg 4610d16fef4Smrg ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4620d16fef4Smrg if (ret == 0) 4630d16fef4Smrg return value == 1; 4640d16fef4Smrg#endif 4650d16fef4Smrg return FALSE; 4660d16fef4Smrg} 4670d16fef4Smrg 4680d16fef4SmrgBool 4690d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4700d16fef4Smrg{ 4710d16fef4Smrg if (radeon_present_has_async_flip(screen)) 4720d16fef4Smrg radeon_present_screen_info.capabilities |= PresentCapabilityAsync; 4730d16fef4Smrg 4740d16fef4Smrg if (!present_screen_init(screen, &radeon_present_screen_info)) { 4750d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING, 4760d16fef4Smrg "Present extension disabled because present_screen_init failed\n"); 4770d16fef4Smrg return FALSE; 4780d16fef4Smrg } 4790d16fef4Smrg 4800d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4810d16fef4Smrg "Present extension enabled\n"); 4820d16fef4Smrg 4830d16fef4Smrg return TRUE; 4840d16fef4Smrg} 4850d16fef4Smrg 4860d16fef4Smrg#else /* !HAVE_PRESENT_H */ 4870d16fef4Smrg 4880d16fef4SmrgBool 4890d16fef4Smrgradeon_present_screen_init(ScreenPtr screen) 4900d16fef4Smrg{ 4910d16fef4Smrg xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO, 4920d16fef4Smrg "Present extension disabled because present.h not available at " 4930d16fef4Smrg "build time\n"); 4940d16fef4Smrg 4950d16fef4Smrg return FALSE; 4960d16fef4Smrg} 4970d16fef4Smrg 4980d16fef4Smrg#endif 499