Merge pull request #2891 from neutrinolabs/gfx_mainline_merge_work
Gfx mainline merge work
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
url = https://github.com/neutrinolabs/librfxcodec.git
|
url = https://github.com/neutrinolabs/librfxcodec.git
|
||||||
branch = .
|
branch = .
|
||||||
ignore = untracked
|
ignore = untracked
|
||||||
|
|
||||||
[submodule "libpainter"]
|
[submodule "libpainter"]
|
||||||
path = libpainter
|
path = libpainter
|
||||||
url = https://github.com/neutrinolabs/libpainter.git
|
url = https://github.com/neutrinolabs/libpainter.git
|
||||||
|
|||||||
+1
-1
@@ -71,6 +71,6 @@ libcommon_la_SOURCES = \
|
|||||||
$(PIXMAN_SOURCES)
|
$(PIXMAN_SOURCES)
|
||||||
|
|
||||||
libcommon_la_LIBADD = \
|
libcommon_la_LIBADD = \
|
||||||
-lpthread \
|
-lpthread -lrt \
|
||||||
$(OPENSSL_LIBS) \
|
$(OPENSSL_LIBS) \
|
||||||
$(DLOPEN_LIBS)
|
$(DLOPEN_LIBS)
|
||||||
|
|||||||
+26
-12
@@ -52,19 +52,29 @@
|
|||||||
|
|
||||||
/* TS_UD_HEADER: type ((2.2.1.3.1) */
|
/* TS_UD_HEADER: type ((2.2.1.3.1) */
|
||||||
/* TODO: to be renamed */
|
/* TODO: to be renamed */
|
||||||
#define SEC_TAG_CLI_INFO 0xc001 /* CS_CORE? */
|
#define SEC_TAG_CLI_INFO 0xc001 /* CS_CORE? */
|
||||||
#define SEC_TAG_CLI_CRYPT 0xc002 /* CS_SECURITY? */
|
#define SEC_TAG_CLI_CRYPT 0xc002 /* CS_SECURITY? */
|
||||||
#define SEC_TAG_CLI_CHANNELS 0xc003 /* CS_CHANNELS? */
|
#define SEC_TAG_CLI_CHANNELS 0xc003 /* CS_CHANNELS? */
|
||||||
#define SEC_TAG_CLI_4 0xc004 /* CS_CLUSTER? */
|
#define SEC_TAG_CLI_4 0xc004 /* CS_CLUSTER? */
|
||||||
#define SEC_TAG_CLI_MONITOR 0xc005 /* CS_MONITOR */
|
#define SEC_TAG_CLI_MONITOR 0xc005 /* CS_MONITOR */
|
||||||
#define SEC_TAG_CLI_MONITOR_EX 0xc008 /* CS_MONITOR_EX */
|
#define SEC_TAG_CLI_MONITOR_EX 0xc008 /* CS_MONITOR_EX */
|
||||||
|
|
||||||
/* Client Core Data: colorDepth, postBeta2ColorDepth (2.2.1.3.2) */
|
/* Client Core Data: colorDepth, postBeta2ColorDepth (2.2.1.3.2) */
|
||||||
#define RNS_UD_COLOR_4BPP 0xCA00
|
#define RNS_UD_COLOR_4BPP 0xCA00
|
||||||
#define RNS_UD_COLOR_8BPP 0xCA01
|
#define RNS_UD_COLOR_8BPP 0xCA01
|
||||||
#define RNS_UD_COLOR_16BPP_555 0xCA02
|
#define RNS_UD_COLOR_16BPP_555 0xCA02
|
||||||
#define RNS_UD_COLOR_16BPP_565 0xCA03
|
#define RNS_UD_COLOR_16BPP_565 0xCA03
|
||||||
#define RNS_UD_COLOR_24BPP 0xCA04
|
#define RNS_UD_COLOR_24BPP 0xCA04
|
||||||
|
|
||||||
|
/* Client Core Data: supportedColorDepths (2.2.1.3.2) */
|
||||||
|
#define RNS_UD_24BPP_SUPPORT 0x0001
|
||||||
|
#define RNS_UD_16BPP_SUPPORT 0x0002
|
||||||
|
#define RNS_UD_15BPP_SUPPORT 0x0004
|
||||||
|
#define RNS_UD_32BPP_SUPPORT 0x0008
|
||||||
|
|
||||||
|
/* Client Core Data: earlyCapabilityFlags (2.2.1.3.2) */
|
||||||
|
#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002
|
||||||
|
#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100
|
||||||
|
|
||||||
/* Client Core Data: connectionType (2.2.1.3.2) */
|
/* Client Core Data: connectionType (2.2.1.3.2) */
|
||||||
#define CONNECTION_TYPE_MODEM 0x01
|
#define CONNECTION_TYPE_MODEM 0x01
|
||||||
@@ -75,11 +85,15 @@
|
|||||||
#define CONNECTION_TYPE_LAN 0x06
|
#define CONNECTION_TYPE_LAN 0x06
|
||||||
#define CONNECTION_TYPE_AUTODETECT 0x07
|
#define CONNECTION_TYPE_AUTODETECT 0x07
|
||||||
|
|
||||||
/* Channel definition structure CHANNEL_DEF (2.2.1.3.4.1) */
|
/* TS_UD_CS_NET (2.2.1.3.4) */
|
||||||
/* This isn't explicitly named in MS-RDPBCGR */
|
/* This isn't explicitly named in MS-RDPBCGR */
|
||||||
|
#define MAX_STATIC_CHANNELS 31
|
||||||
|
|
||||||
|
/* Channel definition structure CHANNEL_DEF (2.2.1.3.4.1) */
|
||||||
#define CHANNEL_NAME_LEN 7
|
#define CHANNEL_NAME_LEN 7
|
||||||
/* These names are also not explicitly defined in MS-RDPBCGR */
|
/* These names are also not explicitly defined in MS-RDPBCGR */
|
||||||
#define CLIPRDR_SVC_CHANNEL_NAME "cliprdr"
|
#define CLIPRDR_SVC_CHANNEL_NAME "cliprdr"
|
||||||
|
#define DRDYNVC_SVC_CHANNEL_NAME "drdynvc"
|
||||||
#define RAIL_SVC_CHANNEL_NAME "rail"
|
#define RAIL_SVC_CHANNEL_NAME "rail"
|
||||||
#define RDPSND_SVC_CHANNEL_NAME "rdpsnd"
|
#define RDPSND_SVC_CHANNEL_NAME "rdpsnd"
|
||||||
#define RDPDR_SVC_CHANNEL_NAME "rdpdr"
|
#define RDPDR_SVC_CHANNEL_NAME "rdpdr"
|
||||||
|
|||||||
+10
-2
@@ -1974,7 +1974,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
|
|||||||
handles[j++] = (HANDLE)(write_objs[i]);
|
handles[j++] = (HANDLE)(write_objs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mstimeout < 1)
|
if (mstimeout < 0)
|
||||||
{
|
{
|
||||||
mstimeout = INFINITE;
|
mstimeout = INFINITE;
|
||||||
}
|
}
|
||||||
@@ -2011,7 +2011,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mstimeout < 1)
|
if (mstimeout < 0)
|
||||||
{
|
{
|
||||||
mstimeout = -1;
|
mstimeout = -1;
|
||||||
}
|
}
|
||||||
@@ -4199,3 +4199,11 @@ g_no_new_privs(void)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void
|
||||||
|
g_qsort(void *base, size_t nitems, size_t size,
|
||||||
|
int (*compar)(const void *, const void *))
|
||||||
|
{
|
||||||
|
qsort(base, nitems, size, compar);
|
||||||
|
}
|
||||||
|
|||||||
+7
-1
@@ -203,10 +203,13 @@ int g_delete_wait_obj(tintptr obj);
|
|||||||
* @param rcount Number of elements in read_objs
|
* @param rcount Number of elements in read_objs
|
||||||
* @param write_objs Array of write objects
|
* @param write_objs Array of write objects
|
||||||
* @param rcount Number of elements in write_objs
|
* @param rcount Number of elements in write_objs
|
||||||
* @param mstimeout Timeout in milliseconds. <= 0 means an infinite timeout.
|
* @param mstimeout Timeout in milliseconds. < 0 means an infinite timeout.
|
||||||
*
|
*
|
||||||
* @return 0 for success. The objects will need to be polled to
|
* @return 0 for success. The objects will need to be polled to
|
||||||
* find out what is readable or writeable.
|
* find out what is readable or writeable.
|
||||||
|
*
|
||||||
|
* An mstimeout of zero will return immediately, although
|
||||||
|
* error conditions may be checked for.
|
||||||
*/
|
*/
|
||||||
int g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs,
|
int g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs,
|
||||||
int wcount, int mstimeout);
|
int wcount, int mstimeout);
|
||||||
@@ -397,6 +400,9 @@ int g_tcp4_bind_address(int sck, const char *port, const char *address);
|
|||||||
int g_tcp6_socket(void);
|
int g_tcp6_socket(void);
|
||||||
int g_tcp6_bind_address(int sck, const char *port, const char *address);
|
int g_tcp6_bind_address(int sck, const char *port, const char *address);
|
||||||
int g_no_new_privs(void);
|
int g_no_new_privs(void);
|
||||||
|
void
|
||||||
|
g_qsort(void *base, size_t nitems, size_t size,
|
||||||
|
int (*compar)(const void *, const void *));
|
||||||
|
|
||||||
/* glib-style wrappers */
|
/* glib-style wrappers */
|
||||||
#define g_new(struct_type, n_structs) \
|
#define g_new(struct_type, n_structs) \
|
||||||
|
|||||||
@@ -199,7 +199,9 @@ struct xrdp_client_info
|
|||||||
int no_orders_supported;
|
int no_orders_supported;
|
||||||
int use_cache_glyph_v2;
|
int use_cache_glyph_v2;
|
||||||
int rail_enable;
|
int rail_enable;
|
||||||
int suppress_output;
|
// Mask of reasons why output may be suppressed
|
||||||
|
// (see enum suppress_output_reason)
|
||||||
|
unsigned int suppress_output_mask;
|
||||||
|
|
||||||
int enable_token_login;
|
int enable_token_login;
|
||||||
char domain_user_separator[16];
|
char domain_user_separator[16];
|
||||||
@@ -215,8 +217,24 @@ struct xrdp_client_info
|
|||||||
unsigned int session_physical_height; /* in mm */
|
unsigned int session_physical_height; /* in mm */
|
||||||
|
|
||||||
int large_pointer_support_flags;
|
int large_pointer_support_flags;
|
||||||
|
int gfx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xrdp_encoder_flags
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
ENCODE_COMPLETE = 1 << 0,
|
||||||
|
GFX_PROGRESSIVE_RFX = 1 << 1,
|
||||||
|
GFX_H264 = 1 << 2,
|
||||||
|
KEY_FRAME_REQUESTED = 1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if output is suppressed for a particular reason
|
||||||
|
*/
|
||||||
|
#define OUTPUT_SUPPRESSED_FOR_REASON(ci,reason) \
|
||||||
|
(((ci)->suppress_output_mask & (unsigned int)reason) != 0)
|
||||||
|
|
||||||
/* yyyymmdd of last incompatible change to xrdp_client_info */
|
/* yyyymmdd of last incompatible change to xrdp_client_info */
|
||||||
/* also used for changes to all the xrdp installed headers */
|
/* also used for changes to all the xrdp installed headers */
|
||||||
#define CLIENT_INFO_CURRENT_VERSION 20230425
|
#define CLIENT_INFO_CURRENT_VERSION 20230425
|
||||||
|
|||||||
@@ -291,4 +291,50 @@
|
|||||||
#define XR_RDP_SCAN_LSHIFT 42
|
#define XR_RDP_SCAN_LSHIFT 42
|
||||||
#define XR_RDP_SCAN_ALT 56
|
#define XR_RDP_SCAN_ALT 56
|
||||||
|
|
||||||
|
// Since we're not guaranteed to have pixman, copy these directives.
|
||||||
|
#define XRDP_PIXMAN_TYPE_ARGB 2
|
||||||
|
#define XRDP_PIXMAN_TYPE_ABGR 3
|
||||||
|
#define XRDP_PIXMAN_FORMAT(bpp,type,a,r,g,b) (((bpp) << 24) | \
|
||||||
|
((type) << 16) | \
|
||||||
|
((a) << 12) | \
|
||||||
|
((r) << 8) | \
|
||||||
|
((g) << 4) | \
|
||||||
|
((b)))
|
||||||
|
|
||||||
|
#define XRDP_a8b8g8r8 \
|
||||||
|
XRDP_PIXMAN_FORMAT(32, XRDP_PIXMAN_TYPE_ABGR, 8, 8, 8, 8)
|
||||||
|
|
||||||
|
#define XRDP_a8r8g8b8 \
|
||||||
|
XRDP_PIXMAN_FORMAT(32, XRDP_PIXMAN_TYPE_ARGB, 8, 8, 8, 8)
|
||||||
|
|
||||||
|
#define XRDP_r5g6b5 \
|
||||||
|
XRDP_PIXMAN_FORMAT(16, XRDP_PIXMAN_TYPE_ARGB, 0, 5, 6, 5)
|
||||||
|
|
||||||
|
#define XRDP_a1r5g5b5 \
|
||||||
|
XRDP_PIXMAN_FORMAT(16, XRDP_PIXMAN_TYPE_ARGB, 1, 5, 5, 5)
|
||||||
|
|
||||||
|
#define XRDP_r3g3b2 \
|
||||||
|
XRDP_PIXMAN_FORMAT(8, XRDP_PIXMAN_TYPE_ARGB, 0, 3, 3, 2)
|
||||||
|
|
||||||
|
// The last used constant in pixman is 63, so use 64+
|
||||||
|
#define XRDP_nv12 \
|
||||||
|
XRDP_PIXMAN_FORMAT(12, 64, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
#define XRDP_i420 \
|
||||||
|
XRDP_PIXMAN_FORMAT(12, 65, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
#define XRDP_nv12_709fr \
|
||||||
|
XRDP_PIXMAN_FORMAT(12, 66, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
#define XRDP_yuv444_709fr \
|
||||||
|
XRDP_PIXMAN_FORMAT(32, 67, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/8131c1bc-1af8-4907-a05a-f72f4581160f
|
||||||
|
#define XRDP_yuv444_v1_stream_709fr \
|
||||||
|
XRDP_PIXMAN_FORMAT(32, 68, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/781406c3-5e24-4f2b-b6ff-42b76bf64f6d
|
||||||
|
#define XRDP_yuv444_v2_stream_709fr \
|
||||||
|
XRDP_PIXMAN_FORMAT(32, 69, 0, 0, 0, 0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ EnvironmentFile=-@sysconfdir@/sysconfig/xrdp
|
|||||||
EnvironmentFile=-@sysconfdir@/default/xrdp
|
EnvironmentFile=-@sysconfdir@/default/xrdp
|
||||||
ExecStart=@sbindir@/xrdp $XRDP_OPTIONS --nodaemon
|
ExecStart=@sbindir@/xrdp $XRDP_OPTIONS --nodaemon
|
||||||
SystemCallArchitectures=native
|
SystemCallArchitectures=native
|
||||||
SystemCallFilter=@basic-io @file-system @io-event @ipc @network-io @process @signal ioctl madvise sysinfo uname
|
SystemCallFilter=@basic-io @file-system @io-event @ipc @network-io @process
|
||||||
|
SystemCallFilter=@signal @system-service ioctl madvise sysinfo uname
|
||||||
|
SystemCallErrorNumber=EPERM
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
@@ -1181,6 +1181,12 @@ libxrdp_reset(struct xrdp_session *session,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop output from the client during the deactivation-reactivation
|
||||||
|
* sequence [MS-RDPBCGR] 1.3.1.3 */
|
||||||
|
xrdp_rdp_suppress_output((struct xrdp_rdp *)session->rdp, 1,
|
||||||
|
XSO_REASON_DEACTIVATE_REACTIVATE, 0, 0, 0, 0);
|
||||||
|
|
||||||
/* shut down the rdp client
|
/* shut down the rdp client
|
||||||
*
|
*
|
||||||
* When resetting the lib, disable application input checks, as
|
* When resetting the lib, disable application input checks, as
|
||||||
|
|||||||
@@ -403,6 +403,20 @@ int
|
|||||||
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s);
|
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s);
|
||||||
|
|
||||||
/* xrdp_rdp.c */
|
/* xrdp_rdp.c */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reasons why output is being suppressed or restarted
|
||||||
|
*/
|
||||||
|
enum suppress_output_reason
|
||||||
|
{
|
||||||
|
/// Client has requested suppress via TS_SUPPRESS_OUTPUT_PDU
|
||||||
|
XSO_REASON_CLIENT_REQUEST = (1 << 0),
|
||||||
|
/// Deactivation-Reactivation Sequence [MS-RDPBCGR] 1.3.1.3
|
||||||
|
XSO_REASON_DEACTIVATE_REACTIVATE = (1 << 1),
|
||||||
|
/// Dynamic resize in progress
|
||||||
|
XSO_REASON_DYNAMIC_RESIZE = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
struct xrdp_rdp *
|
struct xrdp_rdp *
|
||||||
xrdp_rdp_create(struct xrdp_session *session, struct trans *trans);
|
xrdp_rdp_create(struct xrdp_session *session, struct trans *trans);
|
||||||
void
|
void
|
||||||
@@ -438,6 +452,21 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self);
|
|||||||
int
|
int
|
||||||
xrdp_rdp_send_session_info(struct xrdp_rdp *self, const char *data,
|
xrdp_rdp_send_session_info(struct xrdp_rdp *self, const char *data,
|
||||||
int data_bytes);
|
int data_bytes);
|
||||||
|
/**
|
||||||
|
* Request output suppress or resume
|
||||||
|
*
|
||||||
|
* @param self RDP struct
|
||||||
|
* @param suppress (!= 0 for suppress, 0 for resume)
|
||||||
|
* @param reason Why the output is being suppressed or resumed
|
||||||
|
* @param left Left pixel of repaint area (ignored for suppress)
|
||||||
|
* @param top Top pixel of repaint area (ignored for suppress)
|
||||||
|
* @param right Right pixel of inclusive repaint area (ignored for suppress)
|
||||||
|
* @param bottom Bottom pixel of inclusive repaint area (ignored for suppress)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xrdp_rdp_suppress_output(struct xrdp_rdp *self, int suppress,
|
||||||
|
enum suppress_output_reason reason,
|
||||||
|
int left, int top, int right, int bottom);
|
||||||
|
|
||||||
/* xrdp_orders.c */
|
/* xrdp_orders.c */
|
||||||
struct xrdp_orders *
|
struct xrdp_orders *
|
||||||
|
|||||||
+78
-50
@@ -1292,6 +1292,20 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s)
|
|||||||
self->session->up_and_running = 1;
|
self->session->up_and_running = 1;
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "yeah, up_and_running");
|
LOG_DEVEL(LOG_LEVEL_INFO, "yeah, up_and_running");
|
||||||
xrdp_rdp_send_data_update_sync(self);
|
xrdp_rdp_send_data_update_sync(self);
|
||||||
|
|
||||||
|
/* This is also the end of an Deactivation-reactivation
|
||||||
|
* sequence [MS-RDPBCGR] 1.3.1.3 */
|
||||||
|
xrdp_rdp_suppress_output(self, 0, XSO_REASON_DEACTIVATE_REACTIVATE,
|
||||||
|
0, 0,
|
||||||
|
self->client_info.display_sizes.session_width,
|
||||||
|
self->client_info.display_sizes.session_height);
|
||||||
|
|
||||||
|
if (self->session->callback != 0)
|
||||||
|
{
|
||||||
|
/* call to xrdp_wm.c : callback */
|
||||||
|
self->session->callback(self->session->id, 0x555a, 0, 0,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
xrdp_channel_drdynvc_start(self->sec_layer->chan_layer);
|
xrdp_channel_drdynvc_start(self->sec_layer->chan_layer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1401,69 +1415,83 @@ xrdp_rdp_process_frame_ack(struct xrdp_rdp *self, struct stream *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void
|
||||||
|
xrdp_rdp_suppress_output(struct xrdp_rdp *self, int suppress,
|
||||||
|
enum suppress_output_reason reason,
|
||||||
|
int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
int old_suppress = self->client_info.suppress_output_mask != 0;
|
||||||
|
if (suppress)
|
||||||
|
{
|
||||||
|
self->client_info.suppress_output_mask |= (unsigned int)reason;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->client_info.suppress_output_mask &= ~(unsigned int)reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_suppress = self->client_info.suppress_output_mask != 0;
|
||||||
|
if (current_suppress != old_suppress && self->session->callback != 0)
|
||||||
|
{
|
||||||
|
self->session->callback(self->session->id, 0x5559, suppress,
|
||||||
|
MAKELONG(left, top),
|
||||||
|
MAKELONG(right, bottom), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Process a [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU message */
|
/* Process a [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU message */
|
||||||
static int
|
static int
|
||||||
xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s)
|
xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s)
|
||||||
{
|
{
|
||||||
|
int rv = 1;
|
||||||
int allowDisplayUpdates;
|
int allowDisplayUpdates;
|
||||||
int left;
|
int left;
|
||||||
int top;
|
int top;
|
||||||
int right;
|
int right;
|
||||||
int bottom;
|
int bottom;
|
||||||
|
|
||||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU"))
|
if (s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU"))
|
||||||
{
|
{
|
||||||
return 1;
|
in_uint8(s, allowDisplayUpdates);
|
||||||
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||||
|
"Received [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU "
|
||||||
|
"allowDisplayUpdates %d", allowDisplayUpdates);
|
||||||
|
switch (allowDisplayUpdates)
|
||||||
|
{
|
||||||
|
case 0: /* SUPPRESS_DISPLAY_UPDATES */
|
||||||
|
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||||
|
"Client requested display output to be suppressed");
|
||||||
|
xrdp_rdp_suppress_output(self, 1,
|
||||||
|
XSO_REASON_CLIENT_REQUEST,
|
||||||
|
0, 0, 0, 0);
|
||||||
|
rv = 0;
|
||||||
|
break;
|
||||||
|
case 1: /* ALLOW_DISPLAY_UPDATES */
|
||||||
|
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||||
|
"Client requested display output to be enabled");
|
||||||
|
if (s_check_rem_and_log(s, 11,
|
||||||
|
"Parsing [MS-RDPBCGR] Padding and TS_RECTANGLE16"))
|
||||||
|
{
|
||||||
|
in_uint8s(s, 3); /* pad */
|
||||||
|
in_uint16_le(s, left);
|
||||||
|
in_uint16_le(s, top);
|
||||||
|
in_uint16_le(s, right);
|
||||||
|
in_uint16_le(s, bottom);
|
||||||
|
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||||
|
"Received [MS-RDPBCGR] TS_RECTANGLE16 "
|
||||||
|
"left %d, top %d, right %d, bottom %d",
|
||||||
|
left, top, right, bottom);
|
||||||
|
xrdp_rdp_suppress_output(self, 0,
|
||||||
|
XSO_REASON_CLIENT_REQUEST,
|
||||||
|
left, top, right, bottom);
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in_uint8(s, allowDisplayUpdates);
|
return rv;
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU "
|
|
||||||
"allowDisplayUpdates %d", allowDisplayUpdates);
|
|
||||||
switch (allowDisplayUpdates)
|
|
||||||
{
|
|
||||||
case 0: /* SUPPRESS_DISPLAY_UPDATES */
|
|
||||||
self->client_info.suppress_output = 1;
|
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be suppressed");
|
|
||||||
if (self->session->callback != 0)
|
|
||||||
{
|
|
||||||
self->session->callback(self->session->id, 0x5559, 1,
|
|
||||||
0, 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
|
||||||
"Bug: no callback registered for xrdp_rdp_process_suppress");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1: /* ALLOW_DISPLAY_UPDATES */
|
|
||||||
self->client_info.suppress_output = 0;
|
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be enabled");
|
|
||||||
if (!s_check_rem_and_log(s, 11, "Parsing [MS-RDPBCGR] Padding and TS_RECTANGLE16"))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
in_uint8s(s, 3); /* pad */
|
|
||||||
in_uint16_le(s, left);
|
|
||||||
in_uint16_le(s, top);
|
|
||||||
in_uint16_le(s, right);
|
|
||||||
in_uint16_le(s, bottom);
|
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_RECTANGLE16 "
|
|
||||||
"left %d, top %d, right %d, bottom %d",
|
|
||||||
left, top, right, bottom);
|
|
||||||
if (self->session->callback != 0)
|
|
||||||
{
|
|
||||||
self->session->callback(self->session->id, 0x5559, 0,
|
|
||||||
MAKELONG(left, top),
|
|
||||||
MAKELONG(right, bottom), 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
|
||||||
"Bug: no callback registered for xrdp_rdp_process_suppress");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
+31
-8
@@ -2114,10 +2114,14 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
|
|||||||
in_uint16_le(s, supportedColorDepths);
|
in_uint16_le(s, supportedColorDepths);
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
|
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
|
||||||
"<Optional Field> supportedColorDepths %s",
|
"<Optional Field> supportedColorDepths %s",
|
||||||
supportedColorDepths == 0x0001 ? "RNS_UD_24BPP_SUPPORT" :
|
supportedColorDepths == RNS_UD_24BPP_SUPPORT
|
||||||
supportedColorDepths == 0x0002 ? "RNS_UD_16BPP_SUPPORT" :
|
? "RNS_UD_24BPP_SUPPORT" :
|
||||||
supportedColorDepths == 0x0004 ? "RNS_UD_15BPP_SUPPORT" :
|
supportedColorDepths == RNS_UD_16BPP_SUPPORT
|
||||||
supportedColorDepths == 0x0008 ? "RNS_UD_32BPP_SUPPORT" :
|
? "RNS_UD_16BPP_SUPPORT" :
|
||||||
|
supportedColorDepths == RNS_UD_15BPP_SUPPORT
|
||||||
|
? "RNS_UD_15BPP_SUPPORT" :
|
||||||
|
supportedColorDepths == RNS_UD_32BPP_SUPPORT
|
||||||
|
? "RNS_UD_32BPP_SUPPORT" :
|
||||||
"unknown");
|
"unknown");
|
||||||
|
|
||||||
if (!s_check_rem(s, 2))
|
if (!s_check_rem(s, 2))
|
||||||
@@ -2129,11 +2133,30 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
|
|||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
|
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
|
||||||
"<Optional Field> earlyCapabilityFlags 0x%4.4x",
|
"<Optional Field> earlyCapabilityFlags 0x%4.4x",
|
||||||
earlyCapabilityFlags);
|
earlyCapabilityFlags);
|
||||||
if ((earlyCapabilityFlags & 0x0002) && (supportedColorDepths & 0x0008))
|
if ((earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
|
||||||
|
&& (supportedColorDepths & RNS_UD_32BPP_SUPPORT))
|
||||||
{
|
{
|
||||||
client_info->bpp = 32;
|
client_info->bpp = 32;
|
||||||
}
|
}
|
||||||
|
#ifdef XRDP_RFXCODEC
|
||||||
|
if (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)
|
||||||
|
{
|
||||||
|
if (client_info->bpp < 32)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_WARNING,
|
||||||
|
"client requested gfx protocol with insufficient color depth");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_INFO, "client supports gfx protocol");
|
||||||
|
self->rdp_layer->client_info.gfx = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_INFO, "client DOES NOT support gfx");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (!s_check_rem(s, 64))
|
if (!s_check_rem(s, 64))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2365,10 +2388,10 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
|
|||||||
in_uint32_le(s, num_channels);
|
in_uint32_le(s, num_channels);
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_NET "
|
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_NET "
|
||||||
"channelCount %d", num_channels);
|
"channelCount %d", num_channels);
|
||||||
if (num_channels > 31)
|
if (num_channels > MAX_STATIC_CHANNELS)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Protocol error: too many channels requested. "
|
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Protocol error: too many channels requested. "
|
||||||
"max 31, received %d", num_channels);
|
"max %d, received %d", MAX_STATIC_CHANNELS, num_channels);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1790,8 +1790,10 @@ lfreerdp_pre_connect(freerdp *instance)
|
|||||||
int index;
|
int index;
|
||||||
int error;
|
int error;
|
||||||
int num_chans;
|
int num_chans;
|
||||||
|
int target_chan;
|
||||||
int ch_flags;
|
int ch_flags;
|
||||||
char ch_name[256];
|
char ch_name[256];
|
||||||
|
const char *ch_names[MAX_STATIC_CHANNELS];
|
||||||
char *dst_ch_name;
|
char *dst_ch_name;
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_pre_connect:");
|
LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_pre_connect:");
|
||||||
@@ -1805,6 +1807,7 @@ lfreerdp_pre_connect(freerdp *instance)
|
|||||||
num_chans = 0;
|
num_chans = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target_chan = 0;
|
||||||
for (index = 0 ; index < num_chans; ++index)
|
for (index = 0 ; index < num_chans; ++index)
|
||||||
{
|
{
|
||||||
error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
|
error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
|
||||||
@@ -1813,21 +1816,31 @@ lfreerdp_pre_connect(freerdp *instance)
|
|||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pre_connect: "
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pre_connect: "
|
||||||
"got channel [%s], id [%d], flags [0x%8.8x]",
|
"got channel [%s], id [%d], flags [0x%8.8x]",
|
||||||
ch_name, index, ch_flags);
|
ch_name, index, ch_flags);
|
||||||
dst_ch_name = instance->settings->channels[index].name;
|
|
||||||
g_memset(dst_ch_name, 0, 8);
|
if (g_strcmp(ch_name, DRDYNVC_SVC_CHANNEL_NAME) == 0)
|
||||||
g_snprintf(dst_ch_name, 8, "%s", ch_name);
|
{
|
||||||
instance->settings->channels[index].options = ch_flags;
|
/* xrdp currently reserves dynamic channels for its
|
||||||
}
|
* exclusive use (e.g. for GFX support) */
|
||||||
else
|
LOG(LOG_LEVEL_INFO, "Channel '%s' not passed to module",
|
||||||
{
|
ch_name);
|
||||||
LOG(LOG_LEVEL_ERROR, "lfreerdp_pre_connect: "
|
}
|
||||||
"Expected %d channels, got %d",
|
else if (target_chan < MAX_STATIC_CHANNELS)
|
||||||
num_chans, index);
|
{
|
||||||
num_chans = index;
|
dst_ch_name = instance->settings->channels[target_chan].name;
|
||||||
|
ch_names[target_chan] = dst_ch_name;
|
||||||
|
g_memset(dst_ch_name, 0, CHANNEL_NAME_LEN + 1);
|
||||||
|
g_snprintf(dst_ch_name, CHANNEL_NAME_LEN + 1, "%s", ch_name);
|
||||||
|
instance->settings->channels[target_chan].options = ch_flags;
|
||||||
|
++target_chan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->settings->num_channels = num_chans;
|
g_strnjoin(ch_name, sizeof(ch_name), ",", ch_names, target_chan);
|
||||||
|
LOG(LOG_LEVEL_INFO, "Static channels (from %d) passed to module : %s",
|
||||||
|
num_chans, ch_name);
|
||||||
|
|
||||||
|
instance->settings->num_channels = target_chan;
|
||||||
|
|
||||||
instance->settings->offscreen_bitmap_cache = 0;
|
instance->settings->offscreen_bitmap_cache = 0;
|
||||||
instance->settings->draw_nine_grid = 0;
|
instance->settings->draw_nine_grid = 0;
|
||||||
|
|||||||
@@ -1787,7 +1787,7 @@ main(int argc, char **argv)
|
|||||||
waiters[1] = g_exec_event;
|
waiters[1] = g_exec_event;
|
||||||
waiters[2] = g_sigchld_event;
|
waiters[2] = g_sigchld_event;
|
||||||
|
|
||||||
if (g_obj_wait(waiters, 3, 0, 0, 0) != 0)
|
if (g_obj_wait(waiters, 3, 0, 0, -1) != 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed");
|
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed");
|
||||||
break;
|
break;
|
||||||
@@ -1814,7 +1814,7 @@ main(int argc, char **argv)
|
|||||||
while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event))
|
while (g_thread_done_event > 0 && !g_is_wait_obj_set(g_thread_done_event))
|
||||||
{
|
{
|
||||||
/* wait for thread to exit */
|
/* wait for thread to exit */
|
||||||
if (g_obj_wait(&g_thread_done_event, 1, 0, 0, 0) != 0)
|
if (g_obj_wait(&g_thread_done_event, 1, 0, 0, -1) != 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed");
|
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, g_obj_wait failed");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ sesexec_main_loop(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_obj_wait(robjs, robjs_count, NULL, 0, 0) != 0)
|
if (g_obj_wait(robjs, robjs_count, NULL, 0, -1) != 0)
|
||||||
{
|
{
|
||||||
/* should not get here */
|
/* should not get here */
|
||||||
LOG(LOG_LEVEL_WARNING, "sesexec_main_loop: "
|
LOG(LOG_LEVEL_WARNING, "sesexec_main_loop: "
|
||||||
|
|||||||
@@ -1249,6 +1249,12 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
|
|||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_DEBUG, "VNC server successfully resized");
|
LOG(LOG_LEVEL_DEBUG, "VNC server successfully resized");
|
||||||
log_screen_layout(LOG_LEVEL_INFO, "NewLayout", &layout);
|
log_screen_layout(LOG_LEVEL_INFO, "NewLayout", &layout);
|
||||||
|
// If this resize was requested by the client mid-session
|
||||||
|
// (dynamic resize), we need to tell xrdp_mm that
|
||||||
|
// it's OK to continue with the resize state machine.
|
||||||
|
// We do this by sending a reset with bpp == 0
|
||||||
|
error = v->server_reset(v, v->server_width,
|
||||||
|
v->server_height, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-2
@@ -471,6 +471,9 @@ struct display_control_monitor_layout_data
|
|||||||
enum display_resize_state state;
|
enum display_resize_state state;
|
||||||
int last_state_update_timestamp;
|
int last_state_update_timestamp;
|
||||||
int start_time;
|
int start_time;
|
||||||
|
/// This flag is set if the state machine needs to
|
||||||
|
/// shutdown/startup EGFX
|
||||||
|
int using_egfx;
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -478,6 +481,8 @@ xrdp_mm_drdynvc_up(struct xrdp_mm *self);
|
|||||||
int
|
int
|
||||||
xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress,
|
xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress,
|
||||||
int left, int top, int right, int bottom);
|
int left, int top, int right, int bottom);
|
||||||
|
int
|
||||||
|
xrdp_mm_up_and_running(struct xrdp_mm *self);
|
||||||
struct xrdp_mm *
|
struct xrdp_mm *
|
||||||
xrdp_mm_create(struct xrdp_wm *owner);
|
xrdp_mm_create(struct xrdp_wm *owner);
|
||||||
void
|
void
|
||||||
@@ -500,7 +505,8 @@ xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id);
|
|||||||
int
|
int
|
||||||
xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self,
|
xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self,
|
||||||
struct xrdp_bitmap *bitmap,
|
struct xrdp_bitmap *bitmap,
|
||||||
struct xrdp_rect *rect);
|
struct xrdp_rect *rect,
|
||||||
|
int surface_id, int x, int y);
|
||||||
int
|
int
|
||||||
server_begin_update(struct xrdp_mod *mod);
|
server_begin_update(struct xrdp_mod *mod);
|
||||||
int
|
int
|
||||||
@@ -543,7 +549,8 @@ server_set_pointer_large(struct xrdp_mod *mod, int x, int y,
|
|||||||
char *data, char *mask, int bpp,
|
char *data, char *mask, int bpp,
|
||||||
int width, int height);
|
int width, int height);
|
||||||
int
|
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,
|
int num_crects, short *crects,
|
||||||
char *data, int left, int top,
|
char *data, int left, int top,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
@@ -645,5 +652,9 @@ server_add_char_alpha(struct xrdp_mod *mod, int font, int character,
|
|||||||
int width, int height, char *data);
|
int width, int height, char *data);
|
||||||
int
|
int
|
||||||
server_session_info(struct xrdp_mod *mod, const char *data, int data_bytes);
|
server_session_info(struct xrdp_mod *mod, const char *data, int data_bytes);
|
||||||
|
int
|
||||||
|
server_egfx_cmd(struct xrdp_mod *v,
|
||||||
|
char *cmd, int cmd_bytes,
|
||||||
|
char *data, int data_bytes);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+20
-20
@@ -105,7 +105,7 @@ xrdp_egfx_create_surface(struct xrdp_egfx_bulk *bulk, int surface_id,
|
|||||||
int bytes;
|
int bytes;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
|
|
||||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_create_surface:");
|
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_egfx_create_surface:");
|
||||||
make_stream(s);
|
make_stream(s);
|
||||||
init_stream(s, 8192);
|
init_stream(s, 8192);
|
||||||
/* RDP_SEGMENTED_DATA */
|
/* RDP_SEGMENTED_DATA */
|
||||||
@@ -135,12 +135,12 @@ xrdp_egfx_send_create_surface(struct xrdp_egfx *egfx, int surface_id,
|
|||||||
int error;
|
int error;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
|
|
||||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_create_surface:");
|
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_egfx_send_create_surface:");
|
||||||
s = xrdp_egfx_create_surface(egfx->bulk, surface_id, width, height,
|
s = xrdp_egfx_create_surface(egfx->bulk, surface_id, width, height,
|
||||||
pixel_format);
|
pixel_format);
|
||||||
error = xrdp_egfx_send_s(egfx, s);
|
error = xrdp_egfx_send_s(egfx, s);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_create_surface: xrdp_egfx_send_s "
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_send_create_surface: xrdp_egfx_send_s "
|
||||||
"error %d", error);
|
"error %d", error);
|
||||||
free_stream(s);
|
free_stream(s);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -181,8 +181,8 @@ xrdp_egfx_send_delete_surface(struct xrdp_egfx *egfx, int surface_id)
|
|||||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_delete_surface:");
|
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_delete_surface:");
|
||||||
s = xrdp_egfx_delete_surface(egfx->bulk, surface_id);
|
s = xrdp_egfx_delete_surface(egfx->bulk, surface_id);
|
||||||
error = xrdp_egfx_send_s(egfx, s);
|
error = xrdp_egfx_send_s(egfx, s);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_delete_surface: xrdp_egfx_send_s "
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_send_delete_surface: xrdp_egfx_send_s "
|
||||||
"error %d", error);
|
"error %d", error);
|
||||||
free_stream(s);
|
free_stream(s);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -538,16 +538,16 @@ xrdp_egfx_wire_to_surface1(struct xrdp_egfx_bulk *bulk, int surface_id,
|
|||||||
/* RDP8_BULK_ENCODED_DATA */
|
/* RDP8_BULK_ENCODED_DATA */
|
||||||
out_uint8(s, PACKET_COMPR_TYPE_RDP8); /* header */
|
out_uint8(s, PACKET_COMPR_TYPE_RDP8); /* header */
|
||||||
out_uint8a(s, bitmap_data8 + index, segment_size);
|
out_uint8a(s, bitmap_data8 + index, segment_size);
|
||||||
LOG(LOG_LEVEL_DEBUG, " segment index %d segment_size %d",
|
LOG_DEVEL(LOG_LEVEL_DEBUG, " segment index %d segment_size %d",
|
||||||
segment_count, segment_size);
|
segment_count, segment_size);
|
||||||
index += segment_size;
|
index += segment_size;
|
||||||
segment_count++;
|
segment_count++;
|
||||||
}
|
}
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
s_pop_layer(s, iso_hdr);
|
s_pop_layer(s, iso_hdr);
|
||||||
out_uint16_le(s, segment_count);
|
out_uint16_le(s, segment_count);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_wire_to_surface1: segment_count %d",
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_wire_to_surface1: segment_count %d",
|
||||||
segment_count);
|
segment_count);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,13 +561,13 @@ xrdp_egfx_send_wire_to_surface1(struct xrdp_egfx *egfx, int surface_id,
|
|||||||
int error;
|
int error;
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
|
|
||||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_wire_to_surface1:");
|
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_egfx_send_wire_to_surface1:");
|
||||||
s = xrdp_egfx_wire_to_surface1(egfx->bulk, surface_id, codec_id,
|
s = xrdp_egfx_wire_to_surface1(egfx->bulk, surface_id, codec_id,
|
||||||
pixel_format, dest_rect,
|
pixel_format, dest_rect,
|
||||||
bitmap_data, bitmap_data_length);
|
bitmap_data, bitmap_data_length);
|
||||||
error = xrdp_egfx_send_s(egfx, s);
|
error = xrdp_egfx_send_s(egfx, s);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_wire_to_surface1: xrdp_egfx_send_s "
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_send_wire_to_surface1: xrdp_egfx_send_s "
|
||||||
"error %d", error);
|
"error %d", error);
|
||||||
free_stream(s);
|
free_stream(s);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -586,7 +586,7 @@ xrdp_egfx_wire_to_surface2(struct xrdp_egfx_bulk *bulk, int surface_id,
|
|||||||
struct stream *s;
|
struct stream *s;
|
||||||
char *bitmap_data8;
|
char *bitmap_data8;
|
||||||
|
|
||||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_wire_to_surface2:");
|
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_egfx_wire_to_surface2:");
|
||||||
make_stream(s);
|
make_stream(s);
|
||||||
bytes = bitmap_data_length + 8192;
|
bytes = bitmap_data_length + 8192;
|
||||||
bytes += 5 * (bitmap_data_length / MAX_PART_SIZE);
|
bytes += 5 * (bitmap_data_length / MAX_PART_SIZE);
|
||||||
@@ -623,16 +623,16 @@ xrdp_egfx_wire_to_surface2(struct xrdp_egfx_bulk *bulk, int surface_id,
|
|||||||
/* RDP8_BULK_ENCODED_DATA */
|
/* RDP8_BULK_ENCODED_DATA */
|
||||||
out_uint8(s, PACKET_COMPR_TYPE_RDP8); /* header */
|
out_uint8(s, PACKET_COMPR_TYPE_RDP8); /* header */
|
||||||
out_uint8a(s, bitmap_data8 + index, segment_size);
|
out_uint8a(s, bitmap_data8 + index, segment_size);
|
||||||
LOG(LOG_LEVEL_DEBUG, " segment index %d segment_size %d",
|
LOG_DEVEL(LOG_LEVEL_DEBUG, " segment index %d segment_size %d",
|
||||||
segment_count, segment_size);
|
segment_count, segment_size);
|
||||||
index += segment_size;
|
index += segment_size;
|
||||||
segment_count++;
|
segment_count++;
|
||||||
}
|
}
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
s_pop_layer(s, iso_hdr);
|
s_pop_layer(s, iso_hdr);
|
||||||
out_uint16_le(s, segment_count);
|
out_uint16_le(s, segment_count);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_wire_to_surface2: segment_count %d",
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_wire_to_surface2: segment_count %d",
|
||||||
segment_count);
|
segment_count);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,8 +651,8 @@ xrdp_egfx_send_wire_to_surface2(struct xrdp_egfx *egfx, int surface_id,
|
|||||||
codec_context_id, pixel_format,
|
codec_context_id, pixel_format,
|
||||||
bitmap_data, bitmap_data_length);
|
bitmap_data, bitmap_data_length);
|
||||||
error = xrdp_egfx_send_s(egfx, s);
|
error = xrdp_egfx_send_s(egfx, s);
|
||||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_wire_to_surface2: xrdp_egfx_send_s "
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_egfx_send_wire_to_surface2: xrdp_egfx_send_s "
|
||||||
"error %d", error);
|
"error %d", error);
|
||||||
free_stream(s);
|
free_stream(s);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
+652
-74
@@ -27,14 +27,31 @@
|
|||||||
#include "ms-rdpbcgr.h"
|
#include "ms-rdpbcgr.h"
|
||||||
#include "thread_calls.h"
|
#include "thread_calls.h"
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
|
#include "xrdp_egfx.h"
|
||||||
|
|
||||||
#ifdef XRDP_RFXCODEC
|
#ifdef XRDP_RFXCODEC
|
||||||
#include "rfxcodec_encode.h"
|
#include "rfxcodec_encode.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define XRDP_SURCMD_PREFIX_BYTES 256
|
#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 */
|
||||||
|
static const unsigned char g_rfx_quantization_values[] =
|
||||||
|
{
|
||||||
|
0x66, 0x66, 0x77, 0x87, 0x98,
|
||||||
|
0x76, 0x77, 0x88, 0x98, 0x99
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct enc_rect
|
||||||
|
{
|
||||||
|
short x1;
|
||||||
|
short y1;
|
||||||
|
short x2;
|
||||||
|
short y2;
|
||||||
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
static int
|
static int
|
||||||
@@ -42,6 +59,8 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
|||||||
#ifdef XRDP_RFXCODEC
|
#ifdef XRDP_RFXCODEC
|
||||||
static int
|
static int
|
||||||
process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
||||||
|
static int
|
||||||
|
process_enc_egfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
||||||
#endif
|
#endif
|
||||||
static int
|
static int
|
||||||
process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc);
|
||||||
@@ -52,8 +71,8 @@ static void
|
|||||||
xrdp_enc_data_destructor(void *item, void *closure)
|
xrdp_enc_data_destructor(void *item, void *closure)
|
||||||
{
|
{
|
||||||
XRDP_ENC_DATA *enc = (XRDP_ENC_DATA *)item;
|
XRDP_ENC_DATA *enc = (XRDP_ENC_DATA *)item;
|
||||||
g_free(enc->drects);
|
g_free(enc->u.sc.drects);
|
||||||
g_free(enc->crects);
|
g_free(enc->u.sc.crects);
|
||||||
g_free(enc);
|
g_free(enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +89,8 @@ xrdp_enc_data_done_destructor(void *item, void *closure)
|
|||||||
struct xrdp_encoder *
|
struct xrdp_encoder *
|
||||||
xrdp_encoder_create(struct xrdp_mm *mm)
|
xrdp_encoder_create(struct xrdp_mm *mm)
|
||||||
{
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_encoder_create:");
|
||||||
|
|
||||||
struct xrdp_encoder *self;
|
struct xrdp_encoder *self;
|
||||||
struct xrdp_client_info *client_info;
|
struct xrdp_client_info *client_info;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@@ -77,52 +98,70 @@ xrdp_encoder_create(struct xrdp_mm *mm)
|
|||||||
|
|
||||||
client_info = mm->wm->client_info;
|
client_info = mm->wm->client_info;
|
||||||
|
|
||||||
|
/* RemoteFX 7.1 requires LAN but GFX does not */
|
||||||
if (client_info->mcs_connection_type != CONNECTION_TYPE_LAN)
|
if (client_info->mcs_connection_type != CONNECTION_TYPE_LAN)
|
||||||
{
|
{
|
||||||
return 0;
|
if ((mm->egfx_flags & (XRDP_EGFX_H264 | XRDP_EGFX_RFX_PRO)) == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (client_info->bpp < 24)
|
if (client_info->bpp < 24)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
self = (struct xrdp_encoder *)g_malloc(sizeof(struct xrdp_encoder), 1);
|
self = g_new0(struct xrdp_encoder, 1);
|
||||||
|
if (self == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
self->mm = mm;
|
self->mm = mm;
|
||||||
|
|
||||||
if (client_info->jpeg_codec_id != 0)
|
if (client_info->jpeg_codec_id != 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting jpeg codec session");
|
LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting jpeg codec session");
|
||||||
self->codec_id = client_info->jpeg_codec_id;
|
self->codec_id = client_info->jpeg_codec_id;
|
||||||
self->in_codec_mode = 1;
|
self->in_codec_mode = 1;
|
||||||
self->codec_quality = client_info->jpeg_prop[0];
|
self->codec_quality = client_info->jpeg_prop[0];
|
||||||
client_info->capture_code = 0;
|
client_info->capture_code = 0;
|
||||||
client_info->capture_format =
|
client_info->capture_format = XRDP_a8b8g8r8;
|
||||||
/* XRDP_a8b8g8r8 */
|
|
||||||
(32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8;
|
|
||||||
self->process_enc = process_enc_jpg;
|
self->process_enc = process_enc_jpg;
|
||||||
}
|
}
|
||||||
#ifdef XRDP_RFXCODEC
|
#ifdef XRDP_RFXCODEC
|
||||||
|
else if (mm->egfx_flags & XRDP_EGFX_RFX_PRO)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_INFO,
|
||||||
|
"xrdp_encoder_create: starting gfx rfx pro codec session");
|
||||||
|
self->in_codec_mode = 1;
|
||||||
|
client_info->capture_code = 4;
|
||||||
|
self->process_enc = process_enc_egfx;
|
||||||
|
self->gfx = 1;
|
||||||
|
self->quants = (const char *) g_rfx_quantization_values;
|
||||||
|
self->num_quants = 2;
|
||||||
|
self->quant_idx_y = 0;
|
||||||
|
self->quant_idx_u = 1;
|
||||||
|
self->quant_idx_v = 1;
|
||||||
|
}
|
||||||
else if (client_info->rfx_codec_id != 0)
|
else if (client_info->rfx_codec_id != 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session");
|
LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting rfx codec session");
|
||||||
self->codec_id = client_info->rfx_codec_id;
|
self->codec_id = client_info->rfx_codec_id;
|
||||||
self->in_codec_mode = 1;
|
self->in_codec_mode = 1;
|
||||||
client_info->capture_code = 2;
|
client_info->capture_code = 2;
|
||||||
self->process_enc = process_enc_rfx;
|
self->process_enc = process_enc_rfx;
|
||||||
self->codec_handle = rfxcodec_encode_create(mm->wm->screen->width,
|
self->codec_handle_rfx = rfxcodec_encode_create(mm->wm->screen->width,
|
||||||
mm->wm->screen->height,
|
mm->wm->screen->height,
|
||||||
RFX_FORMAT_YUV, 0);
|
RFX_FORMAT_YUV, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (client_info->h264_codec_id != 0)
|
else if (client_info->h264_codec_id != 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_create: starting h264 codec session");
|
LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: starting h264 codec session");
|
||||||
self->codec_id = client_info->h264_codec_id;
|
self->codec_id = client_info->h264_codec_id;
|
||||||
self->in_codec_mode = 1;
|
self->in_codec_mode = 1;
|
||||||
client_info->capture_code = 3;
|
client_info->capture_code = 3;
|
||||||
client_info->capture_format =
|
client_info->capture_format = XRDP_nv12;
|
||||||
/* XRDP_nv12 */
|
|
||||||
(12 << 24) | (64 << 16) | (0 << 12) | (0 << 8) | (0 << 4) | 0;
|
|
||||||
self->process_enc = process_enc_h264;
|
self->process_enc = process_enc_h264;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -131,7 +170,9 @@ xrdp_encoder_create(struct xrdp_mm *mm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "init_xrdp_encoder: initializing encoder codec_id %d", self->codec_id);
|
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||||
|
"init_xrdp_encoder: initializing encoder codec_id %d",
|
||||||
|
self->codec_id);
|
||||||
|
|
||||||
/* setup required FIFOs */
|
/* setup required FIFOs */
|
||||||
self->fifo_to_proc = fifo_create(xrdp_enc_data_destructor);
|
self->fifo_to_proc = fifo_create(xrdp_enc_data_destructor);
|
||||||
@@ -146,8 +187,17 @@ xrdp_encoder_create(struct xrdp_mm *mm)
|
|||||||
self->xrdp_encoder_event_processed = g_create_wait_obj(buf);
|
self->xrdp_encoder_event_processed = g_create_wait_obj(buf);
|
||||||
g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid);
|
g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid);
|
||||||
self->xrdp_encoder_term = g_create_wait_obj(buf);
|
self->xrdp_encoder_term = g_create_wait_obj(buf);
|
||||||
self->max_compressed_bytes = client_info->max_fastpath_frag_bytes & ~15;
|
if (client_info->gfx)
|
||||||
self->frames_in_flight = client_info->max_unacknowledged_frame_count;
|
{
|
||||||
|
// Magic numbers... Why?
|
||||||
|
self->frames_in_flight = 2;
|
||||||
|
self->max_compressed_bytes = 3145728;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->frames_in_flight = client_info->max_unacknowledged_frame_count;
|
||||||
|
self->max_compressed_bytes = client_info->max_fastpath_frag_bytes & ~15;
|
||||||
|
}
|
||||||
/* make sure frames_in_flight is at least 1 */
|
/* make sure frames_in_flight is at least 1 */
|
||||||
self->frames_in_flight = MAX(self->frames_in_flight, 1);
|
self->frames_in_flight = MAX(self->frames_in_flight, 1);
|
||||||
|
|
||||||
@@ -161,6 +211,10 @@ xrdp_encoder_create(struct xrdp_mm *mm)
|
|||||||
void
|
void
|
||||||
xrdp_encoder_delete(struct xrdp_encoder *self)
|
xrdp_encoder_delete(struct xrdp_encoder *self)
|
||||||
{
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
(void)index;
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_delete:");
|
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_delete:");
|
||||||
if (self == 0)
|
if (self == 0)
|
||||||
{
|
{
|
||||||
@@ -174,15 +228,31 @@ xrdp_encoder_delete(struct xrdp_encoder *self)
|
|||||||
g_set_wait_obj(self->xrdp_encoder_term);
|
g_set_wait_obj(self->xrdp_encoder_term);
|
||||||
g_sleep(1000);
|
g_sleep(1000);
|
||||||
|
|
||||||
/* todo delete specific encoder */
|
|
||||||
|
|
||||||
if (self->process_enc == process_enc_jpg)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#ifdef XRDP_RFXCODEC
|
#ifdef XRDP_RFXCODEC
|
||||||
else if (self->process_enc == process_enc_rfx)
|
for (index = 0; index < 16; index++)
|
||||||
{
|
{
|
||||||
rfxcodec_encode_destroy(self->codec_handle);
|
if (self->codec_handle_prfx_gfx[index] != NULL)
|
||||||
|
{
|
||||||
|
rfxcodec_encode_destroy(self->codec_handle_prfx_gfx[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->codec_handle_rfx != NULL)
|
||||||
|
{
|
||||||
|
rfxcodec_encode_destroy(self->codec_handle_rfx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(XRDP_X264)
|
||||||
|
for (index = 0; index < 16; index++)
|
||||||
|
{
|
||||||
|
if (self->codec_handle_h264_gfx[index] != NULL)
|
||||||
|
{
|
||||||
|
rfxcodec_encode_destroy(self->codec_handle_h264_gfx[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->codec_handle_h264 != NULL)
|
||||||
|
{
|
||||||
|
xrdp_encoder_x264_delete(self->codec_handle_h264);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -223,28 +293,31 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
fifo_processed = self->fifo_processed;
|
fifo_processed = self->fifo_processed;
|
||||||
mutex = self->mutex;
|
mutex = self->mutex;
|
||||||
event_processed = self->xrdp_encoder_event_processed;
|
event_processed = self->xrdp_encoder_event_processed;
|
||||||
count = enc->num_crects;
|
count = enc->u.sc.num_crects;
|
||||||
for (index = 0; index < count; index++)
|
for (index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
x = enc->crects[index * 4 + 0];
|
x = enc->u.sc.crects[index * 4 + 0];
|
||||||
y = enc->crects[index * 4 + 1];
|
y = enc->u.sc.crects[index * 4 + 1];
|
||||||
cx = enc->crects[index * 4 + 2];
|
cx = enc->u.sc.crects[index * 4 + 2];
|
||||||
cy = enc->crects[index * 4 + 3];
|
cy = enc->u.sc.crects[index * 4 + 3];
|
||||||
if (cx < 1 || cy < 1)
|
if (cx < 1 || cy < 1)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_WARNING, "process_enc_jpg: error 1");
|
LOG_DEVEL(LOG_LEVEL_WARNING, "process_enc_jpg: error 1");
|
||||||
continue;
|
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);
|
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");
|
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 2");
|
||||||
return 1;
|
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)
|
if (out_data == 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 3");
|
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: error 3");
|
||||||
@@ -253,26 +326,29 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
|
|
||||||
out_data[256] = 0; /* header bytes */
|
out_data[256] = 0; /* header bytes */
|
||||||
out_data[257] = 0;
|
out_data[257] = 0;
|
||||||
error = libxrdp_codec_jpeg_compress(self->mm->wm->session, 0, enc->data,
|
error = libxrdp_codec_jpeg_compress(self->mm->wm->session, 0, enc->u.sc.data,
|
||||||
enc->width, enc->height,
|
enc->u.sc.width, enc->u.sc.height,
|
||||||
enc->width * 4, x, y, cx, cy,
|
enc->u.sc.width * 4, x, y, cx, cy,
|
||||||
quality,
|
quality,
|
||||||
out_data + 256 + 2, &out_data_bytes);
|
out_data
|
||||||
|
+ XRDP_SURCMD_PREFIX_BYTES + 2,
|
||||||
|
&out_data_bytes);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d bytes %d",
|
LOG_DEVEL(LOG_LEVEL_ERROR, "process_enc_jpg: jpeg error %d "
|
||||||
error, out_data_bytes);
|
"bytes %d", error, out_data_bytes);
|
||||||
g_free(out_data);
|
g_free(out_data);
|
||||||
return 1;
|
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 *)
|
enc_done = (XRDP_ENC_DATA_DONE *)
|
||||||
g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1);
|
g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1);
|
||||||
enc_done->comp_bytes = out_data_bytes + 2;
|
enc_done->comp_bytes = out_data_bytes + 2;
|
||||||
enc_done->pad_bytes = 256;
|
enc_done->pad_bytes = 256;
|
||||||
enc_done->comp_pad_data = out_data;
|
enc_done->comp_pad_data = out_data;
|
||||||
enc_done->enc = enc;
|
enc_done->enc = enc;
|
||||||
enc_done->last = index == (enc->num_crects - 1);
|
enc_done->last = index == (enc->u.sc.num_crects - 1);
|
||||||
enc_done->x = x;
|
enc_done->x = x;
|
||||||
enc_done->y = y;
|
enc_done->y = y;
|
||||||
enc_done->cx = cx;
|
enc_done->cx = cx;
|
||||||
@@ -313,28 +389,31 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
struct rfx_tile *tiles;
|
struct rfx_tile *tiles;
|
||||||
struct rfx_rect *rfxrects;
|
struct rfx_rect *rfxrects;
|
||||||
int alloc_bytes;
|
int alloc_bytes;
|
||||||
|
int encode_flags;
|
||||||
|
int encode_passes;
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_rfx:");
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_rfx:");
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_rfx: num_crects %d num_drects %d",
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_enc_rfx: num_crects %d num_drects %d",
|
||||||
enc->num_crects, enc->num_drects);
|
enc->u.sc.num_crects, enc->u.sc.num_drects);
|
||||||
fifo_processed = self->fifo_processed;
|
fifo_processed = self->fifo_processed;
|
||||||
mutex = self->mutex;
|
mutex = self->mutex;
|
||||||
event_processed = self->xrdp_encoder_event_processed;
|
event_processed = self->xrdp_encoder_event_processed;
|
||||||
|
|
||||||
all_tiles_written = 0;
|
all_tiles_written = 0;
|
||||||
|
encode_passes = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tiles_written = 0;
|
tiles_written = 0;
|
||||||
tiles_left = enc->num_crects - all_tiles_written;
|
tiles_left = enc->u.sc.num_crects - all_tiles_written;
|
||||||
out_data = NULL;
|
out_data = NULL;
|
||||||
out_data_bytes = 0;
|
out_data_bytes = 0;
|
||||||
|
|
||||||
if ((tiles_left > 0) && (enc->num_drects > 0))
|
if ((tiles_left > 0) && (enc->u.sc.num_drects > 0))
|
||||||
{
|
{
|
||||||
alloc_bytes = XRDP_SURCMD_PREFIX_BYTES;
|
alloc_bytes = XRDP_SURCMD_PREFIX_BYTES;
|
||||||
alloc_bytes += self->max_compressed_bytes;
|
alloc_bytes += self->max_compressed_bytes;
|
||||||
alloc_bytes += sizeof(struct rfx_tile) * tiles_left +
|
alloc_bytes += sizeof(struct rfx_tile) * tiles_left +
|
||||||
sizeof(struct rfx_rect) * enc->num_drects;
|
sizeof(struct rfx_rect) * enc->u.sc.num_drects;
|
||||||
out_data = g_new(char, alloc_bytes);
|
out_data = g_new(char, alloc_bytes);
|
||||||
if (out_data != NULL)
|
if (out_data != NULL)
|
||||||
{
|
{
|
||||||
@@ -346,26 +425,26 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
count = tiles_left;
|
count = tiles_left;
|
||||||
for (index = 0; index < count; index++)
|
for (index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
x = enc->crects[(index + all_tiles_written) * 4 + 0];
|
x = enc->u.sc.crects[(index + all_tiles_written) * 4 + 0];
|
||||||
y = enc->crects[(index + all_tiles_written) * 4 + 1];
|
y = enc->u.sc.crects[(index + all_tiles_written) * 4 + 1];
|
||||||
cx = enc->crects[(index + all_tiles_written) * 4 + 2];
|
cx = enc->u.sc.crects[(index + all_tiles_written) * 4 + 2];
|
||||||
cy = enc->crects[(index + all_tiles_written) * 4 + 3];
|
cy = enc->u.sc.crects[(index + all_tiles_written) * 4 + 3];
|
||||||
tiles[index].x = x;
|
tiles[index].x = x;
|
||||||
tiles[index].y = y;
|
tiles[index].y = y;
|
||||||
tiles[index].cx = cx;
|
tiles[index].cx = cx;
|
||||||
tiles[index].cy = cy;
|
tiles[index].cy = cy;
|
||||||
tiles[index].quant_y = 0;
|
tiles[index].quant_y = self->quant_idx_y;
|
||||||
tiles[index].quant_cb = 0;
|
tiles[index].quant_cb = self->quant_idx_u;
|
||||||
tiles[index].quant_cr = 0;
|
tiles[index].quant_cr = self->quant_idx_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = enc->num_drects;
|
count = enc->u.sc.num_drects;
|
||||||
for (index = 0; index < count; index++)
|
for (index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
x = enc->drects[index * 4 + 0];
|
x = enc->u.sc.drects[index * 4 + 0];
|
||||||
y = enc->drects[index * 4 + 1];
|
y = enc->u.sc.drects[index * 4 + 1];
|
||||||
cx = enc->drects[index * 4 + 2];
|
cx = enc->u.sc.drects[index * 4 + 2];
|
||||||
cy = enc->drects[index * 4 + 3];
|
cy = enc->u.sc.drects[index * 4 + 3];
|
||||||
rfxrects[index].x = x;
|
rfxrects[index].x = x;
|
||||||
rfxrects[index].y = y;
|
rfxrects[index].y = y;
|
||||||
rfxrects[index].cx = cx;
|
rfxrects[index].cx = cx;
|
||||||
@@ -373,13 +452,23 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out_data_bytes = self->max_compressed_bytes;
|
out_data_bytes = self->max_compressed_bytes;
|
||||||
tiles_written = rfxcodec_encode(self->codec_handle,
|
|
||||||
out_data + XRDP_SURCMD_PREFIX_BYTES,
|
encode_flags = 0;
|
||||||
&out_data_bytes, enc->data,
|
if (((int)enc->flags & KEY_FRAME_REQUESTED) && encode_passes == 0)
|
||||||
enc->width, enc->height, enc->width * 4,
|
{
|
||||||
rfxrects, enc->num_drects,
|
encode_flags = RFX_FLAGS_PRO_KEY;
|
||||||
tiles, tiles_left, 0, 0);
|
}
|
||||||
|
tiles_written = rfxcodec_encode_ex(self->codec_handle_rfx,
|
||||||
|
out_data + XRDP_SURCMD_PREFIX_BYTES,
|
||||||
|
&out_data_bytes, enc->u.sc.data,
|
||||||
|
enc->u.sc.width, enc->u.sc.height,
|
||||||
|
((enc->u.sc.width + 63) & ~63) * 4,
|
||||||
|
rfxrects, enc->u.sc.num_drects,
|
||||||
|
tiles, enc->u.sc.num_crects,
|
||||||
|
self->quants, self->num_quants,
|
||||||
|
encode_flags);
|
||||||
}
|
}
|
||||||
|
++encode_passes;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||||
@@ -397,16 +486,18 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
enc_done->pad_bytes = XRDP_SURCMD_PREFIX_BYTES;
|
enc_done->pad_bytes = XRDP_SURCMD_PREFIX_BYTES;
|
||||||
enc_done->comp_pad_data = out_data;
|
enc_done->comp_pad_data = out_data;
|
||||||
enc_done->enc = enc;
|
enc_done->enc = enc;
|
||||||
enc_done->cx = self->mm->wm->screen->width;
|
enc_done->x = enc->u.sc.left;
|
||||||
enc_done->cy = self->mm->wm->screen->height;
|
enc_done->y = enc->u.sc.top;
|
||||||
|
enc_done->cx = enc->u.sc.width;
|
||||||
|
enc_done->cy = enc->u.sc.height;
|
||||||
|
enc_done->frame_id = enc->u.sc.frame_id;
|
||||||
enc_done->continuation = all_tiles_written > 0;
|
enc_done->continuation = all_tiles_written > 0;
|
||||||
if (tiles_written > 0)
|
if (tiles_written > 0)
|
||||||
{
|
{
|
||||||
all_tiles_written += tiles_written;
|
all_tiles_written += tiles_written;
|
||||||
}
|
}
|
||||||
finished =
|
finished =
|
||||||
(all_tiles_written == enc->num_crects) || (tiles_written < 0);
|
(all_tiles_written == enc->u.sc.num_crects) || (tiles_written < 0);
|
||||||
enc_done->last = finished;
|
enc_done->last = finished;
|
||||||
|
|
||||||
/* done with msg */
|
/* done with msg */
|
||||||
@@ -414,12 +505,12 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
tc_mutex_lock(mutex);
|
tc_mutex_lock(mutex);
|
||||||
fifo_add_item(fifo_processed, enc_done);
|
fifo_add_item(fifo_processed, enc_done);
|
||||||
tc_mutex_unlock(mutex);
|
tc_mutex_unlock(mutex);
|
||||||
/* signal completion for main thread */
|
|
||||||
g_set_wait_obj(event_processed);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
while (!finished);
|
while (!finished);
|
||||||
|
|
||||||
|
/* signal completion for main thread */
|
||||||
|
g_set_wait_obj(event_processed);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -429,10 +520,497 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
|||||||
static int
|
static int
|
||||||
process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
||||||
{
|
{
|
||||||
LOG_DEVEL(LOG_LEVEL_INFO, "process_enc_x264:");
|
LOG_DEVEL(LOG_LEVEL_INFO, "process_enc_h264: dummy func");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XRDP_RFXCODEC
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_wiretosurface1(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s,
|
||||||
|
struct xrdp_enc_gfx_cmd *enc_gfx_cmd)
|
||||||
|
{
|
||||||
|
(void)self;
|
||||||
|
(void)bulk;
|
||||||
|
(void)in_s;
|
||||||
|
(void)enc_gfx_cmd;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_wiretosurface2(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s,
|
||||||
|
struct xrdp_enc_gfx_cmd *enc_gfx_cmd)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int surface_id;
|
||||||
|
int codec_id;
|
||||||
|
int codec_context_id;
|
||||||
|
int pixel_format;
|
||||||
|
int num_rects_d;
|
||||||
|
int num_rects_c;
|
||||||
|
struct stream *rv;
|
||||||
|
short left;
|
||||||
|
short top;
|
||||||
|
short width;
|
||||||
|
short height;
|
||||||
|
char *bitmap_data;
|
||||||
|
int bitmap_data_length;
|
||||||
|
struct rfx_tile *tiles;
|
||||||
|
struct rfx_rect *rfxrects;
|
||||||
|
int flags;
|
||||||
|
int tiles_written;
|
||||||
|
int do_free;
|
||||||
|
int do_send;
|
||||||
|
int mon_index;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 15))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id);
|
||||||
|
in_uint16_le(in_s, codec_id);
|
||||||
|
in_uint32_le(in_s, codec_context_id);
|
||||||
|
in_uint8(in_s, pixel_format);
|
||||||
|
in_uint32_le(in_s, flags);
|
||||||
|
mon_index = (flags >> 28) & 0xF;
|
||||||
|
in_uint16_le(in_s, num_rects_d);
|
||||||
|
if ((num_rects_d < 1) || (num_rects_d > 16 * 1024) ||
|
||||||
|
(!s_check_rem(in_s, num_rects_d * 8)))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rfxrects = g_new0(struct rfx_rect, num_rects_d);
|
||||||
|
if (rfxrects == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (index = 0; index < num_rects_d; index++)
|
||||||
|
{
|
||||||
|
in_uint16_le(in_s, left);
|
||||||
|
in_uint16_le(in_s, top);
|
||||||
|
in_uint16_le(in_s, width);
|
||||||
|
in_uint16_le(in_s, height);
|
||||||
|
rfxrects[index].x = left;
|
||||||
|
rfxrects[index].y = top;
|
||||||
|
rfxrects[index].cx = width;
|
||||||
|
rfxrects[index].cy = height;
|
||||||
|
}
|
||||||
|
if (!s_check_rem(in_s, 2))
|
||||||
|
{
|
||||||
|
g_free(rfxrects);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, num_rects_c);
|
||||||
|
if ((num_rects_c < 1) || (num_rects_c > 16 * 1024) ||
|
||||||
|
(!s_check_rem(in_s, num_rects_c * 8)))
|
||||||
|
{
|
||||||
|
g_free(rfxrects);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tiles = g_new0(struct rfx_tile, num_rects_c);
|
||||||
|
if (tiles == NULL)
|
||||||
|
{
|
||||||
|
g_free(rfxrects);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (index = 0; index < num_rects_c; index++)
|
||||||
|
{
|
||||||
|
in_uint16_le(in_s, left);
|
||||||
|
in_uint16_le(in_s, top);
|
||||||
|
in_uint16_le(in_s, width);
|
||||||
|
in_uint16_le(in_s, height);
|
||||||
|
tiles[index].x = left;
|
||||||
|
tiles[index].y = top;
|
||||||
|
tiles[index].cx = width;
|
||||||
|
tiles[index].cy = height;
|
||||||
|
tiles[index].quant_y = self->quant_idx_y;
|
||||||
|
tiles[index].quant_cb = self->quant_idx_u;
|
||||||
|
tiles[index].quant_cr = self->quant_idx_v;
|
||||||
|
}
|
||||||
|
if (!s_check_rem(in_s, 8))
|
||||||
|
{
|
||||||
|
g_free(tiles);
|
||||||
|
g_free(rfxrects);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, left);
|
||||||
|
in_uint16_le(in_s, top);
|
||||||
|
in_uint16_le(in_s, width);
|
||||||
|
in_uint16_le(in_s, height);
|
||||||
|
if (self->codec_handle_prfx_gfx[mon_index] == NULL)
|
||||||
|
{
|
||||||
|
self->codec_handle_prfx_gfx[mon_index] = rfxcodec_encode_create(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
RFX_FORMAT_YUV,
|
||||||
|
RFX_FLAGS_RLGR1 | RFX_FLAGS_PRO1);
|
||||||
|
if (self->codec_handle_prfx_gfx[mon_index] == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_free = 0;
|
||||||
|
do_send = 0;
|
||||||
|
if (ENC_IS_BIT_SET(flags, 0))
|
||||||
|
{
|
||||||
|
/* already compressed */
|
||||||
|
bitmap_data_length = enc_gfx_cmd->data_bytes;
|
||||||
|
bitmap_data = enc_gfx_cmd->data;
|
||||||
|
do_send = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap_data_length = self->max_compressed_bytes;
|
||||||
|
bitmap_data = g_new(char, bitmap_data_length);
|
||||||
|
if (bitmap_data == NULL)
|
||||||
|
{
|
||||||
|
g_free(tiles);
|
||||||
|
g_free(rfxrects);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
do_free = 1;
|
||||||
|
tiles_written = rfxcodec_encode(self->codec_handle_prfx_gfx[mon_index],
|
||||||
|
bitmap_data,
|
||||||
|
&bitmap_data_length,
|
||||||
|
enc_gfx_cmd->data,
|
||||||
|
width, height,
|
||||||
|
((width + 63) & ~63) * 4,
|
||||||
|
rfxrects, num_rects_d,
|
||||||
|
tiles, num_rects_c,
|
||||||
|
self->quants, self->num_quants);
|
||||||
|
if (tiles_written > 0)
|
||||||
|
{
|
||||||
|
do_send = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(tiles);
|
||||||
|
g_free(rfxrects);
|
||||||
|
rv = NULL;
|
||||||
|
if (do_send)
|
||||||
|
{
|
||||||
|
rv = xrdp_egfx_wire_to_surface2(bulk, surface_id,
|
||||||
|
codec_id, codec_context_id,
|
||||||
|
pixel_format,
|
||||||
|
bitmap_data, bitmap_data_length);
|
||||||
|
}
|
||||||
|
if (do_free)
|
||||||
|
{
|
||||||
|
g_free(bitmap_data);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_solidfill(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int surface_id;
|
||||||
|
int pixel;
|
||||||
|
int num_rects;
|
||||||
|
char *ptr8;
|
||||||
|
struct xrdp_egfx_rect *rects;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 8))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id);
|
||||||
|
in_uint32_le(in_s, pixel);
|
||||||
|
in_uint16_le(in_s, num_rects);
|
||||||
|
if (!s_check_rem(in_s, num_rects * 8))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint8p(in_s, ptr8, num_rects * 8);
|
||||||
|
rects = (struct xrdp_egfx_rect *) ptr8;
|
||||||
|
return xrdp_egfx_fill_surface(bulk, surface_id, pixel, num_rects, rects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_surfacetosurface(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int surface_id_src;
|
||||||
|
int surface_id_dst;
|
||||||
|
char *ptr8;
|
||||||
|
int num_pts;
|
||||||
|
struct xrdp_egfx_rect *rects;
|
||||||
|
struct xrdp_egfx_point *pts;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 14))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id_src);
|
||||||
|
in_uint16_le(in_s, surface_id_dst);
|
||||||
|
in_uint8p(in_s, ptr8, 8);
|
||||||
|
rects = (struct xrdp_egfx_rect *) ptr8;
|
||||||
|
in_uint16_le(in_s, num_pts);
|
||||||
|
if (!s_check_rem(in_s, num_pts * 4))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint8p(in_s, ptr8, num_pts * 4);
|
||||||
|
pts = (struct xrdp_egfx_point *) ptr8;
|
||||||
|
return xrdp_egfx_surface_to_surface(bulk, surface_id_src, surface_id_dst,
|
||||||
|
rects, num_pts, pts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_createsurface(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int surface_id;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int pixel_format;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 7))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id);
|
||||||
|
in_uint16_le(in_s, width);
|
||||||
|
in_uint16_le(in_s, height);
|
||||||
|
in_uint8(in_s, pixel_format);
|
||||||
|
return xrdp_egfx_create_surface(bulk, surface_id,
|
||||||
|
width, height, pixel_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_deletesurface(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int surface_id;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 2))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id);
|
||||||
|
return xrdp_egfx_delete_surface(bulk, surface_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_startframe(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int frame_id;
|
||||||
|
int time_stamp;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 8))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint32_le(in_s, frame_id);
|
||||||
|
in_uint32_le(in_s, time_stamp);
|
||||||
|
return xrdp_egfx_frame_start(bulk, frame_id, time_stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_endframe(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s, int *aframe_id)
|
||||||
|
{
|
||||||
|
int frame_id;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 4))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint32_le(in_s, frame_id);
|
||||||
|
*aframe_id = frame_id;
|
||||||
|
return xrdp_egfx_frame_end(bulk, frame_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_resetgraphics(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int monitor_count;
|
||||||
|
int index;
|
||||||
|
struct monitor_info *mi;
|
||||||
|
struct stream *rv;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 12))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint32_le(in_s, width);
|
||||||
|
in_uint32_le(in_s, height);
|
||||||
|
in_uint32_le(in_s, monitor_count);
|
||||||
|
if ((monitor_count < 1) || (monitor_count > 16) ||
|
||||||
|
!s_check_rem(in_s, monitor_count * 20))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mi = g_new0(struct monitor_info, monitor_count);
|
||||||
|
if (mi == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (index = 0; index < monitor_count; index++)
|
||||||
|
{
|
||||||
|
in_uint32_le(in_s, mi[index].left);
|
||||||
|
in_uint32_le(in_s, mi[index].top);
|
||||||
|
in_uint32_le(in_s, mi[index].right);
|
||||||
|
in_uint32_le(in_s, mi[index].bottom);
|
||||||
|
in_uint32_le(in_s, mi[index].is_primary);
|
||||||
|
}
|
||||||
|
rv = xrdp_egfx_reset_graphics(bulk, width, height, monitor_count, mi);
|
||||||
|
g_free(mi);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
static struct stream *
|
||||||
|
gfx_mapsurfacetooutput(struct xrdp_encoder *self,
|
||||||
|
struct xrdp_egfx_bulk *bulk, struct stream *in_s)
|
||||||
|
{
|
||||||
|
int surface_id;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
if (!s_check_rem(in_s, 10))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
in_uint16_le(in_s, surface_id);
|
||||||
|
in_uint32_le(in_s, x);
|
||||||
|
in_uint32_le(in_s, y);
|
||||||
|
return xrdp_egfx_map_surface(bulk, surface_id, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* called from encoder thread */
|
||||||
|
static int
|
||||||
|
process_enc_egfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
struct stream in_s;
|
||||||
|
struct xrdp_egfx_bulk *bulk;
|
||||||
|
XRDP_ENC_DATA_DONE *enc_done;
|
||||||
|
struct fifo *fifo_processed;
|
||||||
|
tbus mutex;
|
||||||
|
tbus event_processed;
|
||||||
|
int cmd_id;
|
||||||
|
int cmd_bytes;
|
||||||
|
int frame_id;
|
||||||
|
int got_frame_id;
|
||||||
|
char *holdp;
|
||||||
|
char *holdend;
|
||||||
|
|
||||||
|
fifo_processed = self->fifo_processed;
|
||||||
|
mutex = self->mutex;
|
||||||
|
event_processed = self->xrdp_encoder_event_processed;
|
||||||
|
bulk = self->mm->egfx->bulk;
|
||||||
|
g_memset(&in_s, 0, sizeof(in_s));
|
||||||
|
in_s.data = enc->u.gfx.cmd;
|
||||||
|
in_s.size = enc->u.gfx.cmd_bytes;
|
||||||
|
in_s.p = in_s.data;
|
||||||
|
in_s.end = in_s.data + in_s.size;
|
||||||
|
while (s_check_rem(&in_s, 8))
|
||||||
|
{
|
||||||
|
s = NULL;
|
||||||
|
frame_id = 0;
|
||||||
|
got_frame_id = 0;
|
||||||
|
holdp = in_s.p;
|
||||||
|
in_uint16_le(&in_s, cmd_id);
|
||||||
|
in_uint8s(&in_s, 2); /* flags */
|
||||||
|
in_uint32_le(&in_s, cmd_bytes);
|
||||||
|
if ((cmd_bytes < 8) || (cmd_bytes > 32 * 1024))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
holdend = in_s.end;
|
||||||
|
in_s.end = holdp + cmd_bytes;
|
||||||
|
switch (cmd_id)
|
||||||
|
{
|
||||||
|
case XR_RDPGFX_CMDID_WIRETOSURFACE_1: /* 0x0001 */
|
||||||
|
s = gfx_wiretosurface1(self, bulk, &in_s, &(enc->u.gfx));
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_WIRETOSURFACE_2: /* 0x0002 */
|
||||||
|
s = gfx_wiretosurface2(self, bulk, &in_s, &(enc->u.gfx));
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_SOLIDFILL: /* 0x0004 */
|
||||||
|
s = gfx_solidfill(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_SURFACETOSURFACE: /* 0x0005 */
|
||||||
|
s = gfx_surfacetosurface(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_CREATESURFACE: /* 0x0009 */
|
||||||
|
s = gfx_createsurface(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_DELETESURFACE: /* 0x000A */
|
||||||
|
s = gfx_deletesurface(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_STARTFRAME: /* 0x000B */
|
||||||
|
s = gfx_startframe(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_ENDFRAME: /* 0x000C */
|
||||||
|
s = gfx_endframe(self, bulk, &in_s, &frame_id);
|
||||||
|
got_frame_id = 1;
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_RESETGRAPHICS: /* 0x000E */
|
||||||
|
s = gfx_resetgraphics(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
case XR_RDPGFX_CMDID_MAPSURFACETOOUTPUT: /* 0x000F */
|
||||||
|
s = gfx_mapsurfacetooutput(self, bulk, &in_s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s == NULL)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "process_enc_egfx: cmd_id %d s = nil", cmd_id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* setup for next cmd */
|
||||||
|
in_s.p = holdp + cmd_bytes;
|
||||||
|
in_s.end = holdend;
|
||||||
|
/* setup enc_done struct */
|
||||||
|
enc_done = g_new0(XRDP_ENC_DATA_DONE, 1);
|
||||||
|
if (enc_done == NULL)
|
||||||
|
{
|
||||||
|
free_stream(s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ENC_SET_BIT(enc_done->flags, ENC_DONE_FLAGS_GFX_BIT);
|
||||||
|
enc_done->enc = enc;
|
||||||
|
enc_done->last = !s_check_rem(&in_s, 8);
|
||||||
|
enc_done->comp_bytes = (int) (s->end - s->data);
|
||||||
|
enc_done->comp_pad_data = s->data;
|
||||||
|
if (got_frame_id)
|
||||||
|
{
|
||||||
|
ENC_SET_BIT(enc_done->flags, ENC_DONE_FLAGS_FRAME_ID_BIT);
|
||||||
|
enc_done->frame_id = frame_id;
|
||||||
|
}
|
||||||
|
g_free(s); /* don't call free_stream() here so s->data is valid */
|
||||||
|
/* inform main thread done */
|
||||||
|
tc_mutex_lock(mutex);
|
||||||
|
fifo_add_item(fifo_processed, enc_done);
|
||||||
|
tc_mutex_unlock(mutex);
|
||||||
|
/* signal completion for main thread */
|
||||||
|
g_set_wait_obj(event_processed);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder thread main loop
|
* Encoder thread main loop
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|||||||
+57
-8
@@ -3,7 +3,14 @@
|
|||||||
#define _XRDP_ENCODER_H
|
#define _XRDP_ENCODER_H
|
||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
struct fifo;
|
#include "fifo.h"
|
||||||
|
#include "xrdp_client_info.h"
|
||||||
|
|
||||||
|
#define ENC_IS_BIT_SET(_flags, _bit) (((_flags) & (1 << (_bit))) != 0)
|
||||||
|
#define ENC_SET_BIT(_flags, _bit) do { _flags |= (1 << (_bit)); } while (0)
|
||||||
|
#define ENC_CLR_BIT(_flags, _bit) do { _flags &= ~(1 << (_bit)); } while (0)
|
||||||
|
#define ENC_SET_BITS(_flags, _mask, _bits) \
|
||||||
|
do { _flags &= ~(_mask); _flags |= (_bits) & (_mask); } while (0)
|
||||||
|
|
||||||
struct xrdp_enc_data;
|
struct xrdp_enc_data;
|
||||||
|
|
||||||
@@ -22,21 +29,34 @@ struct xrdp_encoder
|
|||||||
struct fifo *fifo_processed;
|
struct fifo *fifo_processed;
|
||||||
tbus mutex;
|
tbus mutex;
|
||||||
int (*process_enc)(struct xrdp_encoder *self, struct xrdp_enc_data *enc);
|
int (*process_enc)(struct xrdp_encoder *self, struct xrdp_enc_data *enc);
|
||||||
void *codec_handle;
|
void *codec_handle_rfx;
|
||||||
|
void *codec_handle_jpg;
|
||||||
|
void *codec_handle_h264;
|
||||||
|
void *codec_handle_prfx_gfx[16];
|
||||||
|
void *codec_handle_h264_gfx[16];
|
||||||
int frame_id_client; /* last frame id received from client */
|
int frame_id_client; /* last frame id received from client */
|
||||||
int frame_id_server; /* last frame id received from Xorg */
|
int frame_id_server; /* last frame id received from Xorg */
|
||||||
int frame_id_server_sent;
|
int frame_id_server_sent;
|
||||||
int frames_in_flight;
|
int frames_in_flight;
|
||||||
|
int gfx;
|
||||||
|
int gfx_ack_off;
|
||||||
|
const char *quants;
|
||||||
|
int num_quants;
|
||||||
|
int quant_idx_y;
|
||||||
|
int quant_idx_u;
|
||||||
|
int quant_idx_v;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* used when scheduling tasks in xrdp_encoder.c */
|
/* cmd_id = 0 */
|
||||||
struct xrdp_enc_data
|
struct xrdp_enc_surface_command
|
||||||
{
|
{
|
||||||
struct xrdp_mod *mod;
|
struct xrdp_mod *mod;
|
||||||
int num_drects;
|
int num_drects;
|
||||||
short *drects; /* 4 * num_drects */
|
int pad0;
|
||||||
|
short *drects; /* 4 * num_drects */
|
||||||
int num_crects;
|
int num_crects;
|
||||||
short *crects; /* 4 * num_crects */
|
int pad1;
|
||||||
|
short *crects; /* 4 * num_crects */
|
||||||
char *data;
|
char *data;
|
||||||
int left;
|
int left;
|
||||||
int top;
|
int top;
|
||||||
@@ -44,12 +64,21 @@ struct xrdp_enc_data
|
|||||||
int height;
|
int height;
|
||||||
int flags;
|
int flags;
|
||||||
int frame_id;
|
int frame_id;
|
||||||
void *shmem_ptr;
|
};
|
||||||
int shmem_bytes;
|
|
||||||
|
struct xrdp_enc_gfx_cmd
|
||||||
|
{
|
||||||
|
char *cmd;
|
||||||
|
char *data;
|
||||||
|
int cmd_bytes;
|
||||||
|
int data_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct xrdp_enc_data XRDP_ENC_DATA;
|
typedef struct xrdp_enc_data XRDP_ENC_DATA;
|
||||||
|
|
||||||
|
#define ENC_DONE_FLAGS_GFX_BIT 0
|
||||||
|
#define ENC_DONE_FLAGS_FRAME_ID_BIT 1
|
||||||
|
|
||||||
/* used when scheduling tasks from xrdp_encoder.c */
|
/* used when scheduling tasks from xrdp_encoder.c */
|
||||||
struct xrdp_enc_data_done
|
struct xrdp_enc_data_done
|
||||||
{
|
{
|
||||||
@@ -63,6 +92,26 @@ struct xrdp_enc_data_done
|
|||||||
int y;
|
int y;
|
||||||
int cx;
|
int cx;
|
||||||
int cy;
|
int cy;
|
||||||
|
int flags; /* ENC_DONE_FLAGS_* */
|
||||||
|
int frame_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ENC_FLAGS_GFX_BIT 0
|
||||||
|
|
||||||
|
/* used when scheduling tasks in xrdp_encoder.c */
|
||||||
|
struct xrdp_enc_data
|
||||||
|
{
|
||||||
|
struct xrdp_mod *mod;
|
||||||
|
int flags; /* ENC_FLAGS_* */
|
||||||
|
int pad0;
|
||||||
|
void *shmem_ptr;
|
||||||
|
int shmem_bytes;
|
||||||
|
int pad1;
|
||||||
|
union _u
|
||||||
|
{
|
||||||
|
struct xrdp_enc_surface_command sc;
|
||||||
|
struct xrdp_enc_gfx_cmd gfx;
|
||||||
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE;
|
typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE;
|
||||||
|
|||||||
+838
-144
File diff suppressed because it is too large
Load Diff
+46
-27
@@ -93,35 +93,54 @@ xrdp_painter_send_dirty(struct xrdp_painter *self)
|
|||||||
Bpp = 4;
|
Bpp = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
jndex = 0;
|
if (self->session->client_info->gfx)
|
||||||
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
|
||||||
while (error == 0)
|
|
||||||
{
|
{
|
||||||
cx = rect.right - rect.left;
|
if (self->wm->screen_dirty_region == NULL)
|
||||||
cy = rect.bottom - rect.top;
|
|
||||||
ldata = (char *)g_malloc(cx * cy * Bpp, 0);
|
|
||||||
if (ldata == 0)
|
|
||||||
{
|
{
|
||||||
return 1;
|
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
|
||||||
}
|
}
|
||||||
src = self->wm->screen->data;
|
jndex = 0;
|
||||||
src += self->wm->screen->line_size * rect.top;
|
|
||||||
src += rect.left * Bpp;
|
|
||||||
dst = ldata;
|
|
||||||
for (index = 0; index < cy; index++)
|
|
||||||
{
|
|
||||||
g_memcpy(dst, src, cx * Bpp);
|
|
||||||
src += self->wm->screen->line_size;
|
|
||||||
dst += cx * Bpp;
|
|
||||||
}
|
|
||||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty: x %d y %d cx %d cy %d",
|
|
||||||
rect.left, rect.top, cx, cy);
|
|
||||||
libxrdp_send_bitmap(self->session, cx, cy, bpp,
|
|
||||||
ldata, rect.left, rect.top, cx, cy);
|
|
||||||
g_free(ldata);
|
|
||||||
|
|
||||||
jndex++;
|
|
||||||
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||||
|
while (error == 0)
|
||||||
|
{
|
||||||
|
xrdp_region_add_rect(self->wm->screen_dirty_region, &rect);
|
||||||
|
jndex++;
|
||||||
|
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jndex = 0;
|
||||||
|
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||||
|
while (error == 0)
|
||||||
|
{
|
||||||
|
cx = rect.right - rect.left;
|
||||||
|
cy = rect.bottom - rect.top;
|
||||||
|
ldata = (char *)g_malloc(cx * cy * Bpp, 0);
|
||||||
|
if (ldata == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
src = self->wm->screen->data;
|
||||||
|
src += self->wm->screen->line_size * rect.top;
|
||||||
|
src += rect.left * Bpp;
|
||||||
|
dst = ldata;
|
||||||
|
for (index = 0; index < cy; index++)
|
||||||
|
{
|
||||||
|
g_memcpy(dst, src, cx * Bpp);
|
||||||
|
src += self->wm->screen->line_size;
|
||||||
|
dst += cx * Bpp;
|
||||||
|
}
|
||||||
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty:"
|
||||||
|
" x %d y %d cx %d cy %d",
|
||||||
|
rect.left, rect.top, cx, cy);
|
||||||
|
libxrdp_send_bitmap(self->session, cx, cy, bpp,
|
||||||
|
ldata, rect.left, rect.top, cx, cy);
|
||||||
|
g_free(ldata);
|
||||||
|
|
||||||
|
jndex++;
|
||||||
|
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xrdp_region_delete(self->dirty_region);
|
xrdp_region_delete(self->dirty_region);
|
||||||
@@ -145,8 +164,8 @@ xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session)
|
|||||||
self->rop = 0xcc; /* copy will use 0xcc */
|
self->rop = 0xcc; /* copy will use 0xcc */
|
||||||
self->clip_children = 1;
|
self->clip_children = 1;
|
||||||
|
|
||||||
|
if (self->session->client_info->no_orders_supported ||
|
||||||
if (self->session->client_info->no_orders_supported)
|
self->session->client_info->gfx)
|
||||||
{
|
{
|
||||||
#if defined(XRDP_PAINTER)
|
#if defined(XRDP_PAINTER)
|
||||||
if (painter_create(&(self->painter)) != PT_ERROR_NONE)
|
if (painter_create(&(self->painter)) != PT_ERROR_NONE)
|
||||||
|
|||||||
@@ -306,6 +306,8 @@ xrdp_process_main_loop(struct xrdp_process *self)
|
|||||||
}
|
}
|
||||||
/* Run end in module */
|
/* Run end in module */
|
||||||
xrdp_process_mod_end(self);
|
xrdp_process_mod_end(self);
|
||||||
|
xrdp_wm_delete(self->wm);
|
||||||
|
self->wm = NULL;
|
||||||
libxrdp_exit(self->session);
|
libxrdp_exit(self->session);
|
||||||
self->session = 0;
|
self->session = 0;
|
||||||
self->status = -1;
|
self->status = -1;
|
||||||
|
|||||||
+31
-6
@@ -28,6 +28,7 @@
|
|||||||
#include "xrdp_constants.h"
|
#include "xrdp_constants.h"
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
#include "guid.h"
|
#include "guid.h"
|
||||||
|
#include "xrdp_client_info.h"
|
||||||
|
|
||||||
#define MAX_NR_CHANNELS 16
|
#define MAX_NR_CHANNELS 16
|
||||||
#define MAX_CHANNEL_NAME 16
|
#define MAX_CHANNEL_NAME 16
|
||||||
@@ -181,7 +182,10 @@ struct xrdp_mod
|
|||||||
int width, int height,
|
int width, int height,
|
||||||
int flags, int frame_id,
|
int flags, int frame_id,
|
||||||
void *shmem_ptr, int shmem_bytes);
|
void *shmem_ptr, int shmem_bytes);
|
||||||
tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server
|
int (*server_egfx_cmd)(struct xrdp_mod *v,
|
||||||
|
char *cmd, int cmd_bytes,
|
||||||
|
char *data, int data_bytes);
|
||||||
|
tintptr server_dumby[100 - 49]; /* align, 100 minus the number of server
|
||||||
functions above */
|
functions above */
|
||||||
/* common */
|
/* common */
|
||||||
tintptr handle; /* pointer to self as int */
|
tintptr handle; /* pointer to self as int */
|
||||||
@@ -343,8 +347,12 @@ enum display_resize_state
|
|||||||
WMRZ_EGFX_CONN_CLOSED,
|
WMRZ_EGFX_CONN_CLOSED,
|
||||||
WRMZ_EGFX_DELETE,
|
WRMZ_EGFX_DELETE,
|
||||||
WMRZ_SERVER_MONITOR_RESIZE,
|
WMRZ_SERVER_MONITOR_RESIZE,
|
||||||
WMRZ_SERVER_VERSION_MESSAGE,
|
WMRZ_SERVER_VERSION_MESSAGE_START,
|
||||||
WMRZ_XRDP_CORE_RESIZE,
|
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING,
|
||||||
|
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED,
|
||||||
|
WMRZ_XRDP_CORE_RESET,
|
||||||
|
WMRZ_XRDP_CORE_RESET_PROCESSING,
|
||||||
|
WMRZ_XRDP_CORE_RESET_PROCESSED,
|
||||||
WMRZ_EGFX_INITIALIZE,
|
WMRZ_EGFX_INITIALIZE,
|
||||||
WMRZ_EGFX_INITALIZING,
|
WMRZ_EGFX_INITALIZING,
|
||||||
WMRZ_EGFX_INITIALIZED,
|
WMRZ_EGFX_INITIALIZED,
|
||||||
@@ -362,8 +370,17 @@ enum display_resize_state
|
|||||||
(status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \
|
(status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \
|
||||||
(status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \
|
(status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \
|
||||||
(status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \
|
(status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \
|
||||||
(status) == WMRZ_SERVER_VERSION_MESSAGE ? "WMRZ_SERVER_VERSION_MESSAGE" : \
|
(status) == WMRZ_SERVER_VERSION_MESSAGE_START ? \
|
||||||
(status) == WMRZ_XRDP_CORE_RESIZE ? "WMRZ_XRDP_CORE_RESIZE" : \
|
"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_RESET ? "WMRZ_XRDP_CORE_RESET" : \
|
||||||
|
(status) == WMRZ_XRDP_CORE_RESET_PROCESSING ? \
|
||||||
|
"WMRZ_XRDP_CORE_RESET_PROCESSING" : \
|
||||||
|
(status) == WMRZ_XRDP_CORE_RESET_PROCESSED ? \
|
||||||
|
"WMRZ_XRDP_CORE_RESET_PROCESSED" : \
|
||||||
(status) == WMRZ_EGFX_INITIALIZE ? "WMRZ_EGFX_INITIALIZE" : \
|
(status) == WMRZ_EGFX_INITIALIZE ? "WMRZ_EGFX_INITIALIZE" : \
|
||||||
(status) == WMRZ_EGFX_INITALIZING ? "WMRZ_EGFX_INITALIZING" : \
|
(status) == WMRZ_EGFX_INITALIZING ? "WMRZ_EGFX_INITALIZING" : \
|
||||||
(status) == WMRZ_EGFX_INITIALIZED ? "WMRZ_EGFX_INITIALIZED" : \
|
(status) == WMRZ_EGFX_INITIALIZED ? "WMRZ_EGFX_INITIALIZED" : \
|
||||||
@@ -374,6 +391,13 @@ enum display_resize_state
|
|||||||
"unknown" \
|
"unknown" \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum xrdp_egfx_flags
|
||||||
|
{
|
||||||
|
XRDP_EGFX_NONE = 0,
|
||||||
|
XRDP_EGFX_H264 = 1,
|
||||||
|
XRDP_EGFX_RFX_PRO = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct xrdp_mm
|
struct xrdp_mm
|
||||||
{
|
{
|
||||||
struct xrdp_wm *wm; /* owner */
|
struct xrdp_wm *wm; /* owner */
|
||||||
@@ -410,7 +434,8 @@ struct xrdp_mm
|
|||||||
int dynamic_monitor_chanid;
|
int dynamic_monitor_chanid;
|
||||||
struct xrdp_egfx *egfx;
|
struct xrdp_egfx *egfx;
|
||||||
int egfx_up;
|
int egfx_up;
|
||||||
|
enum xrdp_egfx_flags egfx_flags;
|
||||||
|
int gfx_delay_autologin;
|
||||||
/* Resize on-the-fly control */
|
/* Resize on-the-fly control */
|
||||||
struct display_control_monitor_layout_data *resize_data;
|
struct display_control_monitor_layout_data *resize_data;
|
||||||
struct list *resize_queue;
|
struct list *resize_queue;
|
||||||
|
|||||||
+16
-4
@@ -767,10 +767,19 @@ xrdp_wm_init(struct xrdp_wm *self)
|
|||||||
list_add_strdup(self->mm->login_values, r);
|
list_add_strdup(self->mm->login_values, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (self->session->client_info->gfx && !self->mm->egfx_up)
|
||||||
* Skip the login box and go straight to the connection phase
|
{
|
||||||
*/
|
/* gfx session but have not recieved caps advertise yet,
|
||||||
xrdp_wm_set_login_state(self, WMLS_START_CONNECT);
|
set flag so we will connect to backend later */
|
||||||
|
self->mm->gfx_delay_autologin = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip the login box and go straight to the connection phase
|
||||||
|
*/
|
||||||
|
xrdp_wm_set_login_state(self, WMLS_START_CONNECT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2020,6 +2029,9 @@ callback(intptr_t id, int msg, intptr_t param1, intptr_t param2,
|
|||||||
xrdp_mm_suppress_output(wm->mm, param1,
|
xrdp_mm_suppress_output(wm->mm, param1,
|
||||||
LOWORD(param2), HIWORD(param2),
|
LOWORD(param2), HIWORD(param2),
|
||||||
LOWORD(param3), HIWORD(param3));
|
LOWORD(param3), HIWORD(param3));
|
||||||
|
case 0x555a:
|
||||||
|
// "yeah, up_and_running"
|
||||||
|
xrdp_mm_up_and_running(wm->mm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
|||||||
@@ -1174,47 +1174,33 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
|
|||||||
in_uint16_le(s, height);
|
in_uint16_le(s, height);
|
||||||
|
|
||||||
bmpdata = 0;
|
bmpdata = 0;
|
||||||
if (flags == 0) /* screen */
|
if (amod->screen_shmem_id_mapped == 0)
|
||||||
{
|
{
|
||||||
/* Do we need to map (or remap) the memory
|
amod->screen_shmem_id = shmem_id;
|
||||||
* area shared with the X server ? */
|
amod->screen_shmem_pixels = (char *) g_shmat(amod->screen_shmem_id);
|
||||||
if (amod->screen_shmem_id_mapped == 0 ||
|
if (amod->screen_shmem_pixels == (void *) -1)
|
||||||
amod->screen_shmem_id != shmem_id)
|
|
||||||
{
|
{
|
||||||
if (amod->screen_shmem_id_mapped != 0)
|
/* failed */
|
||||||
{
|
amod->screen_shmem_id = 0;
|
||||||
g_shmdt(amod->screen_shmem_pixels);
|
amod->screen_shmem_pixels = 0;
|
||||||
}
|
amod->screen_shmem_id_mapped = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (amod->screen_shmem_pixels != 0)
|
|
||||||
{
|
{
|
||||||
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
|
else
|
||||||
@@ -1225,7 +1211,10 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
|
|||||||
flags, frame_id, shmem_id, shmem_offset,
|
flags, frame_id, shmem_id, shmem_offset,
|
||||||
width, height);
|
width, height);
|
||||||
}
|
}
|
||||||
|
if (amod->screen_shmem_pixels != 0)
|
||||||
|
{
|
||||||
|
bmpdata = amod->screen_shmem_pixels + shmem_offset;
|
||||||
|
}
|
||||||
if (bmpdata != 0)
|
if (bmpdata != 0)
|
||||||
{
|
{
|
||||||
rv = amod->server_paint_rects(amod, num_drects, ldrects,
|
rv = amod->server_paint_rects(amod, num_drects, ldrects,
|
||||||
@@ -1238,15 +1227,64 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
|
|||||||
rv = 1;
|
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(lcrects);
|
||||||
g_free(ldrects);
|
g_free(ldrects);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* return error */
|
||||||
|
int
|
||||||
|
process_server_egfx_shmfd(struct mod *amod, struct stream *s)
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
char *cmd;
|
||||||
|
int rv;
|
||||||
|
int cmd_bytes;
|
||||||
|
int shmem_bytes;
|
||||||
|
int fd;
|
||||||
|
int recv_bytes;
|
||||||
|
unsigned int num_fds;
|
||||||
|
void *shmem_ptr;
|
||||||
|
char msg[4];
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
in_uint32_le(s, cmd_bytes);
|
||||||
|
in_uint8p(s, cmd, cmd_bytes);
|
||||||
|
in_uint32_le(s, shmem_bytes);
|
||||||
|
if (shmem_bytes == 0)
|
||||||
|
{
|
||||||
|
return amod->server_egfx_cmd(amod, cmd, cmd_bytes, NULL, 0);
|
||||||
|
}
|
||||||
|
fd = -1;
|
||||||
|
num_fds = -1;
|
||||||
|
if (g_tcp_can_recv(amod->trans->sck, 5000) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
recv_bytes = g_sck_recv_fd_set(amod->trans->sck, msg, 4, &fd, 1, &num_fds);
|
||||||
|
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_server_egfx_shmfd: "
|
||||||
|
"g_sck_recv_fd_set rv %d fd %d", recv_bytes, fd);
|
||||||
|
if (recv_bytes == 4)
|
||||||
|
{
|
||||||
|
if (num_fds == 1)
|
||||||
|
{
|
||||||
|
if (g_file_map(fd, 1, 0, shmem_bytes, &shmem_ptr) == 0)
|
||||||
|
{
|
||||||
|
/* we give up ownership of shmem_ptr
|
||||||
|
will get cleaned up in server_egfx_cmd or
|
||||||
|
xrdp_mm_process_enc_done(gfx) */
|
||||||
|
data = (char *) shmem_ptr;
|
||||||
|
rv = amod->server_egfx_cmd(amod, cmd, cmd_bytes,
|
||||||
|
data, shmem_bytes);
|
||||||
|
}
|
||||||
|
g_file_close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* return error */
|
/* return error */
|
||||||
static int
|
static int
|
||||||
@@ -1289,7 +1327,7 @@ process_server_set_pointer_shmfd(struct mod *amod, struct stream *s)
|
|||||||
{
|
{
|
||||||
Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8;
|
Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8;
|
||||||
shmembytes = width * height * Bpp + width * height / 8;
|
shmembytes = width * height * Bpp + width * height / 8;
|
||||||
if (g_file_map(fd, 1, 1, shmembytes, &shmemptr) == 0)
|
if (g_file_map(fd, 1, 0, shmembytes, &shmemptr) == 0)
|
||||||
{
|
{
|
||||||
cur_data = (char *)shmemptr;
|
cur_data = (char *)shmemptr;
|
||||||
cur_mask = cur_data + width * height * Bpp;
|
cur_mask = cur_data + width * height * Bpp;
|
||||||
@@ -1382,7 +1420,7 @@ process_server_paint_rect_shmfd(struct mod *amod, struct stream *s)
|
|||||||
{
|
{
|
||||||
if (num_fds == 1)
|
if (num_fds == 1)
|
||||||
{
|
{
|
||||||
if (g_file_map(fd, 1, 1, shmem_bytes, &shmem_ptr) == 0)
|
if (g_file_map(fd, 1, 0, shmem_bytes, &shmem_ptr) == 0)
|
||||||
{
|
{
|
||||||
bmpdata = (char *)shmem_ptr;
|
bmpdata = (char *)shmem_ptr;
|
||||||
bmpdata += shmem_offset;
|
bmpdata += shmem_offset;
|
||||||
@@ -1628,6 +1666,9 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s)
|
|||||||
case 61: /* server_paint_rect_shmem_ex */
|
case 61: /* server_paint_rect_shmem_ex */
|
||||||
rv = process_server_paint_rect_shmem_ex(mod, s);
|
rv = process_server_paint_rect_shmem_ex(mod, s);
|
||||||
break;
|
break;
|
||||||
|
case 62:
|
||||||
|
rv = process_server_egfx_shmfd(mod, s);
|
||||||
|
break;
|
||||||
case 63: /* server_set_pointer_shmfd */
|
case 63: /* server_set_pointer_shmfd */
|
||||||
rv = process_server_set_pointer_shmfd(mod, s);
|
rv = process_server_set_pointer_shmfd(mod, s);
|
||||||
break;
|
break;
|
||||||
@@ -1679,74 +1720,97 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
|
|||||||
int type;
|
int type;
|
||||||
char *phold;
|
char *phold;
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "lib_mod_process_message:");
|
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;
|
rv = 0;
|
||||||
if (rv == 0)
|
if (type == 1) /* original order list */
|
||||||
{
|
{
|
||||||
in_uint16_le(s, type);
|
for (index = 0; index < num_orders; ++index)
|
||||||
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++)
|
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;
|
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,
|
phold = s->p;
|
||||||
"lib_mod_process_message: type 2 len %d", len);
|
in_uint16_le(s, type);
|
||||||
for (index = 0; index < num_orders; index++)
|
in_uint16_le(s, len);
|
||||||
|
rv = lib_mod_process_orders(mod, type, s);
|
||||||
|
|
||||||
|
if (rv != 0)
|
||||||
{
|
{
|
||||||
phold = s->p;
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_send_client_info(mod);
|
s->p = phold + len;
|
||||||
}
|
}
|
||||||
else if (type == 3) /* order list with len after type */
|
}
|
||||||
|
else if (type == 100) // metadata commands.
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||||
|
"lib_mod_process_message: type 100 len %d", len);
|
||||||
|
for (index = 0; index < num_orders; ++index)
|
||||||
{
|
{
|
||||||
for (index = 0; index < num_orders; index++)
|
phold = s->p;
|
||||||
|
in_uint16_le(s, type);
|
||||||
|
in_uint16_le(s, len);
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
phold = s->p;
|
case 3: // memory allocation complete
|
||||||
in_uint16_le(s, type);
|
in_uint16_le(s, width);
|
||||||
in_uint16_le(s, len);
|
in_uint16_le(s, height);
|
||||||
rv = lib_mod_process_orders(mod, type, s);
|
LOG(LOG_LEVEL_INFO, "Received memory_allocation_complete"
|
||||||
|
" command. width: %d, height: %d",
|
||||||
if (rv != 0)
|
width, height);
|
||||||
{
|
rv = mod->server_reset(mod, width, height, 0);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
s->p = phold + len;
|
|
||||||
}
|
}
|
||||||
|
s->p = phold + len;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type);
|
{
|
||||||
}
|
LOG_DEVEL(LOG_LEVEL_TRACE, "unknown type %d", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|||||||
@@ -167,7 +167,10 @@ struct mod
|
|||||||
int width, int height,
|
int width, int height,
|
||||||
int flags, int frame_id,
|
int flags, int frame_id,
|
||||||
void *shmem_ptr, int shmem_bytes);
|
void *shmem_ptr, int shmem_bytes);
|
||||||
tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server
|
int (*server_egfx_cmd)(struct mod *v,
|
||||||
|
char *cmd, int cmd_bytes,
|
||||||
|
char *data, int data_bytes);
|
||||||
|
tintptr server_dumby[100 - 49]; /* align, 100 minus the number of server
|
||||||
functions above */
|
functions above */
|
||||||
/* common */
|
/* common */
|
||||||
tintptr handle; /* pointer to self as long */
|
tintptr handle; /* pointer to self as long */
|
||||||
|
|||||||
Reference in New Issue
Block a user