present_screen.c revision eee80088
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#include "present_priv.h" 2435c4bbdfSmrg 2535c4bbdfSmrgint present_request; 2635c4bbdfSmrgDevPrivateKeyRec present_screen_private_key; 2735c4bbdfSmrgDevPrivateKeyRec present_window_private_key; 2835c4bbdfSmrg 2935c4bbdfSmrg/* 3035c4bbdfSmrg * Get a pointer to a present window private, creating if necessary 3135c4bbdfSmrg */ 3235c4bbdfSmrgpresent_window_priv_ptr 3335c4bbdfSmrgpresent_get_window_priv(WindowPtr window, Bool create) 3435c4bbdfSmrg{ 3535c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 3635c4bbdfSmrg 3735c4bbdfSmrg if (!create || window_priv != NULL) 3835c4bbdfSmrg return window_priv; 3935c4bbdfSmrg window_priv = calloc (1, sizeof (present_window_priv_rec)); 4035c4bbdfSmrg if (!window_priv) 4135c4bbdfSmrg return NULL; 4235c4bbdfSmrg xorg_list_init(&window_priv->vblank); 4335c4bbdfSmrg xorg_list_init(&window_priv->notifies); 441b5d61b8Smrg 451b5d61b8Smrg window_priv->window = window; 4635c4bbdfSmrg window_priv->crtc = PresentCrtcNeverSet; 4735c4bbdfSmrg dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); 4835c4bbdfSmrg return window_priv; 4935c4bbdfSmrg} 5035c4bbdfSmrg 5135c4bbdfSmrg/* 5235c4bbdfSmrg * Hook the close screen function to clean up our screen private 5335c4bbdfSmrg */ 5435c4bbdfSmrgstatic Bool 5535c4bbdfSmrgpresent_close_screen(ScreenPtr screen) 5635c4bbdfSmrg{ 5735c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 5835c4bbdfSmrg 59ed6184dfSmrg if (screen_priv->flip_destroy) 60ed6184dfSmrg screen_priv->flip_destroy(screen); 6135c4bbdfSmrg 6235c4bbdfSmrg unwrap(screen_priv, screen, CloseScreen); 6335c4bbdfSmrg (*screen->CloseScreen) (screen); 6435c4bbdfSmrg free(screen_priv); 6535c4bbdfSmrg return TRUE; 6635c4bbdfSmrg} 6735c4bbdfSmrg 6835c4bbdfSmrg/* 6935c4bbdfSmrg * Free any queued presentations for this window 7035c4bbdfSmrg */ 7135c4bbdfSmrgstatic void 7235c4bbdfSmrgpresent_free_window_vblank(WindowPtr window) 7335c4bbdfSmrg{ 741b5d61b8Smrg ScreenPtr screen = window->drawable.pScreen; 751b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 7635c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 7735c4bbdfSmrg present_vblank_ptr vblank, tmp; 7835c4bbdfSmrg 7935c4bbdfSmrg xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { 801b5d61b8Smrg screen_priv->abort_vblank(window->drawable.pScreen, window, vblank->crtc, vblank->event_id, vblank->target_msc); 8135c4bbdfSmrg present_vblank_destroy(vblank); 8235c4bbdfSmrg } 8335c4bbdfSmrg} 8435c4bbdfSmrg 8535c4bbdfSmrg/* 8635c4bbdfSmrg * Hook the close window function to clean up our window private 8735c4bbdfSmrg */ 8835c4bbdfSmrgstatic Bool 8935c4bbdfSmrgpresent_destroy_window(WindowPtr window) 9035c4bbdfSmrg{ 9135c4bbdfSmrg Bool ret; 9235c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 9335c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 9435c4bbdfSmrg present_window_priv_ptr window_priv = present_window_priv(window); 9535c4bbdfSmrg 96eee80088Smrg present_send_config_notify(window, 97eee80088Smrg window->drawable.x, 98eee80088Smrg window->drawable.y, 99eee80088Smrg window->drawable.width, 100eee80088Smrg window->drawable.height, 101eee80088Smrg window->borderWidth, 102eee80088Smrg window->nextSib, 103eee80088Smrg PresentWindowDestroyed); 104eee80088Smrg 10535c4bbdfSmrg if (window_priv) { 10635c4bbdfSmrg present_clear_window_notifies(window); 10735c4bbdfSmrg present_free_events(window); 10835c4bbdfSmrg present_free_window_vblank(window); 1091b5d61b8Smrg 110ed6184dfSmrg screen_priv->clear_window_flip(window); 1111b5d61b8Smrg 11235c4bbdfSmrg free(window_priv); 11335c4bbdfSmrg } 11435c4bbdfSmrg unwrap(screen_priv, screen, DestroyWindow); 11535c4bbdfSmrg if (screen->DestroyWindow) 11635c4bbdfSmrg ret = screen->DestroyWindow (window); 11735c4bbdfSmrg else 11835c4bbdfSmrg ret = TRUE; 11935c4bbdfSmrg wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 12035c4bbdfSmrg return ret; 12135c4bbdfSmrg} 12235c4bbdfSmrg 12335c4bbdfSmrg/* 12435c4bbdfSmrg * Hook the config notify screen function to deliver present config notify events 12535c4bbdfSmrg */ 12635c4bbdfSmrgstatic int 12735c4bbdfSmrgpresent_config_notify(WindowPtr window, 12835c4bbdfSmrg int x, int y, int w, int h, int bw, 12935c4bbdfSmrg WindowPtr sibling) 13035c4bbdfSmrg{ 13135c4bbdfSmrg int ret; 13235c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 13335c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 13435c4bbdfSmrg 135eee80088Smrg present_send_config_notify(window, x, y, w, h, bw, sibling, 0); 13635c4bbdfSmrg 13735c4bbdfSmrg unwrap(screen_priv, screen, ConfigNotify); 13835c4bbdfSmrg if (screen->ConfigNotify) 13935c4bbdfSmrg ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); 14035c4bbdfSmrg else 14135c4bbdfSmrg ret = 0; 14235c4bbdfSmrg wrap(screen_priv, screen, ConfigNotify, present_config_notify); 14335c4bbdfSmrg return ret; 14435c4bbdfSmrg} 14535c4bbdfSmrg 14635c4bbdfSmrg/* 14735c4bbdfSmrg * Hook the clip notify screen function to un-flip as necessary 14835c4bbdfSmrg */ 14935c4bbdfSmrg 15035c4bbdfSmrgstatic void 15135c4bbdfSmrgpresent_clip_notify(WindowPtr window, int dx, int dy) 15235c4bbdfSmrg{ 15335c4bbdfSmrg ScreenPtr screen = window->drawable.pScreen; 15435c4bbdfSmrg present_screen_priv_ptr screen_priv = present_screen_priv(screen); 15535c4bbdfSmrg 1561b5d61b8Smrg screen_priv->check_flip_window(window); 15735c4bbdfSmrg unwrap(screen_priv, screen, ClipNotify) 15835c4bbdfSmrg if (screen->ClipNotify) 15935c4bbdfSmrg screen->ClipNotify (window, dx, dy); 16035c4bbdfSmrg wrap(screen_priv, screen, ClipNotify, present_clip_notify); 16135c4bbdfSmrg} 16235c4bbdfSmrg 163ed6184dfSmrgBool 1641b5d61b8Smrgpresent_screen_register_priv_keys(void) 16535c4bbdfSmrg{ 16635c4bbdfSmrg if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) 16735c4bbdfSmrg return FALSE; 16835c4bbdfSmrg 16935c4bbdfSmrg if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) 17035c4bbdfSmrg return FALSE; 17135c4bbdfSmrg 1721b5d61b8Smrg return TRUE; 1731b5d61b8Smrg} 1741b5d61b8Smrg 175ed6184dfSmrgpresent_screen_priv_ptr 1761b5d61b8Smrgpresent_screen_priv_init(ScreenPtr screen) 1771b5d61b8Smrg{ 1781b5d61b8Smrg present_screen_priv_ptr screen_priv; 1791b5d61b8Smrg 1801b5d61b8Smrg screen_priv = calloc(1, sizeof (present_screen_priv_rec)); 1811b5d61b8Smrg if (!screen_priv) 1821b5d61b8Smrg return NULL; 1831b5d61b8Smrg 1841b5d61b8Smrg wrap(screen_priv, screen, CloseScreen, present_close_screen); 1851b5d61b8Smrg wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 1861b5d61b8Smrg wrap(screen_priv, screen, ConfigNotify, present_config_notify); 1871b5d61b8Smrg wrap(screen_priv, screen, ClipNotify, present_clip_notify); 1881b5d61b8Smrg 1891b5d61b8Smrg dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); 1901b5d61b8Smrg 1911b5d61b8Smrg return screen_priv; 1921b5d61b8Smrg} 1931b5d61b8Smrg 1941b5d61b8Smrg/* 1951b5d61b8Smrg * Initialize a screen for use with present in default screen flip mode (scmd) 1961b5d61b8Smrg */ 1971b5d61b8Smrgint 1981b5d61b8Smrgpresent_screen_init(ScreenPtr screen, present_screen_info_ptr info) 1991b5d61b8Smrg{ 2001b5d61b8Smrg if (!present_screen_register_priv_keys()) 2011b5d61b8Smrg return FALSE; 2021b5d61b8Smrg 2031b5d61b8Smrg if (!present_screen_priv(screen)) { 2041b5d61b8Smrg present_screen_priv_ptr screen_priv = present_screen_priv_init(screen); 2051b5d61b8Smrg if (!screen_priv) 2061b5d61b8Smrg return FALSE; 2071b5d61b8Smrg 2081b5d61b8Smrg screen_priv->info = info; 2091b5d61b8Smrg present_scmd_init_mode_hooks(screen_priv); 21035c4bbdfSmrg 21135c4bbdfSmrg present_fake_screen_init(screen); 21235c4bbdfSmrg } 21335c4bbdfSmrg 21435c4bbdfSmrg return TRUE; 21535c4bbdfSmrg} 21635c4bbdfSmrg 21735c4bbdfSmrg/* 21835c4bbdfSmrg * Initialize the present extension 21935c4bbdfSmrg */ 22035c4bbdfSmrgvoid 22135c4bbdfSmrgpresent_extension_init(void) 22235c4bbdfSmrg{ 22335c4bbdfSmrg ExtensionEntry *extension; 22435c4bbdfSmrg int i; 22535c4bbdfSmrg 22635c4bbdfSmrg#ifdef PANORAMIX 22735c4bbdfSmrg if (!noPanoramiXExtension) 22835c4bbdfSmrg return; 22935c4bbdfSmrg#endif 23035c4bbdfSmrg 23135c4bbdfSmrg extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, 23235c4bbdfSmrg proc_present_dispatch, sproc_present_dispatch, 23335c4bbdfSmrg NULL, StandardMinorOpcode); 23435c4bbdfSmrg if (!extension) 23535c4bbdfSmrg goto bail; 23635c4bbdfSmrg 23735c4bbdfSmrg present_request = extension->base; 23835c4bbdfSmrg 23935c4bbdfSmrg if (!present_init()) 24035c4bbdfSmrg goto bail; 24135c4bbdfSmrg 24235c4bbdfSmrg if (!present_event_init()) 24335c4bbdfSmrg goto bail; 24435c4bbdfSmrg 24535c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 24635c4bbdfSmrg if (!present_screen_init(screenInfo.screens[i], NULL)) 24735c4bbdfSmrg goto bail; 24835c4bbdfSmrg } 24935c4bbdfSmrg return; 25035c4bbdfSmrg 25135c4bbdfSmrgbail: 25235c4bbdfSmrg FatalError("Cannot initialize Present extension"); 25335c4bbdfSmrg} 254