summaryrefslogtreecommitdiff
path: root/src/lib/ecore_x/ecore_x_present.c
blob: a944f7b850d1c01d913116ba9eafd69bfb40b1b0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* ifdef HAVE_CONFIG_H */

#include <stdlib.h>

#include "ecore_x_private.h"
#include "Ecore_X.h"

int _ecore_x_present_major = 0;
static Eina_Bool _ecore_x_present_exists = EINA_FALSE;

void
_ecore_x_present_init(void)
{
   if (ECORE_X_EVENT_PRESENT_CONFIGURE == 0)
     {
        ECORE_X_EVENT_PRESENT_CONFIGURE = ecore_event_type_new();
        ECORE_X_EVENT_PRESENT_COMPLETE = ecore_event_type_new();
        ECORE_X_EVENT_PRESENT_IDLE = ecore_event_type_new();
     }
#ifdef ECORE_XPRESENT
   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   _ecore_x_present_exists = XPresentQueryExtension(_ecore_x_disp, &_ecore_x_present_major, NULL, NULL);
#endif
}

#ifdef ECORE_XPRESENT
#define SET(X) e->X = ev->X

static void
_present_configure(XPresentConfigureNotifyEvent *ev)
{
   Ecore_X_Event_Present_Configure *e;

   e = calloc(1, sizeof(Ecore_X_Event_Present_Configure));
   if (!e) return;

   e->win = ev->window;
   SET(x), SET(y);
   SET(width), SET(height);
   SET(off_x), SET(off_y);
   SET(pixmap_width), SET(pixmap_height);
   SET(pixmap_flags);

   ecore_event_add(ECORE_X_EVENT_PRESENT_CONFIGURE, e, NULL, NULL);
}

static void
_present_complete(XPresentCompleteNotifyEvent *ev)
{
   unsigned int mode[] =
   {
    [PresentCompleteModeCopy] = ECORE_X_PRESENT_COMPLETE_MODE_COPY,
    [PresentCompleteModeFlip] = ECORE_X_PRESENT_COMPLETE_MODE_FLIP,
    [PresentCompleteModeSkip] = ECORE_X_PRESENT_COMPLETE_MODE_SKIP,
   };
   Ecore_X_Event_Present_Complete *e;

   e = calloc(1, sizeof(Ecore_X_Event_Present_Complete));
   if (!e) return;

   e->win = ev->window;
   e->serial = ev->serial_number;
   SET(ust), SET(msc);
   e->kind = (ev->kind == 1); //libXpresent doesn't expose this...
   e->mode = mode[ev->mode];
   ecore_event_add(ECORE_X_EVENT_PRESENT_COMPLETE, e, NULL, NULL);
}

static void
_present_idle(XPresentIdleNotifyEvent *ev)
{
   Ecore_X_Event_Present_Idle *e;

   e = calloc(1, sizeof(Ecore_X_Event_Present_Idle));
   if (!e) return;

   e->win = ev->window;
   e->serial = ev->serial_number;
   SET(pixmap);
   SET(idle_fence);
   ecore_event_add(ECORE_X_EVENT_PRESENT_IDLE, e, NULL, NULL);
}
#undef SET

void
_ecore_x_present_handler(XGenericEvent *ge)
{
   XGenericEventCookie *gec = (XGenericEventCookie*)ge;

   if (XGetEventData(_ecore_x_disp, gec))
     {
        switch (gec->evtype)
          {
           case PresentConfigureNotify:
             _present_configure(gec->data);
             break;
           case PresentCompleteNotify:
             _present_complete(gec->data);
             break;
           case PresentIdleNotify:
             _present_idle(gec->data);
             break;
           default: break;
          }
     }
   XFreeEventData(_ecore_x_disp, gec);
}
#endif

EAPI void
ecore_x_present_select_events(Ecore_X_Window win, unsigned int events)
{
#ifdef ECORE_XPRESENT
   XPresentSelectInput(_ecore_x_disp, win, events);
   if (_ecore_xlib_sync) ecore_x_sync();
#else
   (void)win;
   (void)events;
#endif
}

EAPI void
ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder)
{
#ifdef ECORE_XPRESENT
   XPresentNotifyMSC(_ecore_x_disp, win, serial, target_msc, divisor, remainder);
   if (_ecore_xlib_sync) ecore_x_sync();
#else
   (void)win;
   (void)serial;
   (void)target_msc;
   (void)divisor;
   (void)remainder;
#endif
}

EAPI void
ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid,
                       Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc,
                       Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options,
                       unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder,
                       Ecore_X_Present *notifies, int num_notifies)
{
#ifdef ECORE_XPRESENT
   XPresentPixmap(_ecore_x_disp, win, pixmap, serial, valid, update,
                  x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc,
                  divisor, remainder, (XPresentNotify*)notifies, num_notifies);
   if (_ecore_xlib_sync) ecore_x_sync();
#else
   (void)win;
   (void)pixmap;
   (void)serial;
   (void)valid;
   (void)update,
   (void)x_off;
   (void)y_off;
   (void)target_crtc;
   (void)wait_fence;
   (void)idle_fence;
   (void)options;
   (void)target_msc,
   (void)divisor;
   (void)remainder;
   (void)notifies;
   (void)num_notifies;
#endif
}

EAPI Eina_Bool
ecore_x_present_exists(void)
{
   return _ecore_x_present_exists;
}