GUACAMOLE-377: Add general RDP support for frame markers.
This commit is contained in:
parent
669e02b4dc
commit
bde8cdee46
@ -372,13 +372,67 @@ BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void guac_rdp_gdi_mark_frame(rdpContext* context, int starting) {
|
||||||
|
|
||||||
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
/* The server supports defining explicit frames */
|
||||||
|
rdp_client->frames_supported = 1;
|
||||||
|
|
||||||
|
/* A new frame is beginning */
|
||||||
|
if (starting) {
|
||||||
|
rdp_client->in_frame = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The current frame has ended */
|
||||||
|
guac_timestamp frame_end = guac_timestamp_current();
|
||||||
|
int time_elapsed = frame_end - rdp_client->frame_start;
|
||||||
|
rdp_client->in_frame = 0;
|
||||||
|
|
||||||
|
/* A new frame has been received from the RDP server and processed */
|
||||||
|
rdp_client->frames_received++;
|
||||||
|
|
||||||
|
/* Flush a new frame if the client is ready for it */
|
||||||
|
if (time_elapsed >= guac_client_get_processing_lag(client)) {
|
||||||
|
|
||||||
|
guac_common_display_flush(rdp_client->display);
|
||||||
|
guac_client_end_multiple_frames(client, rdp_client->frames_received);
|
||||||
|
guac_socket_flush(client->socket);
|
||||||
|
|
||||||
|
rdp_client->frame_start = frame_end;
|
||||||
|
rdp_client->frames_received = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL guac_rdp_gdi_frame_marker(rdpContext* context, const FRAME_MARKER_ORDER* frame_marker) {
|
||||||
|
guac_rdp_gdi_mark_frame(context, frame_marker->action == FRAME_START);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL guac_rdp_gdi_surface_frame_marker(rdpContext* context, const SURFACE_FRAME_MARKER* surface_frame_marker) {
|
||||||
|
|
||||||
|
guac_rdp_gdi_mark_frame(context, surface_frame_marker->frameAction == SURFACECMD_FRAMEACTION_END);
|
||||||
|
|
||||||
|
if (context->settings->FrameAcknowledge > 0)
|
||||||
|
IFCALL(context->update->SurfaceFrameAcknowledge, context,
|
||||||
|
surface_frame_marker->frameId);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BOOL guac_rdp_gdi_begin_paint(rdpContext* context) {
|
BOOL guac_rdp_gdi_begin_paint(rdpContext* context) {
|
||||||
|
|
||||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* A new frame is beginning */
|
/* Leverage BeginPaint handler to detect start of frame for RDPGFX channel */
|
||||||
rdp_client->in_frame = 1;
|
if (rdp_client->settings->enable_gfx)
|
||||||
|
guac_rdp_gdi_mark_frame(context, 1);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -390,8 +444,10 @@ BOOL guac_rdp_gdi_end_paint(rdpContext* context) {
|
|||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
rdpGdi* gdi = context->gdi;
|
rdpGdi* gdi = context->gdi;
|
||||||
|
|
||||||
/* The current frame has ended */
|
/* Leverage EndPaint handler to detect end of frame for RDPGFX channel
|
||||||
rdp_client->in_frame = 0;
|
* (ignore otherwise) */
|
||||||
|
if (!rdp_client->settings->enable_gfx)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
/* Ignore paint if GDI output is suppressed */
|
/* Ignore paint if GDI output is suppressed */
|
||||||
if (gdi->suppressOutput)
|
if (gdi->suppressOutput)
|
||||||
@ -411,28 +467,15 @@ BOOL guac_rdp_gdi_end_paint(rdpContext* context) {
|
|||||||
gdi->primary_buffer + 4*x + y*gdi->stride,
|
gdi->primary_buffer + 4*x + y*gdi->stride,
|
||||||
CAIRO_FORMAT_RGB24, w, h, gdi->stride);
|
CAIRO_FORMAT_RGB24, w, h, gdi->stride);
|
||||||
|
|
||||||
guac_timestamp frame_end = guac_timestamp_current();
|
|
||||||
int time_elapsed = frame_end - rdp_client->frame_start;
|
|
||||||
|
|
||||||
/* Send surface to buffer */
|
/* Send surface to buffer */
|
||||||
guac_common_surface_draw(rdp_client->display->default_surface, x, y, surface);
|
guac_common_surface_draw(rdp_client->display->default_surface, x, y, surface);
|
||||||
|
|
||||||
/* Free surface */
|
/* Free surface */
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
/* A new frame has been received from the RDP server and processed */
|
/* Next frame */
|
||||||
rdp_client->frames_received++;
|
if (gdi->inGfxFrame) {
|
||||||
|
guac_rdp_gdi_mark_frame(context, 0);
|
||||||
/* Flush a new frame if the client is ready for it */
|
|
||||||
if (time_elapsed >= guac_client_get_processing_lag(client)) {
|
|
||||||
|
|
||||||
guac_common_display_flush(rdp_client->display);
|
|
||||||
guac_client_end_multiple_frames(client, rdp_client->frames_received);
|
|
||||||
guac_socket_flush(client->socket);
|
|
||||||
|
|
||||||
rdp_client->frame_start = frame_end;
|
|
||||||
rdp_client->frames_received = 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -155,10 +155,56 @@ BOOL guac_rdp_gdi_opaquerect(rdpContext* context,
|
|||||||
*/
|
*/
|
||||||
BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds);
|
BOOL guac_rdp_gdi_set_bounds(rdpContext* context, const rdpBounds* bounds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the internal GDI implementation that a frame is either starting or
|
||||||
|
* ending. If the frame is ending and the connected client is ready to receive
|
||||||
|
* a new frame, a new frame will be flushed to the client.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* The rdpContext associated with the current RDP session.
|
||||||
|
*
|
||||||
|
* @param starting
|
||||||
|
* Non-zero if the frame in question is starting, zero if the frame is
|
||||||
|
* ending.
|
||||||
|
*/
|
||||||
|
void guac_rdp_gdi_mark_frame(rdpContext* context, int starting);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler called when a frame boundary is received from the RDP server in the
|
||||||
|
* form of a frame marker command. Each frame boundary may be the beginning or
|
||||||
|
* the end of a frame.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* The rdpContext associated with the current RDP session.
|
||||||
|
*
|
||||||
|
* @param frame_marker
|
||||||
|
* The received frame marker.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if successful, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
BOOL guac_rdp_gdi_frame_marker(rdpContext* context, const FRAME_MARKER_ORDER* frame_marker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler called when a frame boundary is received from the RDP server in the
|
||||||
|
* form of a surface frame marker. Each frame boundary may be the beginning or
|
||||||
|
* the end of a frame.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* The rdpContext associated with the current RDP session.
|
||||||
|
*
|
||||||
|
* @param surface_frame_marker
|
||||||
|
* The received frame marker.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if successful, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
BOOL guac_rdp_gdi_surface_frame_marker(rdpContext* context, const SURFACE_FRAME_MARKER* surface_frame_marker);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler called when a paint operation is beginning. This function is
|
* Handler called when a paint operation is beginning. This function is
|
||||||
* expected to be called by the FreeRDP GDI implementation of RemoteFX when a
|
* expected to be called by the FreeRDP GDI implementation of RemoteFX when a
|
||||||
* new frame is beginning.
|
* new frame has started.
|
||||||
*
|
*
|
||||||
* @param context
|
* @param context
|
||||||
* The rdpContext associated with the current RDP session.
|
* The rdpContext associated with the current RDP session.
|
||||||
|
@ -183,6 +183,9 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
|||||||
instance->update->EndPaint = guac_rdp_gdi_end_paint;
|
instance->update->EndPaint = guac_rdp_gdi_end_paint;
|
||||||
instance->update->SetBounds = guac_rdp_gdi_set_bounds;
|
instance->update->SetBounds = guac_rdp_gdi_set_bounds;
|
||||||
|
|
||||||
|
instance->update->SurfaceFrameMarker = guac_rdp_gdi_surface_frame_marker;
|
||||||
|
instance->update->altsec->FrameMarker = guac_rdp_gdi_frame_marker;
|
||||||
|
|
||||||
rdpPrimaryUpdate* primary = instance->update->primary;
|
rdpPrimaryUpdate* primary = instance->update->primary;
|
||||||
primary->DstBlt = guac_rdp_gdi_dstblt;
|
primary->DstBlt = guac_rdp_gdi_dstblt;
|
||||||
primary->PatBlt = guac_rdp_gdi_patblt;
|
primary->PatBlt = guac_rdp_gdi_patblt;
|
||||||
@ -623,15 +626,13 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
|||||||
|
|
||||||
/* Flush frame only if successful and an RDP frame is not known to be
|
/* Flush frame only if successful and an RDP frame is not known to be
|
||||||
* in progress */
|
* in progress */
|
||||||
else if (rdp_client->frames_received) {
|
else if (!rdp_client->frames_supported || rdp_client->frames_received) {
|
||||||
|
|
||||||
guac_common_display_flush(rdp_client->display);
|
guac_common_display_flush(rdp_client->display);
|
||||||
guac_client_end_multiple_frames(client, rdp_client->frames_received);
|
guac_client_end_multiple_frames(client, rdp_client->frames_received);
|
||||||
guac_socket_flush(client->socket);
|
guac_socket_flush(client->socket);
|
||||||
|
|
||||||
rdp_client->frame_start = guac_timestamp_current();
|
rdp_client->frame_start = guac_timestamp_current();
|
||||||
rdp_client->frames_received = 0;
|
rdp_client->frames_received = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,11 @@ typedef struct guac_rdp_client {
|
|||||||
*/
|
*/
|
||||||
guac_common_surface* current_surface;
|
guac_common_surface* current_surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the RDP server supports defining explicit frame boundaries.
|
||||||
|
*/
|
||||||
|
int frames_supported;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the RDP server has reported that a new frame is in progress, and
|
* Whether the RDP server has reported that a new frame is in progress, and
|
||||||
* we are now receiving updates relevant to that frame.
|
* we are now receiving updates relevant to that frame.
|
||||||
|
@ -1409,6 +1409,10 @@ void guac_rdp_push_settings(guac_client* client,
|
|||||||
/* Explicitly set flag value */
|
/* Explicitly set flag value */
|
||||||
rdp_settings->PerformanceFlags = guac_rdp_get_performance_flags(guac_settings);
|
rdp_settings->PerformanceFlags = guac_rdp_get_performance_flags(guac_settings);
|
||||||
|
|
||||||
|
/* Always request frame markers */
|
||||||
|
rdp_settings->FrameMarkerCommandEnabled = TRUE;
|
||||||
|
rdp_settings->SurfaceFrameMarkerEnabled = TRUE;
|
||||||
|
|
||||||
/* Enable RemoteFX / Graphics Pipeline */
|
/* Enable RemoteFX / Graphics Pipeline */
|
||||||
if (guac_settings->enable_gfx) {
|
if (guac_settings->enable_gfx) {
|
||||||
|
|
||||||
@ -1423,7 +1427,6 @@ void guac_rdp_push_settings(guac_client* client,
|
|||||||
|
|
||||||
/* Required for RemoteFX / Graphics Pipeline */
|
/* Required for RemoteFX / Graphics Pipeline */
|
||||||
rdp_settings->FastPathOutput = TRUE;
|
rdp_settings->FastPathOutput = TRUE;
|
||||||
rdp_settings->FrameMarkerCommandEnabled = TRUE;
|
|
||||||
rdp_settings->ColorDepth = 32;
|
rdp_settings->ColorDepth = 32;
|
||||||
rdp_settings->SoftwareGdi = TRUE;
|
rdp_settings->SoftwareGdi = TRUE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user