present_screen.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #ifdef HAVE_XORG_CONFIG_H
  23. #include <xorg-config.h>
  24. #endif
  25. #include "present_priv.h"
  26. int present_request;
  27. DevPrivateKeyRec present_screen_private_key;
  28. DevPrivateKeyRec present_window_private_key;
  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. if (!create || window_priv != NULL)
  37. return window_priv;
  38. window_priv = calloc (1, sizeof (present_window_priv_rec));
  39. if (!window_priv)
  40. return NULL;
  41. xorg_list_init(&window_priv->vblank);
  42. xorg_list_init(&window_priv->notifies);
  43. dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
  44. return window_priv;
  45. }
  46. /*
  47. * Hook the close screen function to clean up our screen private
  48. */
  49. static Bool
  50. present_close_screen(ScreenPtr screen)
  51. {
  52. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  53. present_flip_destroy(screen);
  54. unwrap(screen_priv, screen, CloseScreen);
  55. (*screen->CloseScreen) (screen);
  56. free(screen_priv);
  57. return TRUE;
  58. }
  59. /*
  60. * Free any queued presentations for this window
  61. */
  62. static void
  63. present_free_window_vblank(WindowPtr window)
  64. {
  65. present_window_priv_ptr window_priv = present_window_priv(window);
  66. present_vblank_ptr vblank, tmp;
  67. xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
  68. present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc);
  69. present_vblank_destroy(vblank);
  70. }
  71. }
  72. /*
  73. * Clean up any pending or current flips for this window
  74. */
  75. static void
  76. present_clear_window_flip(WindowPtr window)
  77. {
  78. ScreenPtr screen = window->drawable.pScreen;
  79. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  80. present_vblank_ptr flip_pending = screen_priv->flip_pending;
  81. if (flip_pending && flip_pending->window == window) {
  82. assert (flip_pending->abort_flip);
  83. flip_pending->window = NULL;
  84. }
  85. if (screen_priv->flip_window == window)
  86. screen_priv->flip_window = NULL;
  87. }
  88. /*
  89. * Hook the close window function to clean up our window private
  90. */
  91. static Bool
  92. present_destroy_window(WindowPtr window)
  93. {
  94. Bool ret;
  95. ScreenPtr screen = window->drawable.pScreen;
  96. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  97. present_window_priv_ptr window_priv = present_window_priv(window);
  98. if (window_priv) {
  99. present_clear_window_notifies(window);
  100. present_free_events(window);
  101. present_free_window_vblank(window);
  102. present_clear_window_flip(window);
  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. * Hook the config notify screen function to deliver present config notify events
  115. */
  116. static int
  117. present_config_notify(WindowPtr window,
  118. int x, int y, int w, int h, int bw,
  119. WindowPtr sibling)
  120. {
  121. int ret;
  122. ScreenPtr screen = window->drawable.pScreen;
  123. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  124. present_send_config_notify(window, x, y, w, h, bw, sibling);
  125. unwrap(screen_priv, screen, ConfigNotify);
  126. if (screen->ConfigNotify)
  127. ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
  128. else
  129. ret = 0;
  130. wrap(screen_priv, screen, ConfigNotify, present_config_notify);
  131. return ret;
  132. }
  133. /*
  134. * Hook the clip notify screen function to un-flip as necessary
  135. */
  136. static void
  137. present_clip_notify(WindowPtr window, int dx, int dy)
  138. {
  139. ScreenPtr screen = window->drawable.pScreen;
  140. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  141. present_check_flip_window(window);
  142. unwrap(screen_priv, screen, ClipNotify)
  143. if (screen->ClipNotify)
  144. screen->ClipNotify (window, dx, dy);
  145. wrap(screen_priv, screen, ClipNotify, present_clip_notify);
  146. }
  147. /*
  148. * Initialize a screen for use with present
  149. */
  150. int
  151. present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
  152. {
  153. if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
  154. return FALSE;
  155. if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
  156. return FALSE;
  157. if (!present_screen_priv(screen)) {
  158. present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec));
  159. if (!screen_priv)
  160. return FALSE;
  161. wrap(screen_priv, screen, CloseScreen, present_close_screen);
  162. wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
  163. wrap(screen_priv, screen, ConfigNotify, present_config_notify);
  164. wrap(screen_priv, screen, ClipNotify, present_clip_notify);
  165. screen_priv->info = info;
  166. dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
  167. present_fake_screen_init(screen);
  168. }
  169. return TRUE;
  170. }
  171. /*
  172. * Initialize the present extension
  173. */
  174. void
  175. present_extension_init(void)
  176. {
  177. ExtensionEntry *extension;
  178. int i;
  179. #ifdef PANORAMIX
  180. if (!noPanoramiXExtension)
  181. return;
  182. #endif
  183. extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
  184. proc_present_dispatch, sproc_present_dispatch,
  185. NULL, StandardMinorOpcode);
  186. if (!extension)
  187. goto bail;
  188. present_request = extension->base;
  189. if (!present_init())
  190. goto bail;
  191. if (!present_event_init())
  192. goto bail;
  193. for (i = 0; i < screenInfo.numScreens; i++) {
  194. if (!present_screen_init(screenInfo.screens[i], NULL))
  195. goto bail;
  196. }
  197. return;
  198. bail:
  199. FatalError("Cannot initialize Present extension");
  200. }