6 #include <sys/socket.h>
16 #include <linux/input.h>
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>
31 #include <tbm_surface.h>
32 #include <tbm_surface_internal.h>
34 #include "e_mod_main.h"
35 #include "e_mod_rdp.h"
37 #define E_RDP_WIDTH 1280
38 #define E_RDP_HEIGHT 720
39 #define E_MOD_RDP_CONFIG_VERSION 2
40 #define E_MOD_RDP_NAME_LEN 64
41 #define MAX_FREERDP_FDS 10
42 #define DEFAULT_PIXEL_FORMAT PIXEL_FORMAT_BGRA32
46 RDP_PEER_ACTIVATED = (1 << 0),
47 RDP_PEER_OUTPUT_ENABLED = (1 << 1),
50 typedef struct _E_Rdp_Output E_Rdp_Output;
51 typedef struct _E_Rdp_Backend E_Rdp_Backend;
52 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
53 typedef struct _E_Rdp_Peer_Item E_Rdp_Peer_Item;
54 typedef struct _E_Rdp_Peer_Context E_Rdp_Peer_Context;
56 static E_Rdp_Config_Data *g_rdp_config;
57 static E_Rdp_Backend *g_rdp_backend;
58 static unsigned int refresh_raw_frame_id;
62 E_Output *primary_output;
63 Ecore_Timer *frame_timer;
64 pixman_image_t *pix_surface;
65 tbm_surface_h tbm_surface;
72 freerdp_listener *listener;
73 struct wl_event_source *listener_events[MAX_FREERDP_FDS];
80 int no_clients_resize;
81 int force_no_compression;
84 struct _E_Rdp_Peer_Item
92 struct _E_Rdp_Peer_Context
96 E_Rdp_Backend *rdpBackend;
97 struct wl_event_source *events[MAX_FREERDP_FDS];
98 RFX_CONTEXT *rfx_context;
99 wStream *encode_stream;
101 NSC_CONTEXT *nsc_context;
103 E_Rdp_Peer_Item item;
106 struct rdp_to_xkb_keyboard_layout
108 UINT32 rdpLayoutCode;
109 const char *xkbLayout;
110 const char *xkbVariant;
114 _e_rdp_tbm_image_create(E_Rdp_Output *output, int w, int h, int color)
116 tbm_surface_h tbm_surface = NULL;
118 tbm_surface = tbm_surface_internal_create_with_flags(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
125 static pixman_format_code_t
126 _e_rdp_pixman_format_get(tbm_format format)
130 case TBM_FORMAT_ARGB8888:
131 return PIXMAN_a8r8g8b8;
133 case TBM_FORMAT_XRGB8888:
134 return PIXMAN_x8r8g8b8;
143 static pixman_image_t *
144 _e_rdp_pixman_image_create(tbm_surface_h tbm_surface)
147 tbm_surface_info_s info;
148 pixman_image_t *pix_surface = NULL;
149 pixman_format_code_t pix_format = 0;
151 EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
153 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
157 pix_format = _e_rdp_pixman_format_get(info.format);
160 ERR("not supported format");
164 pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
165 if (pix_surface == NULL)
166 ERR("create pixman image failed");
169 tbm_surface_unmap(tbm_surface);
174 e_rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
176 int width, height, nrects, i;
177 pixman_box32_t *region, *rects;
180 rdpUpdate *update = peer->update;
181 SURFACE_BITS_COMMAND cmd = { 0 };
182 E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
184 Stream_Clear(context->encode_stream);
185 Stream_SetPosition(context->encode_stream, 0);
187 width = (damage->extents.x2 - damage->extents.x1);
188 height = (damage->extents.y2 - damage->extents.y1);
190 cmd.skipCompression = TRUE;
191 cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
192 cmd.destLeft = damage->extents.x1;
193 cmd.destTop = damage->extents.y1;
194 cmd.destRight = damage->extents.x2;
195 cmd.destBottom = damage->extents.y2;
197 cmd.bmp.codecID = peer->settings->RemoteFxCodecId;
198 cmd.bmp.width = width;
199 cmd.bmp.height = height;
201 ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
203 rects = pixman_region32_rectangles(damage, &nrects);
204 context->rfx_rects = realloc(context->rfx_rects, nrects * sizeof *rfxRect);
205 if (context->rfx_rects == NULL)
207 ERR("realloc failed");
211 for (i = 0; i < nrects; i++)
214 rfxRect = &context->rfx_rects[i];
216 rfxRect->x = (region->x1 - damage->extents.x1);
217 rfxRect->y = (region->y1 - damage->extents.y1);
218 rfxRect->width = (region->x2 - region->x1);
219 rfxRect->height = (region->y2 - region->y1);
222 rfx_compose_message(context->rfx_context, context->encode_stream, context->rfx_rects, nrects, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
224 cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
225 cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
227 update->SurfaceBits(update->context, &cmd);
232 e_rdp_peer_refresh_nsc(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
236 rdpUpdate *update = peer->update;
237 SURFACE_BITS_COMMAND cmd = { 0 };
238 E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
240 Stream_Clear(context->encode_stream);
241 Stream_SetPosition(context->encode_stream, 0);
243 width = (damage->extents.x2 - damage->extents.x1);
244 height = (damage->extents.y2 - damage->extents.y1);
246 cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
247 cmd.skipCompression = TRUE;
248 cmd.destLeft = damage->extents.x1;
249 cmd.destTop = damage->extents.y1;
250 cmd.destRight = damage->extents.x2;
251 cmd.destBottom = damage->extents.y2;
253 cmd.bmp.codecID = peer->settings->NSCodecId;
254 cmd.bmp.width = width;
255 cmd.bmp.height = height;
257 ptr = pixman_image_get_data(image) + damage->extents.x1 + damage->extents.y1 * (pixman_image_get_stride(image) / sizeof(uint32_t));
259 nsc_compose_message(context->nsc_context, context->encode_stream, (BYTE *)ptr, width, height, pixman_image_get_stride(image));
261 cmd.bmp.bitmapDataLength = Stream_GetPosition(context->encode_stream);
262 cmd.bmp.bitmapData = Stream_Buffer(context->encode_stream);
264 update->SurfaceBits(update->context, &cmd);
268 pixman_image_flipped_subrect(const pixman_box32_t *rect, pixman_image_t *img, BYTE *dest)
270 int stride = pixman_image_get_stride(img);
272 int toCopy = (rect->x2 - rect->x1) * 4;
273 int height = (rect->y2 - rect->y1);
274 const BYTE *src = (const BYTE *)pixman_image_get_data(img);
275 src += ((rect->y2-1) * stride) + (rect->x1 * 4);
277 for (h = 0; h < height; h++, src -= stride, dest += toCopy)
278 memcpy(dest, src, toCopy);
282 e_rdp_peer_refresh_raw(pixman_region32_t *region, pixman_image_t *image, freerdp_peer *peer)
284 rdpUpdate *update = peer->update;
285 SURFACE_BITS_COMMAND cmd = { 0 };
286 SURFACE_FRAME_MARKER marker;
287 pixman_box32_t *rect, subrect;
289 int heightIncrement, remainingHeight, top;
291 rect = pixman_region32_rectangles(region, &nrects);
295 if (refresh_raw_frame_id == 1024)
296 refresh_raw_frame_id = 0;
297 refresh_raw_frame_id++;
299 marker.frameId = refresh_raw_frame_id;
300 marker.frameAction = SURFACECMD_FRAMEACTION_BEGIN;
301 update->SurfaceFrameMarker(peer->context, &marker);
303 cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
307 for (i = 0; i < nrects; i++, rect++)
309 /*INF("rect(%d,%d, %d,%d)\n", rect->x1, rect->y1, rect->x2, rect->y2);*/
310 cmd.destLeft = rect->x1;
311 cmd.destRight = rect->x2;
312 cmd.bmp.width = (rect->x2 - rect->x1);
314 heightIncrement = peer->settings->MultifragMaxRequestSize / (16 + cmd.bmp.width * 4);
315 remainingHeight = rect->y2 - rect->y1;
318 subrect.x1 = rect->x1;
319 subrect.x2 = rect->x2;
321 while (remainingHeight)
323 cmd.bmp.height = (remainingHeight > heightIncrement) ? heightIncrement : remainingHeight;
325 cmd.destBottom = top + cmd.bmp.height;
326 cmd.bmp.bitmapDataLength = cmd.bmp.width * cmd.bmp.height * 4;
327 cmd.bmp.bitmapData = (BYTE *)realloc(cmd.bmp.bitmapData, cmd.bmp.bitmapDataLength);
330 subrect.y2 = top + cmd.bmp.height;
331 pixman_image_flipped_subrect(&subrect, image, cmd.bmp.bitmapData);
333 /*INF("* sending (%d,%d, %d,%d)\n", subrect.x1, subrect.y1, subrect.x2, subrect.y2); */
334 update->SurfaceBits(peer->context, &cmd);
336 remainingHeight -= cmd.bmp.height;
337 top += cmd.bmp.height;
341 free(cmd.bmp.bitmapData);
343 marker.frameAction = SURFACECMD_FRAMEACTION_END;
344 update->SurfaceFrameMarker(peer->context, &marker);
348 e_rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer, tbm_surface_h tbm_surface, pixman_image_t *pix_surface)
350 E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
351 E_Rdp_Output *output = context->rdpBackend->output;
352 rdpSettings *settings = peer->settings;
354 if (settings->RemoteFxCodec)
355 e_rdp_peer_refresh_rfx(region, pix_surface, peer);
356 else if (settings->NSCodec)
357 e_rdp_peer_refresh_nsc(region, pix_surface, peer);
359 e_rdp_peer_refresh_raw(region, pix_surface, peer);
361 if (output->pix_surface)
362 pixman_image_unref(output->pix_surface);
363 output->pix_surface = pix_surface;
365 if (output->tbm_surface)
366 tbm_surface_destroy(output->tbm_surface);
367 output->tbm_surface = tbm_surface;
371 _e_rdp_output_image_showing_rect_get(Eina_Rectangle *out_rect, Eina_Rectangle *dst_rect, Eina_Rectangle *showing_rect)
373 showing_rect->x = dst_rect->x;
374 showing_rect->y = dst_rect->y;
376 if (dst_rect->x >= out_rect->w)
378 else if (dst_rect->x + dst_rect->w > out_rect->w)
379 showing_rect->w = out_rect->w - dst_rect->x;
381 showing_rect->w = dst_rect->w;
383 if (dst_rect->y >= out_rect->h)
385 else if (dst_rect->y + dst_rect->h > out_rect->h)
386 showing_rect->h = out_rect->h - dst_rect->y;
388 showing_rect->h = dst_rect->h;
392 _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)
394 float ratio_x, ratio_y;
395 Eina_Rectangle out_rect;
396 Eina_Rectangle dst_rect;
405 out_rect.w = primary_w;
406 out_rect.h = primary_h;
408 dst_rect.x = hwc_window->current.info.dst_pos.x;
409 dst_rect.y = hwc_window->current.info.dst_pos.y;
410 dst_rect.w = hwc_window->current.info.dst_pos.w;
411 dst_rect.h = hwc_window->current.info.dst_pos.h;
413 _e_rdp_output_image_showing_rect_get(&out_rect, &dst_rect, showing_rect);
415 fit->x = hwc_window->current.info.src_config.pos.x;
416 fit->y = hwc_window->current.info.src_config.pos.y;
418 if (hwc_window->current.info.transform % 2 == 0)
420 ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.w;
421 ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.h;
423 fit->w = showing_rect->w * ratio_x;
424 fit->h = showing_rect->h * ratio_y;
428 ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.h;
429 ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.w;
431 fit->w = showing_rect->h * ratio_x;
432 fit->h = showing_rect->w * ratio_y;
437 _e_rdp_output_center_rect_get (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
441 if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
444 rw = (float)src_w / dst_w;
445 rh = (float)src_h / dst_h;
452 fit->y = (dst_h - fit->h) / 2;
458 fit->x = (dst_w - fit->w) / 2;
474 _e_rdp_output_image_dst_crop_get(E_Hwc_Window *hwc_window, int src_w, int src_h, int w, int h,
475 Eina_Rectangle *pos, Eina_Rectangle *showing_pos, Eina_Rectangle *dst_crop, int rotate)
482 if (hwc_window->current.info.src_config.pos.w == w && hwc_window->current.info.src_config.pos.h == h &&
483 pos->x == 0 && pos->y == 0 && pos->w == src_w && pos->h == src_h)
485 dst_crop->x = pos->x;
486 dst_crop->y = pos->y;
487 dst_crop->w = pos->w;
488 dst_crop->h = pos->h;
490 else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
492 dst_crop->x = hwc_window->current.info.dst_pos.x + pos->x;
493 dst_crop->y = hwc_window->current.info.dst_pos.y + pos->y;
494 dst_crop->w = hwc_window->current.info.dst_pos.w;
495 dst_crop->h = hwc_window->current.info.dst_pos.h;
497 else if (rotate == 0)
499 dst_crop->x = showing_pos->x * pos->w / w + pos->x;
500 dst_crop->y = showing_pos->y * pos->h / h + pos->y;
501 dst_crop->w = showing_pos->w * pos->w / w;
502 dst_crop->h = showing_pos->h * pos->h / h;
506 dst_crop->x = pos->x;
507 dst_crop->y = pos->y;
508 dst_crop->w = pos->w;
509 dst_crop->h = pos->h;
514 _e_rdp_output_image_composite(pixman_image_t *src_img, pixman_image_t *dst_img,
515 int sx, int sy, int sw, int sh,
516 int dx, int dy, int dw, int dh,
517 Eina_Bool over, int rotate, int hflip, int vflip)
519 double scale_x, scale_y;
521 pixman_transform_t t;
522 struct pixman_f_transform ft;
525 pixman_f_transform_init_identity(&ft);
529 pixman_f_transform_scale(&ft, NULL, -1, 1);
530 pixman_f_transform_translate(&ft, NULL, dw, 0);
535 pixman_f_transform_scale(&ft, NULL, 1, -1);
536 pixman_f_transform_translate(&ft, NULL, 0, dh);
539 rotate_step = (rotate + 360) / 90 % 4;
542 int c, s, tx = 0, ty = 0;
546 c = 0, s = -1, tx = -dw;
549 c = -1, s = 0, tx = -dw, ty = -dh;
552 c = 0, s = 1, ty = -dh;
555 pixman_f_transform_translate(&ft, NULL, tx, ty);
556 pixman_f_transform_rotate(&ft, NULL, c, s);
559 if (rotate_step % 2 == 0)
561 scale_x = (double)sw / dw;
562 scale_y = (double)sh / dh;
566 scale_x = (double)sw / dh;
567 scale_y = (double)sh / dw;
570 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
571 pixman_f_transform_translate(&ft, NULL, sx, sy);
572 pixman_transform_from_pixman_f_transform(&t, &ft);
573 pixman_image_set_transform(src_img, &t);
575 if (!over) op = PIXMAN_OP_SRC;
576 else op = PIXMAN_OP_OVER;
578 pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
583 _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)
585 Eina_Rectangle showing_pos = {0, };
586 Eina_Rectangle dst_pos = {0, };
587 Eina_Rectangle src_crop = {0, };
588 Eina_Rectangle dst_crop = {0, };
589 void *src_ptr = NULL;
590 int src_stride, img_w, img_h;
591 pixman_image_t *pix_shm_src = NULL;
593 if (!hwc_window->cursor.buffer)
596 src_ptr = hwc_window->cursor.img_ptr;
597 src_stride = hwc_window->cursor.img_stride;
598 img_w = hwc_window->cursor.img_w;
599 img_h = hwc_window->cursor.img_h;
601 pix_shm_src = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride);
604 ERR("create pixman image failed");
608 _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
609 _e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos);
610 _e_rdp_output_image_dst_crop_get(hwc_window, img_w, img_h, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
612 _e_rdp_output_image_composite(pix_shm_src, pix_surface,
613 src_crop.x, src_crop.y, src_crop.w, src_crop.h,
614 dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
617 pixman_image_unref(pix_shm_src);
623 _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)
625 Eina_Rectangle showing_pos = {0, };
626 Eina_Rectangle dst_pos = {0, };
627 Eina_Rectangle src_crop = {0, };
628 Eina_Rectangle dst_crop = {0, };
629 tbm_surface_h tbm_surface = NULL;
630 tbm_surface_info_s info;
631 pixman_image_t *pix_surface_src = NULL;
632 pixman_format_code_t pix_format = 0;
635 tbm_surface = hwc_window->display.buffer.tsurface;
639 tbm_surface_internal_ref(tbm_surface);
641 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
645 pix_format = _e_rdp_pixman_format_get(info.format);
648 ERR("not supported format");
649 tbm_surface_unmap(tbm_surface);
653 pix_surface_src = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
654 if (pix_surface_src == NULL)
656 ERR("create pixman image failed");
657 tbm_surface_unmap(tbm_surface);
661 _e_rdp_output_image_src_crop_get(hwc_window, &src_crop, &showing_pos, primary_w, primary_h);
662 _e_rdp_output_center_rect_get(primary_w, primary_h, pix_w, pix_h, &dst_pos);
663 _e_rdp_output_image_dst_crop_get(hwc_window, info.width, info.height, primary_w, primary_h, &dst_pos, &showing_pos, &dst_crop, 0);
665 _e_rdp_output_image_composite(pix_surface_src, pix_surface,
666 src_crop.x, src_crop.y, src_crop.w, src_crop.h,
667 dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
670 pixman_image_unref(pix_surface_src);
671 tbm_surface_unmap(tbm_surface);
672 tbm_surface_internal_unref(tbm_surface);
678 _e_rdp_cb_hwc_window_sort(const void *d1, const void *d2)
680 E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
681 E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
682 int zpos1 = 0, zpos2 = 0;
684 if (!hwc_window1) return(1);
685 if (!hwc_window2) return(-1);
687 if (hwc_window1->state == E_HWC_WINDOW_STATE_NONE)
690 zpos1 = hwc_window1->zpos;
692 if (hwc_window2->state == E_HWC_WINDOW_STATE_NONE)
695 zpos2 = hwc_window2->zpos;
697 return (zpos1 - zpos2);
700 static pixman_image_t *
701 _e_rdp_pixman_output_image_get(E_Rdp_Output *output, tbm_surface_h tbm_surface)
703 E_Output *e_output = NULL;
705 E_Hwc_Window *hwc_window = NULL;
707 Eina_List *visible_list = NULL;
708 Eina_Bool target_window = EINA_FALSE;
710 tbm_surface_info_s info;
711 pixman_image_t *pix_surface = NULL;
712 pixman_format_code_t pix_format = 0;
713 int e_output_w, e_output_h;
715 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
716 EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
718 e_output = output->primary_output;
719 EINA_SAFETY_ON_NULL_RETURN_VAL(e_output, NULL);
722 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
724 e_output_w = e_output->config.mode.w;
725 e_output_h = e_output->config.mode.h;
727 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
731 pix_format = _e_rdp_pixman_format_get(info.format);
734 ERR("not supported format");
738 pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
739 if (pix_surface == NULL)
741 ERR("create pixman image failed");
745 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
747 if (!hwc_window) continue;
748 if (hwc_window->is_target) continue;
749 if (hwc_window->is_video) continue;
750 if (hwc_window->state == E_HWC_WINDOW_STATE_NONE || hwc_window->zpos == -999) continue;
752 if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
754 target_window = EINA_TRUE;
755 visible_list = eina_list_append(visible_list, hwc_window);
759 if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE)
760 visible_list = eina_list_append(visible_list, hwc_window);
762 if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR)
764 if (hwc_window->cursor.buffer)
765 visible_list = eina_list_append(visible_list, hwc_window);
769 if (eina_list_count(visible_list) == 0)
771 ERR("no visible hwc_window for capture");
772 _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);
776 visible_list = eina_list_sort(visible_list, eina_list_count(visible_list), _e_rdp_cb_hwc_window_sort);
778 EINA_LIST_FOREACH(visible_list, l, hwc_window)
780 if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
784 target_window = EINA_FALSE;
785 _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);
790 if (hwc_window->is_cursor)
791 _e_rdp_pixman_output_image_composite_cursor(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
793 _e_rdp_pixman_output_image_composite(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
797 tbm_surface_unmap(tbm_surface);
803 _e_rdp_frame_timer(void *data)
805 E_Rdp_Output *output;
806 tbm_surface_h tbm_surface = NULL;
807 pixman_image_t *pix_surface = NULL;
809 pixman_region32_t damage;
810 E_Rdp_Peer_Item *rdp_peer, *tmp;
811 freerdp_peer *client = NULL;
813 EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
815 output = (E_Rdp_Output *)data;
817 tbm_surface = _e_rdp_tbm_image_create(output, E_RDP_WIDTH, E_RDP_HEIGHT, 0x00000000);
818 if (tbm_surface == NULL)
820 ERR("create tbm surface failed");
821 return ECORE_CALLBACK_RENEW;
824 pix_surface = _e_rdp_pixman_output_image_get(output, tbm_surface);
825 if (pix_surface == NULL)
827 ERR("create output pixman surface failed");
828 tbm_surface_destroy(tbm_surface);
829 return ECORE_CALLBACK_RENEW;
832 /* sends a full refresh */
835 box.x2 = E_RDP_WIDTH;
836 box.y2 = E_RDP_HEIGHT;
837 pixman_region32_init_with_extents(&damage, &box);
839 wl_list_for_each_safe(rdp_peer, tmp, &output->peers, link)
841 client = rdp_peer->peer;
845 e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
847 pixman_region32_fini(&damage);
849 return ECORE_CALLBACK_RENEW;
854 e_rdp_peer_capabilities(freerdp_peer *client)
860 e_rdp_peer_post_connect(freerdp_peer *client)
866 e_rdp_peer_activate(freerdp_peer *client)
868 E_Rdp_Peer_Context *peerCtx;
870 E_Rdp_Output *output;
871 rdpSettings *settings;
872 rdpPointerUpdate *pointer;
873 E_Rdp_Peer_Item *peersItem;
875 pixman_region32_t damage;
876 POINTER_SYSTEM_UPDATE pointer_system;
877 tbm_surface_h tbm_surface = NULL;
878 pixman_image_t *pix_surface = NULL;
880 EINA_SAFETY_ON_NULL_RETURN_VAL(client, FALSE);
881 EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, FALSE);
882 EINA_SAFETY_ON_NULL_RETURN_VAL(client->settings, FALSE);
884 peerCtx = (E_Rdp_Peer_Context *)client->context;
885 EINA_SAFETY_ON_NULL_RETURN_VAL(peerCtx, FALSE);
887 b = peerCtx->rdpBackend;
888 EINA_SAFETY_ON_NULL_RETURN_VAL(b, FALSE);
890 peersItem = &peerCtx->item;
891 EINA_SAFETY_ON_NULL_RETURN_VAL(peersItem, FALSE);
894 settings = client->settings;
896 if (!settings->SurfaceCommandsEnabled)
898 ERR("client doesn't support required SurfaceCommands\n");
902 if (b->force_no_compression && settings->CompressionEnabled)
904 ERR("Forcing compression off\n");
905 settings->CompressionEnabled = FALSE;
908 if (E_RDP_WIDTH != (int)settings->DesktopWidth || E_RDP_HEIGHT != (int)settings->DesktopHeight)
910 if (b->no_clients_resize)
912 /* RDP peers don't dictate their resolution to e */
913 if (!settings->DesktopResize)
915 /* peer does not support desktop resize */
916 ERR("%s: client doesn't support resizing, closing connection\n", __FUNCTION__);
921 settings->DesktopWidth = E_RDP_WIDTH;
922 settings->DesktopHeight = E_RDP_HEIGHT;
923 client->update->DesktopResize(client->context);
933 rfx_context_reset(peerCtx->rfx_context, E_RDP_WIDTH, E_RDP_HEIGHT);
934 nsc_context_reset(peerCtx->nsc_context, E_RDP_WIDTH, E_RDP_HEIGHT);
935 if (peersItem->flags & RDP_PEER_ACTIVATED)
938 /* when here it's the first reactivation, we need to setup a little more */
939 DBG("kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x kbd_functionKeys:0x%x\n",
940 settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType, settings->KeyboardFunctionKey);
942 peersItem->flags |= RDP_PEER_ACTIVATED;
944 /* disable pointer on the client side */
945 pointer = client->update->pointer;
946 pointer_system.type = SYSPTR_NULL;
947 pointer->PointerSystem(client->context, &pointer_system);
949 tbm_surface = _e_rdp_tbm_image_create(output, E_RDP_WIDTH, E_RDP_HEIGHT, 0xFFFFCCFF);
950 if (tbm_surface == NULL)
952 ERR("create sample tbm surface failed");
955 pix_surface = _e_rdp_pixman_image_create(tbm_surface);
956 if (pix_surface == NULL)
958 ERR("create sample pixman failed");
959 tbm_surface_destroy(tbm_surface);
963 /* sends a full refresh */
966 box.x2 = E_RDP_WIDTH;
967 box.y2 = E_RDP_HEIGHT;
968 pixman_region32_init_with_extents(&damage, &box);
970 e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
972 pixman_region32_fini(&damage);
974 if (output->frame_timer != NULL)
975 ecore_timer_del(output->frame_timer);
976 output->frame_timer = ecore_timer_add(0.2, _e_rdp_frame_timer, output);
982 e_rdp_suppress_output(rdpContext *context, BYTE allow, const RECTANGLE_16 *area)
984 E_Rdp_Peer_Context *peerContext = (E_Rdp_Peer_Context *)context;
987 peerContext->item.flags |= RDP_PEER_OUTPUT_ENABLED;
989 peerContext->item.flags &= (~RDP_PEER_OUTPUT_ENABLED);
995 e_rdp_input_synchronize_event(rdpInput *input, UINT32 flags)
1002 e_rdp_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1009 e_rdp_extended_mouse_event(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
1016 e_rdp_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1023 e_rdp_input_unicode_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
1025 DBG("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code);
1030 e_rdp_client_activity(int fd, uint32_t mask, void *data)
1032 freerdp_peer *client = (freerdp_peer *)data;
1033 E_Rdp_Peer_Context *peerCtx;
1035 E_Rdp_Output *output;
1037 EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
1038 EINA_SAFETY_ON_NULL_RETURN_VAL(client->context, 0);
1040 if (client->CheckFileDescriptor(client))
1042 // DBG("enable client activity %p", client);
1046 INF("unable to checkDescriptor for %p\n", client);
1047 peerCtx = (E_Rdp_Peer_Context *)client->context;
1048 EINA_SAFETY_ON_NULL_GOTO(peerCtx, out_clean);
1050 b = peerCtx->rdpBackend;
1051 EINA_SAFETY_ON_NULL_GOTO(b, out_clean);
1054 if (output->frame_timer)
1056 ecore_timer_del(output->frame_timer);
1057 output->frame_timer = NULL;
1060 freerdp_peer_context_free(client);
1061 freerdp_peer_free(client);
1066 e_rdp_peer_context_new(freerdp_peer *client, E_Rdp_Peer_Context *context)
1068 context->item.peer = client;
1069 context->item.flags = RDP_PEER_OUTPUT_ENABLED;
1071 context->rfx_context = rfx_context_new(TRUE);
1072 if (!context->rfx_context)
1075 context->rfx_context->mode = RLGR3;
1076 context->rfx_context->width = client->settings->DesktopWidth;
1077 context->rfx_context->height = client->settings->DesktopHeight;
1078 rfx_context_set_pixel_format(context->rfx_context, DEFAULT_PIXEL_FORMAT);
1080 context->nsc_context = nsc_context_new();
1081 if (!context->nsc_context)
1084 nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, DEFAULT_PIXEL_FORMAT);
1085 context->encode_stream = Stream_New(NULL, 65536);
1086 if (!context->encode_stream)
1087 goto out_error_stream;
1092 rfx_context_free(context->rfx_context);
1094 nsc_context_free(context->nsc_context);
1099 e_rdp_peer_context_free(freerdp_peer *client, E_Rdp_Peer_Context *context)
1105 wl_list_remove(&context->item.link);
1106 for (i = 0; i < MAX_FREERDP_FDS; i++)
1108 if (context->events[i])
1109 wl_event_source_remove(context->events[i]);
1112 Stream_Free(context->encode_stream, TRUE);
1113 nsc_context_free(context->nsc_context);
1114 rfx_context_free(context->rfx_context);
1115 free(context->rfx_rects);
1120 e_rdp_peer_init(freerdp_peer *client, E_Rdp_Backend *b)
1123 void *rfds[MAX_FREERDP_FDS];
1125 struct wl_event_loop *loop;
1126 rdpSettings *settings;
1128 E_Rdp_Peer_Context *peerCtx;
1130 client->ContextSize = sizeof(E_Rdp_Peer_Context);
1131 client->ContextNew = (psPeerContextNew)e_rdp_peer_context_new;
1132 client->ContextFree = (psPeerContextFree)e_rdp_peer_context_free;
1133 freerdp_peer_context_new(client);
1135 peerCtx = (E_Rdp_Peer_Context *)client->context;
1136 peerCtx->rdpBackend = b;
1138 settings = client->settings;
1142 settings->CertificateFile = strdup(b->server_cert);
1143 settings->PrivateKeyFile = strdup(b->server_key);
1147 settings->TlsSecurity = FALSE;
1149 settings->NlaSecurity = FALSE;
1151 if (!client->Initialize(client))
1153 ERR("peer initialization failed\n");
1157 settings->OsMajorType = OSMAJORTYPE_UNIX;
1158 settings->OsMinorType = OSMINORTYPE_PSEUDO_XSERVER;
1159 settings->ColorDepth = 32;
1160 settings->RefreshRect = TRUE;
1161 settings->RemoteFxCodec = TRUE;
1162 settings->NSCodec = TRUE;
1163 settings->FrameMarkerCommandEnabled = TRUE;
1164 settings->SurfaceFrameMarkerEnabled = TRUE;
1166 client->Capabilities = e_rdp_peer_capabilities;
1167 client->PostConnect = e_rdp_peer_post_connect;
1168 client->Activate = e_rdp_peer_activate;
1170 client->update->SuppressOutput = (pSuppressOutput)e_rdp_suppress_output;
1172 input = client->input;
1173 input->SynchronizeEvent = e_rdp_input_synchronize_event;
1174 input->MouseEvent = e_rdp_mouse_event;
1175 input->ExtendedMouseEvent = e_rdp_extended_mouse_event;
1176 input->KeyboardEvent = e_rdp_input_keyboard_event;
1177 input->UnicodeKeyboardEvent = e_rdp_input_unicode_keyboard_event;
1179 if (!client->GetFileDescriptor(client, rfds, &rcount))
1181 ERR("unable to retrieve client fds");
1182 goto error_initialize;
1185 if (rcount > MAX_FREERDP_FDS)
1187 ERR("check fds max count. count:%d, max:%d", rcount, MAX_FREERDP_FDS);
1188 goto error_initialize;
1191 loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
1192 for (i = 0; i < rcount; i++)
1194 fd = (int)(long)(rfds[i]);
1196 peerCtx->events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_client_activity, client);
1198 for ( ; i < MAX_FREERDP_FDS; i++)
1199 peerCtx->events[i] = 0;
1201 wl_list_insert(&b->output->peers, &peerCtx->item.link);
1205 client->Close(client);
1210 e_rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
1212 E_Rdp_Backend *b = (E_Rdp_Backend *)instance->param4;
1214 if (e_rdp_peer_init(client, b) < 0)
1216 ERR("error when treating incoming peer\n");
1224 e_rdp_listener_activity(int fd, uint32_t mask, void *data)
1226 freerdp_listener* instance = (freerdp_listener *)data;
1228 if (!(mask & WL_EVENT_READABLE))
1231 if (!instance->CheckFileDescriptor(instance))
1233 ERR("failed to check FreeRDP file descriptor\n");
1241 e_rdp_implant_listener(E_Rdp_Backend *b, freerdp_listener *instance)
1245 void* rfds[MAX_FREERDP_FDS];
1246 struct wl_event_loop *loop;
1248 if (!instance->GetFileDescriptor(instance, rfds, &rcount))
1250 ERR("Failed to get FreeRDP file descriptor\n");
1254 loop = wl_display_get_event_loop(e_comp_wl->wl.disp);
1255 for (i = 0; i < rcount; i++)
1257 fd = (int)(long)(rfds[i]);
1258 b->listener_events[i] = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, e_rdp_listener_activity, instance);
1261 for ( ; i < MAX_FREERDP_FDS; i++)
1262 b->listener_events[i] = 0;
1268 e_rdp_output_destroy(E_Rdp_Output *output)
1270 EINA_SAFETY_ON_NULL_RETURN(output);
1272 if (output->pix_surface)
1273 pixman_image_unref(output->pix_surface);
1274 if (output->tbm_surface)
1275 tbm_surface_destroy(output->tbm_surface);
1281 e_rdp_output_create(void)
1283 E_Rdp_Output *output = NULL;
1285 output = E_NEW(E_Rdp_Output, 1);
1286 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1288 output->primary_output = e_output_find_by_index(0);
1290 wl_list_init(&output->peers);
1296 e_rdp_backend_destroy(void)
1298 E_Rdp_Backend *b = NULL;
1299 E_Rdp_Peer_Item *rdp_peer, *tmp;
1303 EINA_SAFETY_ON_NULL_RETURN(b);
1305 if (b->output->frame_timer)
1307 ecore_timer_del(b->output->frame_timer);
1308 b->output->frame_timer = NULL;
1311 wl_list_for_each_safe(rdp_peer, tmp, &b->output->peers, link)
1313 freerdp_peer* client = rdp_peer->peer;
1315 client->Disconnect(client);
1316 freerdp_peer_context_free(client);
1317 freerdp_peer_free(client);
1320 for (i = 0; i < MAX_FREERDP_FDS; i++)
1321 if (b->listener_events[i])
1322 wl_event_source_remove(b->listener_events[i]);
1324 freerdp_listener_free(b->listener);
1326 e_rdp_output_destroy(b->output);
1328 free(b->server_cert);
1329 free(b->server_key);
1335 e_rdp_backend_create(E_Rdp_Conf_Edd *config)
1339 b = E_NEW(E_Rdp_Backend, 1);
1340 EINA_SAFETY_ON_NULL_RETURN_VAL(b, EINA_FALSE);
1343 b->no_clients_resize = config->no_clients_resize;
1344 b->force_no_compression = config->force_no_compression;
1346 /* activate TLS only if certificate/key are available */
1347 if (config->server_cert && config->server_key)
1349 DBG("TLS support activated\n");
1350 b->server_cert = strdup(config->server_cert);
1351 b->server_key = strdup(config->server_key);
1352 if (!b->server_cert || !b->server_key)
1353 goto err_free_strings;
1357 b->output = e_rdp_output_create();
1360 ERR("output create failed");
1361 goto err_free_strings;
1364 b->listener = freerdp_listener_new();
1365 b->listener->PeerAccepted = e_rdp_incoming_peer;
1366 b->listener->param4 = b;
1367 if (!b->listener->Open(b->listener, NULL, config->port))
1369 ERR("unable to bind rdp socket\n");
1373 if (e_rdp_implant_listener(b, b->listener) == EINA_FALSE)
1381 freerdp_listener_free(b->listener);
1383 e_rdp_output_destroy(b->output);
1387 free(b->server_cert);
1388 free(b->server_key);
1395 e_mod_rdp_init(void)
1397 int major, minor, revision;
1398 Eina_Bool ret = EINA_FALSE;
1400 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
1401 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
1403 #if FREERDP_VERSION_MAJOR >= 2
1404 winpr_InitializeSSL(0);
1407 freerdp_get_version(&major, &minor, &revision);
1408 if (major < E_MOD_RDP_CONFIG_VERSION)
1410 ERR("Not supported version");
1413 INF("freerdp version : %d.%d.%d", major, minor, revision);
1417 g_rdp_config = E_NEW(E_Rdp_Config_Data, 1);
1418 EINA_SAFETY_ON_NULL_RETURN_VAL(g_rdp_config, EINA_FALSE);
1420 ret = e_rdp_conf_init(g_rdp_config);
1421 EINA_SAFETY_ON_FALSE_GOTO(ret, conf_err);
1423 ret = e_rdp_backend_create(g_rdp_config->conf);
1424 EINA_SAFETY_ON_FALSE_GOTO(ret, create_err);
1429 e_rdp_conf_deinit(g_rdp_config);
1431 E_FREE(g_rdp_config);
1437 e_mod_rdp_deinit(void)
1439 e_rdp_backend_destroy();
1442 e_rdp_conf_deinit(g_rdp_config);
1443 E_FREE(g_rdp_config);