Add uniconify client event
[platform/core/uifw/e-mod-tizen-rdp.git] / src / e_mod_rdp.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <errno.h>
10
11 #include <assert.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <linux/input.h>
17
18 #include <freerdp/version.h>
19 #include <freerdp/freerdp.h>
20 #include <freerdp/listener.h>
21 #include <freerdp/update.h>
22 #include <freerdp/input.h>
23 #include <freerdp/codec/color.h>
24 #include <freerdp/codec/rfx.h>
25 #include <freerdp/codec/nsc.h>
26 #include <freerdp/locale/keyboard.h>
27 #include <winpr/input.h>
28 #include <winpr/ssl.h>
29
30 #include <pixman.h>
31 #include <tbm_surface.h>
32 #include <tbm_surface_internal.h>
33 #include <e_info_server_input.h>
34
35 #if HAVE_LIBGOMP
36 #include <omp.h>
37 #endif
38
39 #include "e_mod_main.h"
40 #include "e_mod_rdp.h"
41
42 #define RDP_DEBUG 0
43
44 #define E_RDP_WIDTH 1280
45 #define E_RDP_HEIGHT 720
46 #define E_RDP_DEVICE_NAME "rdp_input"
47 #define E_MOD_RDP_CONFIG_VERSION  2
48 #define E_MOD_RDP_NAME_LEN        64
49 #define MAX_FREERDP_FDS           10
50 #define DEFAULT_PIXEL_FORMAT PIXEL_FORMAT_BGRA32
51
52 #define VGA_TIME 0.05
53 #define SVGA_TIME 0.075
54 #define XGA_TIME 0.06
55 #define HD_TIME 0.15
56 #define WXGA_TIME 0.18
57 #define SXGAP_TIME 0.18
58 #define FHD_TIME 0.2
59
60 enum peer_item_flags
61 {
62    RDP_PEER_ACTIVATED      = (1 << 0),
63    RDP_PEER_OUTPUT_ENABLED = (1 << 1),
64 };
65
66 typedef struct _E_Rdp_Output E_Rdp_Output;
67 typedef struct _E_Rdp_Backend E_Rdp_Backend;
68 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
69 typedef struct _E_Rdp_Peer_Item E_Rdp_Peer_Item;
70 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
71
72 static E_Rdp_Config_Data *g_rdp_config;
73 static E_Rdp_Backend *g_rdp_backend;
74 static unsigned int refresh_raw_frame_id;
75 static E_Pointer_Hook *pointer_hook = NULL;
76
77 struct _E_Rdp_Output
78 {
79    E_Output *primary_output;
80    Ecore_Timer *frame_timer;
81    pixman_image_t *showing_surface;
82    tbm_surface_h prepare_tbm_surface;
83    tbm_surface_h showing_tbm_surface;
84    tbm_surface_h backup_tbm_surface;
85    uint32_t w;
86    uint32_t h;
87
88    uint32_t primary_w;
89    uint32_t primary_h;
90
91    float mouse_scale_w;
92    float mouse_scale_h;
93
94    uint32_t prev_x;
95    uint32_t prev_y;
96
97    Eina_Bool frame_changed;
98    Eina_Bool cursor_changed;
99    double refresh_time;
100    int refresh_count;
101
102    Eina_Bool mouse_moved;
103    Eina_Bool buffer_changed;
104
105    Eina_Bool buffer_reuse;
106    Eina_Rectangle cursor_crop_dst;
107    Eina_Rectangle cursor_damage_rect;
108
109    int mouse_x;
110    int mouse_y;
111
112    struct wl_list peers;
113 };
114
115 struct _E_Rdp_Backend
116 {
117    freerdp_listener *listener;
118    struct wl_event_source *listener_events[MAX_FREERDP_FDS];
119    E_Rdp_Output *output;
120    Eina_List *handlers;
121
122    char *server_cert;
123    char *server_key;
124    char *rdp_key;
125    int tls_enabled;
126    int no_clients_resize;
127    int force_no_compression;
128    int motionless;
129
130    int client_count;
131 };
132
133 struct _E_Rdp_Peer_Item
134 {
135    int flags;
136    freerdp_peer *peer;
137
138    struct wl_list link;
139 };
140
141 struct _E_Rdp_Peer_Context
142 {
143    rdpContext _p;
144
145    E_Rdp_Backend *rdpBackend;
146    struct wl_event_source *events[MAX_FREERDP_FDS];
147    RFX_CONTEXT *rfx_context;
148    wStream *encode_stream;
149    RFX_RECT *rfx_rects;
150    NSC_CONTEXT *nsc_context;
151
152    E_Rdp_Peer_Item item;
153 };
154
155 struct rdp_to_xkb_keyboard_layout
156 {
157    UINT32 rdpLayoutCode;
158    const char *xkbLayout;
159    const char *xkbVariant;
160 };
161
162 static tbm_surface_h
163 _e_rdp_tbm_image_create(E_Rdp_Output *output, int w, int h, int color)
164 {
165    tbm_surface_h tbm_surface = NULL;
166
167    tbm_surface = tbm_surface_internal_create_with_flags(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
168    if (!tbm_surface)
169      return NULL;
170
171    return tbm_surface;
172 }
173
174 static pixman_format_code_t
175 _e_rdp_pixman_format_get(tbm_format format)
176 {
177    switch (format)
178      {
179       case TBM_FORMAT_ARGB8888:
180         return PIXMAN_a8r8g8b8;
181
182       case TBM_FORMAT_XRGB8888:
183         return PIXMAN_x8r8g8b8;
184
185       default:
186         return 0;
187      }
188
189    return 0;
190 }
191
192 static pixman_image_t *
193 _e_rdp_pixman_image_create(tbm_surface_h tbm_surface)
194 {
195    int err;
196    tbm_surface_info_s info;
197    pixman_image_t *pix_surface = NULL;
198    pixman_format_code_t pix_format = 0;
199
200    EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
201
202    err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
203    if (err)
204      return NULL;
205
206    pix_format = _e_rdp_pixman_format_get(info.format);
207    if (pix_format == 0)
208      {
209         ERR("not supported format");
210         goto out;
211      }
212
213    pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
214    if (pix_surface == NULL)
215      ERR("create pixman image failed");
216
217 out:
218    tbm_surface_unmap(tbm_surface);
219    return pix_surface;
220 }
221
222 static void
223 e_rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
224 {
225    int width, height, nrects, i;
226    pixman_box32_t *region, *rects;
227    uint32_t *ptr;
228    RFX_RECT *rfxRect;
229    rdpUpdate *update = peer->update;
230    SURFACE_BITS_COMMAND cmd = { 0 };
231    E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
232
233    Stream_Clear(context->encode_stream);
234    Stream_SetPosition(context->encode_stream, 0);
235
236    width = (damage->extents.x2 - damage->extents.x1);
237    height = (damage->extents.y2 - damage->extents.y1);
238
239    cmd.skipCompression = TRUE;
240    cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
241    cmd.destLeft = damage->extents.x1;
242    cmd.destTop = damage->extents.y1;
243    cmd.destRight = damage->extents.x2;
244    cmd.destBottom = damage->extents.y2;
245    cmd.bmp.bpp = 32;
246    cmd.bmp.codecID = peer->settings->RemoteFxCodecId;
247    cmd.bmp.width = width;
248    cmd.bmp.height = height;
249
250    ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
251
252    rects = pixman_region32_rectangles(damage, &nrects);
253    context->rfx_rects = realloc(context->rfx_rects, nrects * sizeof *rfxRect);
254    if (context->rfx_rects == NULL)
255      {
256         ERR("realloc failed");
257         return;
258      }
259
260    for (i = 0; i < nrects; i++)
261      {
262         region = &rects[i];
263         rfxRect = &context->rfx_rects[i];
264
265         rfxRect->x = (region->x1 - damage->extents.x1);
266         rfxRect->y = (region->y1 - damage->extents.y1);
267         rfxRect->width = (region->x2 - region->x1);
268         rfxRect->height = (region->y2 - region->y1);
269      }
270
271    rfx_compose_message(context->rfx_context, context->encode_stream, context->rfx_rects, nrects, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
272
273    cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
274    cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
275 #if RDP_DEBUG
276    double start, end;
277    start = ecore_time_get();
278 #endif
279    update->SurfaceBits(update->context, &cmd);
280 #if RDP_DEBUG
281    end = ecore_time_get();
282    INF("pixman refresh time rfx: %.1f ms", (end - start) * 1000);
283 #endif
284 }
285
286
287 static void
288 e_rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
289 {
290    int width, height;
291    uint32_t *ptr;
292    rdpUpdate *update = peer->update;
293    SURFACE_BITS_COMMAND cmd = { 0 };
294    E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
295
296    Stream_Clear(context->encode_stream);
297    Stream_SetPosition(context->encode_stream, 0);
298
299    width = (damage->extents.x2 - damage->extents.x1);
300    height = (damage->extents.y2 - damage->extents.y1);
301
302    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
303    cmd.skipCompression = TRUE;
304    cmd.destLeft = damage->extents.x1;
305    cmd.destTop = damage->extents.y1;
306    cmd.destRight = damage->extents.x2;
307    cmd.destBottom = damage->extents.y2;
308    cmd.bmp.bpp = 32;
309    cmd.bmp.codecID = peer->settings->NSCodecId;
310    cmd.bmp.width = width;
311    cmd.bmp.height = height;
312
313    ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
314
315    nsc_compose_message(context->nsc_context, context->encode_stream, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
316
317    cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
318    cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
319 #if RDP_DEBUG
320    double start, end;
321    start = ecore_time_get();
322 #endif
323    update->SurfaceBits(update->context, &cmd);
324 #if RDP_DEBUG
325    end = ecore_time_get();
326    INF("pixman refresh time nsc: %.1f ms", (end - start) * 1000);
327 #endif
328 }
329
330 static void
331 pixman_image_flipped_subrect(const pixman_box32_t *rect, pixman_image_t *img, BYTE *dest)
332 {
333    int stride = pixman_image_get_stride(img);
334    int h;
335    int toCopy = (rect->x2 - rect->x1) * 4;
336    int height = (rect->y2 - rect->y1);
337    const BYTE *src = (const BYTE *)pixman_image_get_data(img);
338    src += ((rect->y2-1) * stride) + (rect->x1 * 4);
339
340    for (h = 0; h < height; h++, src -= stride, dest += toCopy)
341      memcpy(dest, src, toCopy);
342 }
343
344 static void
345 e_rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_peer *peer)
346 {
347    rdpUpdate *update = peer->update;
348    SURFACE_BITS_COMMAND cmd = { 0 };
349    SURFACE_FRAME_MARKER marker;
350    pixman_box32_t *rect, subrect;
351    int nrects, i;
352    int heightIncrement, remainingHeight, top;
353
354    rect = pixman_region32_rectangles(region, &nrects);
355    if (!nrects)
356      return;
357
358    if (refresh_raw_frame_id == 1024)
359      refresh_raw_frame_id = 0;
360    refresh_raw_frame_id++;
361
362    marker.frameId = refresh_raw_frame_id;
363    marker.frameAction = SURFACECMD_FRAMEACTION_BEGIN;
364    update->SurfaceFrameMarker(peer->context, &marker);
365
366    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
367    cmd.bmp.bpp = 32;
368    cmd.bmp.codecID = 0;
369
370 #if RDP_DEBUG
371    double start, end;
372    start = ecore_time_get();
373 #endif
374
375    for (i = 0; i < nrects; i++, rect++)
376      {
377         /*INF("rect(%d,%d, %d,%d)", rect->x1, rect->y1, rect->x2, rect->y2);*/
378         cmd.destLeft = rect->x1;
379         cmd.destRight = rect->x2;
380         cmd.bmp.width = (rect->x2 - rect->x1);
381
382         heightIncrement = peer->settings->MultifragMaxRequestSize / (16 + cmd.bmp.width * 4);
383         remainingHeight = rect->y2 - rect->y1;
384         top = rect->y1;
385
386         subrect.x1 = rect->x1;
387         subrect.x2 = rect->x2;
388
389         while (remainingHeight)
390           {
391              cmd.bmp.height = (remainingHeight > heightIncrement) ? heightIncrement : remainingHeight;
392              cmd.destTop = top;
393              cmd.destBottom = top + cmd.bmp.height;
394              cmd.bmp.bitmapDataLength = cmd.bmp.width * cmd.bmp.height * 4;
395              cmd.bmp.bitmapData = (BYTE *)realloc(cmd.bmp.bitmapData, cmd.bmp.bitmapDataLength);
396
397              subrect.y1 = top;
398              subrect.y2 = top + cmd.bmp.height;
399              pixman_image_flipped_subrect(&subrect, image, cmd.bmp.bitmapData);
400
401              /*INF("*  sending (%d,%d, %d,%d)", subrect.x1, subrect.y1, subrect.x2, subrect.y2); */
402              update->SurfaceBits(peer->context, &cmd);
403
404              remainingHeight -= cmd.bmp.height;
405              top += cmd.bmp.height;
406           }
407      }
408 #if RDP_DEBUG
409      end = ecore_time_get();
410      INF("pixman refresh time raw: %.1f ms", (end - start) * 1000);
411 #endif
412
413    free(cmd.bmp.bitmapData);
414
415    marker.frameAction = SURFACECMD_FRAMEACTION_END;
416    update->SurfaceFrameMarker(peer->context, &marker);
417 }
418
419 static void
420 e_rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer, pixman_image_t *pix_surface)
421 {
422    rdpSettings *settings = peer->settings;
423
424    if (settings->RemoteFxCodec)
425      e_rdp_peer_refresh_rfx(region, pix_surface, peer);
426    else if (settings->NSCodec)
427      e_rdp_peer_refresh_nsc(region, pix_surface, peer);
428    else
429      e_rdp_peer_refresh_raw(region, pix_surface, peer);
430 }
431
432 static void
433 _e_rdp_output_image_showing_rect_get(Eina_Rectangle *out_rect, Eina_Rectangle *dst_rect, Eina_Rectangle *showing_rect)
434 {
435    showing_rect->x = dst_rect->x;
436    showing_rect->y = dst_rect->y;
437
438    if (dst_rect->x >= out_rect->w)
439      showing_rect->w = 0;
440    else if (dst_rect->x + dst_rect->w > out_rect->w)
441      showing_rect->w = out_rect->w - dst_rect->x;
442    else
443      showing_rect->w = dst_rect->w;
444
445    if (dst_rect->y >= out_rect->h)
446      showing_rect->h = 0;
447    else if (dst_rect->y + dst_rect->h > out_rect->h)
448      showing_rect->h = out_rect->h - dst_rect->y;
449    else
450      showing_rect->h = dst_rect->h;
451 }
452
453 static void
454 _e_rdp_output_image_src_crop_get(E_Hwc_Window *hwc_window, Eina_Rectangle *fit, Eina_Rectangle *showing_rect, int primary_w, int primary_h)
455 {
456    float ratio_x, ratio_y;
457    Eina_Rectangle out_rect;
458    Eina_Rectangle dst_rect;
459
460    fit->x = 0;
461    fit->y = 0;
462    fit->w = 0;
463    fit->h = 0;
464
465    out_rect.x = 0;
466    out_rect.y = 0;
467    out_rect.w = primary_w;
468    out_rect.h = primary_h;
469
470    dst_rect.x = hwc_window->current.info.dst_pos.x;
471    dst_rect.y = hwc_window->current.info.dst_pos.y;
472    dst_rect.w = hwc_window->current.info.dst_pos.w;
473    dst_rect.h = hwc_window->current.info.dst_pos.h;
474
475    _e_rdp_output_image_showing_rect_get(&out_rect, &dst_rect, showing_rect);
476
477    fit->x = hwc_window->current.info.src_config.pos.x;
478    fit->y = hwc_window->current.info.src_config.pos.y;
479
480    if (hwc_window->current.info.transform % 2 == 0)
481      {
482         ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.w;
483         ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.h;
484
485         fit->w = showing_rect->w * ratio_x;
486         fit->h = showing_rect->h * ratio_y;
487      }
488    else
489      {
490         ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.h;
491         ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.w;
492
493         fit->w = showing_rect->h * ratio_x;
494         fit->h = showing_rect->w * ratio_y;
495      }
496 }
497
498 static Eina_Bool
499 _e_rdp_output_center_rect_get (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
500 {
501    float rw, rh;
502
503    if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
504      return EINA_FALSE;
505
506    rw = (float)src_w / dst_w;
507    rh = (float)src_h / dst_h;
508
509    if (rw > rh)
510      {
511         fit->w = dst_w;
512         fit->h = src_h / rw;
513         fit->x = 0;
514         fit->y = (dst_h - fit->h) / 2;
515      }
516    else if (rw < rh)
517      {
518         fit->w = src_w / rh;
519         fit->h = dst_h;
520         fit->x = (dst_w - fit->w) / 2;
521         fit->y = 0;
522      }
523    else
524      {
525         fit->w = dst_w;
526         fit->h = dst_h;
527         fit->x = 0;
528         fit->y = 0;
529      }
530
531    if (fit->x % 2)
532      fit->x = fit->x - 1;
533
534    return EINA_TRUE;
535 }
536
537 static void
538 _e_rdp_output_image_dst_crop_get(E_Hwc_Window *hwc_window, int src_w, int src_h, int w, int h,
539                                  Eina_Rectangle *pos, Eina_Rectangle *showing_pos, Eina_Rectangle *dst_crop, int rotate)
540 {
541    dst_crop->x = 0;
542    dst_crop->y = 0;
543    dst_crop->w = 0;
544    dst_crop->h = 0;
545
546    if (hwc_window->current.info.src_config.pos.w == w && hwc_window->current.info.src_config.pos.h == h &&
547        pos->x == 0 && pos->y == 0 && pos->w == src_w && pos->h == src_h)
548      {
549         dst_crop->x = pos->x;
550         dst_crop->y = pos->y;
551         dst_crop->w = pos->w;
552         dst_crop->h = pos->h;
553      }
554    else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
555      {
556         dst_crop->x = hwc_window->current.info.dst_pos.x + pos->x;
557         dst_crop->y = hwc_window->current.info.dst_pos.y + pos->y;
558         dst_crop->w = hwc_window->current.info.dst_pos.w;
559         dst_crop->h = hwc_window->current.info.dst_pos.h;
560      }
561    else if (rotate == 0)
562      {
563         dst_crop->x = showing_pos->x * pos->w / w + pos->x;
564         dst_crop->y = showing_pos->y * pos->h / h + pos->y;
565         dst_crop->w = showing_pos->w * pos->w / w;
566         dst_crop->h = showing_pos->h * pos->h / h;
567      }
568    else
569      {
570         dst_crop->x = pos->x;
571         dst_crop->y = pos->y;
572         dst_crop->w = pos->w;
573         dst_crop->h = pos->h;
574      }
575 }
576
577 static void
578 _e_rdp_output_image_composite(pixman_image_t *src_img, pixman_image_t *dst_img,
579                           int sx, int sy, int sw, int sh,
580                           int dx, int dy, int dw, int dh,
581                           Eina_Bool over, int rotate, int hflip, int vflip)
582 {
583    double scale_x, scale_y;
584    int rotate_step;
585    pixman_transform_t t;
586    struct pixman_f_transform ft;
587    pixman_op_t op;
588
589    pixman_f_transform_init_identity(&ft);
590
591    if (hflip)
592      {
593         pixman_f_transform_scale(&ft, NULL, -1, 1);
594         pixman_f_transform_translate(&ft, NULL, dw, 0);
595      }
596
597    if (vflip)
598      {
599         pixman_f_transform_scale(&ft, NULL, 1, -1);
600         pixman_f_transform_translate(&ft, NULL, 0, dh);
601      }
602
603    rotate_step = (rotate + 360) / 90 % 4;
604    if (rotate_step > 0)
605      {
606         int c, s, tx = 0, ty = 0;
607         switch (rotate_step)
608           {
609            case 1:
610               c = 0, s = -1, tx = -dw;
611               break;
612            case 2:
613               c = -1, s = 0, tx = -dw, ty = -dh;
614               break;
615            case 3:
616               c = 0, s = 1, ty = -dh;
617               break;
618           }
619         pixman_f_transform_translate(&ft, NULL, tx, ty);
620         pixman_f_transform_rotate(&ft, NULL, c, s);
621      }
622
623    if (rotate_step % 2 == 0)
624      {
625         scale_x = (double)sw / dw;
626         scale_y = (double)sh / dh;
627      }
628    else
629      {
630         scale_x = (double)sw / dh;
631         scale_y = (double)sh / dw;
632      }
633
634    pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
635    pixman_f_transform_translate(&ft, NULL, sx, sy);
636    pixman_transform_from_pixman_f_transform(&t, &ft);
637    pixman_image_set_transform(src_img, &t);
638
639    if (!over) op = PIXMAN_OP_SRC;
640    else op = PIXMAN_OP_OVER;
641
642    pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
643                           dx, dy, dw, dh);
644 }
645
646 static void
647 _e_rdp_pixman_output_image_cusror_damage_area_get(E_Rdp_Output *output, Eina_Rectangle *rect)
648 {
649    if (output->cursor_crop_dst.x == 0 && output->cursor_crop_dst.y == 0 &&
650        output->cursor_crop_dst.w == 0 && output->cursor_crop_dst.h == 0)
651      {
652         output->cursor_damage_rect.x = 0;
653         output->cursor_damage_rect.y = 0;
654         output->cursor_damage_rect.w = output->w;
655         output->cursor_damage_rect.h = output->h;
656      }
657    else
658      {
659         /* x axis */
660         if (output->cursor_crop_dst.x < rect->x)
661           {
662              output->cursor_damage_rect.x = output->cursor_crop_dst.x;
663              output->cursor_damage_rect.w = rect->x - output->cursor_crop_dst.x + rect->w;
664           }
665         else
666           {
667              output->cursor_damage_rect.x = rect->x;
668              output->cursor_damage_rect.w = output->cursor_crop_dst.x - rect->x + output->cursor_crop_dst.w;
669           }
670         if (output->cursor_damage_rect.x + output->cursor_damage_rect.w > output->w)
671           output->cursor_damage_rect.w = output->w - output->cursor_damage_rect.x;
672
673         /* y axis */
674         if (output->cursor_crop_dst.y < rect->y)
675           {
676              output->cursor_damage_rect.y = output->cursor_crop_dst.y;
677              output->cursor_damage_rect.h = rect->y - output->cursor_crop_dst.y + rect->h;
678           }
679         else
680           {
681              output->cursor_damage_rect.y = rect->y;
682              output->cursor_damage_rect.h = output->cursor_crop_dst.y - rect->y + output->cursor_crop_dst.h;
683           }
684         if (output->cursor_damage_rect.y + output->cursor_damage_rect.h > output->h)
685           output->cursor_damage_rect.h = output->h - output->cursor_damage_rect.y;
686      }
687 }
688
689 static Eina_Bool
690 _e_rdp_pixman_output_image_composite_cursor(E_Rdp_Output *output, E_Hwc_Window *hwc_window, pixman_image_t *pix_surface, int pix_w, int pix_h, int primary_w, int primary_h)
691 {
692    Eina_Rectangle showing_pos = {0, };
693    Eina_Rectangle dst_pos = {0, };
694    Eina_Rectangle src_crop = {0, };
695    Eina_Rectangle dst_crop = {0, };
696    void *src_ptr = NULL;
697    int src_stride, img_w, img_h;
698    pixman_image_t *pix_shm_src = NULL;
699
700    if (!hwc_window->cursor.buffer)
701      return EINA_FALSE;
702
703    src_ptr = hwc_window->cursor.img_ptr;
704    src_stride = hwc_window->cursor.img_stride;
705    img_w = hwc_window->cursor.img_w;
706    img_h = hwc_window->cursor.img_h;
707
708    pix_shm_src = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride);
709    if (!pix_shm_src)
710      {
711         ERR("create pixman image failed");
712         return EINA_FALSE;
713      }
714
715    _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
716    if (_e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos) == EINA_FALSE)
717      {
718         pixman_image_unref(pix_shm_src);
719         return EINA_FALSE;
720      }
721    _e_rdp_output_image_dst_crop_get(hwc_window, img_w, img_h, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
722
723    _e_rdp_output_image_composite(pix_shm_src, pix_surface,
724                                  src_crop.x, src_crop.y, src_crop.w, src_crop.h,
725                                  dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
726                                  EINA_TRUE, 0, 0, 0);
727
728    pixman_image_unref(pix_shm_src);
729
730    output->mouse_x = hwc_window->current.info.dst_pos.x;
731    output->mouse_y = hwc_window->current.info.dst_pos.y;
732
733    _e_rdp_pixman_output_image_cusror_damage_area_get(output, &dst_crop);
734    output->cursor_crop_dst.x = dst_crop.x;
735    output->cursor_crop_dst.y = dst_crop.y;
736    output->cursor_crop_dst.w = dst_crop.w;
737    output->cursor_crop_dst.h = dst_crop.h;
738
739    return EINA_TRUE;
740 }
741
742 static Eina_Bool
743 _e_rdp_pixman_output_image_composite(E_Rdp_Output *output, E_Hwc_Window *hwc_window, pixman_image_t *pix_surface, int pix_w, int pix_h, int primary_w, int primary_h)
744 {
745    Eina_Rectangle showing_pos = {0, };
746    Eina_Rectangle dst_pos = {0, };
747    Eina_Rectangle src_crop = {0, };
748    Eina_Rectangle dst_crop = {0, };
749    tbm_surface_h tbm_surface = NULL;
750    tbm_surface_info_s info;
751    pixman_image_t *pix_surface_src = NULL;
752    pixman_format_code_t pix_format = 0;
753
754    tbm_surface = hwc_window->display.buffer.tsurface;
755    if (!tbm_surface)
756      return EINA_FALSE;
757
758    tbm_surface_internal_ref(tbm_surface);
759
760    if (tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info) != TBM_SURFACE_ERROR_NONE)
761      {
762         tbm_surface_internal_unref(tbm_surface);
763         return EINA_FALSE;
764      }
765
766    pix_format = _e_rdp_pixman_format_get(info.format);
767    if (pix_format == 0)
768      {
769         ERR("not supported format");
770         goto error;
771      }
772
773    pix_surface_src = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
774    if (pix_surface_src == NULL)
775      {
776         ERR("create pixman image failed");
777         goto error;
778      }
779
780    _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
781    _e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos);
782    if (_e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos) == EINA_FALSE)
783      {
784         pixman_image_unref(pix_surface_src);
785         goto error;
786      }
787    _e_rdp_output_image_dst_crop_get(hwc_window, info.width, info.height, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
788
789    _e_rdp_output_image_composite(pix_surface_src, pix_surface,
790                                  src_crop.x, src_crop.y, src_crop.w, src_crop.h,
791                                  dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
792                                  EINA_TRUE, 0, 0, 0);
793
794    pixman_image_unref(pix_surface_src);
795    tbm_surface_unmap(tbm_surface);
796    tbm_surface_internal_unref(tbm_surface);
797
798    return EINA_TRUE;
799
800 error:
801    tbm_surface_unmap(tbm_surface);
802    tbm_surface_internal_unref(tbm_surface);
803    return EINA_FALSE;
804 }
805
806 static int
807 _e_rdp_cb_hwc_window_sort(const void *d1, const void *d2)
808 {
809    E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
810    E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
811    int zpos1 = 0, zpos2 = 0;
812
813    if (!hwc_window1) return(1);
814    if (!hwc_window2) return(-1);
815
816    if (hwc_window1->state == E_HWC_WINDOW_STATE_NONE)
817      zpos1 = -999;
818    else
819      zpos1 = hwc_window1->zpos;
820
821    if (hwc_window2->state == E_HWC_WINDOW_STATE_NONE)
822      zpos2 = -999;
823    else
824      zpos2 = hwc_window2->zpos;
825
826    return (zpos1 - zpos2);
827 }
828
829 static void
830 _e_rdp_tbm_surface_copy(tbm_surface_h src_tbm_surface, tbm_surface_info_s *src_info, tbm_surface_h dst_tbm_surface, tbm_surface_info_s *dst_info)
831 {
832 #if HAVE_LIBGOMP
833 # define LIBGOMP_COPY_THREAD_NUM 4
834 # define LIBGOMP_COPY_PAGE_SIZE getpagesize()
835 # define PAGE_ALIGN(addr) ((addr)&(~((LIBGOMP_COPY_PAGE_SIZE)-1)))
836    if (src_info->planes[0].size > (LIBGOMP_COPY_THREAD_NUM * LIBGOMP_COPY_PAGE_SIZE))
837      {
838         size_t step[2];
839         step[0] = PAGE_ALIGN(src_info->planes[0].size / LIBGOMP_COPY_THREAD_NUM);
840         step[1] = src_info->planes[0].size - (step[0] * (LIBGOMP_COPY_THREAD_NUM - 1));
841
842         omp_set_num_threads(LIBGOMP_COPY_THREAD_NUM);
843         #pragma omp parallel
844         #pragma omp sections
845           {
846              #pragma omp section
847                {
848                   memcpy(dst_info->planes[0].ptr,
849                          src_info->planes[0].ptr,
850                          step[0]);
851                }
852              #pragma omp section
853                {
854                   memcpy(dst_info->planes[0].ptr + step[0],
855                          src_info->planes[0].ptr + step[0],
856                          step[0]);
857                }
858              #pragma omp section
859                {
860                   memcpy(dst_info->planes[0].ptr + (step[0] * 2),
861                          src_info->planes[0].ptr + (step[0] * 2),
862                          step[0]);
863                }
864              #pragma omp section
865                {
866                   memcpy(dst_info->planes[0].ptr + (step[0] * 3),
867                          src_info->planes[0].ptr + (step[0] * 3),
868                          step[1]);
869                }
870           }
871      }
872    else
873      {
874         memcpy(dst_info->planes[0].ptr, src_info->planes[0].ptr, src_info->planes[0].size);
875      }
876
877 #else /* HAVE_LIBGOMP */
878    memcpy(dst_info->planes[0].ptr, src_info->planes[0].ptr, src_info->planes[0].size);
879 #endif /* end of HAVE_LIBGOMP */
880 }
881
882 static void
883 _e_rdp_backup_buffer_create(E_Rdp_Output *output, tbm_surface_h src_tbm_surface, tbm_surface_info_s *src_info)
884 {
885    tbm_surface_h new_tsurface = NULL;
886    tbm_surface_info_s info;
887    int ret = TBM_SURFACE_ERROR_NONE;
888
889     new_tsurface = tbm_surface_create(src_info->width, src_info->height, src_info->format);
890     if (!new_tsurface)
891       {
892          ERR("tbm_surface_create failed");
893          return;
894       }
895
896    ret = tbm_surface_map(new_tsurface, TBM_SURF_OPTION_WRITE, &info);
897    if (ret != TBM_SURFACE_ERROR_NONE)
898      {
899         ERR("tbm_surface_map failed");
900         tbm_surface_destroy(new_tsurface);
901         return;
902      }
903
904    _e_rdp_tbm_surface_copy(src_tbm_surface, src_info, new_tsurface, &info);
905
906    tbm_surface_unmap(new_tsurface);
907
908    if (output->backup_tbm_surface)
909      tbm_surface_destroy(output->backup_tbm_surface);
910    output->backup_tbm_surface = new_tsurface;
911 }
912
913 static pixman_image_t *
914 _e_rdp_pixman_output_image_get_all(E_Rdp_Output *output, Eina_List *visible_list, E_Hwc_Window *hwc_window_cursor, int e_output_w, int e_output_h)
915 {
916    tbm_surface_h tbm_surface = NULL;
917    tbm_surface_info_s info;
918    pixman_image_t *pix_surface = NULL;
919    pixman_format_code_t pix_format = 0;
920    E_Hwc *hwc = NULL;
921    E_Hwc_Window *hwc_window = NULL;
922    Eina_Bool target_window = EINA_TRUE;
923    Eina_List *l;
924    int err;
925
926    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
927    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output, NULL);
928    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output->hwc, NULL);
929
930    hwc = output->primary_output->hwc;
931
932    tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0x00000000);
933    if (tbm_surface == NULL)
934      {
935         ERR("create tbm surface failed");
936         output->prepare_tbm_surface = NULL;
937         return NULL;
938      }
939
940    err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &info);
941    if (err)
942      {
943         ERR("tbm_surface_map failed");
944         tbm_surface_destroy(tbm_surface);
945         output->prepare_tbm_surface = NULL;
946         return NULL;
947      }
948
949    pix_format = _e_rdp_pixman_format_get(info.format);
950    if (pix_format == 0)
951      {
952         ERR("not supported format");
953         goto fail;
954      }
955
956    pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
957    if (pix_surface == NULL)
958      {
959         ERR("create pixman image failed");
960         goto fail;
961      }
962
963    EINA_LIST_FOREACH(visible_list, l, hwc_window)
964      {
965         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
966           {
967              if (target_window)
968                {
969                   target_window = EINA_FALSE;
970                   _e_rdp_pixman_output_image_composite(output, (E_Hwc_Window *)hwc->target_hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
971                }
972              continue;
973           }
974
975         _e_rdp_pixman_output_image_composite(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
976      }
977
978    if (output->refresh_count == 0)
979      _e_rdp_backup_buffer_create(output, tbm_surface, &info);
980
981    if (hwc_window_cursor != NULL)
982      _e_rdp_pixman_output_image_composite_cursor(output, hwc_window_cursor, pix_surface, info.width, info.height, e_output_w, e_output_h);
983
984    tbm_surface_unmap(tbm_surface);
985
986    output->prepare_tbm_surface = tbm_surface;
987
988    return pix_surface;
989
990 fail:
991    tbm_surface_unmap(tbm_surface);
992    tbm_surface_destroy(tbm_surface);
993    output->prepare_tbm_surface = NULL;
994    return NULL;
995 }
996
997 static Eina_Bool
998 _e_rdp_pixman_output_image_erase_cursor(E_Rdp_Output *output)
999 {
1000    pixman_image_t *pix_backup = NULL;
1001    tbm_surface_info_s info, dst_info;
1002    pixman_format_code_t pix_format = 0;
1003    pixman_region32_t clip_region;
1004    pixman_transform_t t;
1005    struct pixman_f_transform ft;
1006    int err;
1007
1008    EINA_SAFETY_ON_NULL_RETURN_VAL(output->backup_tbm_surface, EINA_FALSE);
1009    EINA_SAFETY_ON_NULL_RETURN_VAL(output->showing_tbm_surface, EINA_FALSE);
1010    if (output->cursor_crop_dst.w == 0 && output->cursor_crop_dst.h == 0)
1011      return EINA_FALSE;
1012
1013    err = tbm_surface_map(output->showing_tbm_surface, TBM_SURF_OPTION_WRITE, &dst_info);
1014    if (err)
1015      {
1016         ERR("tbm_surface_map failed");
1017         return EINA_FALSE;
1018      }
1019
1020    err = tbm_surface_map(output->backup_tbm_surface, TBM_SURF_OPTION_READ, &info);
1021    if (err)
1022      {
1023         ERR("tbm_surface_map failed");
1024         tbm_surface_unmap(output->showing_tbm_surface);
1025         return EINA_FALSE;
1026      }
1027
1028    pix_format = _e_rdp_pixman_format_get(info.format);
1029    if (pix_format == 0)
1030      {
1031         ERR("not supported format");
1032         tbm_surface_unmap(output->showing_tbm_surface);
1033         tbm_surface_unmap(output->backup_tbm_surface);
1034         return EINA_FALSE;
1035      }
1036
1037    pix_backup = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
1038    if (pix_backup == NULL)
1039      {
1040         ERR("create pixman image failed");
1041         tbm_surface_unmap(output->showing_tbm_surface);
1042         tbm_surface_unmap(output->backup_tbm_surface);
1043         return EINA_FALSE;
1044      }
1045
1046    pixman_image_ref(output->showing_surface);
1047
1048    pixman_region32_init_rect(&clip_region, output->cursor_crop_dst.x, output->cursor_crop_dst.y, output->cursor_crop_dst.w, output->cursor_crop_dst.h);
1049    pixman_image_set_clip_region32(pix_backup, &clip_region);
1050    pixman_image_set_source_clipping(pix_backup, TRUE);
1051    pixman_image_set_has_client_clip (pix_backup, TRUE);
1052    pixman_f_transform_init_identity(&ft);
1053    pixman_f_transform_scale(&ft, NULL, 1, 1);
1054    pixman_f_transform_translate(&ft, NULL, 0, 0);
1055    pixman_transform_from_pixman_f_transform(&t, &ft);
1056    pixman_image_set_transform(pix_backup, &t);
1057    pixman_image_composite(PIXMAN_OP_OVER, pix_backup, NULL, output->showing_surface, 0, 0, 0, 0, 0, 0, output->w, output->h);
1058
1059    pixman_image_unref(pix_backup);
1060    pixman_image_unref(output->showing_surface);
1061    tbm_surface_unmap(output->showing_tbm_surface);
1062    tbm_surface_unmap(output->backup_tbm_surface);
1063
1064    return EINA_TRUE;
1065 }
1066
1067 static pixman_image_t *
1068 _e_rdp_pixman_output_image_get_cursor(E_Rdp_Output *output, E_Hwc_Window *hwc_window_cursor, int e_output_w, int e_output_h)
1069 {
1070    tbm_surface_h tbm_surface = NULL;
1071    tbm_surface_info_s src_info, info;
1072    pixman_image_t *pix_surface = NULL;
1073    pixman_format_code_t pix_format = 0;
1074    int err;
1075    Eina_Bool ret = EINA_FALSE;
1076
1077    if ((output->mouse_x == hwc_window_cursor->current.info.dst_pos.x) &&
1078        (output->mouse_y == hwc_window_cursor->current.info.dst_pos.y))
1079      {
1080 //        INF("same position. do not update. (%dx%d)", output->mouse_x, output->mouse_y);
1081         return NULL;
1082      }
1083
1084    if (_e_rdp_pixman_output_image_erase_cursor(output))
1085      {
1086         err = tbm_surface_map(output->showing_tbm_surface, TBM_SURF_OPTION_WRITE, &info);
1087         if (err)
1088           ERR("tbm_surface_map failed");
1089         else
1090           {
1091              ret = _e_rdp_pixman_output_image_composite_cursor(output, hwc_window_cursor, output->showing_surface, info.width, info.height, e_output_w, e_output_h);
1092              tbm_surface_unmap(output->showing_tbm_surface);
1093           }
1094
1095         if (ret == EINA_TRUE)
1096           {
1097              output->buffer_reuse = EINA_TRUE;
1098              pix_surface = output->showing_surface;
1099              output->prepare_tbm_surface = output->showing_tbm_surface;
1100           }
1101      }
1102
1103    if (!output->buffer_reuse)
1104      {
1105         err = tbm_surface_map(output->backup_tbm_surface, TBM_SURF_OPTION_READ, &src_info);
1106         if (err)
1107           {
1108              ERR("tbm_surface_map failed");
1109              return NULL;
1110           }
1111
1112         tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0x00000000);
1113         if (tbm_surface == NULL)
1114           {
1115              ERR("create tbm surface failed");
1116              output->prepare_tbm_surface = NULL;
1117              tbm_surface_unmap(output->backup_tbm_surface);
1118              return NULL;
1119           }
1120
1121        err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
1122        if (err)
1123          {
1124             ERR("tbm_surface_map failed");
1125             tbm_surface_destroy(tbm_surface);
1126             output->prepare_tbm_surface = NULL;
1127             tbm_surface_unmap(output->backup_tbm_surface);
1128             return NULL;
1129          }
1130
1131         _e_rdp_tbm_surface_copy(output->backup_tbm_surface, &src_info, tbm_surface, &info);
1132
1133         pix_format = _e_rdp_pixman_format_get(info.format);
1134         if (pix_format == 0)
1135           {
1136              ERR("not supported format");
1137              tbm_surface_unmap(tbm_surface);
1138              tbm_surface_destroy(tbm_surface);
1139              output->prepare_tbm_surface = NULL;
1140              return NULL;
1141           }
1142
1143         pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
1144         if (pix_surface == NULL)
1145           {
1146              ERR("create pixman image failed");
1147              tbm_surface_unmap(tbm_surface);
1148              tbm_surface_destroy(tbm_surface);
1149              output->prepare_tbm_surface = NULL;
1150              return NULL;
1151           }
1152
1153         _e_rdp_pixman_output_image_composite_cursor(output, hwc_window_cursor, pix_surface, info.width, info.height, e_output_w, e_output_h);
1154
1155         tbm_surface_unmap(tbm_surface);
1156         tbm_surface_unmap(output->backup_tbm_surface);
1157
1158         output->prepare_tbm_surface = tbm_surface;
1159      }
1160
1161    return pix_surface;
1162 }
1163
1164 static pixman_image_t *
1165 _e_rdp_pixman_output_image_get(E_Rdp_Output *output)
1166 {
1167    E_Output *e_output = NULL;
1168    E_Hwc *hwc = NULL;
1169    E_Hwc_Window *hwc_window = NULL;
1170    E_Hwc_Window *hwc_window_cursor = NULL;
1171    Eina_List *l;
1172    Eina_List *visible_list = NULL;
1173    int e_output_w, e_output_h;
1174    pixman_image_t *pix_surface = NULL;
1175
1176    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1177
1178    e_output = output->primary_output;
1179    EINA_SAFETY_ON_NULL_RETURN_VAL(e_output, NULL);
1180
1181    hwc = e_output->hwc;
1182    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1183
1184    e_output_w = e_output->config.mode.w;
1185    e_output_h = e_output->config.mode.h;
1186
1187    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
1188      {
1189         if (!hwc_window) continue;
1190         if (hwc_window->is_target) continue;
1191         if (hwc_window->is_video) continue;
1192         if (hwc_window->state == E_HWC_WINDOW_STATE_NONE || hwc_window->zpos == -999) continue;
1193
1194         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
1195           {
1196              visible_list = eina_list_append(visible_list, hwc_window);
1197              continue;
1198           }
1199
1200         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE)
1201           visible_list = eina_list_append(visible_list, hwc_window);
1202
1203         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR)
1204           {
1205              if (hwc_window->cursor.buffer)
1206                {
1207                   hwc_window_cursor = hwc_window;
1208                }
1209           }
1210      }
1211
1212    if (eina_list_count(visible_list) == 0)
1213      {
1214         ERR("no visible hwc_window for capture");
1215         return pix_surface;
1216      }
1217    visible_list = eina_list_sort(visible_list, eina_list_count(visible_list), _e_rdp_cb_hwc_window_sort);
1218
1219    if (output->buffer_changed)
1220      {
1221         pix_surface = _e_rdp_pixman_output_image_get_all(output, visible_list, hwc_window_cursor, e_output_w, e_output_h);
1222      }
1223    else if ((output->mouse_moved) && (hwc_window_cursor != NULL))
1224      {
1225         pix_surface = _e_rdp_pixman_output_image_get_cursor(output, hwc_window_cursor, e_output_w, e_output_h);
1226      }
1227
1228    return pix_surface;
1229 }
1230
1231 static Eina_Bool
1232 _e_rdp_frame_timer(void *data)
1233 {
1234    E_Rdp_Output *output;
1235    pixman_image_t *pix_surface = NULL;
1236    pixman_box32_t box;
1237    pixman_region32_t damage;
1238    E_Rdp_Peer_Item *rdp_peer, *tmp;
1239    freerdp_peer *client = NULL;
1240
1241    EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
1242
1243    output = (E_Rdp_Output *)data;
1244
1245    output->refresh_count--;
1246    if (output->refresh_count < 0)
1247      {
1248         output->frame_timer = NULL;
1249         output->refresh_count = 0;
1250         output->mouse_moved = EINA_FALSE;
1251         output->buffer_changed = EINA_FALSE;
1252
1253         return ECORE_CALLBACK_CANCEL;
1254      }
1255
1256 #if RDP_DEBUG
1257    double start, end_capture, end_refresh;
1258    start = ecore_time_get();
1259 #endif
1260
1261    pix_surface = _e_rdp_pixman_output_image_get(output);
1262    if (pix_surface == NULL)
1263      {
1264 #if RDP_DEBUG
1265         end_capture = ecore_time_get();
1266         INF("pixman capture time (no result): %.1f ms", (end_capture - start) * 1000);
1267 #endif
1268         return ECORE_CALLBACK_RENEW;
1269      }
1270
1271 #if RDP_DEBUG
1272    end_capture = ecore_time_get();
1273    INF("pixman capture time: %.1f ms", (end_capture - start) * 1000);
1274 #endif
1275
1276    if (output->buffer_reuse)
1277      {
1278         box.x1 = output->cursor_damage_rect.x;
1279         box.y1 = output->cursor_damage_rect.y;
1280         box.x2 = output->cursor_damage_rect.x + output->cursor_damage_rect.w;
1281         box.y2 = output->cursor_damage_rect.y + output->cursor_damage_rect.h;
1282      }
1283    else
1284      {
1285         box.x1 = 0;
1286         box.y1 = 0;
1287         box.x2 = output->w;
1288         box.y2 = output->h;
1289      }
1290
1291    pixman_region32_init_with_extents(&damage, &box);
1292
1293    wl_list_for_each_safe(rdp_peer, tmp, &output->peers, link)
1294      {
1295         client = rdp_peer->peer;
1296         if (!client)
1297           continue;
1298
1299         if ((rdp_peer->flags & RDP_PEER_ACTIVATED) &&
1300             (rdp_peer->flags & RDP_PEER_OUTPUT_ENABLED))
1301           e_rdp_peer_refresh_region(&damage, client, pix_surface);
1302      }
1303    pixman_region32_fini(&damage);
1304
1305    if (!output->buffer_reuse)
1306      {
1307         if (output->showing_surface)
1308           pixman_image_unref(output->showing_surface);
1309         output->showing_surface = pix_surface;
1310
1311         if (output->showing_tbm_surface)
1312           tbm_surface_destroy(output->showing_tbm_surface);
1313
1314      }
1315    output->showing_tbm_surface = output->prepare_tbm_surface;
1316    output->prepare_tbm_surface = NULL;
1317    output->buffer_reuse = EINA_FALSE;
1318
1319 #if RDP_DEBUG
1320    end_refresh = ecore_time_get();
1321    INF("pixman refresh time: %.1f ms", (end_refresh - end_capture) * 1000);
1322 #endif
1323
1324    return ECORE_CALLBACK_RENEW;
1325 }
1326
1327 static void
1328 _e_rdp_free_keyfile(E_Rdp_Backend *b, rdpSettings *settings)
1329 {
1330    if (b->rdp_key)
1331      free(settings->RdpKeyFile);
1332    if (b->tls_enabled)
1333      {
1334         free(settings->CertificateFile);
1335         free(settings->PrivateKeyFile);
1336      }
1337 }
1338
1339 static Eina_Bool
1340 _e_rdp_cb_client_buffer_change(void *data, int type, void *event)
1341 {
1342    E_Rdp_Backend *b = NULL;
1343    E_Rdp_Output *output = NULL;
1344    E_Event_Client *ev = event;
1345    E_Client *ec = NULL;
1346    E_Hwc *hwc = NULL;
1347    E_Hwc_Window *hwc_window = NULL;
1348    Eina_List *l;
1349    Eina_Bool find = EINA_FALSE;
1350
1351    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1352    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
1353
1354    ec = ev->ec;
1355    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), ECORE_CALLBACK_PASS_ON);
1356    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, ECORE_CALLBACK_PASS_ON);
1357
1358    b = g_rdp_backend;
1359    EINA_SAFETY_ON_NULL_RETURN_VAL(b, ECORE_CALLBACK_PASS_ON);
1360    EINA_SAFETY_ON_NULL_RETURN_VAL(b->output, ECORE_CALLBACK_PASS_ON);
1361    output = b->output;
1362    if (b->client_count == 0)
1363      return ECORE_CALLBACK_PASS_ON;
1364
1365    EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_PASS_ON);
1366    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output, ECORE_CALLBACK_PASS_ON);
1367    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output->hwc, ECORE_CALLBACK_PASS_ON);
1368
1369    hwc = output->primary_output->hwc;
1370
1371    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
1372      {
1373         if (!hwc_window) continue;
1374         if (hwc_window->is_target) continue;
1375         if (hwc_window->is_video) continue;
1376         if (hwc_window->state == E_HWC_WINDOW_STATE_NONE || hwc_window->zpos == -999) continue;
1377
1378         if (hwc_window == ec->hwc_window)
1379           {
1380              find = EINA_TRUE;
1381              break;
1382           }
1383      }
1384
1385    if (find == EINA_FALSE)
1386         return ECORE_CALLBACK_PASS_ON;
1387
1388    if (!output->frame_timer)
1389      {
1390         output->refresh_count = 5;
1391         output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
1392      }
1393    else
1394      output->refresh_count = 5;
1395    output->buffer_changed = EINA_TRUE;
1396
1397    return ECORE_CALLBACK_PASS_ON;
1398 }
1399
1400 static Eina_Bool
1401 _e_rdp_cb_client_uniconify(void *data, int type, void *event)
1402 {
1403    E_Rdp_Backend *b = NULL;
1404    E_Rdp_Output *output = NULL;
1405    E_Event_Client *ev = event;
1406    E_Client *ec = NULL;
1407    E_Hwc *hwc = NULL;
1408    E_Hwc_Window *hwc_window = NULL;
1409    Eina_List *l;
1410    Eina_Bool find = EINA_FALSE;
1411
1412    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1413    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
1414
1415    ec = ev->ec;
1416    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), ECORE_CALLBACK_PASS_ON);
1417    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, ECORE_CALLBACK_PASS_ON);
1418
1419    b = g_rdp_backend;
1420    EINA_SAFETY_ON_NULL_RETURN_VAL(b, ECORE_CALLBACK_PASS_ON);
1421    EINA_SAFETY_ON_NULL_RETURN_VAL(b->output, ECORE_CALLBACK_PASS_ON);
1422    output = b->output;
1423    if (b->client_count == 0)
1424      return ECORE_CALLBACK_PASS_ON;
1425
1426    EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_PASS_ON);
1427    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output, ECORE_CALLBACK_PASS_ON);
1428    EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output->hwc, ECORE_CALLBACK_PASS_ON);
1429
1430    hwc = output->primary_output->hwc;
1431
1432    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
1433      {
1434         if (!hwc_window) continue;
1435         if (hwc_window->is_target) continue;
1436         if (hwc_window->is_video) continue;
1437
1438         if (hwc_window == ec->hwc_window)
1439           {
1440              find = EINA_TRUE;
1441              break;
1442           }
1443      }
1444
1445    if (find == EINA_FALSE)
1446      return ECORE_CALLBACK_PASS_ON;
1447
1448    if (!output->frame_timer)
1449      output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
1450    output->refresh_count = 5;
1451    output->buffer_changed = EINA_TRUE;
1452
1453    return ECORE_CALLBACK_PASS_ON;
1454 }
1455
1456 static void
1457 _e_rdp_cb_pointer_mouse_move(void *data, E_Pointer *ptr)
1458 {
1459    E_Rdp_Backend *b = NULL;
1460    E_Rdp_Output *output = NULL;
1461
1462    EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ptr)));
1463    EINA_SAFETY_ON_FALSE_RETURN(e_comp->pointer);
1464
1465    b = g_rdp_backend;
1466    EINA_SAFETY_ON_NULL_RETURN(b);
1467    EINA_SAFETY_ON_NULL_RETURN(b->output);
1468    output = b->output;
1469
1470    if (b->client_count == 0)
1471      return;
1472
1473    if (!output->frame_timer)
1474      {
1475         output->refresh_count = 5;
1476         output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
1477      }
1478    else
1479      output->refresh_count = 5;
1480    output->mouse_moved = EINA_TRUE;
1481 }
1482
1483 static double
1484 _e_rdp_refresh_time_set(uint32_t w, uint32_t h)
1485 {
1486    uint32_t temp;
1487    if (h > w)
1488      {
1489         temp = h;
1490         h = w;
1491         w = temp;
1492      }
1493    if (w >= 1400 || h >= 900)
1494      return FHD_TIME;
1495    else if (w >= 1024 || h >= 720)
1496      return HD_TIME;
1497    else if (w >= 800 || h >= 600)
1498      return SVGA_TIME;
1499    else //640x480
1500      return VGA_TIME;
1501 }
1502
1503 static BOOL
1504 e_rdp_peer_capabilities(freerdp_peer *client)
1505 {
1506    return TRUE;
1507 }
1508
1509 static BOOL
1510 e_rdp_peer_post_connect(freerdp_peer *client)
1511 {
1512    return TRUE;
1513 }
1514
1515 static BOOL
1516 e_rdp_peer_activate(freerdp_peer *client)
1517 {
1518    E_Rdp_Peer_Context *peerCtx;
1519    E_Rdp_Backend *b;
1520    E_Rdp_Output *output;
1521    rdpSettings *settings;
1522    rdpPointerUpdate *pointer;
1523    E_Rdp_Peer_Item *peersItem;
1524    pixman_box32_t box;
1525    pixman_region32_t damage;
1526    POINTER_SYSTEM_UPDATE pointer_system;
1527    tbm_surface_h tbm_surface = NULL;
1528    pixman_image_t *pix_surface = NULL;
1529
1530    EINA_SAFETY_ON_NULL_RETURN_VAL(client, FALSE);
1531    EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, FALSE);
1532    EINA_SAFETY_ON_NULL_RETURN_VAL(client->settings, FALSE);
1533
1534    peerCtx = (E_Rdp_Peer_Context *)client->context;
1535    EINA_SAFETY_ON_NULL_RETURN_VAL(peerCtx, FALSE);
1536
1537    b = peerCtx->rdpBackend;
1538    EINA_SAFETY_ON_NULL_RETURN_VAL(b, FALSE);
1539
1540    peersItem = &peerCtx->item;
1541    EINA_SAFETY_ON_NULL_RETURN_VAL(peersItem, FALSE);
1542
1543    output = b->output;
1544    settings = client->settings;
1545
1546    if (!settings->SurfaceCommandsEnabled)
1547      {
1548         ERR("client doesn't support required SurfaceCommands");
1549         return FALSE;
1550      }
1551
1552    if (b->force_no_compression && settings->CompressionEnabled)
1553      {
1554         ERR("Forcing compression off");
1555         settings->CompressionEnabled = FALSE;
1556      }
1557
1558    if (output->w != settings->DesktopWidth || output->h != settings->DesktopHeight)
1559      {
1560         if (b->no_clients_resize)
1561           {
1562              /* RDP peers don't dictate their resolution to e */
1563              if (!settings->DesktopResize)
1564                {
1565                   /* peer does not support desktop resize */
1566                   ERR("%s: client doesn't support resizing, closing connection", __FUNCTION__);
1567                   return FALSE;
1568                }
1569              else
1570                {
1571                   settings->DesktopWidth = output->w;
1572                   settings->DesktopHeight = output->h;
1573                   client->update->DesktopResize(client->context);
1574                }
1575           }
1576         else
1577           {
1578              output->w = settings->DesktopWidth;
1579              output->h = settings->DesktopHeight;
1580           }
1581      }
1582
1583    output->mouse_scale_w = (float)output->primary_w / output->w;
1584    output->mouse_scale_h = (float)output->primary_h / output->h;
1585
1586    rfx_context_reset(peerCtx->rfx_context, output->w, output->h);
1587    nsc_context_reset(peerCtx->nsc_context, output->w, output->h);
1588    if (peersItem->flags & RDP_PEER_ACTIVATED)
1589      return TRUE;
1590
1591    /* when here it's the first reactivation, we need to setup a little more */
1592    DBG("kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x kbd_functionKeys:0x%x",
1593        settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType, settings->KeyboardFunctionKey);
1594
1595    peersItem->flags |= RDP_PEER_ACTIVATED;
1596    b->client_count++;
1597
1598    /* disable pointer on the client side */
1599    pointer = client->update->pointer;
1600    pointer_system.type = SYSPTR_NULL;
1601    pointer->PointerSystem(client->context, &pointer_system);
1602
1603    if (b->client_count == 1)
1604      {
1605         tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0xFFFFCCFF);
1606         if (tbm_surface == NULL)
1607           {
1608              ERR("create sample tbm surface failed");
1609              return TRUE;
1610           }
1611         pix_surface = _e_rdp_pixman_image_create(tbm_surface);
1612         if (pix_surface == NULL)
1613           {
1614              ERR("create sample pixman failed");
1615              tbm_surface_destroy(tbm_surface);
1616              return TRUE;
1617           }
1618
1619         /* sends a full refresh */
1620         box.x1 = 0;
1621         box.y1 = 0;
1622         box.x2 = output->w;
1623         box.y2 = output->h;
1624         pixman_region32_init_with_extents(&damage, &box);
1625
1626         e_rdp_peer_refresh_region(&damage, client, pix_surface);
1627
1628         pixman_region32_fini(&damage);
1629
1630         output->showing_surface = pix_surface;
1631         output->showing_tbm_surface = tbm_surface;
1632
1633         if (output->frame_timer != NULL)
1634           ecore_timer_del(output->frame_timer);
1635         output->refresh_time = _e_rdp_refresh_time_set(output->w, output->h);
1636         output->refresh_count = 5;
1637         output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
1638         output->buffer_changed = EINA_TRUE;
1639
1640         e_video_debug_display_primary_plane_set(EINA_TRUE);
1641      }
1642    else
1643      {
1644         output->refresh_count = 5;
1645         output->buffer_changed = EINA_TRUE;
1646      }
1647
1648    return TRUE;
1649 }
1650
1651 static BOOL
1652 e_rdp_suppress_output(rdpContext *context, BYTE allow, const RECTANGLE_16 *area)
1653 {
1654    E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)context;
1655
1656    if (allow)
1657      peerContext->item.flags |= RDP_PEER_OUTPUT_ENABLED;
1658    else
1659      peerContext->item.flags &= (~RDP_PEER_OUTPUT_ENABLED);
1660
1661    return TRUE;
1662 }
1663
1664 static BOOL
1665 e_rdp_input_synchronize_event(rdpInput *input, UINT32 flags)
1666 {
1667    E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)input->context;
1668    E_Rdp_Output *output = peerContext->rdpBackend->output;
1669    E_Rdp_Backend *b = NULL;
1670
1671    DBG("e_rdp_input_synchronize_event");
1672
1673    b = g_rdp_backend;
1674    EINA_SAFETY_ON_NULL_RETURN_VAL(b, FALSE);
1675    EINA_SAFETY_ON_NULL_RETURN_VAL(b->output, FALSE);
1676
1677    if (output != b->output)
1678      return FALSE;
1679
1680    if (b->client_count == 0)
1681      return TRUE;
1682
1683    if (!output->frame_timer)
1684      {
1685         output->refresh_count = 5;
1686         output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
1687      }
1688    else
1689      output->refresh_count = 5;
1690    output->buffer_changed = EINA_TRUE;
1691
1692    return TRUE;
1693 }
1694
1695 static BOOL
1696 e_rdp_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1697 {
1698    int e_output_w, e_output_h;
1699    int move_x = 0, move_y = 0;
1700    int motionless = 0;
1701    uint32_t button = 0;
1702    uint32_t state = 0;
1703
1704    E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)input->context;
1705    E_Rdp_Output *output = peerContext->rdpBackend->output;
1706    E_Output *e_output = output->primary_output;
1707    e_output_w = e_output->config.mode.w;
1708    e_output_h = e_output->config.mode.h;
1709    motionless = peerContext->rdpBackend->motionless;
1710
1711    if (flags & PTR_FLAGS_MOVE && !motionless)
1712      {
1713         if (x < e_output_w && y < e_output_h)
1714           {
1715              state = E_INFO_EVENT_STATE_MOTION;
1716              move_x = (int)((int)(x - output->prev_x) * output->mouse_scale_w);
1717              move_y = (int)((int)(y - output->prev_y) * output->mouse_scale_h);
1718              output->prev_x = x;
1719              output->prev_y = y;
1720           }
1721      }
1722
1723    if (flags & PTR_FLAGS_BUTTON1)
1724      button = BTN_LEFT;
1725    else if (flags & PTR_FLAGS_BUTTON2)
1726      button = BTN_RIGHT;
1727    else if (flags & PTR_FLAGS_BUTTON3)
1728      button = BTN_MIDDLE;
1729
1730    if (button)
1731      state = (flags & PTR_FLAGS_DOWN) ? E_INFO_EVENT_STATE_PRESS : E_INFO_EVENT_STATE_RELEASE;
1732
1733    if (flags & PTR_FLAGS_WHEEL)
1734      {
1735         double value;
1736         value = (flags & 0xff) / 120.0;
1737
1738         button = E_INFO_BUTTON_WHEEL;
1739         state = E_INFO_EVENT_STATE_MOTION;
1740
1741         if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
1742           value = -value;
1743
1744         move_x = (int)value;
1745      }
1746
1747    if (!motionless)
1748      e_info_server_input_mousegen(button, move_x, move_y, state);
1749    else
1750      {
1751         if (!(flags & PTR_FLAGS_MOVE))
1752           {
1753              if (x < e_output_w && y < e_output_h)
1754                {
1755                   move_x = (int)((int)(x - output->prev_x) * output->mouse_scale_w);
1756                   move_y = (int)((int)(y - output->prev_y) * output->mouse_scale_h);
1757                   output->prev_x = x;
1758                   output->prev_y = y;
1759                }
1760
1761              e_info_server_input_mousegen(0, move_x, move_y, E_INFO_EVENT_STATE_MOTION);
1762              e_info_server_input_mousegen(button, move_x, move_y, state);
1763           }
1764      }
1765
1766    return TRUE;
1767 }
1768
1769 static BOOL
1770 e_rdp_extended_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1771 {
1772    //To do
1773    DBG("e_rdp_extended_mouse_event");
1774    return TRUE;
1775 }
1776
1777 static BOOL
1778 e_rdp_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1779 {
1780    uint32_t full_code;
1781    int notify = 0;
1782    int key_state = 0;
1783    char name[16] = {0,};
1784
1785    E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)input->context;
1786
1787    if (!(peerContext->item.flags & RDP_PEER_ACTIVATED))
1788      return TRUE;
1789
1790    if (flags & KBD_FLAGS_DOWN)
1791      {
1792         key_state = E_INFO_EVENT_STATE_PRESS;
1793         notify = 1;
1794      }
1795    else if (flags & KBD_FLAGS_RELEASE)
1796      {
1797         key_state = E_INFO_EVENT_STATE_RELEASE;
1798         notify = 1;
1799      }
1800
1801    if (notify)
1802      {
1803         full_code = code;
1804         DBG("rdp key kernel fullcode = %d", full_code);
1805
1806         // Todo. check extended role
1807
1808         e_info_server_input_keygen(name, full_code + 8, key_state);
1809      }
1810
1811    return TRUE;
1812 }
1813
1814 static BOOL
1815 e_rdp_input_unicode_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1816 {
1817    DBG("Client sent a unicode keyboard event (flags:0x%X code:0x%X)", flags, code);
1818    return TRUE;
1819 }
1820
1821 static int
1822 e_rdp_client_activity(int fd, uint32_t mask, void *data)
1823 {
1824    freerdp_peer *client = (freerdp_peer *)data;
1825    E_Rdp_Peer_Context *peerCtx;
1826    E_Rdp_Backend *b;
1827    E_Rdp_Output *output;
1828
1829    EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1830    EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, 0);
1831
1832    if (client->CheckFileDescriptor(client))
1833      {
1834 //        DBG("enable client activity %p", client);
1835         return 0;
1836      }
1837
1838    INF("unable to checkDescriptor for %p", client);
1839    peerCtx = (E_Rdp_Peer_Context *)client->context;
1840    EINA_SAFETY_ON_NULL_GOTO(peerCtx, out_clean);
1841
1842    b = peerCtx->rdpBackend;
1843    EINA_SAFETY_ON_NULL_GOTO(b, out_clean);
1844
1845    if (peerCtx->item.flags & RDP_PEER_ACTIVATED)
1846      b->client_count--;
1847
1848    output = b->output;
1849    if (output && b->client_count == 0)
1850      {
1851         if (output->frame_timer)
1852           {
1853              ecore_timer_del(output->frame_timer);
1854              output->frame_timer = NULL;
1855           }
1856         if (output->showing_surface)
1857           {
1858              pixman_image_unref(output->showing_surface);
1859              output->showing_surface = NULL;
1860           }
1861         if (output->prepare_tbm_surface)
1862           {
1863              tbm_surface_destroy(output->prepare_tbm_surface);
1864              output->prepare_tbm_surface = NULL;
1865           }
1866         if (output->showing_tbm_surface)
1867           {
1868              tbm_surface_destroy(output->showing_tbm_surface);
1869              output->showing_tbm_surface = NULL;
1870           }
1871         if (output->backup_tbm_surface)
1872           {
1873              tbm_surface_destroy(output->backup_tbm_surface);
1874              output->backup_tbm_surface = NULL;
1875           }
1876
1877         e_video_debug_display_primary_plane_set(EINA_FALSE);
1878      }
1879
1880 out_clean:
1881    freerdp_peer_context_free(client);
1882    freerdp_peer_free(client);
1883    return 0;
1884 }
1885
1886 static BOOL
1887 e_rdp_peer_context_new(freerdp_peer *client, E_Rdp_Peer_Context *context)
1888 {
1889    context->item.peer = client;
1890    context->item.flags = RDP_PEER_OUTPUT_ENABLED;
1891
1892    context->rfx_context = rfx_context_new(TRUE);
1893    if (!context->rfx_context)
1894      return FALSE;
1895
1896    context->rfx_context->mode = RLGR3;
1897    context->rfx_context->width = client->settings->DesktopWidth;
1898    context->rfx_context->height = client->settings->DesktopHeight;
1899    rfx_context_set_pixel_format(context->rfx_context, DEFAULT_PIXEL_FORMAT);
1900
1901    context->nsc_context = nsc_context_new();
1902    if (!context->nsc_context)
1903      goto out_error_nsc;
1904
1905    nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, DEFAULT_PIXEL_FORMAT);
1906    context->encode_stream = Stream_New(NULL, 65536);
1907    if (!context->encode_stream)
1908      goto out_error_stream;
1909
1910    return TRUE;
1911
1912 out_error_nsc:
1913    rfx_context_free(context->rfx_context);
1914 out_error_stream:
1915    nsc_context_free(context->nsc_context);
1916    return FALSE;
1917 }
1918
1919 static void
1920 e_rdp_peer_context_free(freerdp_peer *client, E_Rdp_Peer_Context *context)
1921 {
1922    int i;
1923    if (!context)
1924      return;
1925
1926    wl_list_remove(&context->item.link);
1927    for (i = 0; i < MAX_FREERDP_FDS; i++)
1928      {
1929         if (context->events[i])
1930           wl_event_source_remove(context->events[i]);
1931      }
1932
1933    Stream_Free(context->encode_stream, TRUE);
1934    nsc_context_free(context->nsc_context);
1935    rfx_context_free(context->rfx_context);
1936    free(context->rfx_rects);
1937 }
1938
1939
1940 static int
1941 e_rdp_peer_init(freerdp_peer *client, E_Rdp_Backend *b)
1942 {
1943    int rcount = 0;
1944    void *rfds[MAX_FREERDP_FDS];
1945    int i, fd;
1946    struct wl_event_loop *loop;
1947    char *device_name = NULL, *result = NULL;
1948    unsigned int device_type = 0x0;
1949    rdpSettings *settings;
1950    rdpInput *input;
1951    E_Rdp_Peer_Context *peerCtx;
1952
1953    client->ContextSize = sizeof(E_Rdp_Peer_Context);
1954    client->ContextNew = (psPeerContextNew)e_rdp_peer_context_new;
1955    client->ContextFree = (psPeerContextFree)e_rdp_peer_context_free;
1956    freerdp_peer_context_new(client);
1957
1958    peerCtx = (E_Rdp_Peer_Context *)client->context;
1959    peerCtx->rdpBackend = b;
1960
1961    settings = client->settings;
1962
1963    if (b->rdp_key)
1964      settings->RdpKeyFile = strdup(b->rdp_key);
1965
1966    if (b->tls_enabled)
1967      {
1968         settings->CertificateFile = strdup(b->server_cert);
1969         settings->PrivateKeyFile = strdup(b->server_key);
1970      }
1971    else
1972      {
1973         settings->TlsSecurity = FALSE;
1974      }
1975    settings->NlaSecurity = FALSE;
1976
1977    if (!client->Initialize(client))
1978      {
1979         ERR("peer initialization failed");
1980         _e_rdp_free_keyfile(b, settings);
1981         return -1;
1982      }
1983
1984    settings->OsMajorType = OSMAJORTYPE_UNIX;
1985    settings->OsMinorType = OSMINORTYPE_NATIVE_WAYLAND;
1986    settings->ColorDepth = 32;
1987    settings->RefreshRect = TRUE;
1988    settings->RemoteFxCodec = TRUE;
1989    settings->NSCodec = TRUE;
1990    settings->FrameMarkerCommandEnabled = TRUE;
1991    settings->SurfaceFrameMarkerEnabled = TRUE;
1992
1993    client->Capabilities = e_rdp_peer_capabilities;
1994    client->PostConnect = e_rdp_peer_post_connect;
1995    client->Activate = e_rdp_peer_activate;
1996
1997    client->update->SuppressOutput = (pSuppressOutput)e_rdp_suppress_output;
1998
1999    device_type = E_INPUT_SEAT_POINTER | E_INPUT_SEAT_TOUCH | E_INPUT_SEAT_KEYBOARD;
2000    device_name = E_RDP_DEVICE_NAME;
2001    result = e_info_server_input_init_device(device_type, device_name);
2002
2003    if (e_util_strcmp(result, E_INFO_INPUT_RESULT_NONE))
2004      {
2005         e_info_server_input_deinit_device();
2006         result = e_info_server_input_init_device(device_type, device_name);
2007      }
2008
2009    DBG("rdp peer init | init input device | result = %s", result);
2010
2011    input = client->input;
2012    input->SynchronizeEvent = e_rdp_input_synchronize_event;
2013    input->MouseEvent = e_rdp_mouse_event;
2014    input->ExtendedMouseEvent = e_rdp_extended_mouse_event;
2015    input->KeyboardEvent = e_rdp_input_keyboard_event;
2016    input->UnicodeKeyboardEvent = e_rdp_input_unicode_keyboard_event;
2017
2018    if (!client->GetFileDescriptor(client, rfds, &rcount))
2019      {
2020         ERR("unable to retrieve client fds");
2021         goto error_initialize;
2022      }
2023
2024    if (rcount > MAX_FREERDP_FDS)
2025      {
2026         ERR("check fds max count. count:%d, max:%d", rcount, MAX_FREERDP_FDS);
2027         goto error_initialize;
2028      }
2029
2030    loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
2031    for (i = 0; i < rcount; i++)
2032      {
2033         fd = (int)(long)(rfds[i]);
2034
2035         peerCtx->events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_client_activity, client);
2036      }
2037    for ( ; i < MAX_FREERDP_FDS; i++)
2038      peerCtx->events[i] = 0;
2039
2040    wl_list_insert(&b->output->peers, &peerCtx->item.link);
2041    return 0;
2042
2043 error_initialize:
2044    _e_rdp_free_keyfile(b, settings);
2045    client->Close(client);
2046    return -1;
2047 }
2048
2049 static BOOL
2050 e_rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
2051 {
2052    E_Rdp_Backend *b = (E_Rdp_Backend *)instance->param4;
2053
2054    if (e_rdp_peer_init(client, b) < 0)
2055      {
2056         ERR("error when treating incoming peer");
2057         return FALSE;
2058      }
2059
2060    return TRUE;
2061 }
2062
2063 static int
2064 e_rdp_listener_activity(int fd, uint32_t mask, void *data)
2065 {
2066    freerdp_listener* instance = (freerdp_listener *)data;
2067
2068    if (!(mask & WL_EVENT_READABLE))
2069      return 0;
2070
2071    if (!instance->CheckFileDescriptor(instance))
2072      {
2073         ERR("failed to check FreeRDP file descriptor");
2074         return -1;
2075      }
2076
2077    return 0;
2078 }
2079
2080 static Eina_Bool
2081 e_rdp_implant_listener(E_Rdp_Backend *b, freerdp_listener *instance)
2082 {
2083    int i, fd;
2084    int rcount = 0;
2085    void* rfds[MAX_FREERDP_FDS];
2086    struct wl_event_loop *loop;
2087
2088    if (!instance->GetFileDescriptor(instance, rfds, &rcount))
2089      {
2090         ERR("Failed to get FreeRDP file descriptor");
2091         return EINA_FALSE;
2092      }
2093
2094    loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
2095    for (i = 0; i < rcount; i++)
2096      {
2097         fd = (int)(long)(rfds[i]);
2098         b->listener_events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_listener_activity, instance);
2099      }
2100
2101    for ( ; i < MAX_FREERDP_FDS; i++)
2102      b->listener_events[i] = 0;
2103
2104    return EINA_TRUE;
2105 }
2106
2107 static void
2108 e_rdp_output_destroy(E_Rdp_Output *output)
2109 {
2110    EINA_SAFETY_ON_NULL_RETURN(output);
2111
2112    if (output->showing_surface)
2113      pixman_image_unref(output->showing_surface);
2114    if (output->prepare_tbm_surface)
2115      tbm_surface_destroy(output->prepare_tbm_surface);
2116    if (output->showing_tbm_surface)
2117      tbm_surface_destroy(output->showing_tbm_surface);
2118    if (output->backup_tbm_surface)
2119      tbm_surface_destroy(output->backup_tbm_surface);
2120
2121    free(output);
2122 }
2123
2124 E_Rdp_Output *
2125 e_rdp_output_create(void)
2126 {
2127    E_Rdp_Output *output = NULL;
2128    Eina_List *l;
2129    E_Output_Mode *emode = NULL;
2130    Eina_Bool mode = EINA_FALSE;
2131
2132    output = E_NEW(E_Rdp_Output, 1);
2133    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2134
2135    output->primary_output = e_output_find_by_index(0);
2136
2137    EINA_LIST_FOREACH(output->primary_output->info.modes, l, emode)
2138      {
2139         if (emode->current)
2140           {
2141              output->primary_w = emode->w;
2142              output->primary_h = emode->h;
2143              output->w = emode->w / 2;
2144              output->h = emode->h / 2;
2145              mode = EINA_TRUE;
2146              break;
2147           }
2148      }
2149    if (mode == EINA_FALSE)
2150      {
2151         output->w = E_RDP_WIDTH;
2152         output->h = E_RDP_HEIGHT;
2153      }
2154
2155    output->prev_x = output->prev_y = 0;
2156
2157    wl_list_init(&output->peers);
2158
2159    return output;
2160 }
2161
2162 static void
2163 e_rdp_backend_destroy(void)
2164 {
2165    E_Rdp_Backend *b = NULL;
2166    E_Rdp_Peer_Item *rdp_peer, *tmp;
2167    Ecore_Event_Handler *h = NULL;
2168    int i;
2169
2170    b = g_rdp_backend;
2171    EINA_SAFETY_ON_NULL_RETURN(b);
2172
2173    if (pointer_hook)
2174      {
2175         e_pointer_hook_del(pointer_hook);
2176         pointer_hook = NULL;
2177      }
2178    if (b->handlers)
2179      {
2180         EINA_LIST_FREE(b->handlers, h)
2181           ecore_event_handler_del(h);
2182         b->handlers = NULL;
2183      }
2184
2185    if (b->output->frame_timer)
2186      {
2187         ecore_timer_del(b->output->frame_timer);
2188         b->output->frame_timer = NULL;
2189      }
2190
2191    wl_list_for_each_safe(rdp_peer, tmp, &b->output->peers, link)
2192      {
2193         freerdp_peer* client = rdp_peer->peer;
2194
2195         client->Disconnect(client);
2196         freerdp_peer_context_free(client);
2197         freerdp_peer_free(client);
2198      }
2199
2200    for (i = 0; i < MAX_FREERDP_FDS; i++)
2201      if (b->listener_events[i])
2202        wl_event_source_remove(b->listener_events[i]);
2203
2204    freerdp_listener_free(b->listener);
2205
2206    e_rdp_output_destroy(b->output);
2207
2208    if (b->rdp_key)
2209      free(b->rdp_key);
2210    if (b->tls_enabled)
2211      {
2212         free(b->server_cert);
2213         free(b->server_key);
2214      }
2215    free(b);
2216 }
2217
2218
2219 Eina_Bool
2220 e_rdp_backend_create(E_Rdp_Conf_Edd *config)
2221 {
2222    E_Rdp_Backend *b;
2223
2224    b = E_NEW(E_Rdp_Backend, 1);
2225    EINA_SAFETY_ON_NULL_RETURN_VAL(b, EINA_FALSE);
2226
2227    b->no_clients_resize = config->no_clients_resize;
2228    b->force_no_compression = config->force_no_compression;
2229    b->motionless = config->motionless;
2230
2231    if (config->rdp_key)
2232      {
2233         b->rdp_key = strdup(config->rdp_key);
2234         if (!b->rdp_key)
2235           goto err_config;
2236      }
2237
2238    /* activate TLS only if certificate/key are available */
2239    if (config->server_cert && config->server_key)
2240      {
2241         DBG("TLS support activated");
2242         b->server_cert = strdup(config->server_cert);
2243         b->server_key = strdup(config->server_key);
2244         if (!b->server_cert || !b->server_key)
2245           goto err_config;
2246         b->tls_enabled = 1;
2247      }
2248
2249    b->output = e_rdp_output_create();
2250    if (!b->output)
2251      {
2252         ERR("output create failed");
2253         goto err_output_create;
2254      }
2255
2256    b->listener = freerdp_listener_new();
2257    b->listener->PeerAccepted = e_rdp_incoming_peer;
2258    b->listener->param4 = b;
2259    if (!b->listener->Open(b->listener, NULL, config->port))
2260      {
2261         ERR("unable to bind rdp socket");
2262         goto err_listener;
2263      }
2264
2265    if (e_rdp_implant_listener(b, b->listener) == EINA_FALSE)
2266      goto err_listener;
2267
2268    E_LIST_HANDLER_APPEND(b->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_rdp_cb_client_buffer_change, g_rdp_backend);
2269    E_LIST_HANDLER_APPEND(b->handlers, E_EVENT_CLIENT_UNICONIFY, _e_rdp_cb_client_uniconify, g_rdp_backend);
2270    pointer_hook = e_pointer_hook_add(E_POINTER_HOOK_MOUSE_MOVE, _e_rdp_cb_pointer_mouse_move, g_rdp_backend);
2271
2272    g_rdp_backend = b;
2273
2274    return EINA_TRUE;
2275
2276 err_listener:
2277    freerdp_listener_free(b->listener);
2278
2279    e_rdp_output_destroy(b->output);
2280    b->output = NULL;
2281
2282 err_output_create:
2283 err_config:
2284    if (b->server_cert)
2285      free(b->server_cert);
2286    if (b->server_key)
2287      free(b->server_key);
2288    if (b->rdp_key)
2289      free(b->rdp_key);
2290    free(b);
2291
2292    return EINA_FALSE;
2293 }
2294
2295 Eina_Bool
2296 e_mod_rdp_init(void)
2297 {
2298    int major, minor, revision;
2299    Eina_Bool ret = EINA_FALSE;
2300
2301    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
2302    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
2303
2304 #if FREERDP_VERSION_MAJOR >= 2
2305    winpr_InitializeSSL(0);
2306 #endif
2307
2308    freerdp_get_version(&major, &minor, &revision);
2309    if (major < E_MOD_RDP_CONFIG_VERSION)
2310      {
2311         ERR("Not supported version");
2312         return EINA_FALSE;
2313      }
2314    INF("freerdp version : %d.%d.%d", major, minor, revision);
2315
2316
2317    /* Init config */
2318    g_rdp_config = E_NEW(E_Rdp_Config_Data, 1);
2319    EINA_SAFETY_ON_NULL_RETURN_VAL(g_rdp_config, EINA_FALSE);
2320
2321    ret = e_rdp_conf_init(g_rdp_config);
2322    EINA_SAFETY_ON_FALSE_GOTO(ret, conf_err);
2323
2324    ret = e_rdp_backend_create(g_rdp_config->conf);
2325    EINA_SAFETY_ON_FALSE_GOTO(ret, create_err);
2326
2327    return ret;
2328
2329 create_err:
2330    e_rdp_conf_deinit(g_rdp_config);
2331 conf_err:
2332    E_FREE(g_rdp_config);
2333
2334    return ret;
2335 }
2336
2337 void
2338 e_mod_rdp_deinit(void)
2339 {
2340    e_info_server_input_deinit_device();
2341    e_rdp_backend_destroy();
2342    if (g_rdp_config)
2343      {
2344         e_rdp_conf_deinit(g_rdp_config);
2345         E_FREE(g_rdp_config);
2346      }
2347 }