{
E_Output *primary_output;
Ecore_Timer *frame_timer;
- pixman_image_t *pix_surface;
- tbm_surface_h tbm_surface;
+ pixman_image_t *showing_surface;
+ tbm_surface_h prepare_tbm_surface;
+ tbm_surface_h showing_tbm_surface;
+ tbm_surface_h backup_tbm_surface;
uint32_t w;
uint32_t h;
double refresh_time;
int refresh_count;
+ Eina_Bool mouse_moved;
+ Eina_Bool buffer_changed;
+
+ int mouse_x;
+ int mouse_y;
+
struct wl_list peers;
};
}
static void
-e_rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer, tbm_surface_h tbm_surface, pixman_image_t *pix_surface)
+e_rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer, pixman_image_t *pix_surface)
{
E_Rdp_Peer_Context *context = (E_Rdp_Peer_Context *)peer->context;
E_Rdp_Output *output = context->rdpBackend->output;
else
e_rdp_peer_refresh_raw(region, pix_surface, peer);
- if (output->pix_surface)
- pixman_image_unref(output->pix_surface);
- output->pix_surface = pix_surface;
+ if (output->showing_surface)
+ pixman_image_unref(output->showing_surface);
+ output->showing_surface = pix_surface;
- if (output->tbm_surface)
- tbm_surface_destroy(output->tbm_surface);
- output->tbm_surface = tbm_surface;
+ if (output->showing_tbm_surface)
+ tbm_surface_destroy(output->showing_tbm_surface);
+ output->showing_tbm_surface = output->prepare_tbm_surface;
+ output->prepare_tbm_surface = NULL;
}
static void
pixman_image_unref(pix_shm_src);
+ output->mouse_x = hwc_window->current.info.dst_pos.x;
+ output->mouse_y = hwc_window->current.info.dst_pos.y;
+
return EINA_TRUE;
}
return (zpos1 - zpos2);
}
+static void
+_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)
+{
+ memcpy(dst_info->planes[0].ptr, src_info->planes[0].ptr, src_info->planes[0].size);
+}
+
+static void
+_e_rdp_backup_buffer_create(E_Rdp_Output *output, tbm_surface_h src_tbm_surface, tbm_surface_info_s *src_info)
+{
+ tbm_surface_h new_tsurface = NULL;
+ tbm_surface_info_s info;
+ int ret = TBM_SURFACE_ERROR_NONE;
+
+ new_tsurface = tbm_surface_create(src_info->width, src_info->height, src_info->format);
+ if (!new_tsurface)
+ {
+ ERR("tbm_surface_create failed");
+ return;
+ }
+
+ ret = tbm_surface_map(new_tsurface, TBM_SURF_OPTION_WRITE, &info);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ {
+ ERR("tbm_surface_map failed");
+ tbm_surface_destroy(new_tsurface);
+ return;
+ }
+
+ _e_rdp_tbm_surface_copy(src_tbm_surface, src_info, new_tsurface, &info);
+
+ tbm_surface_unmap(new_tsurface);
+
+ if (output->backup_tbm_surface)
+ tbm_surface_destroy(output->backup_tbm_surface);
+ output->backup_tbm_surface = new_tsurface;
+}
+
static pixman_image_t *
-_e_rdp_pixman_output_image_get(E_Rdp_Output *output, tbm_surface_h tbm_surface)
+_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)
{
- E_Output *e_output = NULL;
+ tbm_surface_h tbm_surface = NULL;
+ tbm_surface_info_s info;
+ pixman_image_t *pix_surface = NULL;
+ pixman_format_code_t pix_format = 0;
E_Hwc *hwc = NULL;
E_Hwc_Window *hwc_window = NULL;
+ Eina_Bool target_window = EINA_TRUE;
Eina_List *l;
- Eina_List *visible_list = NULL;
- Eina_Bool target_window = EINA_FALSE;
int err;
- tbm_surface_info_s info;
- pixman_image_t *pix_surface = NULL;
- pixman_format_code_t pix_format = 0;
- int e_output_w, e_output_h;
EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
- EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surface, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output->primary_output->hwc, NULL);
- e_output = output->primary_output;
- EINA_SAFETY_ON_NULL_RETURN_VAL(e_output, NULL);
+ hwc = output->primary_output->hwc;
- hwc = e_output->hwc;
- EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+ tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0x00000000);
+ if (tbm_surface == NULL)
+ {
+ ERR("create tbm surface failed");
+ output->prepare_tbm_surface = NULL;
+ return NULL;
+ }
- e_output_w = e_output->config.mode.w;
- e_output_h = e_output->config.mode.h;
+ err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &info);
+ if (err)
+ {
+ ERR("tbm_surface_map failed");
+ tbm_surface_destroy(tbm_surface);
+ output->prepare_tbm_surface = NULL;
+ return NULL;
+ }
+
+ pix_format = _e_rdp_pixman_format_get(info.format);
+ if (pix_format == 0)
+ {
+ ERR("not supported format");
+ goto fail;
+ }
+
+ pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
+ if (pix_surface == NULL)
+ {
+ ERR("create pixman image failed");
+ goto fail;
+ }
+
+ EINA_LIST_FOREACH(visible_list, l, hwc_window)
+ {
+ if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
+ {
+ if (target_window)
+ {
+ target_window = EINA_FALSE;
+ _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);
+ }
+ continue;
+ }
+
+ _e_rdp_pixman_output_image_composite(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
+ }
+
+ if (output->refresh_count == 0)
+ _e_rdp_backup_buffer_create(output, tbm_surface, &info);
+
+ if (hwc_window_cursor != NULL)
+ _e_rdp_pixman_output_image_composite_cursor(output, hwc_window_cursor, pix_surface, info.width, info.height, e_output_w, e_output_h);
+
+ tbm_surface_unmap(tbm_surface);
+
+ output->prepare_tbm_surface = tbm_surface;
+
+ return pix_surface;
+
+fail:
+ tbm_surface_unmap(tbm_surface);
+ tbm_surface_destroy(tbm_surface);
+ output->prepare_tbm_surface = NULL;
+ return NULL;
+}
+
+static pixman_image_t *
+_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)
+{
+ tbm_surface_h tbm_surface = NULL;
+ tbm_surface_info_s src_info, info;
+ pixman_image_t *pix_surface = NULL;
+ pixman_format_code_t pix_format = 0;
+ int err;
+
+ if ((output->mouse_x == hwc_window_cursor->current.info.dst_pos.x) &&
+ (output->mouse_y == hwc_window_cursor->current.info.dst_pos.y))
+ {
+// INF("same position. do not update. (%dx%d)", output->mouse_x, output->mouse_y);
+ return NULL;
+ }
+
+ err = tbm_surface_map(output->backup_tbm_surface, TBM_SURF_OPTION_READ, &src_info);
+ if (err)
+ {
+ ERR("tbm_surface_map failed");
+ return NULL;
+ }
+
+ tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0x00000000);
+ if (tbm_surface == NULL)
+ {
+ ERR("create tbm surface failed");
+ output->prepare_tbm_surface = NULL;
+ tbm_surface_unmap(output->backup_tbm_surface);
+ return NULL;
+ }
err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_WRITE, &info);
if (err)
- return NULL;
+ {
+ ERR("tbm_surface_map failed");
+ tbm_surface_destroy(tbm_surface);
+ output->prepare_tbm_surface = NULL;
+ tbm_surface_unmap(output->backup_tbm_surface);
+ return NULL;
+ }
+
+ _e_rdp_tbm_surface_copy(output->backup_tbm_surface, &src_info, tbm_surface, &info);
pix_format = _e_rdp_pixman_format_get(info.format);
if (pix_format == 0)
{
ERR("not supported format");
- goto out;
+ goto fail;
}
pix_surface = pixman_image_create_bits(pix_format, info.width, info.height, (uint32_t *)info.planes[0].ptr, info.planes[0].stride);
if (pix_surface == NULL)
{
ERR("create pixman image failed");
- goto out;
+ goto fail;
}
+ if (hwc_window_cursor != NULL)
+ _e_rdp_pixman_output_image_composite_cursor(output, hwc_window_cursor, pix_surface, info.width, info.height, e_output_w, e_output_h);
+
+ tbm_surface_unmap(tbm_surface);
+ tbm_surface_unmap(output->backup_tbm_surface);
+
+ output->prepare_tbm_surface = tbm_surface;
+
+ return pix_surface;
+
+fail:
+ tbm_surface_unmap(tbm_surface);
+ tbm_surface_destroy(tbm_surface);
+ output->prepare_tbm_surface = NULL;
+ return NULL;
+}
+
+static pixman_image_t *
+_e_rdp_pixman_output_image_get(E_Rdp_Output *output)
+{
+ E_Output *e_output = NULL;
+ E_Hwc *hwc = NULL;
+ E_Hwc_Window *hwc_window = NULL;
+ E_Hwc_Window *hwc_window_cursor = NULL;
+ Eina_List *l;
+ Eina_List *visible_list = NULL;
+ int e_output_w, e_output_h;
+ pixman_image_t *pix_surface = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+ e_output = output->primary_output;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_output, NULL);
+
+ hwc = e_output->hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
+
+ e_output_w = e_output->config.mode.w;
+ e_output_h = e_output->config.mode.h;
+
EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
{
if (!hwc_window) continue;
if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
{
- target_window = EINA_TRUE;
visible_list = eina_list_append(visible_list, hwc_window);
continue;
}
if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR)
{
if (hwc_window->cursor.buffer)
- visible_list = eina_list_append(visible_list, hwc_window);
+ {
+ hwc_window_cursor = hwc_window;
+ }
}
}
if (eina_list_count(visible_list) == 0)
{
ERR("no visible hwc_window for capture");
- _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);
- goto out;
+ return pix_surface;
}
-
visible_list = eina_list_sort(visible_list, eina_list_count(visible_list), _e_rdp_cb_hwc_window_sort);
- EINA_LIST_FOREACH(visible_list, l, hwc_window)
+ if (output->buffer_changed)
{
- if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT)
- {
- if (target_window)
- {
- target_window = EINA_FALSE;
- _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);
- }
- continue;
- }
-
- if (hwc_window->is_cursor)
- _e_rdp_pixman_output_image_composite_cursor(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
- else
- _e_rdp_pixman_output_image_composite(output, hwc_window, pix_surface, info.width, info.height, e_output_w, e_output_h);
+ pix_surface = _e_rdp_pixman_output_image_get_all(output, visible_list, hwc_window_cursor, e_output_w, e_output_h);
+ }
+ else if ((output->mouse_moved) && (hwc_window_cursor != NULL))
+ {
+ pix_surface = _e_rdp_pixman_output_image_get_cursor(output, hwc_window_cursor, e_output_w, e_output_h);
}
-
-out:
- tbm_surface_unmap(tbm_surface);
return pix_surface;
}
_e_rdp_frame_timer(void *data)
{
E_Rdp_Output *output;
- tbm_surface_h tbm_surface = NULL;
pixman_image_t *pix_surface = NULL;
pixman_box32_t box;
pixman_region32_t damage;
{
output->frame_timer = NULL;
output->refresh_count = 0;
+ output->mouse_moved = EINA_FALSE;
+ output->buffer_changed = EINA_FALSE;
+
return ECORE_CALLBACK_CANCEL;
}
gettimeofday(&start_tv, NULL);
#endif
- tbm_surface = _e_rdp_tbm_image_create(output, output->w, output->h, 0x00000000);
- if (tbm_surface == NULL)
- {
- ERR("create tbm surface failed");
- return ECORE_CALLBACK_RENEW;
- }
-
- pix_surface = _e_rdp_pixman_output_image_get(output, tbm_surface);
+ pix_surface = _e_rdp_pixman_output_image_get(output);
if (pix_surface == NULL)
{
- ERR("create output pixman surface failed");
- tbm_surface_destroy(tbm_surface);
+#if RDP_DEBUG
+ gettimeofday(&end_capture_tv, NULL);
+ INF("pixman capture time (no result): %ld ms", ((end_capture_tv.tv_sec * 1000 + end_capture_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
+#endif
return ECORE_CALLBACK_RENEW;
}
if (!client)
continue;
- e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
+ e_rdp_peer_refresh_region(&damage, client, pix_surface);
}
pixman_region32_fini(&damage);
}
else
output->refresh_count = 5;
+ output->buffer_changed = EINA_TRUE;
return ECORE_CALLBACK_PASS_ON;
}
}
else
output->refresh_count = 5;
+ output->mouse_moved = EINA_TRUE;
}
static double
box.y2 = output->h;
pixman_region32_init_with_extents(&damage, &box);
- e_rdp_peer_refresh_region(&damage, client, tbm_surface, pix_surface);
+ output->prepare_tbm_surface = tbm_surface;
+
+ e_rdp_peer_refresh_region(&damage, client, pix_surface);
pixman_region32_fini(&damage);
output->refresh_time = _e_rdp_refresh_time_set(output->w, output->h);
output->refresh_count = 5;
output->frame_timer = ecore_timer_add(output->refresh_time, _e_rdp_frame_timer, output);
+ output->buffer_changed = EINA_TRUE;
return TRUE;
}
}
else
output->refresh_count = 5;
+ output->buffer_changed = EINA_TRUE;
return TRUE;
}
output->frame_timer = NULL;
}
+ if (b->client_count == 0)
+ {
+ if (output->showing_surface)
+ {
+ pixman_image_unref(output->showing_surface);
+ output->showing_surface = NULL;
+ }
+ if (output->prepare_tbm_surface)
+ {
+ tbm_surface_destroy(output->prepare_tbm_surface);
+ output->prepare_tbm_surface = NULL;
+ }
+ if (output->showing_tbm_surface)
+ {
+ tbm_surface_destroy(output->showing_tbm_surface);
+ output->showing_tbm_surface = NULL;
+ }
+ if (output->backup_tbm_surface)
+ {
+ tbm_surface_destroy(output->backup_tbm_surface);
+ output->backup_tbm_surface = NULL;
+ }
+ }
+
out_clean:
freerdp_peer_context_free(client);
freerdp_peer_free(client);
{
EINA_SAFETY_ON_NULL_RETURN(output);
- if (output->pix_surface)
- pixman_image_unref(output->pix_surface);
- if (output->tbm_surface)
- tbm_surface_destroy(output->tbm_surface);
+ if (output->showing_surface)
+ pixman_image_unref(output->showing_surface);
+ if (output->prepare_tbm_surface)
+ tbm_surface_destroy(output->prepare_tbm_surface);
+ if (output->showing_tbm_surface)
+ tbm_surface_destroy(output->showing_tbm_surface);
+ if (output->backup_tbm_surface)
+ tbm_surface_destroy(output->backup_tbm_surface);
free(output);
}