Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / server / X11 / xf_encode.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * X11 RemoteFX Encoder
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <X11/Xlib.h>
21 #include <freerdp/utils/sleep.h>
22
23 #include "xf_encode.h"
24
25 XImage* xf_snapshot(xfPeerContext* xfp, int x, int y, int width, int height)
26 {
27         XImage* image;
28         xfInfo* xfi = xfp->info;
29
30         if (xfi->use_xshm)
31         {
32                 pthread_mutex_lock(&(xfp->mutex));
33
34                 XCopyArea(xfi->display, xfi->root_window, xfi->fb_pixmap,
35                                 xfi->xdamage_gc, x, y, width, height, x, y);
36
37                 XSync(xfi->display, False);
38
39                 image = xfi->fb_image;
40
41                 pthread_mutex_unlock(&(xfp->mutex));
42         }
43         else
44         {
45                 pthread_mutex_lock(&(xfp->mutex));
46
47                 image = XGetImage(xfi->display, xfi->root_window,
48                                 x, y, width, height, AllPlanes, ZPixmap);
49
50                 pthread_mutex_unlock(&(xfp->mutex));
51         }
52
53         return image;
54 }
55
56 void xf_xdamage_subtract_region(xfPeerContext* xfp, int x, int y, int width, int height)
57 {
58         XRectangle region;
59         xfInfo* xfi = xfp->info;
60
61         region.x = x;
62         region.y = y;
63         region.width = width;
64         region.height = height;
65
66 #ifdef WITH_XFIXES
67         pthread_mutex_lock(&(xfp->mutex));
68         XFixesSetRegion(xfi->display, xfi->xdamage_region, &region, 1);
69         XDamageSubtract(xfi->display, xfi->xdamage, xfi->xdamage_region, None);
70         pthread_mutex_unlock(&(xfp->mutex));
71 #endif
72 }
73
74 void* xf_frame_rate_thread(void* param)
75 {
76         xfInfo* xfi;
77         xfEvent* event;
78         xfPeerContext* xfp;
79         freerdp_peer* client;
80         uint32 wait_interval;
81
82         client = (freerdp_peer*) param;
83         xfp = (xfPeerContext*) client->context;
84         xfi = xfp->info;
85
86         wait_interval = 1000000 / xfp->fps;
87
88         while (1)
89         {
90                 event = xf_event_new(XF_EVENT_TYPE_FRAME_TICK);
91                 xf_event_push(xfp->event_queue, (xfEvent*) event);
92                 freerdp_usleep(wait_interval);
93         }
94 }
95
96 void* xf_monitor_updates(void* param)
97 {
98         int fds;
99         xfInfo* xfi;
100         XEvent xevent;
101         fd_set rfds_set;
102         int select_status;
103         int pending_events;
104         xfPeerContext* xfp;
105         freerdp_peer* client;
106         uint32 wait_interval;
107         struct timeval timeout;
108         int x, y, width, height;
109         XDamageNotifyEvent* notify;
110         xfEventRegion* event_region;
111
112         client = (freerdp_peer*) param;
113         xfp = (xfPeerContext*) client->context;
114         xfi = xfp->info;
115
116         fds = xfi->xfds;
117         wait_interval = (1000000 / 2500);
118         memset(&timeout, 0, sizeof(struct timeval));
119
120         pthread_create(&(xfp->frame_rate_thread), 0, xf_frame_rate_thread, (void*) client);
121
122         pthread_detach(pthread_self());
123
124         while (1)
125         {
126                 FD_ZERO(&rfds_set);
127                 FD_SET(fds, &rfds_set);
128
129                 timeout.tv_sec = 0;
130                 timeout.tv_usec = wait_interval;
131                 select_status = select(fds + 1, &rfds_set, NULL, NULL, &timeout);
132
133                 if (select_status == -1)
134                 {
135                         printf("select failed\n");
136                 }
137                 else if (select_status == 0)
138                 {
139                         //printf("select timeout\n");
140                 }
141
142                 pthread_mutex_lock(&(xfp->mutex));
143                 pending_events = XPending(xfi->display);
144                 pthread_mutex_unlock(&(xfp->mutex));
145
146                 if (pending_events > 0)
147                 {
148                         pthread_mutex_lock(&(xfp->mutex));
149                         memset(&xevent, 0, sizeof(xevent));
150                         XNextEvent(xfi->display, &xevent);
151                         pthread_mutex_unlock(&(xfp->mutex));
152
153                         if (xevent.type == xfi->xdamage_notify_event)
154                         {
155                                 notify = (XDamageNotifyEvent*) &xevent;
156
157                                 x = notify->area.x;
158                                 y = notify->area.y;
159                                 width = notify->area.width;
160                                 height = notify->area.height;
161
162                                 xf_xdamage_subtract_region(xfp, x, y, width, height);
163
164                                 event_region = xf_event_region_new(x, y, width, height);
165                                 xf_event_push(xfp->event_queue, (xfEvent*) event_region);
166                         }
167                 }
168         }
169
170         return NULL;
171 }