present_screen.c revision 1b5d61b8
135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2013 Keith Packard 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_XORG_CONFIG_H 2435c4bbdfSmrg#include <xorg-config.h> 2535c4bbdfSmrg#endif 2635c4bbdfSmrg 2735c4bbdfSmrg#include "present_priv.h" 2835c4bbdfSmrg 2935c4bbdfSmrgint present_request; 3035c4bbdfSmrgDevPrivateKeyRec present_screen_private_key; 3135c4bbdfSmrgDevPrivateKeyRec present_window_private_key; 3235c4bbdfSmrg 3335c4bbdfSmrg/* 3435c4bbdfSmrg * Get a pointer to a present window private, creating if necessary 3535c4bbdfSmrg */ 3635c4bbdfSmrgpresent_window_priv_ptr 3735c4bbdfSmrgpresent_get_window_priv(WindowPtr window, Bool create) 3835c4bbdfSmrg{ 3935c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 4035c4bbdfSmrg 4135c4bbdfSmrg if (!create || window_priv != NULL) 4235c4bbdfSmrg return window_priv; 4335c4bbdfSmrg window_priv = calloc (1, sizeof (present_window_priv_rec)); 4435c4bbdfSmrg if (!window_priv) 4535c4bbdfSmrg return NULL; 4635c4bbdfSmrg xorg_list_init(&window_priv->vblank); 4735c4bbdfSmrg xorg_list_init(&window_priv->notifies); 481b5d61b8Smrg 491b5d61b8Smrg xorg_list_init(&window_priv->exec_queue); 501b5d61b8Smrg xorg_list_init(&window_priv->flip_queue); 511b5d61b8Smrg xorg_list_init(&window_priv->idle_queue); 521b5d61b8Smrg 531b5d61b8Smrg window_priv->window = window; 5435c4bbdfSmrg window_priv->crtc = PresentCrtcNeverSet; 5535c4bbdfSmrg dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); 5635c4bbdfSmrg return window_priv; 5735c4bbdfSmrg} 5835c4bbdfSmrg 5935c4bbdfSmrg/* 6035c4bbdfSmrg * Hook the close screen function to clean up our screen private 6135c4bbdfSmrg */ 6235c4bbdfSmrgstatic Bool 6335c4bbdfSmrgpresent_close_screen(ScreenPtr screen) 6435c4bbdfSmrg{ 6535c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 6635c4bbdfSmrg 671b5d61b8Smrg screen_priv->flip_destroy(screen); 6835c4bbdfSmrg 6935c4bbdfSmrg unwrap(screen_priv, screen, CloseScreen); 7035c4bbdfSmrg (*screen->CloseScreen) (screen); 7135c4bbdfSmrg free(screen_priv); 7235c4bbdfSmrg return TRUE; 7335c4bbdfSmrg} 7435c4bbdfSmrg 7535c4bbdfSmrg/* 7635c4bbdfSmrg * Free any queued presentations for this window 7735c4bbdfSmrg */ 7835c4bbdfSmrgstatic void 7935c4bbdfSmrgpresent_free_window_vblank(WindowPtr window) 8035c4bbdfSmrg{ 811b5d61b8Smrg ScreenPtr screen = window->drawable.pScreen; 821b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 8335c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 8435c4bbdfSmrg present_vblank_ptr vblank, tmp; 8535c4bbdfSmrg 8635c4bbdfSmrg xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { 871b5d61b8Smrg screen_priv->abort_vblank(window->drawable.pScreen, window, vblank->crtc, vblank->event_id, vblank->target_msc); 8835c4bbdfSmrg present_vblank_destroy(vblank); 8935c4bbdfSmrg } 9035c4bbdfSmrg} 9135c4bbdfSmrg 9235c4bbdfSmrg/* 9335c4bbdfSmrg * Clean up any pending or current flips for this window 9435c4bbdfSmrg */ 9535c4bbdfSmrgstatic void 9635c4bbdfSmrgpresent_clear_window_flip(WindowPtr window) 9735c4bbdfSmrg{ 9835c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 9935c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 10035c4bbdfSmrg present_vblank_ptr flip_pending = screen_priv->flip_pending; 10135c4bbdfSmrg 10235c4bbdfSmrg if (flip_pending && flip_pending->window == window) { 1031b5d61b8Smrg present_set_abort_flip(screen); 10435c4bbdfSmrg flip_pending->window = NULL; 10535c4bbdfSmrg } 1061b5d61b8Smrg if (screen_priv->flip_window == window) { 1071b5d61b8Smrg present_restore_screen_pixmap(screen); 10835c4bbdfSmrg screen_priv->flip_window = NULL; 1091b5d61b8Smrg } 1101b5d61b8Smrg} 1111b5d61b8Smrg 1121b5d61b8Smrgstatic void 1131b5d61b8Smrgpresent_wnmd_clear_window_flip(WindowPtr window) 1141b5d61b8Smrg{ 1151b5d61b8Smrg present_window_priv_ptr window_priv = present_window_priv(window); 1161b5d61b8Smrg present_vblank_ptr vblank, tmp; 1171b5d61b8Smrg 1181b5d61b8Smrg if (window_priv->flip_pending) { 1191b5d61b8Smrg present_wnmd_set_abort_flip(window); 1201b5d61b8Smrg window_priv->flip_pending->window = NULL; 1211b5d61b8Smrg } 1221b5d61b8Smrg 1231b5d61b8Smrg xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->idle_queue, event_queue) { 1241b5d61b8Smrg present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 1251b5d61b8Smrg /* The pixmap will be destroyed by freeing the window resources. */ 1261b5d61b8Smrg vblank->pixmap = NULL; 1271b5d61b8Smrg present_vblank_destroy(vblank); 1281b5d61b8Smrg } 1291b5d61b8Smrg 1301b5d61b8Smrg vblank = window_priv->flip_active; 1311b5d61b8Smrg if (vblank) { 1321b5d61b8Smrg present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); 1331b5d61b8Smrg present_vblank_destroy(vblank); 1341b5d61b8Smrg } 1351b5d61b8Smrg window_priv->flip_active = NULL; 13635c4bbdfSmrg} 13735c4bbdfSmrg 13835c4bbdfSmrg/* 13935c4bbdfSmrg * Hook the close window function to clean up our window private 14035c4bbdfSmrg */ 14135c4bbdfSmrgstatic Bool 14235c4bbdfSmrgpresent_destroy_window(WindowPtr window) 14335c4bbdfSmrg{ 14435c4bbdfSmrg Bool ret; 14535c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 14635c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 14735c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 14835c4bbdfSmrg 14935c4bbdfSmrg if (window_priv) { 15035c4bbdfSmrg present_clear_window_notifies(window); 15135c4bbdfSmrg present_free_events(window); 15235c4bbdfSmrg present_free_window_vblank(window); 1531b5d61b8Smrg 1541b5d61b8Smrg if (screen_priv->wnmd_info) 1551b5d61b8Smrg present_wnmd_clear_window_flip(window); 1561b5d61b8Smrg else 1571b5d61b8Smrg present_clear_window_flip(window); 1581b5d61b8Smrg 15935c4bbdfSmrg free(window_priv); 16035c4bbdfSmrg } 16135c4bbdfSmrg unwrap(screen_priv, screen, DestroyWindow); 16235c4bbdfSmrg if (screen->DestroyWindow) 16335c4bbdfSmrg ret = screen->DestroyWindow (window); 16435c4bbdfSmrg else 16535c4bbdfSmrg ret = TRUE; 16635c4bbdfSmrg wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 16735c4bbdfSmrg return ret; 16835c4bbdfSmrg} 16935c4bbdfSmrg 17035c4bbdfSmrg/* 17135c4bbdfSmrg * Hook the config notify screen function to deliver present config notify events 17235c4bbdfSmrg */ 17335c4bbdfSmrgstatic int 17435c4bbdfSmrgpresent_config_notify(WindowPtr window, 17535c4bbdfSmrg int x, int y, int w, int h, int bw, 17635c4bbdfSmrg WindowPtr sibling) 17735c4bbdfSmrg{ 17835c4bbdfSmrg int ret; 17935c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 18035c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 18135c4bbdfSmrg 18235c4bbdfSmrg present_send_config_notify(window, x, y, w, h, bw, sibling); 18335c4bbdfSmrg 18435c4bbdfSmrg unwrap(screen_priv, screen, ConfigNotify); 18535c4bbdfSmrg if (screen->ConfigNotify) 18635c4bbdfSmrg ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); 18735c4bbdfSmrg else 18835c4bbdfSmrg ret = 0; 18935c4bbdfSmrg wrap(screen_priv, screen, ConfigNotify, present_config_notify); 19035c4bbdfSmrg return ret; 19135c4bbdfSmrg} 19235c4bbdfSmrg 19335c4bbdfSmrg/* 19435c4bbdfSmrg * Hook the clip notify screen function to un-flip as necessary 19535c4bbdfSmrg */ 19635c4bbdfSmrg 19735c4bbdfSmrgstatic void 19835c4bbdfSmrgpresent_clip_notify(WindowPtr window, int dx, int dy) 19935c4bbdfSmrg{ 20035c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 20135c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 20235c4bbdfSmrg 2031b5d61b8Smrg screen_priv->check_flip_window(window); 20435c4bbdfSmrg unwrap(screen_priv, screen, ClipNotify) 20535c4bbdfSmrg if (screen->ClipNotify) 20635c4bbdfSmrg screen->ClipNotify (window, dx, dy); 20735c4bbdfSmrg wrap(screen_priv, screen, ClipNotify, present_clip_notify); 20835c4bbdfSmrg} 20935c4bbdfSmrg 2101b5d61b8Smrgstatic Bool 2111b5d61b8Smrgpresent_screen_register_priv_keys(void) 21235c4bbdfSmrg{ 21335c4bbdfSmrg if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) 21435c4bbdfSmrg return FALSE; 21535c4bbdfSmrg 21635c4bbdfSmrg if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) 21735c4bbdfSmrg return FALSE; 21835c4bbdfSmrg 2191b5d61b8Smrg return TRUE; 2201b5d61b8Smrg} 2211b5d61b8Smrg 2221b5d61b8Smrgstatic present_screen_priv_ptr 2231b5d61b8Smrgpresent_screen_priv_init(ScreenPtr screen) 2241b5d61b8Smrg{ 2251b5d61b8Smrg present_screen_priv_ptr screen_priv; 2261b5d61b8Smrg 2271b5d61b8Smrg screen_priv = calloc(1, sizeof (present_screen_priv_rec)); 2281b5d61b8Smrg if (!screen_priv) 2291b5d61b8Smrg return NULL; 2301b5d61b8Smrg 2311b5d61b8Smrg wrap(screen_priv, screen, CloseScreen, present_close_screen); 2321b5d61b8Smrg wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 2331b5d61b8Smrg wrap(screen_priv, screen, ConfigNotify, present_config_notify); 2341b5d61b8Smrg wrap(screen_priv, screen, ClipNotify, present_clip_notify); 2351b5d61b8Smrg 2361b5d61b8Smrg dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); 2371b5d61b8Smrg 2381b5d61b8Smrg return screen_priv; 2391b5d61b8Smrg} 2401b5d61b8Smrg 2411b5d61b8Smrg/* 2421b5d61b8Smrg * Initialize a screen for use with present in window flip mode (wnmd) 2431b5d61b8Smrg */ 2441b5d61b8Smrgint 2451b5d61b8Smrgpresent_wnmd_screen_init(ScreenPtr screen, present_wnmd_info_ptr info) 2461b5d61b8Smrg{ 2471b5d61b8Smrg if (!present_screen_register_priv_keys()) 2481b5d61b8Smrg return FALSE; 2491b5d61b8Smrg 25035c4bbdfSmrg if (!present_screen_priv(screen)) { 2511b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv_init(screen); 25235c4bbdfSmrg if (!screen_priv) 25335c4bbdfSmrg return FALSE; 25435c4bbdfSmrg 2551b5d61b8Smrg screen_priv->wnmd_info = info; 2561b5d61b8Smrg present_wnmd_init_mode_hooks(screen_priv); 2571b5d61b8Smrg } 25835c4bbdfSmrg 2591b5d61b8Smrg return TRUE; 2601b5d61b8Smrg} 26135c4bbdfSmrg 2621b5d61b8Smrg/* 2631b5d61b8Smrg * Initialize a screen for use with present in default screen flip mode (scmd) 2641b5d61b8Smrg */ 2651b5d61b8Smrgint 2661b5d61b8Smrgpresent_screen_init(ScreenPtr screen, present_screen_info_ptr info) 2671b5d61b8Smrg{ 2681b5d61b8Smrg if (!present_screen_register_priv_keys()) 2691b5d61b8Smrg return FALSE; 2701b5d61b8Smrg 2711b5d61b8Smrg if (!present_screen_priv(screen)) { 2721b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv_init(screen); 2731b5d61b8Smrg if (!screen_priv) 2741b5d61b8Smrg return FALSE; 2751b5d61b8Smrg 2761b5d61b8Smrg screen_priv->info = info; 2771b5d61b8Smrg present_scmd_init_mode_hooks(screen_priv); 27835c4bbdfSmrg 27935c4bbdfSmrg present_fake_screen_init(screen); 28035c4bbdfSmrg } 28135c4bbdfSmrg 28235c4bbdfSmrg return TRUE; 28335c4bbdfSmrg} 28435c4bbdfSmrg 28535c4bbdfSmrg/* 28635c4bbdfSmrg * Initialize the present extension 28735c4bbdfSmrg */ 28835c4bbdfSmrgvoid 28935c4bbdfSmrgpresent_extension_init(void) 29035c4bbdfSmrg{ 29135c4bbdfSmrg ExtensionEntry *extension; 29235c4bbdfSmrg int i; 29335c4bbdfSmrg 29435c4bbdfSmrg#ifdef PANORAMIX 29535c4bbdfSmrg if (!noPanoramiXExtension) 29635c4bbdfSmrg return; 29735c4bbdfSmrg#endif 29835c4bbdfSmrg 29935c4bbdfSmrg extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, 30035c4bbdfSmrg proc_present_dispatch, sproc_present_dispatch, 30135c4bbdfSmrg NULL, StandardMinorOpcode); 30235c4bbdfSmrg if (!extension) 30335c4bbdfSmrg goto bail; 30435c4bbdfSmrg 30535c4bbdfSmrg present_request = extension->base; 30635c4bbdfSmrg 30735c4bbdfSmrg if (!present_init()) 30835c4bbdfSmrg goto bail; 30935c4bbdfSmrg 31035c4bbdfSmrg if (!present_event_init()) 31135c4bbdfSmrg goto bail; 31235c4bbdfSmrg 31335c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 31435c4bbdfSmrg if (!present_screen_init(screenInfo.screens[i], NULL)) 31535c4bbdfSmrg goto bail; 31635c4bbdfSmrg } 31735c4bbdfSmrg return; 31835c4bbdfSmrg 31935c4bbdfSmrgbail: 32035c4bbdfSmrg FatalError("Cannot initialize Present extension"); 32135c4bbdfSmrg} 322