diff --git a/tests/xrdp/Makefile.am b/tests/xrdp/Makefile.am index 02f8b3e2..e9fab447 100644 --- a/tests/xrdp/Makefile.am +++ b/tests/xrdp/Makefile.am @@ -1,6 +1,5 @@ AM_CPPFLAGS = \ -DXRDP_TOP_SRCDIR=\"$(top_srcdir)\" \ - -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -I$(top_builddir) \ -I$(top_srcdir)/xrdp \ -I$(top_srcdir)/libxrdp \ @@ -21,7 +20,14 @@ EXTRA_DIST = \ test_not4_8bit.bmp \ test_not4_24bit.bmp \ test1.jpg \ - test_alpha_blend.png + test_alpha_blend.png \ + gfx/gfx.toml\ + gfx/gfx_codec_order_undefined.toml \ + gfx/gfx_codec_h264_preferred.toml \ + gfx/gfx_codec_h264_only.toml \ + gfx/gfx_codec_rfx_preferred.toml \ + gfx/gfx_codec_rfx_preferred_odd.toml \ + gfx/gfx_codec_rfx_only.toml TESTS = test_xrdp check_PROGRAMS = test_xrdp diff --git a/tests/xrdp/gfx/gfx.toml b/tests/xrdp/gfx/gfx.toml new file mode 100644 index 00000000..af3fcf86 --- /dev/null +++ b/tests/xrdp/gfx/gfx.toml @@ -0,0 +1,40 @@ +[codec] +order = [ "H.264", "RFX" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +# inherits default + +[x264.wan] +vbv_max_bitrate = 15000 +vbv_buffer_size = 1500 + +[x264.broadband_high] +preset = "superfast" +vbv_max_bitrate = 8000 +vbv_buffer_Size = 800 + +[x264.satellite] +preset = "superfast" +vbv_max_bitrate = 5000 +vbv_buffer_size = 500 + +[x264.broadband_low] +preset = "veryfast" +tune = "zerolatency" +vbv_max_bitrate = 1600 +vbv_buffer_size = 66 + +[x264.modem] +preset = "fast" +tune = "zerolatency" +vbv_max_bitrate = 1200 +vbv_buffer_size = 50 diff --git a/tests/xrdp/gfx/gfx_codec_h264_only.toml b/tests/xrdp/gfx/gfx_codec_h264_only.toml new file mode 100644 index 00000000..86fa7d70 --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_h264_only.toml @@ -0,0 +1,18 @@ +[codec] +order = [ "H.264" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_codec_h264_preferred.toml b/tests/xrdp/gfx/gfx_codec_h264_preferred.toml new file mode 100644 index 00000000..7d5b11ad --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_h264_preferred.toml @@ -0,0 +1,18 @@ +[codec] +order = [ "H.264", "RFX" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_codec_order_undefined.toml b/tests/xrdp/gfx/gfx_codec_order_undefined.toml new file mode 100644 index 00000000..7432cb97 --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_order_undefined.toml @@ -0,0 +1,18 @@ +[codec] +order = [ ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_only.toml b/tests/xrdp/gfx/gfx_codec_rfx_only.toml new file mode 100644 index 00000000..9ab14ea2 --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_rfx_only.toml @@ -0,0 +1,18 @@ +[codec] +order = [ "RFX" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml b/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml new file mode 100644 index 00000000..c09d029b --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml @@ -0,0 +1,18 @@ +[codec] +order = [ "RFX", "H.264" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml b/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml new file mode 100644 index 00000000..ff5c7015 --- /dev/null +++ b/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml @@ -0,0 +1,18 @@ +[codec] +order = [ "RFX", "H.264", "RFX" ] + +[x264.default] +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 24 +fps_den = 1 + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/gfx/gfx_missing_h264.toml b/tests/xrdp/gfx/gfx_missing_h264.toml new file mode 100644 index 00000000..90e2eeb4 --- /dev/null +++ b/tests/xrdp/gfx/gfx_missing_h264.toml @@ -0,0 +1,9 @@ +[codec] +order = [ "H.264", "RFX" ] + +[x264.lan] +[x264.wan] +[x264.broadband_high] +[x264.satellite] +[x264.broadband_low] +[x264.modem] diff --git a/tests/xrdp/test_tconfig.c b/tests/xrdp/test_tconfig.c index 586278eb..81184984 100644 --- a/tests/xrdp/test_tconfig.c +++ b/tests/xrdp/test_tconfig.c @@ -6,6 +6,8 @@ #include "test_xrdp.h" #include "xrdp.h" +#define GFXCONF_STUBDIR XRDP_TOP_SRCDIR "/tests/xrdp/gfx/" + START_TEST(test_tconfig_gfx_always_success) { ck_assert_int_eq(1, 1); @@ -15,7 +17,7 @@ END_TEST START_TEST(test_tconfig_gfx_x264_load_basic) { struct xrdp_tconfig_gfx gfxconfig; - int rv = tconfig_load_gfx(XRDP_TOP_SRCDIR "/xrdp/gfx.toml", &gfxconfig); + int rv = tconfig_load_gfx(GFXCONF_STUBDIR "/gfx.toml", &gfxconfig); ck_assert_int_eq(rv, 0); @@ -31,6 +33,68 @@ START_TEST(test_tconfig_gfx_x264_load_basic) } END_TEST +START_TEST(test_tconfig_gfx_codec_order) +{ + struct xrdp_tconfig_gfx gfxconfig; + + /* H264 earlier */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_h264_preferred.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 2); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_H264); + ck_assert_int_eq(gfxconfig.codec.codecs[1], XTC_RFX); + + /* H264 only */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_h264_only.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 1); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_H264); + + /* RFX earlier */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_rfx_preferred.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 2); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_RFX); + ck_assert_int_eq(gfxconfig.codec.codecs[1], XTC_H264); + + /* RFX appears twice like: RFX, H264, RFX */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_rfx_preferred_odd.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 2); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_RFX); + ck_assert_int_eq(gfxconfig.codec.codecs[1], XTC_H264); + + /* RFX only */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_rfx_only.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 1); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_RFX); + + /* H264 is preferred if order undefined */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_codec_order_undefined.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 2); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_H264); + ck_assert_int_eq(gfxconfig.codec.codecs[1], XTC_RFX); +} +END_TEST + +START_TEST(test_tconfig_gfx_missing_file) +{ + struct xrdp_tconfig_gfx gfxconfig; + + /* Check RFX config is returned if the file doesn't exist */ + tconfig_load_gfx(GFXCONF_STUBDIR "/no_such_file.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 1); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_RFX); +} +END_TEST + +START_TEST(test_tconfig_gfx_missing_h264) +{ + struct xrdp_tconfig_gfx gfxconfig; + + /* Check RFX config only is returned if H.264 parameters are missing */ + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_missing_h264.toml", &gfxconfig); + ck_assert_int_eq(gfxconfig.codec.codec_count, 1); + ck_assert_int_eq(gfxconfig.codec.codecs[0], XTC_RFX); +} +END_TEST + /******************************************************************************/ Suite * make_suite_tconfig_load_gfx(void) @@ -43,6 +107,9 @@ make_suite_tconfig_load_gfx(void) tc_tconfig_load_gfx = tcase_create("xrdp_tconfig_load_gfx"); tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_always_success); tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_x264_load_basic); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_codec_order); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_missing_file); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_missing_h264); suite_add_tcase(s, tc_tconfig_load_gfx); diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index 5b7f27c4..af3fcf86 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -1,3 +1,6 @@ +[codec] +order = [ "H.264", "RFX" ] + [x264.default] preset = "ultrafast" tune = "zerolatency" diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 32286f9b..c40557eb 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -38,6 +38,14 @@ #include "xrdp_client_info.h" #include "log.h" +#if defined(XRDP_X264) || defined(XRDP_OPENH264) || defined(XRDP_NVENC) +#if !defined(XRDP_H264) +#define XRDP_H264 1 +#endif +#else +#undef XRDP_H264 +#endif + /* xrdp.c */ long g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1, diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index fa4da6ff..c3ae935d 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1362,7 +1362,6 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, struct xrdp_mm *self; struct xrdp_bitmap *screen; int index; - int best_index; int best_h264_index; int best_pro_index; int error; @@ -1370,6 +1369,10 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, int flags; struct ver_flags_t *ver_flags; +#if !defined(XRDP_H264) + UNUSED_VAR(best_h264_index); +#endif + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise:"); self = (struct xrdp_mm *) user; screen = self->wm->screen; @@ -1390,7 +1393,6 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, } /* sort by version */ g_qsort(ver_flags, caps_count, sizeof(struct ver_flags_t), cmpverfunc); - best_index = -1; best_h264_index = -1; best_pro_index = -1; for (index = 0; index < caps_count; index++) @@ -1437,19 +1439,34 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, break; } } - if (best_pro_index >= 0) + + int best_index = -1; + struct xrdp_tconfig_gfx_codec_order *co = &self->wm->gfx_config->codec; + char cobuff[64]; + + LOG(LOG_LEVEL_INFO, "Codec search order is %s", + tconfig_codec_order_to_str(co, cobuff, sizeof(cobuff))); + for (index = 0 ; index < co->codec_count ; ++index) { - best_index = best_pro_index; - self->egfx_flags = XRDP_EGFX_RFX_PRO; - } - /* prefer h264, todo use setting in xrdp.ini for this */ - if (best_h264_index >= 0) - { -#if defined(XRDP_X264) || defined(XRDP_NVENC) - best_index = best_h264_index; - self->egfx_flags = XRDP_EGFX_H264; +#if defined(XRDP_H264) + if (co->codecs[index] == XTC_H264 && best_h264_index >= 0) + { + LOG(LOG_LEVEL_INFO, "Matched H264 mode"); + best_index = best_h264_index; + self->egfx_flags = XRDP_EGFX_H264; + break; + } #endif + + if (co->codecs[index] == XTC_RFX && best_pro_index >= 0) + { + LOG(LOG_LEVEL_INFO, "Matched RFX mode"); + best_index = best_pro_index; + self->egfx_flags = XRDP_EGFX_RFX_PRO; + break; + } } + if (best_index >= 0) { LOG(LOG_LEVEL_INFO, " replying version 0x%8.8x flags 0x%8.8x", diff --git a/xrdp/xrdp_tconfig.c b/xrdp/xrdp_tconfig.c index 663f9bce..744cc3d8 100644 --- a/xrdp/xrdp_tconfig.c +++ b/xrdp/xrdp_tconfig.c @@ -48,6 +48,54 @@ #define X264_DEFAULT_FPS_NUM 24 #define X264_DEFAULT_FPS_DEN 1 +const char * +tconfig_codec_order_to_str( + const struct xrdp_tconfig_gfx_codec_order *codec_order, + char *buff, + unsigned int bufflen) +{ + if (bufflen < (8 * codec_order->codec_count)) + { + snprintf(buff, bufflen, "???"); + } + else + { + unsigned int p = 0; + int i; + for (i = 0 ; i < codec_order->codec_count; ++i) + { + if (p > 0) + { + buff[p++] = ','; + } + + switch (codec_order->codecs[i]) + { + case XTC_H264: + buff[p++] = 'H'; + buff[p++] = '2'; + buff[p++] = '6'; + buff[p++] = '4'; + break; + + case XTC_RFX: + buff[p++] = 'R'; + buff[p++] = 'F'; + buff[p++] = 'X'; + break; + + default: + buff[p++] = '?'; + buff[p++] = '?'; + buff[p++] = '?'; + } + } + buff[p++] = '\0'; + } + + return buff; +} + static int tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, struct xrdp_tconfig_gfx_x264_param *param) @@ -199,12 +247,132 @@ tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, return 0; } +static int tconfig_load_gfx_order(toml_table_t *tfile, struct xrdp_tconfig_gfx *config) +{ + char buff[64]; + + /* + * This config loader is not responsible to check if xrdp is built with + * H264/RFX support. Just loads configurations as-is. + */ + + TCLOG(LOG_LEVEL_TRACE, "[codec]"); + + int h264_found = 0; + int rfx_found = 0; + + config->codec.codec_count = 0; + + toml_table_t *codec; + toml_array_t *order; + + if ((codec = toml_table_in(tfile, "codec")) != NULL && + (order = toml_array_in(codec, "order")) != NULL) + { + for (int i = 0; ; i++) + { + toml_datum_t datum = toml_string_at(order, i); + + if (datum.ok) + { + if (h264_found == 0 && + (g_strcasecmp(datum.u.s, "h264") == 0 || + g_strcasecmp(datum.u.s, "h.264") == 0)) + { + h264_found = 1; + config->codec.codecs[config->codec.codec_count] = XTC_H264; + ++config->codec.codec_count; + } + if (rfx_found == 0 && + g_strcasecmp(datum.u.s, "rfx") == 0) + { + rfx_found = 1; + config->codec.codecs[config->codec.codec_count] = XTC_RFX; + ++config->codec.codec_count; + } + free(datum.u.s); + } + else + { + break; + } + } + } + + if (h264_found == 0 && rfx_found == 0) + { + /* prefer H264 if no priority found */ + config->codec.codecs[0] = XTC_H264; + config->codec.codecs[1] = XTC_RFX; + config->codec.codec_count = 2; + + TCLOG(LOG_LEVEL_WARNING, "[codec] could not get GFX codec order, " + "using default order %s", + tconfig_codec_order_to_str(&config->codec, buff, sizeof(buff))); + + return 1; + } + + TCLOG(LOG_LEVEL_DEBUG, "[codec] %s", + tconfig_codec_order_to_str(&config->codec, buff, sizeof(buff))); + return 0; +} + +/** + * Determines whether a codec is enabled + * @param co Ordered codec list + * @param code Code of codec to look for + * @return boolean + */ +static int +codec_enabled(const struct xrdp_tconfig_gfx_codec_order *co, + enum xrdp_tconfig_codecs code) +{ + for (unsigned short i = 0; i < co->codec_count; ++i) + { + if (co->codecs[i] == code) + { + return 1; + } + } + + return 0; +} + +/** + * Disables a Codec by removing it from the codec list + * @param co Ordered codec list + * @param code Code of codec to remove from list + * + * The order of the passed-in codec list is preserved. + */ +static void +disable_codec(struct xrdp_tconfig_gfx_codec_order *co, + enum xrdp_tconfig_codecs code) +{ + unsigned short j = 0; + for (unsigned short i = 0; i < co->codec_count; ++i) + { + if (co->codecs[i] != code) + { + co->codecs[j++] = co->codecs[i]; + } + } + co->codec_count = j; +} + int tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config) { FILE *fp; char errbuf[200]; toml_table_t *tfile; + int rv = 0; + + /* Default to just RFX support. in case we can't load anything */ + config->codec.codec_count = 1; + config->codec.codecs[0] = XTC_RFX; + memset(config->x264_param, 0, sizeof(config->x264_param)); if ((fp = fopen(filename, "r")) == NULL) { @@ -212,33 +380,45 @@ tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config) filename, g_get_strerror()); return 1; } - else if ((tfile = toml_parse_file(fp, errbuf, sizeof(errbuf))) == NULL) + + if ((tfile = toml_parse_file(fp, errbuf, sizeof(errbuf))) == NULL) { TCLOG(LOG_LEVEL_ERROR, "Error in GFX config file %s - %s", filename, errbuf); fclose(fp); return 1; } - else + + TCLOG(LOG_LEVEL_INFO, "Loading GFX config file %s", filename); + fclose(fp); + + /* Load GFX codec order */ + tconfig_load_gfx_order(tfile, config); + + /* H.264 configuration */ + if (codec_enabled(&config->codec, XTC_H264)) { - TCLOG(LOG_LEVEL_INFO, "Loading GFX config file %s", filename); - fclose(fp); - - memset(config, 0, sizeof(struct xrdp_tconfig_gfx)); - - /* First of all, read the default params and override later */ - tconfig_load_gfx_x264_ct(tfile, 0, config->x264_param); - - for (int ct = CONNECTION_TYPE_MODEM; ct < NUM_CONNECTION_TYPES; ct++) + /* First of all, read the default params */ + if (tconfig_load_gfx_x264_ct(tfile, 0, config->x264_param) != 0) { - memcpy(&config->x264_param[ct], &config->x264_param[0], - sizeof(struct xrdp_tconfig_gfx_x264_param)); - - tconfig_load_gfx_x264_ct(tfile, ct, config->x264_param); + /* We can't read the H.264 defaults. Disable H.264 */ + LOG(LOG_LEVEL_WARNING, "H.264 support will be disabled"); + disable_codec(&config->codec, XTC_H264); + rv = 1; + } + else + { + /* Copy default params to other connection types, and + * then override them */ + for (int ct = CONNECTION_TYPE_MODEM; ct < NUM_CONNECTION_TYPES; + ct++) + { + config->x264_param[ct] = config->x264_param[0]; + tconfig_load_gfx_x264_ct(tfile, ct, config->x264_param); + } } - - toml_free(tfile); - - return 0; } + toml_free(tfile); + + return rv; } diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index 6a5ba970..649d6490 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -42,8 +42,21 @@ struct xrdp_tconfig_gfx_x264_param int fps_den; }; +enum xrdp_tconfig_codecs +{ + XTC_H264, + XTC_RFX +}; + +struct xrdp_tconfig_gfx_codec_order +{ + enum xrdp_tconfig_codecs codecs[2]; + unsigned short codec_count; +}; + struct xrdp_tconfig_gfx { + struct xrdp_tconfig_gfx_codec_order codec; /* store x264 parameters for each connection type */ struct xrdp_tconfig_gfx_x264_param x264_param[NUM_CONNECTION_TYPES]; }; @@ -61,6 +74,31 @@ static const char *const rdpbcgr_connection_type_names[] = 0 }; -int tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config); +/** + * Provide a string representation of a codec order + * + * @param codec_order Codec order struct + * @param buff Buffer for result + * @param bufflen Length of above + * @return Convenience copy of buff + */ +const char * +tconfig_codec_order_to_str( + const struct xrdp_tconfig_gfx_codec_order *codec_order, + char *buff, + unsigned int bufflen); + +/** + * Loads the GFX config from the specified file + * + * @param filename Name of file to load + * @param config Struct to receive result + * @return 0 for success + * + * In the event of failure, an error is logged. A minimal + * useable configuration is always returned + */ +int +tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config); #endif diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 110b1d00..c5c80975 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -30,6 +30,7 @@ #include "guid.h" #include "scancode.h" #include "xrdp_client_info.h" +#include "xrdp_tconfig.h" #define MAX_NR_CHANNELS 16 #define MAX_CHANNEL_NAME 16 @@ -581,6 +582,8 @@ struct xrdp_wm /* configuration derived from xrdp.ini */ struct xrdp_config *xrdp_config; + /* configuration derived from gfx.toml */ + struct xrdp_tconfig_gfx *gfx_config; struct xrdp_region *screen_dirty_region; int last_screen_draw_time; diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index c93d959d..1efffc15 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -115,8 +115,9 @@ xrdp_wm_create(struct xrdp_process *owner, self->target_surface = self->screen; self->current_surface_index = 0xffff; /* screen */ - /* to store configuration from xrdp.ini */ + /* to store configuration from xrdp.ini, gfx.toml */ self->xrdp_config = g_new0(struct xrdp_config, 1); + self->gfx_config = g_new0(struct xrdp_tconfig_gfx, 1); /* Load the channel config so libxrdp can check whether drdynvc is enabled or not */ @@ -163,6 +164,11 @@ xrdp_wm_delete(struct xrdp_wm *self) g_free(self->xrdp_config); } + if (self->gfx_config) + { + g_free(self->gfx_config); + } + /* free self */ g_free(self); } @@ -643,6 +649,8 @@ xrdp_wm_init(struct xrdp_wm *self) load_xrdp_config(self->xrdp_config, self->session->xrdp_ini, self->screen->bpp); + tconfig_load_gfx(XRDP_CFG_PATH "/gfx.toml", self->gfx_config); + /* Remove a font loaded on the previous config */ xrdp_font_delete(self->default_font); self->painter->font = NULL; /* May be set to the default_font */