More integration work from mainline_merge_shm

- Introduce functional EGFX caps.
- Prototype of RFX Progressive working.
- Update resizing to work with it.
- Refactoring
This commit is contained in:
Nexarian 2023-12-24 15:35:28 -05:00 committed by Christopher Pitstick
parent afa70e464a
commit 65137e6edb
6 changed files with 661 additions and 203 deletions

View File

@ -222,7 +222,8 @@ enum xrdp_encoder_flags
{
NONE = 0,
ENCODE_COMPLETE = 1 << 0,
GFX_PROGRESSIVE_RFX = 1 << 1
GFX_PROGRESSIVE_RFX = 1 << 1,
GFX_H264 = 1 << 2
};
/* yyyymmdd of last incompatible change to xrdp_client_info */

View File

@ -543,7 +543,8 @@ server_set_pointer_large(struct xrdp_mod *mod, int x, int y,
char *data, char *mask, int bpp,
int width, int height);
int
server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects,
server_paint_rects_ex(struct xrdp_mod *mod,
int num_drects, short *drects,
int num_crects, short *crects,
char *data, int left, int top,
int width, int height,

View File

@ -33,6 +33,7 @@
#endif
#define XRDP_SURCMD_PREFIX_BYTES 256
#define OUT_DATA_BYTES_DEFAULT_SIZE (16 * 1024 * 1024)
#ifdef XRDP_RFXCODEC
/* LH3 LL3, HH3 HL3, HL2 LH2, LH1 HH2, HH1 HL1 todo check this */
@ -77,6 +78,8 @@ xrdp_enc_data_done_destructor(void *item, void *closure)
struct xrdp_encoder *
xrdp_encoder_create(struct xrdp_mm *mm)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_encoder_create:");
struct xrdp_encoder *self;
struct xrdp_client_info *client_info;
char buf[1024];
@ -106,7 +109,8 @@ xrdp_encoder_create(struct xrdp_mm *mm)
if (client_info->jpeg_codec_id != 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting jpeg codec session");
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: "
"starting jpeg codec session");
self->codec_id = client_info->jpeg_codec_id;
self->in_codec_mode = 1;
self->codec_quality = client_info->jpeg_prop[0];
@ -136,7 +140,8 @@ xrdp_encoder_create(struct xrdp_mm *mm)
}
else if (client_info->rfx_codec_id != 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session");
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: "
"starting rfx codec session");
self->codec_id = client_info->rfx_codec_id;
self->in_codec_mode = 1;
client_info->capture_code = 2;
@ -148,7 +153,8 @@ xrdp_encoder_create(struct xrdp_mm *mm)
#endif
else if (client_info->h264_codec_id != 0)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting h264 codec session");
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: "
"starting h264 codec session");
self->codec_id = client_info->h264_codec_id;
self->in_codec_mode = 1;
client_info->capture_code = 3;
@ -277,15 +283,18 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
continue;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d", x, y, cx, cy);
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_jpg: x %d y %d cx %d cy %d",
x, y, cx, cy);
out_data_bytes = MAX((cx + 4) * cy * 4, 8192);
if ((out_data_bytes < 1) || (out_data_bytes > 16 * 1024 * 1024))
if ((out_data_bytes < 1)
|| (out_data_bytes > OUT_DATA_BYTES_DEFAULT_SIZE))
{
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 2");
return 1;
}
out_data = (char *) g_malloc(out_data_bytes + 256 + 2, 0);
out_data = (char *) g_malloc(out_data_bytes
+ XRDP_SURCMD_PREFIX_BYTES + 2, 0);
if (out_data == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 3");
@ -298,15 +307,18 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
enc->width, enc->height,
enc->width * 4, x, y, cx, cy,
quality,
out_data + 256 + 2, &out_data_bytes);
out_data
+ XRDP_SURCMD_PREFIX_BYTES + 2,
&out_data_bytes);
if (error < 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d bytes %d",
error, out_data_bytes);
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d "
"bytes %d", error, out_data_bytes);
g_free(out_data);
return 1;
}
LOG_DEVEL(LOG_LEVEL_WARNING, "jpeg error %d bytes %d", error, out_data_bytes);
LOG_DEVEL(LOG_LEVEL_WARNING,
"jpeg error %d bytes %d", error, out_data_bytes);
enc_done = (XRDP_ENC_DATA_DONE *)
g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1);
enc_done->comp_bytes = out_data_bytes + 2;

View File

