135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2014 Intel Corporation 335c4bbdfSmrg * 435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 935c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1035c4bbdfSmrg * written prior permission. The copyright holders make no representations 1135c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1235c4bbdfSmrg * is" without express or implied warranty. 1335c4bbdfSmrg * 1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2035c4bbdfSmrg * OF THIS SOFTWARE. 2135c4bbdfSmrg */ 2235c4bbdfSmrg 2335c4bbdfSmrg#ifdef HAVE_DIX_CONFIG_H 2435c4bbdfSmrg#include "dix-config.h" 2535c4bbdfSmrg#endif 2635c4bbdfSmrg 2735c4bbdfSmrg#include <assert.h> 2835c4bbdfSmrg#include <errno.h> 2935c4bbdfSmrg#include <fcntl.h> 3035c4bbdfSmrg#include <unistd.h> 3135c4bbdfSmrg#include <stdio.h> 3235c4bbdfSmrg#include <stdint.h> 3335c4bbdfSmrg#include <string.h> 3435c4bbdfSmrg#include <sys/ioctl.h> 3535c4bbdfSmrg#include <sys/time.h> 3635c4bbdfSmrg#include <sys/types.h> 3735c4bbdfSmrg#include <time.h> 3835c4bbdfSmrg 3935c4bbdfSmrg#include <xf86.h> 4035c4bbdfSmrg#include <xf86Crtc.h> 4135c4bbdfSmrg#include <xf86drm.h> 4235c4bbdfSmrg#include <xf86str.h> 4335c4bbdfSmrg#include <present.h> 4435c4bbdfSmrg 4535c4bbdfSmrg#include "driver.h" 4635c4bbdfSmrg#include "drmmode_display.h" 4735c4bbdfSmrg 4835c4bbdfSmrg#if 0 4935c4bbdfSmrg#define DebugPresent(x) ErrorF x 5035c4bbdfSmrg#else 5135c4bbdfSmrg#define DebugPresent(x) 5235c4bbdfSmrg#endif 5335c4bbdfSmrg 5435c4bbdfSmrgstruct ms_present_vblank_event { 5535c4bbdfSmrg uint64_t event_id; 567e31ba66Smrg Bool unflip; 5735c4bbdfSmrg}; 5835c4bbdfSmrg 5935c4bbdfSmrgstatic RRCrtcPtr 6035c4bbdfSmrgms_present_get_crtc(WindowPtr window) 6135c4bbdfSmrg{ 624e185dc0Smrg return ms_randr_crtc_covering_drawable(&window->drawable); 6335c4bbdfSmrg} 6435c4bbdfSmrg 6535c4bbdfSmrgstatic int 662c83f951Sryoms_present_get_ust_msc(RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) 6735c4bbdfSmrg{ 6835c4bbdfSmrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 6935c4bbdfSmrg 7035c4bbdfSmrg return ms_get_crtc_ust_msc(xf86_crtc, ust, msc); 7135c4bbdfSmrg} 7235c4bbdfSmrg 735a112b11Smrg/* 745a112b11Smrg * Changes the variable refresh state for every CRTC on the screen. 755a112b11Smrg */ 765a112b11Smrgvoid 775a112b11Smrgms_present_set_screen_vrr(ScrnInfoPtr scrn, Bool vrr_enabled) 785a112b11Smrg{ 795a112b11Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 805a112b11Smrg xf86CrtcPtr crtc; 815a112b11Smrg int i; 825a112b11Smrg 835a112b11Smrg for (i = 0; i < config->num_crtc; i++) { 845a112b11Smrg crtc = config->crtc[i]; 855a112b11Smrg drmmode_crtc_set_vrr(crtc, vrr_enabled); 865a112b11Smrg } 875a112b11Smrg} 885a112b11Smrg 8935c4bbdfSmrg/* 9035c4bbdfSmrg * Called when the queued vblank event has occurred 9135c4bbdfSmrg */ 9235c4bbdfSmrgstatic void 9335c4bbdfSmrgms_present_vblank_handler(uint64_t msc, uint64_t usec, void *data) 9435c4bbdfSmrg{ 9535c4bbdfSmrg struct ms_present_vblank_event *event = data; 9635c4bbdfSmrg 9735c4bbdfSmrg DebugPresent(("\t\tmh %lld msc %llu\n", 9835c4bbdfSmrg (long long) event->event_id, (long long) msc)); 9935c4bbdfSmrg 10035c4bbdfSmrg present_event_notify(event->event_id, usec, msc); 10135c4bbdfSmrg free(event); 10235c4bbdfSmrg} 10335c4bbdfSmrg 10435c4bbdfSmrg/* 10535c4bbdfSmrg * Called when the queued vblank is aborted 10635c4bbdfSmrg */ 10735c4bbdfSmrgstatic void 10835c4bbdfSmrgms_present_vblank_abort(void *data) 10935c4bbdfSmrg{ 11035c4bbdfSmrg struct ms_present_vblank_event *event = data; 11135c4bbdfSmrg 11235c4bbdfSmrg DebugPresent(("\t\tma %lld\n", (long long) event->event_id)); 11335c4bbdfSmrg 11435c4bbdfSmrg free(event); 11535c4bbdfSmrg} 11635c4bbdfSmrg 11735c4bbdfSmrg/* 11835c4bbdfSmrg * Queue an event to report back to the Present extension when the specified 11935c4bbdfSmrg * MSC has past 12035c4bbdfSmrg */ 12135c4bbdfSmrgstatic int 12235c4bbdfSmrgms_present_queue_vblank(RRCrtcPtr crtc, 12335c4bbdfSmrg uint64_t event_id, 12435c4bbdfSmrg uint64_t msc) 12535c4bbdfSmrg{ 12635c4bbdfSmrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 12735c4bbdfSmrg struct ms_present_vblank_event *event; 12835c4bbdfSmrg uint32_t seq; 12935c4bbdfSmrg 13035c4bbdfSmrg event = calloc(sizeof(struct ms_present_vblank_event), 1); 13135c4bbdfSmrg if (!event) 13235c4bbdfSmrg return BadAlloc; 13335c4bbdfSmrg event->event_id = event_id; 13435c4bbdfSmrg seq = ms_drm_queue_alloc(xf86_crtc, event, 13535c4bbdfSmrg ms_present_vblank_handler, 13635c4bbdfSmrg ms_present_vblank_abort); 13735c4bbdfSmrg if (!seq) { 13835c4bbdfSmrg free(event); 13935c4bbdfSmrg return BadAlloc; 14035c4bbdfSmrg } 14135c4bbdfSmrg 1427e31ba66Smrg if (!ms_queue_vblank(xf86_crtc, MS_QUEUE_ABSOLUTE, msc, NULL, seq)) 1437e31ba66Smrg return BadAlloc; 1447e31ba66Smrg 1455a112b11Smrg DebugPresent(("\t\tmq %lld seq %u msc %llu\n", 1465a112b11Smrg (long long) event_id, seq, (long long) msc)); 14735c4bbdfSmrg return Success; 14835c4bbdfSmrg} 14935c4bbdfSmrg 15035c4bbdfSmrgstatic Bool 15135c4bbdfSmrgms_present_event_match(void *data, void *match_data) 15235c4bbdfSmrg{ 15335c4bbdfSmrg struct ms_present_vblank_event *event = data; 15435c4bbdfSmrg uint64_t *match = match_data; 15535c4bbdfSmrg 15635c4bbdfSmrg return *match == event->event_id; 15735c4bbdfSmrg} 15835c4bbdfSmrg 15935c4bbdfSmrg/* 16035c4bbdfSmrg * Remove a pending vblank event from the DRM queue so that it is not reported 16135c4bbdfSmrg * to the extension 16235c4bbdfSmrg */ 16335c4bbdfSmrgstatic void 16435c4bbdfSmrgms_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) 16535c4bbdfSmrg{ 16635c4bbdfSmrg ScreenPtr screen = crtc->pScreen; 16735c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 16835c4bbdfSmrg 16935c4bbdfSmrg ms_drm_abort(scrn, ms_present_event_match, &event_id); 17035c4bbdfSmrg} 17135c4bbdfSmrg 17235c4bbdfSmrg/* 17335c4bbdfSmrg * Flush our batch buffer when requested by the Present extension. 17435c4bbdfSmrg */ 17535c4bbdfSmrgstatic void 17635c4bbdfSmrgms_present_flush(WindowPtr window) 17735c4bbdfSmrg{ 1787e31ba66Smrg#ifdef GLAMOR_HAS_GBM 17935c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 18035c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 18135c4bbdfSmrg modesettingPtr ms = modesettingPTR(scrn); 18235c4bbdfSmrg 18335c4bbdfSmrg if (ms->drmmode.glamor) 1845a112b11Smrg ms->glamor.block_handler(screen); 18535c4bbdfSmrg#endif 18635c4bbdfSmrg} 18735c4bbdfSmrg 1887e31ba66Smrg#ifdef GLAMOR_HAS_GBM 18935c4bbdfSmrg 19035c4bbdfSmrg/** 1917e31ba66Smrg * Callback for the DRM event queue when a flip has completed on all pipes 19235c4bbdfSmrg * 1937e31ba66Smrg * Notify the extension code 19435c4bbdfSmrg */ 19535c4bbdfSmrgstatic void 1967e31ba66Smrgms_present_flip_handler(modesettingPtr ms, uint64_t msc, 1977e31ba66Smrg uint64_t ust, void *data) 19835c4bbdfSmrg{ 1997e31ba66Smrg struct ms_present_vblank_event *event = data; 20035c4bbdfSmrg 2017e31ba66Smrg DebugPresent(("\t\tms:fc %lld msc %llu ust %llu\n", 2027e31ba66Smrg (long long) event->event_id, 20335c4bbdfSmrg (long long) msc, (long long) ust)); 20435c4bbdfSmrg 2057e31ba66Smrg if (event->unflip) 2067e31ba66Smrg ms->drmmode.present_flipping = FALSE; 20735c4bbdfSmrg 2087e31ba66Smrg ms_present_vblank_handler(msc, ust, event); 20935c4bbdfSmrg} 21035c4bbdfSmrg 21135c4bbdfSmrg/* 21235c4bbdfSmrg * Callback for the DRM queue abort code. A flip has been aborted. 21335c4bbdfSmrg */ 21435c4bbdfSmrgstatic void 2157e31ba66Smrgms_present_flip_abort(modesettingPtr ms, void *data) 21635c4bbdfSmrg{ 2177e31ba66Smrg struct ms_present_vblank_event *event = data; 21835c4bbdfSmrg 2197e31ba66Smrg DebugPresent(("\t\tms:fa %lld\n", (long long) event->event_id)); 22035c4bbdfSmrg 2217e31ba66Smrg free(event); 22235c4bbdfSmrg} 22335c4bbdfSmrg 22435c4bbdfSmrg/* 22535c4bbdfSmrg * Test to see if page flipping is possible on the target crtc 226806e81e9Smrg * 227806e81e9Smrg * We ignore sw-cursors when *disabling* flipping, we may very well be 228806e81e9Smrg * returning to scanning out the normal framebuffer *because* we just 229806e81e9Smrg * switched to sw-cursor mode and check_flip just failed because of that. 23035c4bbdfSmrg */ 23135c4bbdfSmrgstatic Bool 232806e81e9Smrgms_present_check_unflip(RRCrtcPtr crtc, 233806e81e9Smrg WindowPtr window, 234806e81e9Smrg PixmapPtr pixmap, 235806e81e9Smrg Bool sync_flip, 236806e81e9Smrg PresentFlipReason *reason) 23735c4bbdfSmrg{ 23835c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 23935c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 24035c4bbdfSmrg modesettingPtr ms = modesettingPTR(scrn); 24135c4bbdfSmrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 24235c4bbdfSmrg int num_crtcs_on = 0; 24335c4bbdfSmrg int i; 2447e31ba66Smrg struct gbm_bo *gbm; 24535c4bbdfSmrg 24635c4bbdfSmrg if (!ms->drmmode.pageflip) 24735c4bbdfSmrg return FALSE; 24835c4bbdfSmrg 2497e31ba66Smrg if (ms->drmmode.dri2_flipping) 2507e31ba66Smrg return FALSE; 2517e31ba66Smrg 25235c4bbdfSmrg if (!scrn->vtSema) 25335c4bbdfSmrg return FALSE; 25435c4bbdfSmrg 25535c4bbdfSmrg for (i = 0; i < config->num_crtc; i++) { 25635c4bbdfSmrg drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private; 25735c4bbdfSmrg 25835c4bbdfSmrg /* Don't do pageflipping if CRTCs are rotated. */ 25935c4bbdfSmrg if (drmmode_crtc->rotate_bo.gbm) 26035c4bbdfSmrg return FALSE; 26135c4bbdfSmrg 262d44ca368Smrg if (xf86_crtc_on(config->crtc[i])) 26335c4bbdfSmrg num_crtcs_on++; 26435c4bbdfSmrg } 26535c4bbdfSmrg 26635c4bbdfSmrg /* We can't do pageflipping if all the CRTCs are off. */ 26735c4bbdfSmrg if (num_crtcs_on == 0) 26835c4bbdfSmrg return FALSE; 26935c4bbdfSmrg 2705a112b11Smrg /* 2715a112b11Smrg * Check stride, can't change that reliably on flip on some drivers, unless 2725a112b11Smrg * the kms driver is atomic_modeset_capable. 2735a112b11Smrg */ 2745a112b11Smrg if (!ms->atomic_modeset_capable && 2757e31ba66Smrg pixmap->devKind != drmmode_bo_get_pitch(&ms->drmmode.front_bo)) 27635c4bbdfSmrg return FALSE; 27735c4bbdfSmrg 278b3a28be8Smrg if (!ms->drmmode.glamor) 279b3a28be8Smrg return FALSE; 280b3a28be8Smrg 2817e31ba66Smrg#ifdef GBM_BO_WITH_MODIFIERS 2827e31ba66Smrg /* Check if buffer format/modifier is supported by all active CRTCs */ 2835a112b11Smrg gbm = ms->glamor.gbm_bo_from_pixmap(screen, pixmap); 2847e31ba66Smrg if (gbm) { 2857e31ba66Smrg uint32_t format; 2867e31ba66Smrg uint64_t modifier; 2877e31ba66Smrg 2887e31ba66Smrg format = gbm_bo_get_format(gbm); 2897e31ba66Smrg modifier = gbm_bo_get_modifier(gbm); 2907e31ba66Smrg gbm_bo_destroy(gbm); 2917e31ba66Smrg 2927e31ba66Smrg if (!drmmode_is_format_supported(scrn, format, modifier)) { 2937e31ba66Smrg if (reason) 2947e31ba66Smrg *reason = PRESENT_FLIP_REASON_BUFFER_FORMAT; 2957e31ba66Smrg return FALSE; 2967e31ba66Smrg } 2977e31ba66Smrg } 2987e31ba66Smrg#endif 2997e31ba66Smrg 30035c4bbdfSmrg /* Make sure there's a bo we can get to */ 30135c4bbdfSmrg /* XXX: actually do this. also...is it sufficient? 30235c4bbdfSmrg * if (!glamor_get_pixmap_private(pixmap)) 30335c4bbdfSmrg * return FALSE; 30435c4bbdfSmrg */ 30535c4bbdfSmrg 30635c4bbdfSmrg return TRUE; 30735c4bbdfSmrg} 30835c4bbdfSmrg 309806e81e9Smrgstatic Bool 310806e81e9Smrgms_present_check_flip(RRCrtcPtr crtc, 311806e81e9Smrg WindowPtr window, 312806e81e9Smrg PixmapPtr pixmap, 313806e81e9Smrg Bool sync_flip, 314806e81e9Smrg PresentFlipReason *reason) 315806e81e9Smrg{ 316806e81e9Smrg ScreenPtr screen = window->drawable.pScreen; 317806e81e9Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 318806e81e9Smrg modesettingPtr ms = modesettingPTR(scrn); 319806e81e9Smrg 320806e81e9Smrg if (ms->drmmode.sprites_visible > 0) 321806e81e9Smrg return FALSE; 322806e81e9Smrg 3235a112b11Smrg if(!ms_present_check_unflip(crtc, window, pixmap, sync_flip, reason)) 3245a112b11Smrg return FALSE; 3255a112b11Smrg 3265a112b11Smrg ms->flip_window = window; 3275a112b11Smrg 3285a112b11Smrg return TRUE; 329806e81e9Smrg} 330806e81e9Smrg 33135c4bbdfSmrg/* 33235c4bbdfSmrg * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true, 33335c4bbdfSmrg * then wait for vblank. Otherwise, flip immediately 33435c4bbdfSmrg */ 33535c4bbdfSmrgstatic Bool 33635c4bbdfSmrgms_present_flip(RRCrtcPtr crtc, 33735c4bbdfSmrg uint64_t event_id, 33835c4bbdfSmrg uint64_t target_msc, 33935c4bbdfSmrg PixmapPtr pixmap, 34035c4bbdfSmrg Bool sync_flip) 34135c4bbdfSmrg{ 34235c4bbdfSmrg ScreenPtr screen = crtc->pScreen; 34335c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3447e31ba66Smrg modesettingPtr ms = modesettingPTR(scrn); 34535c4bbdfSmrg xf86CrtcPtr xf86_crtc = crtc->devPrivate; 34635c4bbdfSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 34735c4bbdfSmrg Bool ret; 34835c4bbdfSmrg struct ms_present_vblank_event *event; 34935c4bbdfSmrg 3505a112b11Smrg if (!ms_present_check_flip(crtc, ms->flip_window, pixmap, sync_flip, NULL)) 35135c4bbdfSmrg return FALSE; 35235c4bbdfSmrg 35335c4bbdfSmrg event = calloc(1, sizeof(struct ms_present_vblank_event)); 35435c4bbdfSmrg if (!event) 35535c4bbdfSmrg return FALSE; 35635c4bbdfSmrg 3577e31ba66Smrg DebugPresent(("\t\tms:pf %lld msc %llu\n", 3587e31ba66Smrg (long long) event_id, (long long) target_msc)); 3597e31ba66Smrg 36035c4bbdfSmrg event->event_id = event_id; 3617e31ba66Smrg event->unflip = FALSE; 3627e31ba66Smrg 3635a112b11Smrg /* A window can only flip if it covers the entire X screen. 3645a112b11Smrg * Only one window can flip at a time. 3655a112b11Smrg * 3665a112b11Smrg * If the window also has the variable refresh property then 3675a112b11Smrg * variable refresh supported can be enabled on every CRTC. 3685a112b11Smrg */ 3695a112b11Smrg if (ms->vrr_support && ms->is_connector_vrr_capable && 3705a112b11Smrg ms_window_has_variable_refresh(ms, ms->flip_window)) { 3715a112b11Smrg ms_present_set_screen_vrr(scrn, TRUE); 3725a112b11Smrg } 3735a112b11Smrg 3747e31ba66Smrg ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip, 3755a112b11Smrg ms_present_flip_handler, ms_present_flip_abort, 3765a112b11Smrg "Present-flip"); 3775a112b11Smrg if (ret) 3787e31ba66Smrg ms->drmmode.present_flipping = TRUE; 37935c4bbdfSmrg 38035c4bbdfSmrg return ret; 38135c4bbdfSmrg} 38235c4bbdfSmrg 38335c4bbdfSmrg/* 38435c4bbdfSmrg * Queue a flip back to the normal frame buffer 38535c4bbdfSmrg */ 38635c4bbdfSmrgstatic void 38735c4bbdfSmrgms_present_unflip(ScreenPtr screen, uint64_t event_id) 38835c4bbdfSmrg{ 38935c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 3907e31ba66Smrg modesettingPtr ms = modesettingPTR(scrn); 39135c4bbdfSmrg PixmapPtr pixmap = screen->GetScreenPixmap(screen); 39235c4bbdfSmrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); 39335c4bbdfSmrg int i; 39435c4bbdfSmrg 3955a112b11Smrg ms_present_set_screen_vrr(scrn, FALSE); 3965a112b11Smrg 397d566a54bSmrg if (ms_present_check_unflip(NULL, screen->root, pixmap, TRUE, NULL)) { 398d566a54bSmrg struct ms_present_vblank_event *event; 39935c4bbdfSmrg 400d566a54bSmrg event = calloc(1, sizeof(struct ms_present_vblank_event)); 401d566a54bSmrg if (!event) 402d566a54bSmrg return; 403d566a54bSmrg 404d566a54bSmrg event->event_id = event_id; 405d566a54bSmrg event->unflip = TRUE; 40635c4bbdfSmrg 407d566a54bSmrg if (ms_do_pageflip(screen, pixmap, event, -1, FALSE, 408d566a54bSmrg ms_present_flip_handler, ms_present_flip_abort, 409d566a54bSmrg "Present-unflip")) { 410d566a54bSmrg return; 411d566a54bSmrg } 41235c4bbdfSmrg } 41335c4bbdfSmrg 41435c4bbdfSmrg for (i = 0; i < config->num_crtc; i++) { 41535c4bbdfSmrg xf86CrtcPtr crtc = config->crtc[i]; 41635c4bbdfSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 41735c4bbdfSmrg 41835c4bbdfSmrg if (!crtc->enabled) 41935c4bbdfSmrg continue; 42035c4bbdfSmrg 42135c4bbdfSmrg /* info->drmmode.fb_id still points to the FB for the last flipped BO. 42235c4bbdfSmrg * Clear it, drmmode_set_mode_major will re-create it 42335c4bbdfSmrg */ 42435c4bbdfSmrg if (drmmode_crtc->drmmode->fb_id) { 42535c4bbdfSmrg drmModeRmFB(drmmode_crtc->drmmode->fd, 42635c4bbdfSmrg drmmode_crtc->drmmode->fb_id); 42735c4bbdfSmrg drmmode_crtc->drmmode->fb_id = 0; 42835c4bbdfSmrg } 42935c4bbdfSmrg 43035c4bbdfSmrg if (drmmode_crtc->dpms_mode == DPMSModeOn) 43135c4bbdfSmrg crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, 43235c4bbdfSmrg crtc->x, crtc->y); 43335c4bbdfSmrg else 43435c4bbdfSmrg drmmode_crtc->need_modeset = TRUE; 43535c4bbdfSmrg } 43635c4bbdfSmrg 43735c4bbdfSmrg present_event_notify(event_id, 0, 0); 4387e31ba66Smrg ms->drmmode.present_flipping = FALSE; 43935c4bbdfSmrg} 44035c4bbdfSmrg#endif 44135c4bbdfSmrg 44235c4bbdfSmrgstatic present_screen_info_rec ms_present_screen_info = { 44335c4bbdfSmrg .version = PRESENT_SCREEN_INFO_VERSION, 44435c4bbdfSmrg 44535c4bbdfSmrg .get_crtc = ms_present_get_crtc, 44635c4bbdfSmrg .get_ust_msc = ms_present_get_ust_msc, 44735c4bbdfSmrg .queue_vblank = ms_present_queue_vblank, 44835c4bbdfSmrg .abort_vblank = ms_present_abort_vblank, 44935c4bbdfSmrg .flush = ms_present_flush, 45035c4bbdfSmrg 45135c4bbdfSmrg .capabilities = PresentCapabilityNone, 4527e31ba66Smrg#ifdef GLAMOR_HAS_GBM 4537e31ba66Smrg .check_flip = NULL, 4547e31ba66Smrg .check_flip2 = ms_present_check_flip, 45535c4bbdfSmrg .flip = ms_present_flip, 45635c4bbdfSmrg .unflip = ms_present_unflip, 45735c4bbdfSmrg#endif 45835c4bbdfSmrg}; 45935c4bbdfSmrg 46035c4bbdfSmrgBool 46135c4bbdfSmrgms_present_screen_init(ScreenPtr screen) 46235c4bbdfSmrg{ 46335c4bbdfSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 46435c4bbdfSmrg modesettingPtr ms = modesettingPTR(scrn); 46535c4bbdfSmrg uint64_t value; 46635c4bbdfSmrg int ret; 46735c4bbdfSmrg 46835c4bbdfSmrg ret = drmGetCap(ms->fd, DRM_CAP_ASYNC_PAGE_FLIP, &value); 4695a112b11Smrg if (ret == 0 && value == 1) { 47035c4bbdfSmrg ms_present_screen_info.capabilities |= PresentCapabilityAsync; 4715a112b11Smrg ms->drmmode.can_async_flip = TRUE; 4725a112b11Smrg } 47335c4bbdfSmrg 47435c4bbdfSmrg return present_screen_init(screen, &ms_present_screen_info); 47535c4bbdfSmrg} 476