present_screen.c revision ed6184df
1/* 2 * Copyright © 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#include "present_priv.h" 24 25int present_request; 26DevPrivateKeyRec present_screen_private_key; 27DevPrivateKeyRec present_window_private_key; 28 29/* 30 * Get a pointer to a present window private, creating if necessary 31 */ 32present_window_priv_ptr 33present_get_window_priv(WindowPtr window, Bool create) 34{ 35 present_window_priv_ptr window_priv = present_window_priv(window); 36 37 if (!create || window_priv != NULL) 38 return window_priv; 39 window_priv = calloc (1, sizeof (present_window_priv_rec)); 40 if (!window_priv) 41 return NULL; 42 xorg_list_init(&window_priv->vblank); 43 xorg_list_init(&window_priv->notifies); 44 45 window_priv->window = window; 46 window_priv->crtc = PresentCrtcNeverSet; 47 dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); 48 return window_priv; 49} 50 51/* 52 * Hook the close screen function to clean up our screen private 53 */ 54static Bool 55present_close_screen(ScreenPtr screen) 56{ 57 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 58 59 if (screen_priv->flip_destroy) 60 screen_priv->flip_destroy(screen); 61 62 unwrap(screen_priv, screen, CloseScreen); 63 (*screen->CloseScreen) (screen); 64 free(screen_priv); 65 return TRUE; 66} 67 68/* 69 * Free any queued presentations for this window 70 */ 71static void 72present_free_window_vblank(WindowPtr window) 73{ 74 ScreenPtr screen = window->drawable.pScreen; 75 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 76 present_window_priv_ptr window_priv = present_window_priv(window); 77 present_vblank_ptr vblank, tmp; 78 79 xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { 80 screen_priv->abort_vblank(window->drawable.pScreen, window, vblank->crtc, vblank->event_id, vblank->target_msc); 81 present_vblank_destroy(vblank); 82 } 83} 84 85/* 86 * Hook the close window function to clean up our window private 87 */ 88static Bool 89present_destroy_window(WindowPtr window) 90{ 91 Bool ret; 92 ScreenPtr screen = window->drawable.pScreen; 93 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 94 present_window_priv_ptr window_priv = present_window_priv(window); 95 96 if (window_priv) { 97 present_clear_window_notifies(window); 98 present_free_events(window); 99 present_free_window_vblank(window); 100 101 screen_priv->clear_window_flip(window); 102 103 free(window_priv); 104 } 105 unwrap(screen_priv, screen, DestroyWindow); 106 if (screen->DestroyWindow) 107 ret = screen->DestroyWindow (window); 108 else 109 ret = TRUE; 110 wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 111 return ret; 112} 113 114/* 115 * Hook the config notify screen function to deliver present config notify events 116 */ 117static int 118present_config_notify(WindowPtr window, 119 int x, int y, int w, int h, int bw, 120 WindowPtr sibling) 121{ 122 int ret; 123 ScreenPtr screen = window->drawable.pScreen; 124 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 125 126 present_send_config_notify(window, x, y, w, h, bw, sibling); 127 128 unwrap(screen_priv, screen, ConfigNotify); 129 if (screen->ConfigNotify) 130 ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); 131 else 132 ret = 0; 133 wrap(screen_priv, screen, ConfigNotify, present_config_notify); 134 return ret; 135} 136 137/* 138 * Hook the clip notify screen function to un-flip as necessary 139 */ 140 141static void 142present_clip_notify(WindowPtr window, int dx, int dy) 143{ 144 ScreenPtr screen = window->drawable.pScreen; 145 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 146 147 screen_priv->check_flip_window(window); 148 unwrap(screen_priv, screen, ClipNotify) 149 if (screen->ClipNotify) 150 screen->ClipNotify (window, dx, dy); 151 wrap(screen_priv, screen, ClipNotify, present_clip_notify); 152} 153 154Bool 155present_screen_register_priv_keys(void) 156{ 157 if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) 158 return FALSE; 159 160 if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) 161 return FALSE; 162 163 return TRUE; 164} 165 166present_screen_priv_ptr 167present_screen_priv_init(ScreenPtr screen) 168{ 169 present_screen_priv_ptr screen_priv; 170 171 screen_priv = calloc(1, sizeof (present_screen_priv_rec)); 172 if (!screen_priv) 173 return NULL; 174 175 wrap(screen_priv, screen, CloseScreen, present_close_screen); 176 wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 177 wrap(screen_priv, screen, ConfigNotify, present_config_notify); 178 wrap(screen_priv, screen, ClipNotify, present_clip_notify); 179 180 dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); 181 182 return screen_priv; 183} 184 185/* 186 * Initialize a screen for use with present in default screen flip mode (scmd) 187 */ 188int 189present_screen_init(ScreenPtr screen, present_screen_info_ptr info) 190{ 191 if (!present_screen_register_priv_keys()) 192 return FALSE; 193 194 if (!present_screen_priv(screen)) { 195 present_screen_priv_ptr screen_priv = present_screen_priv_init(screen); 196 if (!screen_priv) 197 return FALSE; 198 199 screen_priv->info = info; 200 present_scmd_init_mode_hooks(screen_priv); 201 202 present_fake_screen_init(screen); 203 } 204 205 return TRUE; 206} 207 208/* 209 * Initialize the present extension 210 */ 211void 212present_extension_init(void) 213{ 214 ExtensionEntry *extension; 215 int i; 216 217#ifdef PANORAMIX 218 if (!noPanoramiXExtension) 219 return; 220#endif 221 222 extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, 223 proc_present_dispatch, sproc_present_dispatch, 224 NULL, StandardMinorOpcode); 225 if (!extension) 226 goto bail; 227 228 present_request = extension->base; 229 230 if (!present_init()) 231 goto bail; 232 233 if (!present_event_init()) 234 goto bail; 235 236 for (i = 0; i < screenInfo.numScreens; i++) { 237 if (!present_screen_init(screenInfo.screens[i], NULL)) 238 goto bail; 239 } 240 return; 241 242bail: 243 FatalError("Cannot initialize Present extension"); 244} 245