@ -27,17 +27,15 @@
#include "guid.h"
#include "ms-rdpedisp.h"
#include "ms-rdpbcgr.h"
#include "scp.h"
#include <ctype.h>
#include "xrdp_encoder.h"
#include "xrdp_sockets.h"
#include "xrdp_egfx.h"
#include "libxrdp.h"
#include "xrdp_channel.h"
#include <limits.h>
/* Forward declarations */
static int
xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *port);
@ -49,8 +47,6 @@ struct xrdp_mm *
xrdp_mm_create(struct xrdp_wm *owner)
{
struct xrdp_mm *self;
char buf[1024];
int pid;
self = (struct xrdp_mm *)g_malloc(sizeof(struct xrdp_mm), 1);
self->wm = owner;
@ -58,17 +54,9 @@ xrdp_mm_create(struct xrdp_wm *owner)
self->login_names->auto_free = 1;
self->login_values = list_create();
self->login_values->auto_free = 1;
self->resize_queue = list_create();
self->resize_queue->auto_free = 1;
self->uid = -1; /* Never good to default UIDs to 0 */
pid = g_getpid();
/* setup wait objects for signalling */
g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid);
self->resize_ready = g_create_wait_obj(buf);
self->resize_data = NULL;
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_create: bpp %d mcs_connection_type %d "
"jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d "
"h264_codec_id %d",
@ -170,6 +158,7 @@ xrdp_mm_delete(struct xrdp_mm *self)
list_delete(self->resize_queue);
g_free(self->resize_data);
g_delete_wait_obj(self->resize_ready);
xrdp_egfx_shutdown_full(self->egfx);
g_free(self);
}
@ -1090,6 +1079,30 @@ xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self,
return 0;
}
/******************************************************************************/
static int
xrdp_mm_egfx_invalidate_all(struct xrdp_mm *self)
{
struct xrdp_rect xr_rect;
struct xrdp_bitmap *screen;
int error;
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_all:");
screen = self->wm->screen;
xr_rect.left = 0;
xr_rect.top = 0;
xr_rect.right = screen->width;
xr_rect.bottom = screen->height;
if (self->wm->screen_dirty_region == NULL)
{
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
}
error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect);
return error;
}
/******************************************************************************/
static int
dynamic_monitor_open_response(intptr_t id, int chan_id, int creation_status)
@ -1139,6 +1152,265 @@ dynamic_monitor_data_first(intptr_t id, int chan_id, char *data, int bytes,
return 0;
}
/******************************************************************************/
int
advance_resize_state_machine(struct xrdp_mm *mm,
enum display_resize_state new_state)
{
struct display_control_monitor_layout_data *description = mm->resize_data;
LOG_DEVEL(LOG_LEVEL_INFO,
"advance_resize_state_machine:"
" Processing resize to: %d x %d."
" Advancing state from %s to %s."
" Previous state took %d MS.",
description->description.session_width,
description->description.session_height,
XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state),
XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state),
g_time3() - description->last_state_update_timestamp);
description->state = new_state;
description->last_state_update_timestamp = g_time3();
g_set_wait_obj(mm->resize_ready);
return 0;
}
/******************************************************************************/
static int
xrdp_mm_egfx_caps_advertise(void *user, int caps_count,
int *versions, int *flagss)
{
struct xrdp_mm *self;
struct xrdp_bitmap *screen;
int index;
int best_index;
int best_h264_index;
int best_pro_index;
int error;
int version;
int flags;
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise:");
self = (struct xrdp_mm *) user;
screen = self->wm->screen;
if (screen->data == NULL)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: can not do gfx");
}
best_index = -1;
best_h264_index = -1;
best_pro_index = -1;
for (index = 0; index < caps_count; index++)
{
version = versions[index];
flags = flagss[index];
LOG(LOG_LEVEL_INFO, " version 0x%8.8x flags 0x%8.8x (index: %d)",
version, flags, index);
switch (version)
{
case XR_RDPGFX_CAPVERSION_8:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_81:
if (flags & XR_RDPGFX_CAPS_FLAG_AVC420_ENABLED)
{
best_h264_index = index;
}
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_10:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_101:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_102:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_103:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_104:
if (!(flags & XR_RDPGFX_CAPS_FLAG_AVC_DISABLED))
{
best_h264_index = index;
}
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_105:
best_pro_index = index;
break;
case XR_RDPGFX_CAPVERSION_106:
best_pro_index = index;
break;
}
}
if (best_pro_index >= 0)
{
best_index = best_pro_index;
self->egfx_flags = XRDP_EGFX_RFX_PRO;
}
/* prefer h264, todo use setting in xrdp.ini for this */
if (best_h264_index >= 0)
{
#if defined(XRDP_X264) || defined(XRDP_NVENC)
best_index = best_h264_index;
self->egfx_flags = XRDP_EGFX_H264;
#endif
}
if (best_index >= 0)
{
LOG(LOG_LEVEL_INFO, " replying version 0x%8.8x flags 0x%8.8x",
versions[best_index], flagss[best_index]);
error = xrdp_egfx_send_capsconfirm(self->egfx,
versions[best_index],
flagss[best_index]);
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: xrdp_egfx_send_capsconfirm "
"error %d best_index %d", error, best_index);
error = xrdp_egfx_send_reset_graphics(self->egfx,
screen->width, screen->height,
self->wm->client_info->display_sizes.monitorCount,
self->wm->client_info->display_sizes.minfo_wm);
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: xrdp_egfx_send_reset_graphics "
"error %d monitorCount %d",
error, self->wm->client_info->display_sizes.monitorCount);
self->egfx_up = 1;
xrdp_egfx_send_create_surface(self->egfx, self->egfx->surface_id,
screen->width, screen->height,
XR_PIXEL_FORMAT_XRGB_8888);
xrdp_egfx_send_map_surface(self->egfx, self->egfx->surface_id, 0, 0);
self->encoder = xrdp_encoder_create(self);
xrdp_mm_egfx_invalidate_all(self);
if (self->resize_data != NULL
&& self->resize_data->state == WMRZ_EGFX_INITALIZING)
{
advance_resize_state_machine(self, WMRZ_EGFX_INITIALIZED);
}
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: egfx created.");
if (self->gfx_delay_autologin)
{
self->gfx_delay_autologin = 0;
xrdp_wm_set_login_state(self->wm, WMLS_START_CONNECT);
}
}
else
{
struct xrdp_rect lrect;
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: no good gfx, canceling");
lrect.left = 0;
lrect.top = 0;
lrect.right = screen->width;
lrect.bottom = screen->height;
self->wm->client_info->gfx = 0;
xrdp_encoder_delete(self->encoder);
self->encoder = xrdp_encoder_create(self);
xrdp_bitmap_invalidate(screen, &lrect);
}
return 0;
}
/*****************************************************************************/
static int
xrdp_mm_update_module_frame_ack(struct xrdp_mm *self)
{
int fif;
struct xrdp_encoder *encoder;
encoder = self->encoder;
fif = encoder->frames_in_flight;
if (encoder->frame_id_client + fif > encoder->frame_id_server)
{
if (encoder->frame_id_server > encoder->frame_id_server_sent)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_update_module_ack: "
"frame_id_server %d", encoder->frame_id_server);
encoder->frame_id_server_sent = encoder->frame_id_server;
self->mod->mod_frame_ack(self->mod, 0, encoder->frame_id_server);
}
}
return 0;
}
static int
xrdp_mm_egfx_frame_ack(void *user, uint32_t queue_depth, int frame_id,
int frames_decoded)
{
struct xrdp_mm *self;
struct xrdp_encoder *encoder;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack:");
self = (struct xrdp_mm *) user;
encoder = self->encoder;
if (encoder == NULL)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: encoder is nil");
return 0;
}
if (queue_depth == XR_SUSPEND_FRAME_ACKNOWLEDGEMENT)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: "
"queue_depth %d frame_id %d frames_decoded %d",
queue_depth, frame_id, frames_decoded);
if (encoder->gfx_ack_off == 0)
{
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_frame_ack: "
"client request turn off frame acks.");
encoder->gfx_ack_off = 1;
frame_id = -1;
}
}
else
{
if (encoder->gfx_ack_off)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: "
"client request turn on frame acks");
encoder->gfx_ack_off = 0;
}
}
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_egfx_frame_ack: "
"incoming %d, client %d, server %d",
frame_id, encoder->frame_id_client, encoder->frame_id_server);
if (frame_id < 0 || frame_id > encoder->frame_id_server)
{
/* if frame_id is negative or bigger then what server last sent
just ack all sent frames */
/* some clients can send big number just to clear all
pending frames */
encoder->frame_id_client = encoder->frame_id_server;
}
else
{
/* frame acks can come out of order so ignore older one */
encoder->frame_id_client = MAX(frame_id, encoder->frame_id_client);
}
xrdp_mm_update_module_frame_ack(self);
return 0;
}
/******************************************************************************/
int
egfx_initialize(struct xrdp_mm *self)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "egfx_initialize");
if (!(self->wm->client_info->mcs_early_capability_flags
& RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL))
{
return 0;
}
LOG_DEVEL(LOG_LEVEL_INFO, "egfx_initialize: gfx capable client");
if (xrdp_egfx_create(self, &(self->egfx)) == 0)
{
self->egfx->user = self;
self->egfx->caps_advertise = xrdp_mm_egfx_caps_advertise;
self->egfx->frame_ack = xrdp_mm_egfx_frame_ack;
return 0;
}
LOG_DEVEL(LOG_LEVEL_INFO, "egfx_initialize: xrdp_egfx_create failed");
return 1;
}
/******************************************************************************/
static const int MAXIMUM_MONITOR_SIZE
= sizeof(struct monitor_info) * CLIENT_MONITOR_DATA_MAXIMUM_MONITORS;
@ -1162,27 +1434,6 @@ sync_dynamic_monitor_data(struct xrdp_wm *wm,
MAXIMUM_MONITOR_SIZE);
}
int
advance_resize_state_machine(struct xrdp_mm *mm,
enum display_resize_state new_state)
{
struct display_control_monitor_layout_data *description = mm->resize_data;
LOG_DEVEL(LOG_LEVEL_INFO,
"advance_resize_state_machine:"
" Processing resize to: %d x %d."
" Advancing state from %s to %s."
" Previous state took %d MS.",
description->description.session_width,
description->description.session_height,
XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state),
XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state),
g_time3() - description->last_state_update_timestamp);
description->state = new_state;
description->last_state_update_timestamp = g_time3();
g_set_wait_obj(mm->resize_ready);
return 0;
}
/******************************************************************************/
static int
dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
@ -1269,7 +1520,8 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
list_add_item(wm->mm->resize_queue, (tintptr)display_size_data);
g_set_wait_obj(wm->mm->resize_ready);
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_data:"
" received width %d, received height %d.", display_size_data->session_width, display_size_data->session_height);
" received width %d, received height %d.",
display_size_data->session_width, display_size_data->session_height);
return 0;
}
@ -1289,6 +1541,9 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
int error = 0;
struct xrdp_mm *mm;
struct xrdp_mod *module;
struct xrdp_rdp *rdp;
struct xrdp_sec *sec;
struct xrdp_channel *chan;
LOG_DEVEL(LOG_LEVEL_TRACE, "process_display_control_monitor_layout_data:");
@ -1326,6 +1581,56 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
xrdp_encoder_delete(mm->encoder);
mm->encoder = NULL;
}
if (mm->egfx == 0)
{
advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE);
}
else
{
advance_resize_state_machine(mm, WMRZ_EGFX_DELETE_SURFACE);
}
break;
case WMRZ_EGFX_DELETE_SURFACE:
if (error == 0 && module != 0)
{
xrdp_egfx_shutdown_delete_surface(mm->egfx);
}
advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSE);
break;
case WMRZ_EGFX_CONN_CLOSE:
if (error == 0 && module != 0)
{
xrdp_egfx_shutdown_close_connection(wm->mm->egfx);
}
advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSING);
break;
// Also processed in xrdp_egfx_close_response
case WMRZ_EGFX_CONN_CLOSING:
rdp = (struct xrdp_rdp *) (mm->wm->session->rdp);
sec = rdp->sec_layer;
chan = sec->chan_layer;
// Continue to check to see if the connection is closed. If it
// ever is, advance the state machine!
if (chan->drdynvcs[mm->egfx->channel_id].status
== XRDP_DRDYNVC_STATUS_CLOSED
|| (g_time3() - description->last_state_update_timestamp) > 100)
{
advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSED);
break;
}
g_set_wait_obj(mm->resize_ready);
break;
case WMRZ_EGFX_CONN_CLOSED:
advance_resize_state_machine(mm, WRMZ_EGFX_DELETE);
break;
case WRMZ_EGFX_DELETE:
if (error == 0 && module != 0)
{
xrdp_egfx_shutdown_delete(wm->mm->egfx);
mm->egfx = NULL;
mm->egfx_up = 0;
}
advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE);
break;
case WMRZ_SERVER_MONITOR_RESIZE:
@ -1338,9 +1643,10 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
" mod_server_monitor_resize failed %d", error);
return advance_error(error, mm);
}
advance_resize_state_machine(mm, WMRZ_SERVER_VERSION_MESSAGE);
advance_resize_state_machine(
mm, WMRZ_SERVER_VERSION_MESSAGE_START);
break;
case WMRZ_SERVER_VERSION_MESSAGE:
case WMRZ_SERVER_VERSION_MESSAGE_START:
error = module->mod_server_version_message(module);
if (error != 0)
{
@ -1349,6 +1655,12 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
" mod_server_version_message failed %d", error);
return advance_error(error, mm);
}
advance_resize_state_machine(
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING);
break;
// Not processed here. Processed in server_reset
// case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING:
case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED:
advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESIZE);
break;
case WMRZ_XRDP_CORE_RESIZE:
@ -1400,6 +1712,22 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
return advance_error(error, mm);
}
sync_dynamic_monitor_data(wm, &(description->description));
advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZE);
break;
case WMRZ_EGFX_INITIALIZE:
if (error == 0 && mm->egfx == NULL && mm->egfx_up == 0)
{
egfx_initialize(mm);
advance_resize_state_machine(mm, WMRZ_EGFX_INITALIZING);
}
else
{
advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZED);
}
break;
// Not processed here. Processed in xrdp_mm_egfx_caps_advertise
// case WMRZ_EGFX_INITALIZING:
case WMRZ_EGFX_INITIALIZED:
advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE);
break;
case WMRZ_ENCODER_CREATE:
@ -1450,7 +1778,7 @@ dynamic_monitor_process_queue(struct xrdp_mm *self)
return 0;
}
if (self->resize_data == NULL)
if (self->resize_data == NULL && self->resize_queue != NULL)
{
if (self->resize_queue->count <= 0)
{
@ -1518,6 +1846,11 @@ dynamic_monitor_process_queue(struct xrdp_mm *self)
" Resize data is not null.");
}
if (self->resize_data == NULL)
{
return 0;
}
if (self->resize_data->state == WMRZ_COMPLETE)
{
LOG(LOG_LEVEL_INFO, "dynamic_monitor_process_queue: Clearing"
@ -1552,6 +1885,8 @@ dynamic_monitor_initialize(struct xrdp_mm *self)
struct xrdp_drdynvc_procs d_procs;
int flags;
int error;
char buf[1024];
int pid;
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_initialize:");
@ -1567,9 +1902,20 @@ dynamic_monitor_initialize(struct xrdp_mm *self)
&(self->dynamic_monitor_chanid));
if (error != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mm_drdynvc_up: "
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_initialize: "
"libxrdp_drdynvc_open failed %d", error);
return error;
}
// Initialize xrdp_mm specific variables.
self->resize_queue = list_create();
self->resize_queue->auto_free = 1;
pid = g_getpid();
/* setup wait objects for signaling */
g_snprintf(buf, sizeof(buf), "xrdp_%8.8x_resize_ready", pid);
self->resize_ready = g_create_wait_obj(buf);
self->resize_data = NULL;
return error;
}
@ -1583,6 +1929,12 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self)
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_drdynvc_up:");
error = egfx_initialize(self);
if (error != 0)
{
return error;
}
enable_dynamic_resize = xrdp_mm_get_value(self, "enable_dynamic_resizing");
/*
* User can disable dynamic resizing if necessary
@ -1593,10 +1945,17 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self)
LOG(LOG_LEVEL_INFO, "User has disabled dynamic resizing.");
return error;
}
ignore_marker = (struct display_control_monitor_layout_data *)
g_malloc(sizeof(struct display_control_monitor_layout_data), 1);
list_add_item(self->resize_queue, (tintptr)ignore_marker);
error = dynamic_monitor_initialize(self);
if (error != 0)
{
LOG(LOG_LEVEL_INFO, "Dynamic monitor initialize failed."
" Client likely does not support it.");
return error;
}
ignore_marker = (struct display_control_monitor_layout_data *)
g_malloc(sizeof(struct display_control_monitor_layout_data),
1);
list_add_item(self->resize_queue, (tintptr)ignore_marker);
return error;
}
@ -2795,7 +3154,10 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
}
}
#define MIN_MS_BETWEEN_FRAMES 40
/* can not change this to zero yet, g_obj_wait in os_calls.c treats
everything less then 1 to mean wait forever */
#define MIN_MS_TO_WAIT_FOR_MORE_UPDATES 1
/*****************************************************************************/
int
xrdp_mm_get_wait_objs(struct xrdp_mm *self,
@ -2842,6 +3204,25 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self,
read_objs[(*rcount)++] = self->resize_ready;
}
if (self->wm->screen_dirty_region != NULL)
{
if (xrdp_region_not_empty(self->wm->screen_dirty_region))
{
int now = g_time3();
int next_screen_draw_time = self->wm->last_screen_draw_time +
MIN_MS_BETWEEN_FRAMES;
int diff = next_screen_draw_time - now;
int ltimeout = *timeout;
diff = MAX(diff, MIN_MS_TO_WAIT_FOR_MORE_UPDATES);
diff = MIN(diff, MIN_MS_BETWEEN_FRAMES);
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_get_wait_objs:"
" not empty diff %d", diff);
if ((ltimeout < 0) || (ltimeout > diff))
{
*timeout = diff;
}
}
}
return rv;
}
@ -2919,28 +3300,6 @@ xrdp_mm_check_chan(struct xrdp_mm *self)
return 0;
}
/*****************************************************************************/
static int
xrdp_mm_update_module_frame_ack(struct xrdp_mm *self)
{
int fif;
struct xrdp_encoder *encoder;
encoder = self->encoder;
fif = encoder->frames_in_flight;
if (encoder->frame_id_client + fif > encoder->frame_id_server)
{
if (encoder->frame_id_server > encoder->frame_id_server_sent)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_update_module_ack: frame_id_server %d",
encoder->frame_id_server);
encoder->frame_id_server_sent = encoder->frame_id_server;
self->mod->mod_frame_ack(self->mod, 0, encoder->frame_id_server);
}
}
return 0;
}
/*****************************************************************************/
static int
xrdp_mm_process_enc_done(struct xrdp_mm *self)
@ -2973,22 +3332,45 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self)
cy = enc_done->cy;
if (enc_done->comp_bytes > 0)
{
if (!enc_done->continuation)
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_process_enc_done: "
"x %d y %d cx %d cy %d frame_id %d use_frame_acks %d",
x, y, cx, cy, enc_done->enc->frame_id,
self->wm->client_info->use_frame_acks);
if (enc_done->flags & GFX_H264)
{
libxrdp_fastpath_send_frame_marker(self->wm->session, 0,
enc_done->enc->frame_id);
LOG(LOG_LEVEL_INFO, "GFX H264 Unimplemeted.");
}
libxrdp_fastpath_send_surface(self->wm->session,
enc_done->comp_pad_data,
enc_done->pad_bytes,
enc_done->comp_bytes,
x, y, x + cx, y + cy,
32, self->encoder->codec_id,
cx, cy);
if (enc_done->last)
else if (enc_done->flags & GFX_PROGRESSIVE_RFX) /* gfx progressive rfx */
{
libxrdp_fastpath_send_frame_marker(self->wm->session, 1,
enc_done->enc->frame_id);
xrdp_egfx_send_frame_start(self->egfx,
enc_done->enc->frame_id, 0);
xrdp_egfx_send_wire_to_surface2(self->egfx,
self->egfx->surface_id, 9, 1,
XR_PIXEL_FORMAT_XRGB_8888,
enc_done->comp_pad_data
+ enc_done->pad_bytes,
enc_done->comp_bytes);
xrdp_egfx_send_frame_end(self->egfx, enc_done->enc->frame_id);
}
else
{
if (!enc_done->continuation)
{
libxrdp_fastpath_send_frame_marker(self->wm->session, 0,
enc_done->enc->frame_id);
}
libxrdp_fastpath_send_surface(self->wm->session,
enc_done->comp_pad_data,
enc_done->pad_bytes,
enc_done->comp_bytes,
x, y, x + cx, y + cy,
32, self->encoder->codec_id,
cx, cy);
if (enc_done->last)
{
libxrdp_fastpath_send_frame_marker(self->wm->session, 1,
enc_done->enc->frame_id);
}
}
}
/* free enc_done */
@ -2996,16 +3378,35 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self)
{
enc = enc_done->enc;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_process_enc_done: last set");
if (self->wm->client_info->use_frame_acks == 0)
if (enc_done->flags & GFX_H264) /* gfx */
{
self->mod->mod_frame_ack(self->mod,
enc->flags,
enc->frame_id);
if (self->encoder->gfx_ack_off)
{
/* gfx and client turned off client frame acks */
self->mod->mod_frame_ack(self->mod,
enc->flags,
enc->frame_id);
}
else
{
self->encoder->frame_id_server = enc->frame_id;
xrdp_mm_update_module_frame_ack(self);
}
}
else
{
self->encoder->frame_id_server = enc->frame_id;
xrdp_mm_update_module_frame_ack(self);
if (self->wm->client_info->use_frame_acks == 0)
{
/* surface commmand and client does not do frame acks */
self->mod->mod_frame_ack(self->mod,
enc->flags,
enc->frame_id);
}
else
{
self->encoder->frame_id_server = enc_done->enc->frame_id;
xrdp_mm_update_module_frame_ack(self);
}
}
g_free(enc->drects);
g_free(enc->crects);
@ -3143,8 +3544,9 @@ xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id)
return 1;
}
encoder = self->encoder;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack: incoming %d, client %d, server %d",
frame_id, encoder->frame_id_client, encoder->frame_id_server);
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mm_frame_ack: "
"incoming %d, client %d, server %d", frame_id,
encoder->frame_id_client, encoder->frame_id_server);
if ((frame_id < 0) || (frame_id > encoder->frame_id_server))
{
/* if frame_id is negative or bigger then what server last sent
@ -3389,9 +3791,11 @@ server_paint_rects(struct xrdp_mod *mod, int num_drects, short *drects,
/*****************************************************************************/
int
server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects,
int num_crects, short *crects, char *data,
int left, int top, int width, int height,
server_paint_rects_ex(struct xrdp_mod *mod,
int num_drects, short *drects,
int num_crects, short *crects,
char *data, int left, int top,
int width, int height,
int flags, int frame_id,
void *shmem_ptr, int shmem_bytes)
{
@ -3406,7 +3810,7 @@ server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects,
wm = (struct xrdp_wm *)(mod->wm);
mm = wm->mm;
LOG_DEVEL(LOG_LEVEL_DEBUG, "server_paint_rects: %p", mm->encoder);
LOG(LOG_LEVEL_TRACE, "server_paint_rects_ex: %p", mm->encoder);
if (mm->encoder != 0)
{
@ -3477,7 +3881,12 @@ server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects,
return 0;
}
LOG(LOG_LEVEL_TRACE, "server_paint_rects:");
if (wm->client_info->gfx)
{
LOG(LOG_LEVEL_DEBUG, "server_paint_rects: gfx session and no encoder");
mm->mod->mod_frame_ack(mm->mod, flags, frame_id);
return 0;
}
p = (struct xrdp_painter *)(mod->painter);
if (p == 0)
@ -3796,8 +4205,16 @@ int
server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
{
struct xrdp_wm *wm;
struct xrdp_mm *mm;
LOG(LOG_LEVEL_TRACE, "server_reset:");
wm = (struct xrdp_wm *)(mod->wm);
if (wm == 0)
{
return 1;
}
mm = wm->mm;
if (wm->client_info == 0)
{
@ -3810,6 +4227,42 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
return 0;
}
// bpp of zero is impossible.
// This is a signal from xup that
// It is finished resizing.
if (bpp == 0)
{
if (mm == 0)
{
return 1;
}
if (!xrdp_wm_can_resize(wm))
{
return 1;
}
if (mm->resize_data == NULL)
{
mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height);
return 0;
}
if (mm->resize_data != NULL
&& mm->resize_data->state
== WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING)
{
LOG(LOG_LEVEL_INFO,
"server_reset: Advancing server monitor resized.");
advance_resize_state_machine(
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED);
}
else if (mm->resize_data != NULL
&& mm->resize_data->description.session_height == 0
&& mm->resize_data->description.session_width == 0)
{
mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height);
}
return 0;
}
/* if same (and only one monitor on client) don't need to do anything */
if (wm->client_info->display_sizes.session_width == (uint32_t)width &&
wm->client_info->display_sizes.session_height == (uint32_t)height &&

View File

@ -28,6 +28,7 @@
#include "xrdp_constants.h"
#include "fifo.h"
#include "guid.h"
#include "xrdp_client_info.h"
#define MAX_NR_CHANNELS 16
#define MAX_CHANNEL_NAME 16
@ -343,7 +344,9 @@ enum display_resize_state
WMRZ_EGFX_CONN_CLOSED,
WRMZ_EGFX_DELETE,
WMRZ_SERVER_MONITOR_RESIZE,
WMRZ_SERVER_VERSION_MESSAGE,
WMRZ_SERVER_VERSION_MESSAGE_START,
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING,
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED,
WMRZ_XRDP_CORE_RESIZE,
WMRZ_EGFX_INITIALIZE,
WMRZ_EGFX_INITALIZING,
@ -362,7 +365,12 @@ enum display_resize_state
(status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \
(status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \
(status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \
(status) == WMRZ_SERVER_VERSION_MESSAGE ? "WMRZ_SERVER_VERSION_MESSAGE" : \
(status) == WMRZ_SERVER_VERSION_MESSAGE_START ? \
"WMRZ_SERVER_VERSION_MESSAGE_START" : \
(status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING ? \
"WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING" : \
(status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED ? \
"WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED" : \
(status) == WMRZ_XRDP_CORE_RESIZE ? "WMRZ_XRDP_CORE_RESIZE" : \
(status) == WMRZ_EGFX_INITIALIZE ? "WMRZ_EGFX_INITIALIZE" : \
(status) == WMRZ_EGFX_INITALIZING ? "WMRZ_EGFX_INITALIZING" : \
@ -417,7 +425,7 @@ struct xrdp_mm
int dynamic_monitor_chanid;
struct xrdp_egfx *egfx;
int egfx_up;
int egfx_flags;
enum xrdp_egfx_flags egfx_flags;
int gfx_delay_autologin;
/* Resize on-the-fly control */
struct display_control_monitor_layout_data *resize_data;

175
xup/xup.c
View File

@ -1174,47 +1174,33 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
in_uint16_le(s, height);
bmpdata = 0;
if (flags == 0) /* screen */
if (amod->screen_shmem_id_mapped == 0)
{
/* Do we need to map (or remap) the memory
* area shared with the X server ? */
if (amod->screen_shmem_id_mapped == 0 ||
amod->screen_shmem_id != shmem_id)
amod->screen_shmem_id = shmem_id;
amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
if (amod->screen_shmem_pixels == (void *) -1)
{
if (amod->screen_shmem_id_mapped != 0)
{
g_shmdt(amod->screen_shmem_pixels);
}
amod->screen_shmem_pixels = (char *) g_shmat(shmem_id);
if (amod->screen_shmem_pixels == (void *) -1)
{
/* failed */
if (amod->screen_shmem_id_mapped == 0)
{
LOG(LOG_LEVEL_ERROR,
"Can't attach to shared memory id %d [%s]",
shmem_id, g_get_strerror());
}
else
{
LOG(LOG_LEVEL_ERROR,
"Can't attach to shared memory id %d from id %d [%s]",
shmem_id, amod->screen_shmem_id, g_get_strerror());
}
amod->screen_shmem_id = 0;
amod->screen_shmem_pixels = 0;
amod->screen_shmem_id_mapped = 0;
}
else
{
amod->screen_shmem_id = shmem_id;
amod->screen_shmem_id_mapped = 1;
}
/* failed */
amod->screen_shmem_id = 0;
amod->screen_shmem_pixels = 0;
amod->screen_shmem_id_mapped = 0;
}
if (amod->screen_shmem_pixels != 0)
else
{
bmpdata = amod->screen_shmem_pixels + shmem_offset;
amod->screen_shmem_id_mapped = 1;
}
}
else if (amod->screen_shmem_id != shmem_id)
{
amod->screen_shmem_id = shmem_id;
g_shmdt(amod->screen_shmem_pixels);
amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
if (amod->screen_shmem_pixels == (void *) -1)
{
/* failed */
amod->screen_shmem_id = 0;
amod->screen_shmem_pixels = 0;
amod->screen_shmem_id_mapped = 0;
}
}
else
@ -1225,7 +1211,10 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
flags, frame_id, shmem_id, shmem_offset,
width, height);
}
if (amod->screen_shmem_pixels != 0)
{
bmpdata = amod->screen_shmem_pixels + shmem_offset;
}
if (bmpdata != 0)
{
rv = amod->server_paint_rects(amod, num_drects, ldrects,
@ -1238,9 +1227,6 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
rv = 1;
}
//LOG_DEVEL(LOG_LEVEL_TRACE, "frame_id %d", frame_id);
//send_paint_rect_ex_ack(amod, flags, frame_id);
g_free(lcrects);
g_free(ldrects);
@ -1680,74 +1666,71 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
char *phold;
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message:");
in_uint16_le(s, type);
in_uint16_le(s, num_orders);
in_uint32_le(s, len);
LOG_DEVEL(LOG_LEVEL_DEBUG, "lib_mod_process_message: type %d", type);
rv = 0;
if (rv == 0)
if (type == 1) /* original order list */
{
in_uint16_le(s, type);
in_uint16_le(s, num_orders);
in_uint32_le(s, len);
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message: type %d", type);
if (type == 1) /* original order list */
for (index = 0; index < num_orders; index++)
{
for (index = 0; index < num_orders; index++)
{
in_uint16_le(s, type);
rv = lib_mod_process_orders(mod, type, s);
in_uint16_le(s, type);
rv = lib_mod_process_orders(mod, type, s);
if (rv != 0)
{
if (rv != 0)
{
break;
}
}
}
else if (type == 2) /* caps */
{
LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: type 2 len %d", len);
for (index = 0; index < num_orders; index++)
{
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, len);
switch (type)
{
default:
LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: unknown"
" cap type %d len %d",
type, len);
break;
}
}
s->p = phold + len;
}
else if (type == 2) /* caps */
lib_send_client_info(mod);
}
else if (type == 3) /* order list with len after type */
{
LOG_DEVEL(LOG_LEVEL_INFO,
"lib_mod_process_message: type 3 len %d", len);
for (index = 0; index < num_orders; index++)
{
LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: type 2 len %d", len);
for (index = 0; index < num_orders; index++)
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, len);
rv = lib_mod_process_orders(mod, type, s);
if (rv != 0)
{
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, len);
switch (type)
{
default:
LOG_DEVEL(LOG_LEVEL_TRACE,
"lib_mod_process_message: unknown"
" cap type %d len %d",
type, len);
break;
}
s->p = phold + len;
break;
}
lib_send_client_info(mod);
}
else if (type == 3) /* order list with len after type */
{
for (index = 0; index < num_orders; index++)
{
phold = s->p;
in_uint16_le(s, type);
in_uint16_le(s, len);
rv = lib_mod_process_orders(mod, type, s);
if (rv != 0)
{
break;
}
s->p = phold + len;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type);
s->p = phold + len;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type);
}
return rv;
}