present_screen.c revision eee80088
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 present_send_config_notify(window, 97 window->drawable.x, 98 window->drawable.y, 99 window->drawable.width, 100 window->drawable.height, 101 window->borderWidth, 102 window->nextSib, 103 PresentWindowDestroyed); 104 105 if (window_priv) { 106 present_clear_window_notifies(window); 107 present_free_events(window); 108 present_free_window_vblank(window); 109 110 screen_priv->clear_window_flip(window); 111 112 free(window_priv); 113 } 114 unwrap(screen_priv, screen, DestroyWindow); 115 if (screen->DestroyWindow) 116 ret = screen->DestroyWindow (window); 117 else 118 ret = TRUE; 119 wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 120 return ret; 121} 122 123/* 124 * Hook the config notify screen function to deliver present config notify events 125 */ 126static int 127present_config_notify(WindowPtr window, 128 int x, int y, int w, int h, int bw, 129 WindowPtr sibling) 130{ 131 int ret; 132 ScreenPtr screen = window->drawable.pScreen; 133 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 134 135 present_send_config_notify(window, x, y, w, h, bw, sibling, 0); 136 137 unwrap(screen_priv, screen, ConfigNotify); 138 if (screen->ConfigNotify) 139 ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); 140 else 141 ret = 0; 142 wrap(screen_priv, screen, ConfigNotify, present_config_notify); 143 return ret; 144} 145 146/* 147 * Hook the clip notify screen function to un-flip as necessary 148 */ 149 150static void 151present_clip_notify(WindowPtr window, int dx, int dy) 152{ 153 ScreenPtr screen = window->drawable.pScreen; 154 present_screen_priv_ptr screen_priv = present_screen_priv(screen); 155 156 screen_priv->check_flip_window(window); 157 unwrap(screen_priv, screen, ClipNotify) 158 if (screen->ClipNotify) 159 screen->ClipNotify (window, dx, dy); 160 wrap(screen_priv, screen, ClipNotify, present_clip_notify); 161} 162 163Bool 164present_screen_register_priv_keys(void) 165{ 166 if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) 167 return FALSE; 168 169 if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) 170 return FALSE; 171 172 return TRUE; 173} 174 175present_screen_priv_ptr 176present_screen_priv_init(ScreenPtr screen) 177{ 178 present_screen_priv_ptr screen_priv; 179 180 screen_priv = calloc(1, sizeof (present_screen_priv_rec)); 181 if (!screen_priv) 182 return NULL; 183 184 wrap(screen_priv, screen, CloseScreen, present_close_screen); 185 wrap(screen_priv, screen, DestroyWindow, present_destroy_window); 186 wrap(screen_priv, screen, ConfigNotify, present_config_notify); 187 wrap(screen_priv, screen, ClipNotify, present_clip_notify); 188 189 dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); 190 191 return screen_priv; 192} 193 194/* 195 * Initialize a screen for use with present in default screen flip mode (scmd) 196 */ 197int 198present_screen_init(ScreenPtr screen, present_screen_info_ptr info) 199{ 200 if (!present_screen_register_priv_keys()) 201 return FALSE; 202 203 if (!present_screen_priv(screen)) { 204 present_screen_priv_ptr screen_priv = present_screen_priv_init(screen); 205 if (!screen_priv) 206 return FALSE; 207 208 screen_priv->info = info; 209 present_scmd_init_mode_hooks(screen_priv); 210 211 present_fake_screen_init(screen); 212 } 213 214 return TRUE; 215} 216 217/* 218 * Initialize the present extension 219 */ 220void 221present_extension_init(void) 222{ 223 ExtensionEntry *extension; 224 int i; 225 226#ifdef PANORAMIX 227 if (!noPanoramiXExtension) 228 return; 229#endif 230 231 extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, 232 proc_present_dispatch, sproc_present_dispatch, 233 NULL, StandardMinorOpcode); 234 if (!extension) 235 goto bail; 236 237 present_request = extension->base; 238 239 if (!present_init()) 240 goto bail; 241 242 if (!present_event_init()) 243 goto bail; 244 245 for (i = 0; i < screenInfo.numScreens; i++) { 246 if (!present_screen_init(screenInfo.screens[i], NULL)) 247 goto bail; 248 } 249 return; 250 251bail: 252 FatalError("Cannot initialize Present extension"); 253} 254