present_screen.c revision ed6184df
135c4bbdfSmrg/*
235c4bbdfSmrg * Copyright © 2013 Keith Packard
335c4bbdfSmrg *
435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its
535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that
635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright
735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and
835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or
935c4bbdfSmrg * publicity pertaining to distribution of the software without specific,
1035c4bbdfSmrg * written prior permission.  The copyright holders make no representations
1135c4bbdfSmrg * about the suitability of this software for any purpose.  It is provided "as
1235c4bbdfSmrg * is" without express or implied warranty.
1335c4bbdfSmrg *
1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2035c4bbdfSmrg * OF THIS SOFTWARE.
2135c4bbdfSmrg */
2235c4bbdfSmrg
2335c4bbdfSmrg#include "present_priv.h"
2435c4bbdfSmrg
2535c4bbdfSmrgint present_request;
2635c4bbdfSmrgDevPrivateKeyRec present_screen_private_key;
2735c4bbdfSmrgDevPrivateKeyRec present_window_private_key;
2835c4bbdfSmrg
2935c4bbdfSmrg/*
3035c4bbdfSmrg * Get a pointer to a present window private, creating if necessary
3135c4bbdfSmrg */
3235c4bbdfSmrgpresent_window_priv_ptr
3335c4bbdfSmrgpresent_get_window_priv(WindowPtr window, Bool create)
3435c4bbdfSmrg{
3535c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
3635c4bbdfSmrg
3735c4bbdfSmrg    if (!create || window_priv != NULL)
3835c4bbdfSmrg        return window_priv;
3935c4bbdfSmrg    window_priv = calloc (1, sizeof (present_window_priv_rec));
4035c4bbdfSmrg    if (!window_priv)
4135c4bbdfSmrg        return NULL;
4235c4bbdfSmrg    xorg_list_init(&window_priv->vblank);
4335c4bbdfSmrg    xorg_list_init(&window_priv->notifies);
441b5d61b8Smrg
451b5d61b8Smrg    window_priv->window = window;
4635c4bbdfSmrg    window_priv->crtc = PresentCrtcNeverSet;
4735c4bbdfSmrg    dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
4835c4bbdfSmrg    return window_priv;
4935c4bbdfSmrg}
5035c4bbdfSmrg
5135c4bbdfSmrg/*
5235c4bbdfSmrg * Hook the close screen function to clean up our screen private
5335c4bbdfSmrg */
5435c4bbdfSmrgstatic Bool
5535c4bbdfSmrgpresent_close_screen(ScreenPtr screen)
5635c4bbdfSmrg{
5735c4bbdfSmrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
5835c4bbdfSmrg
59ed6184dfSmrg    if (screen_priv->flip_destroy)
60ed6184dfSmrg        screen_priv->flip_destroy(screen);
6135c4bbdfSmrg
6235c4bbdfSmrg    unwrap(screen_priv, screen, CloseScreen);
6335c4bbdfSmrg    (*screen->CloseScreen) (screen);
6435c4bbdfSmrg    free(screen_priv);
6535c4bbdfSmrg    return TRUE;
6635c4bbdfSmrg}
6735c4bbdfSmrg
6835c4bbdfSmrg/*
6935c4bbdfSmrg * Free any queued presentations for this window
7035c4bbdfSmrg */
7135c4bbdfSmrgstatic void
7235c4bbdfSmrgpresent_free_window_vblank(WindowPtr window)
7335c4bbdfSmrg{
741b5d61b8Smrg    ScreenPtr                   screen = window->drawable.pScreen;
751b5d61b8Smrg    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
7635c4bbdfSmrg    present_window_priv_ptr     window_priv = present_window_priv(window);
7735c4bbdfSmrg    present_vblank_ptr          vblank, tmp;
7835c4bbdfSmrg
7935c4bbdfSmrg    xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
801b5d61b8Smrg        screen_priv->abort_vblank(window->drawable.pScreen, window, vblank->crtc, vblank->event_id, vblank->target_msc);
8135c4bbdfSmrg        present_vblank_destroy(vblank);
8235c4bbdfSmrg    }
8335c4bbdfSmrg}
8435c4bbdfSmrg
8535c4bbdfSmrg/*
8635c4bbdfSmrg * Hook the close window function to clean up our window private
8735c4bbdfSmrg */
8835c4bbdfSmrgstatic Bool
8935c4bbdfSmrgpresent_destroy_window(WindowPtr window)
9035c4bbdfSmrg{
9135c4bbdfSmrg    Bool ret;
9235c4bbdfSmrg    ScreenPtr screen = window->drawable.pScreen;
9335c4bbdfSmrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
9435c4bbdfSmrg    present_window_priv_ptr window_priv = present_window_priv(window);
9535c4bbdfSmrg
9635c4bbdfSmrg    if (window_priv) {
9735c4bbdfSmrg        present_clear_window_notifies(window);
9835c4bbdfSmrg        present_free_events(window);
9935c4bbdfSmrg        present_free_window_vblank(window);
1001b5d61b8Smrg
101ed6184dfSmrg        screen_priv->clear_window_flip(window);
1021b5d61b8Smrg
10335c4bbdfSmrg        free(window_priv);
10435c4bbdfSmrg    }
10535c4bbdfSmrg    unwrap(screen_priv, screen, DestroyWindow);
10635c4bbdfSmrg    if (screen->DestroyWindow)
10735c4bbdfSmrg        ret = screen->DestroyWindow (window);
10835c4bbdfSmrg    else
10935c4bbdfSmrg        ret = TRUE;
11035c4bbdfSmrg    wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
11135c4bbdfSmrg    return ret;
11235c4bbdfSmrg}
11335c4bbdfSmrg
11435c4bbdfSmrg/*
11535c4bbdfSmrg * Hook the config notify screen function to deliver present config notify events
11635c4bbdfSmrg */
11735c4bbdfSmrgstatic int
11835c4bbdfSmrgpresent_config_notify(WindowPtr window,
11935c4bbdfSmrg                   int x, int y, int w, int h, int bw,
12035c4bbdfSmrg                   WindowPtr sibling)
12135c4bbdfSmrg{
12235c4bbdfSmrg    int ret;
12335c4bbdfSmrg    ScreenPtr screen = window->drawable.pScreen;
12435c4bbdfSmrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
12535c4bbdfSmrg
12635c4bbdfSmrg    present_send_config_notify(window, x, y, w, h, bw, sibling);
12735c4bbdfSmrg
12835c4bbdfSmrg    unwrap(screen_priv, screen, ConfigNotify);
12935c4bbdfSmrg    if (screen->ConfigNotify)
13035c4bbdfSmrg        ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
13135c4bbdfSmrg    else
13235c4bbdfSmrg        ret = 0;
13335c4bbdfSmrg    wrap(screen_priv, screen, ConfigNotify, present_config_notify);
13435c4bbdfSmrg    return ret;
13535c4bbdfSmrg}
13635c4bbdfSmrg
13735c4bbdfSmrg/*
13835c4bbdfSmrg * Hook the clip notify screen function to un-flip as necessary
13935c4bbdfSmrg */
14035c4bbdfSmrg
14135c4bbdfSmrgstatic void
14235c4bbdfSmrgpresent_clip_notify(WindowPtr window, int dx, int dy)
14335c4bbdfSmrg{
14435c4bbdfSmrg    ScreenPtr screen = window->drawable.pScreen;
14535c4bbdfSmrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
14635c4bbdfSmrg
1471b5d61b8Smrg    screen_priv->check_flip_window(window);
14835c4bbdfSmrg    unwrap(screen_priv, screen, ClipNotify)
14935c4bbdfSmrg    if (screen->ClipNotify)
15035c4bbdfSmrg        screen->ClipNotify (window, dx, dy);
15135c4bbdfSmrg    wrap(screen_priv, screen, ClipNotify, present_clip_notify);
15235c4bbdfSmrg}
15335c4bbdfSmrg
154ed6184dfSmrgBool
1551b5d61b8Smrgpresent_screen_register_priv_keys(void)
15635c4bbdfSmrg{
15735c4bbdfSmrg    if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
15835c4bbdfSmrg        return FALSE;
15935c4bbdfSmrg
16035c4bbdfSmrg    if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
16135c4bbdfSmrg        return FALSE;
16235c4bbdfSmrg
1631b5d61b8Smrg    return TRUE;
1641b5d61b8Smrg}
1651b5d61b8Smrg
166ed6184dfSmrgpresent_screen_priv_ptr
1671b5d61b8Smrgpresent_screen_priv_init(ScreenPtr screen)
1681b5d61b8Smrg{
1691b5d61b8Smrg    present_screen_priv_ptr screen_priv;
1701b5d61b8Smrg
1711b5d61b8Smrg    screen_priv = calloc(1, sizeof (present_screen_priv_rec));
1721b5d61b8Smrg    if (!screen_priv)
1731b5d61b8Smrg        return NULL;
1741b5d61b8Smrg
1751b5d61b8Smrg    wrap(screen_priv, screen, CloseScreen, present_close_screen);
1761b5d61b8Smrg    wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
1771b5d61b8Smrg    wrap(screen_priv, screen, ConfigNotify, present_config_notify);
1781b5d61b8Smrg    wrap(screen_priv, screen, ClipNotify, present_clip_notify);
1791b5d61b8Smrg
1801b5d61b8Smrg    dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
1811b5d61b8Smrg
1821b5d61b8Smrg    return screen_priv;
1831b5d61b8Smrg}
1841b5d61b8Smrg
1851b5d61b8Smrg/*
1861b5d61b8Smrg * Initialize a screen for use with present in default screen flip mode (scmd)
1871b5d61b8Smrg */
1881b5d61b8Smrgint
1891b5d61b8Smrgpresent_screen_init(ScreenPtr screen, present_screen_info_ptr info)
1901b5d61b8Smrg{
1911b5d61b8Smrg    if (!present_screen_register_priv_keys())
1921b5d61b8Smrg        return FALSE;
1931b5d61b8Smrg
1941b5d61b8Smrg    if (!present_screen_priv(screen)) {
1951b5d61b8Smrg        present_screen_priv_ptr screen_priv = present_screen_priv_init(screen);
1961b5d61b8Smrg        if (!screen_priv)
1971b5d61b8Smrg            return FALSE;
1981b5d61b8Smrg
1991b5d61b8Smrg        screen_priv->info = info;
2001b5d61b8Smrg        present_scmd_init_mode_hooks(screen_priv);
20135c4bbdfSmrg
20235c4bbdfSmrg        present_fake_screen_init(screen);
20335c4bbdfSmrg    }
20435c4bbdfSmrg
20535c4bbdfSmrg    return TRUE;
20635c4bbdfSmrg}
20735c4bbdfSmrg
20835c4bbdfSmrg/*
20935c4bbdfSmrg * Initialize the present extension
21035c4bbdfSmrg */
21135c4bbdfSmrgvoid
21235c4bbdfSmrgpresent_extension_init(void)
21335c4bbdfSmrg{
21435c4bbdfSmrg    ExtensionEntry *extension;
21535c4bbdfSmrg    int i;
21635c4bbdfSmrg
21735c4bbdfSmrg#ifdef PANORAMIX
21835c4bbdfSmrg    if (!noPanoramiXExtension)
21935c4bbdfSmrg        return;
22035c4bbdfSmrg#endif
22135c4bbdfSmrg
22235c4bbdfSmrg    extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
22335c4bbdfSmrg                             proc_present_dispatch, sproc_present_dispatch,
22435c4bbdfSmrg                             NULL, StandardMinorOpcode);
22535c4bbdfSmrg    if (!extension)
22635c4bbdfSmrg        goto bail;
22735c4bbdfSmrg
22835c4bbdfSmrg    present_request = extension->base;
22935c4bbdfSmrg
23035c4bbdfSmrg    if (!present_init())
23135c4bbdfSmrg        goto bail;
23235c4bbdfSmrg
23335c4bbdfSmrg    if (!present_event_init())
23435c4bbdfSmrg        goto bail;
23535c4bbdfSmrg
23635c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
23735c4bbdfSmrg        if (!present_screen_init(screenInfo.screens[i], NULL))
23835c4bbdfSmrg            goto bail;
23935c4bbdfSmrg    }
24035c4bbdfSmrg    return;
24135c4bbdfSmrg
24235c4bbdfSmrgbail:
24335c4bbdfSmrg    FatalError("Cannot initialize Present extension");
24435c4bbdfSmrg}
245