GUACAMOLE-1302: Merge support for forcing lossless compression in VNC and RDP connections.
This commit is contained in:
commit
e2a136f41e
@ -99,6 +99,13 @@ typedef struct guac_common_display {
|
|||||||
*/
|
*/
|
||||||
guac_common_display_layer* buffers;
|
guac_common_display_layer* buffers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-zero if all graphical updates for this display should use lossless
|
||||||
|
* compression, 0 otherwise. By default, newly-created displays will use
|
||||||
|
* lossy compression when heuristics determine it is appropriate.
|
||||||
|
*/
|
||||||
|
int lossless;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutex which is locked internally when access to the display must be
|
* Mutex which is locked internally when access to the display must be
|
||||||
* synchronized. All public functions of guac_common_display should be
|
* synchronized. All public functions of guac_common_display should be
|
||||||
@ -228,5 +235,27 @@ void guac_common_display_free_layer(guac_common_display* display,
|
|||||||
void guac_common_display_free_buffer(guac_common_display* display,
|
void guac_common_display_free_buffer(guac_common_display* display,
|
||||||
guac_common_display_layer* display_buffer);
|
guac_common_display_layer* display_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the overall lossless compression policy of the given display to the
|
||||||
|
* given value, affecting all current and future layers/buffers maintained by
|
||||||
|
* the display. By default, newly-created displays will use lossy compression
|
||||||
|
* for graphical updates when heuristics determine that doing so is
|
||||||
|
* appropriate. Specifying a non-zero value here will force all graphical
|
||||||
|
* updates to always use lossless compression, whereas specifying zero will
|
||||||
|
* restore the default policy.
|
||||||
|
*
|
||||||
|
* Note that this can also be adjusted on a per-layer / per-buffer basis with
|
||||||
|
* guac_common_surface_set_lossless().
|
||||||
|
*
|
||||||
|
* @param display
|
||||||
|
* The display to modify.
|
||||||
|
*
|
||||||
|
* @param lossless
|
||||||
|
* Non-zero if all graphical updates for this display should use lossless
|
||||||
|
* compression, 0 otherwise.
|
||||||
|
*/
|
||||||
|
void guac_common_display_set_lossless(guac_common_display* display,
|
||||||
|
int lossless);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -126,6 +126,13 @@ typedef struct guac_common_surface {
|
|||||||
*/
|
*/
|
||||||
int touches;
|
int touches;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-zero if all graphical updates for this surface should use lossless
|
||||||
|
* compression, 0 otherwise. By default, newly-created surfaces will use
|
||||||
|
* lossy compression when heuristics determine it is appropriate.
|
||||||
|
*/
|
||||||
|
int lossless;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The X coordinate of the upper-left corner of this layer, in pixels,
|
* The X coordinate of the upper-left corner of this layer, in pixels,
|
||||||
* relative to its parent layer. This is only applicable to visible
|
* relative to its parent layer. This is only applicable to visible
|
||||||
@ -510,5 +517,23 @@ void guac_common_surface_dup(guac_common_surface* surface, guac_user* user,
|
|||||||
void guac_common_surface_set_multitouch(guac_common_surface* surface,
|
void guac_common_surface_set_multitouch(guac_common_surface* surface,
|
||||||
int touches);
|
int touches);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lossless compression policy of the given surface to the given
|
||||||
|
* value. By default, newly-created surfaces will use lossy compression for
|
||||||
|
* graphical updates when heuristics determine that doing so is appropriate.
|
||||||
|
* Specifying a non-zero value here will force all graphical updates to always
|
||||||
|
* use lossless compression, whereas specifying zero will restore the default
|
||||||
|
* policy.
|
||||||
|
*
|
||||||
|
* @param surface
|
||||||
|
* The surface to modify.
|
||||||
|
*
|
||||||
|
* @param lossless
|
||||||
|
* Non-zero if all graphical updates for this surface should use lossless
|
||||||
|
* compression, 0 otherwise.
|
||||||
|
*/
|
||||||
|
void guac_common_surface_set_lossless(guac_common_surface* surface,
|
||||||
|
int lossless);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -182,6 +182,30 @@ void guac_common_display_dup(guac_common_display* display, guac_user* user,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void guac_common_display_set_lossless(guac_common_display* display,
|
||||||
|
int lossless) {
|
||||||
|
|
||||||
|
pthread_mutex_lock(&display->_lock);
|
||||||
|
|
||||||
|
/* Update lossless setting to be applied to all newly-allocated
|
||||||
|
* layers/buffers */
|
||||||
|
display->lossless = lossless;
|
||||||
|
|
||||||
|
/* Update losslessness of all allocated layers/buffers */
|
||||||
|
guac_common_display_layer* current = display->layers;
|
||||||
|
while (current != NULL) {
|
||||||
|
guac_common_surface_set_lossless(current->surface, lossless);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update losslessness of default display layer (not included within layers
|
||||||
|
* list) */
|
||||||
|
guac_common_surface_set_lossless(display->default_surface, lossless);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&display->_lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void guac_common_display_flush(guac_common_display* display) {
|
void guac_common_display_flush(guac_common_display* display) {
|
||||||
|
|
||||||
pthread_mutex_lock(&display->_lock);
|
pthread_mutex_lock(&display->_lock);
|
||||||
@ -287,6 +311,9 @@ guac_common_display_layer* guac_common_display_alloc_layer(
|
|||||||
guac_common_surface* surface = guac_common_surface_alloc(display->client,
|
guac_common_surface* surface = guac_common_surface_alloc(display->client,
|
||||||
display->client->socket, layer, width, height);
|
display->client->socket, layer, width, height);
|
||||||
|
|
||||||
|
/* Apply current display losslessness */
|
||||||
|
guac_common_surface_set_lossless(surface, display->lossless);
|
||||||
|
|
||||||
/* Add layer and surface to list */
|
/* Add layer and surface to list */
|
||||||
guac_common_display_layer* display_layer =
|
guac_common_display_layer* display_layer =
|
||||||
guac_common_display_add_layer(&display->layers, layer, surface);
|
guac_common_display_add_layer(&display->layers, layer, surface);
|
||||||
@ -308,6 +335,9 @@ guac_common_display_layer* guac_common_display_alloc_buffer(
|
|||||||
guac_common_surface* surface = guac_common_surface_alloc(display->client,
|
guac_common_surface* surface = guac_common_surface_alloc(display->client,
|
||||||
display->client->socket, buffer, width, height);
|
display->client->socket, buffer, width, height);
|
||||||
|
|
||||||
|
/* Apply current display losslessness */
|
||||||
|
guac_common_surface_set_lossless(surface, display->lossless);
|
||||||
|
|
||||||
/* Add buffer and surface to list */
|
/* Add buffer and surface to list */
|
||||||
guac_common_display_layer* display_layer =
|
guac_common_display_layer* display_layer =
|
||||||
guac_common_display_add_layer(&display->buffers, buffer, surface);
|
guac_common_display_add_layer(&display->buffers, buffer, surface);
|
||||||
|
@ -116,6 +116,15 @@ void guac_common_surface_set_multitouch(guac_common_surface* surface,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void guac_common_surface_set_lossless(guac_common_surface* surface,
|
||||||
|
int lossless) {
|
||||||
|
|
||||||
|
pthread_mutex_lock(&surface->_lock);
|
||||||
|
surface->lossless = lossless;
|
||||||
|
pthread_mutex_unlock(&surface->_lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void guac_common_surface_move(guac_common_surface* surface, int x, int y) {
|
void guac_common_surface_move(guac_common_surface* surface, int x, int y) {
|
||||||
|
|
||||||
pthread_mutex_lock(&surface->_lock);
|
pthread_mutex_lock(&surface->_lock);
|
||||||
@ -534,6 +543,10 @@ static int __guac_common_surface_png_optimality(guac_common_surface* surface,
|
|||||||
static int __guac_common_surface_should_use_jpeg(guac_common_surface* surface,
|
static int __guac_common_surface_should_use_jpeg(guac_common_surface* surface,
|
||||||
const guac_common_rect* rect) {
|
const guac_common_rect* rect) {
|
||||||
|
|
||||||
|
/* Do not use JPEG if lossless quality is required */
|
||||||
|
if (surface->lossless)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Calculate the average framerate for the given rect */
|
/* Calculate the average framerate for the given rect */
|
||||||
int framerate = __guac_common_surface_calculate_framerate(surface, rect);
|
int framerate = __guac_common_surface_calculate_framerate(surface, rect);
|
||||||
|
|
||||||
@ -1806,7 +1819,8 @@ static void __guac_common_surface_flush_to_webp(guac_common_surface* surface,
|
|||||||
/* Send WebP for rect */
|
/* Send WebP for rect */
|
||||||
guac_client_stream_webp(surface->client, socket, GUAC_COMP_OVER, layer,
|
guac_client_stream_webp(surface->client, socket, GUAC_COMP_OVER, layer,
|
||||||
surface->dirty_rect.x, surface->dirty_rect.y, rect,
|
surface->dirty_rect.x, surface->dirty_rect.y, rect,
|
||||||
guac_common_surface_suggest_quality(surface->client), 0);
|
guac_common_surface_suggest_quality(surface->client),
|
||||||
|
surface->lossless ? 1 : 0);
|
||||||
|
|
||||||
cairo_surface_destroy(rect);
|
cairo_surface_destroy(rect);
|
||||||
surface->realized = 1;
|
surface->realized = 1;
|
||||||
|
@ -435,6 +435,10 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
|||||||
rdp_client->settings->width,
|
rdp_client->settings->width,
|
||||||
rdp_client->settings->height);
|
rdp_client->settings->height);
|
||||||
|
|
||||||
|
/* Use lossless compression only if requested (otherwise, use default
|
||||||
|
* heuristics) */
|
||||||
|
guac_common_display_set_lossless(rdp_client->display, settings->lossless);
|
||||||
|
|
||||||
rdp_client->current_surface = rdp_client->display->default_surface;
|
rdp_client->current_surface = rdp_client->display->default_surface;
|
||||||
|
|
||||||
rdp_client->available_svc = guac_common_list_alloc();
|
rdp_client->available_svc = guac_common_list_alloc();
|
||||||
|
@ -128,6 +128,8 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
|
|||||||
"wol-broadcast-addr",
|
"wol-broadcast-addr",
|
||||||
"wol-udp-port",
|
"wol-udp-port",
|
||||||
"wol-wait-time",
|
"wol-wait-time",
|
||||||
|
|
||||||
|
"force-lossless",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -639,6 +641,12 @@ enum RDP_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_WOL_WAIT_TIME,
|
IDX_WOL_WAIT_TIME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "true" if all graphical updates for this connection should use lossless
|
||||||
|
* compresion only, "false" or blank otherwise.
|
||||||
|
*/
|
||||||
|
IDX_FORCE_LOSSLESS,
|
||||||
|
|
||||||
RDP_ARGS_COUNT
|
RDP_ARGS_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -779,6 +787,11 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user,
|
|||||||
settings->height,
|
settings->height,
|
||||||
settings->resolution);
|
settings->resolution);
|
||||||
|
|
||||||
|
/* Lossless compression */
|
||||||
|
settings->lossless =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,
|
||||||
|
IDX_FORCE_LOSSLESS, 0);
|
||||||
|
|
||||||
/* Domain */
|
/* Domain */
|
||||||
settings->domain =
|
settings->domain =
|
||||||
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
|
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
|
||||||
|
@ -192,6 +192,12 @@ typedef struct guac_rdp_settings {
|
|||||||
*/
|
*/
|
||||||
int resolution;
|
int resolution;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether all graphical updates for this connection should use lossless
|
||||||
|
* compression only.
|
||||||
|
*/
|
||||||
|
int lossless;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether audio is enabled.
|
* Whether audio is enabled.
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +91,8 @@ const char* GUAC_VNC_CLIENT_ARGS[] = {
|
|||||||
"wol-broadcast-addr",
|
"wol-broadcast-addr",
|
||||||
"wol-udp-port",
|
"wol-udp-port",
|
||||||
"wol-wait-time",
|
"wol-wait-time",
|
||||||
|
|
||||||
|
"force-lossless",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -373,6 +375,12 @@ enum VNC_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_WOL_WAIT_TIME,
|
IDX_WOL_WAIT_TIME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "true" if all graphical updates for this connection should use lossless
|
||||||
|
* compresion only, "false" or blank otherwise.
|
||||||
|
*/
|
||||||
|
IDX_FORCE_LOSSLESS,
|
||||||
|
|
||||||
VNC_ARGS_COUNT
|
VNC_ARGS_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -432,6 +440,11 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user,
|
|||||||
guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv,
|
guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv,
|
||||||
IDX_COLOR_DEPTH, 0);
|
IDX_COLOR_DEPTH, 0);
|
||||||
|
|
||||||
|
/* Lossless compression */
|
||||||
|
settings->lossless =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv,
|
||||||
|
IDX_FORCE_LOSSLESS, false);
|
||||||
|
|
||||||
#ifdef ENABLE_VNC_REPEATER
|
#ifdef ENABLE_VNC_REPEATER
|
||||||
/* Set repeater parameters if specified */
|
/* Set repeater parameters if specified */
|
||||||
settings->dest_host =
|
settings->dest_host =
|
||||||
|
@ -77,6 +77,12 @@ typedef struct guac_vnc_settings {
|
|||||||
*/
|
*/
|
||||||
bool read_only;
|
bool read_only;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether all graphical updates for this connection should use lossless
|
||||||
|
* compression only.
|
||||||
|
*/
|
||||||
|
bool lossless;
|
||||||
|
|
||||||
#ifdef ENABLE_VNC_REPEATER
|
#ifdef ENABLE_VNC_REPEATER
|
||||||
/**
|
/**
|
||||||
* The VNC host to connect to, if using a repeater.
|
* The VNC host to connect to, if using a repeater.
|
||||||
|
@ -435,6 +435,10 @@ void* guac_vnc_client_thread(void* data) {
|
|||||||
vnc_client->display = guac_common_display_alloc(client,
|
vnc_client->display = guac_common_display_alloc(client,
|
||||||
rfb_client->width, rfb_client->height);
|
rfb_client->width, rfb_client->height);
|
||||||
|
|
||||||
|
/* Use lossless compression only if requested (otherwise, use default
|
||||||
|
* heuristics) */
|
||||||
|
guac_common_display_set_lossless(vnc_client->display, settings->lossless);
|
||||||
|
|
||||||
/* If not read-only, set an appropriate cursor */
|
/* If not read-only, set an appropriate cursor */
|
||||||
if (settings->read_only == 0) {
|
if (settings->read_only == 0) {
|
||||||
if (settings->remote_cursor)
|
if (settings->remote_cursor)
|
||||||
|
@ -221,6 +221,9 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
|
|||||||
display->display_surface = guac_common_surface_alloc(client,
|
display->display_surface = guac_common_surface_alloc(client,
|
||||||
client->socket, display->display_layer, 0, 0);
|
client->socket, display->display_layer, 0, 0);
|
||||||
|
|
||||||
|
/* Never use lossy compression for terminal contents */
|
||||||
|
guac_common_surface_set_lossless(display->display_surface, 1);
|
||||||
|
|
||||||
/* Select layer is a child of the display layer */
|
/* Select layer is a child of the display layer */
|
||||||
guac_protocol_send_move(client->socket, display->select_layer,
|
guac_protocol_send_move(client->socket, display->select_layer,
|
||||||
display->display_layer, 0, 0, 0);
|
display->display_layer, 0, 0, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user