Imported Upstream version 1.15.1
[deb_xorg-server.git] / present / present_screen.c
CommitLineData
a09e091a
JB
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#ifdef HAVE_XORG_CONFIG_H
24#include <xorg-config.h>
25#endif
26
27#include "present_priv.h"
28
29int present_request;
30DevPrivateKeyRec present_screen_private_key;
31DevPrivateKeyRec present_window_private_key;
32
33/*
34 * Get a pointer to a present window private, creating if necessary
35 */
36present_window_priv_ptr
37present_get_window_priv(WindowPtr window, Bool create)
38{
39 present_window_priv_ptr window_priv = present_window_priv(window);
40
41 if (!create || window_priv != NULL)
42 return window_priv;
43 window_priv = calloc (1, sizeof (present_window_priv_rec));
44 if (!window_priv)
45 return NULL;
46 xorg_list_init(&window_priv->vblank);
47 xorg_list_init(&window_priv->notifies);
48 dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
49 return window_priv;
50}
51
52/*
53 * Hook the close screen function to clean up our screen private
54 */
55static Bool
56present_close_screen(ScreenPtr screen)
57{
58 present_screen_priv_ptr screen_priv = present_screen_priv(screen);
59
60 present_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 present_window_priv_ptr window_priv = present_window_priv(window);
75 present_vblank_ptr vblank, tmp;
76
77 xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
78 present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc);
79 present_vblank_destroy(vblank);
80 }
81}
82
83/*
84 * Clean up any pending or current flips for this window
85 */
86static void
87present_clear_window_flip(WindowPtr window)
88{
89 ScreenPtr screen = window->drawable.pScreen;
90 present_screen_priv_ptr screen_priv = present_screen_priv(screen);
91 present_vblank_ptr flip_pending = screen_priv->flip_pending;
92
93 if (flip_pending && flip_pending->window == window) {
94 assert (flip_pending->abort_flip);
95 flip_pending->window = NULL;
96 }
97 if (screen_priv->flip_window == window)
98 screen_priv->flip_window = NULL;
99}
100
101/*
102 * Hook the close window function to clean up our window private
103 */
104static Bool
105present_destroy_window(WindowPtr window)
106{
107 Bool ret;
108 ScreenPtr screen = window->drawable.pScreen;
109 present_screen_priv_ptr screen_priv = present_screen_priv(screen);
110 present_window_priv_ptr window_priv = present_window_priv(window);
111
112 if (window_priv) {
113 present_clear_window_notifies(window);
114 present_free_events(window);
115 present_free_window_vblank(window);
116 present_clear_window_flip(window);
117 free(window_priv);
118 }
119 unwrap(screen_priv, screen, DestroyWindow);
120 if (screen->DestroyWindow)
121 ret = screen->DestroyWindow (window);
122 else
123 ret = TRUE;
124 wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
125 return ret;
126}
127
128/*
129 * Hook the config notify screen function to deliver present config notify events
130 */
131static int
132present_config_notify(WindowPtr window,
133 int x, int y, int w, int h, int bw,
134 WindowPtr sibling)
135{
136 int ret;
137 ScreenPtr screen = window->drawable.pScreen;
138 present_screen_priv_ptr screen_priv = present_screen_priv(screen);
139
140 present_send_config_notify(window, x, y, w, h, bw, sibling);
141
142 unwrap(screen_priv, screen, ConfigNotify);
143 if (screen->ConfigNotify)
144 ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
145 else
146 ret = 0;
147 wrap(screen_priv, screen, ConfigNotify, present_config_notify);
148 return ret;
149}
150
151/*
152 * Hook the clip notify screen function to un-flip as necessary
153 */
154
155static void
156present_clip_notify(WindowPtr window, int dx, int dy)
157{
158 ScreenPtr screen = window->drawable.pScreen;
159 present_screen_priv_ptr screen_priv = present_screen_priv(screen);
160
161 present_check_flip_window(window);
162 unwrap(screen_priv, screen, ClipNotify)
163 if (screen->ClipNotify)
164 screen->ClipNotify (window, dx, dy);
165 wrap(screen_priv, screen, ClipNotify, present_clip_notify);
166}
167
168/*
169 * Initialize a screen for use with present
170 */
171int
172present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
173{
174 if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
175 return FALSE;
176
177 if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
178 return FALSE;
179
180 if (!present_screen_priv(screen)) {
181 present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec));
182 if (!screen_priv)
183 return FALSE;
184
185 wrap(screen_priv, screen, CloseScreen, present_close_screen);
186 wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
187 wrap(screen_priv, screen, ConfigNotify, present_config_notify);
188 wrap(screen_priv, screen, ClipNotify, present_clip_notify);
189
190 screen_priv->info = info;
191
192 dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
193
194 present_fake_screen_init(screen);
195 }
196
197 return TRUE;
198}
199
200/*
201 * Initialize the present extension
202 */
203void
204present_extension_init(void)
205{
206 ExtensionEntry *extension;
207 int i;
208
209#ifdef PANORAMIX
210 if (!noPanoramiXExtension)
211 return;
212#endif
213
214 extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
215 proc_present_dispatch, sproc_present_dispatch,
216 NULL, StandardMinorOpcode);
217 if (!extension)
218 goto bail;
219
220 present_request = extension->base;
221
222 if (!present_init())
223 goto bail;
224
225 if (!present_event_init())
226 goto bail;
227
228 for (i = 0; i < screenInfo.numScreens; i++) {
229 if (!present_screen_init(screenInfo.screens[i], NULL))
230 goto bail;
231 }
232 return;
233
234bail:
235 FatalError("Cannot initialize Present extension");
236}