present_screen.c (7271B)
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 25 int present_request; 26 DevPrivateKeyRec present_screen_private_key; 27 DevPrivateKeyRec present_window_private_key; 28 29 /* 30 * Get a pointer to a present window private, creating if necessary 31 */ 32 present_window_priv_ptr 33 present_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 */ 54 static Bool 55 present_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 */ 71 static void 72 present_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 */ 88 static Bool 89 present_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 */ 117 static int 118 present_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 141 static void 142 present_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 154 Bool 155 present_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 166 present_screen_priv_ptr 167 present_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 */ 188 int 189 present_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 */ 211 void 212 present_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 242 bail: 243 FatalError("Cannot initialize Present extension"); 244 }