mirror of https://github.com/FreeRDP/FreeRDP
rdpgfx/client: Add callbacks for manual caps sending and frame acking
This commit is contained in:
parent
f867c90e4c
commit
eee234c239
|
@ -52,20 +52,75 @@
|
||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
|
static UINT rdpgfx_send_caps_advertise_pdu(RdpgfxClientContext* context,
|
||||||
|
const RDPGFX_CAPS_ADVERTISE_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error;
|
UINT error = CHANNEL_RC_OK;
|
||||||
UINT32 x;
|
|
||||||
wStream* s;
|
|
||||||
UINT16 index;
|
UINT16 index;
|
||||||
RDPGFX_PLUGIN* gfx;
|
|
||||||
RDPGFX_HEADER header;
|
RDPGFX_HEADER header;
|
||||||
RDPGFX_CAPSET* capsSet;
|
RDPGFX_CAPSET* capsSet;
|
||||||
|
RDPGFX_PLUGIN* gfx;
|
||||||
|
RDPGFX_CHANNEL_CALLBACK* callback;
|
||||||
|
wStream* s;
|
||||||
|
gfx = (RDPGFX_PLUGIN*) context->handle;
|
||||||
|
callback = gfx->listener_callback->channel_callback;
|
||||||
|
header.flags = 0;
|
||||||
|
header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
|
||||||
|
header.pduLength = RDPGFX_HEADER_SIZE + 2;
|
||||||
|
|
||||||
|
for (index = 0; index < pdu->capsSetCount; index++)
|
||||||
|
{
|
||||||
|
capsSet = &(pdu->capsSets[index]);
|
||||||
|
header.pduLength += RDPGFX_CAPSET_BASE_SIZE + capsSet->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu->capsSetCount);
|
||||||
|
s = Stream_New(NULL, header.pduLength);
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Stream_New failed!");
|
||||||
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = rdpgfx_write_header(s, &header)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* RDPGFX_CAPS_ADVERTISE_PDU */
|
||||||
|
Stream_Write_UINT16(s, pdu->capsSetCount); /* capsSetCount (2 bytes) */
|
||||||
|
|
||||||
|
for (index = 0; index < pdu->capsSetCount; index++)
|
||||||
|
{
|
||||||
|
capsSet = &(pdu->capsSets[index]);
|
||||||
|
Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, capsSet->length); /* capsDataLength (4 bytes) */
|
||||||
|
Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */
|
||||||
|
Stream_Zero(s, capsSet->length - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream_SealLength(s);
|
||||||
|
error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
|
||||||
|
Stream_Buffer(s), NULL);
|
||||||
|
fail:
|
||||||
|
Stream_Free(s, TRUE);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function description
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
|
*/
|
||||||
|
static UINT rdpgfx_send_supported_caps(RDPGFX_CHANNEL_CALLBACK* callback)
|
||||||
|
{
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
RDPGFX_PLUGIN* gfx;
|
||||||
|
RdpgfxClientContext* context;
|
||||||
|
RDPGFX_CAPSET* capsSet;
|
||||||
RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 };
|
RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 };
|
||||||
RDPGFX_CAPS_ADVERTISE_PDU pdu;
|
RDPGFX_CAPS_ADVERTISE_PDU pdu;
|
||||||
gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||||
header.flags = 0;
|
context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||||
header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
|
|
||||||
pdu.capsSetCount = 0;
|
pdu.capsSetCount = 0;
|
||||||
pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
|
pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
|
||||||
capsSet = &capsSets[pdu.capsSetCount++];
|
capsSet = &capsSets[pdu.capsSetCount++];
|
||||||
|
@ -160,40 +215,11 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
header.pduLength = RDPGFX_HEADER_SIZE + 2;
|
if (context)
|
||||||
|
|
||||||
for (x = 0; x < pdu.capsSetCount; x++)
|
|
||||||
header.pduLength += RDPGFX_CAPSET_BASE_SIZE + capsSets[x].length;
|
|
||||||
|
|
||||||
WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
|
|
||||||
s = Stream_New(NULL, header.pduLength);
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Stream_New failed!");
|
IFCALLRET(context->CapsAdvertise, error, context, &pdu);
|
||||||
return CHANNEL_RC_NO_MEMORY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = rdpgfx_write_header(s, &header)))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* RDPGFX_CAPS_ADVERTISE_PDU */
|
|
||||||
Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */
|
|
||||||
|
|
||||||
for (index = 0; index < pdu.capsSetCount; index++)
|
|
||||||
{
|
|
||||||
capsSet = &(pdu.capsSets[index]);
|
|
||||||
Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */
|
|
||||||
Stream_Write_UINT32(s, capsSet->length); /* capsDataLength (4 bytes) */
|
|
||||||
Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */
|
|
||||||
Stream_Zero(s, capsSet->length - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream_SealLength(s);
|
|
||||||
error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
|
|
||||||
Stream_Buffer(s), NULL);
|
|
||||||
fail:
|
|
||||||
Stream_Free(s, TRUE);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +235,7 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
UINT32 capsDataLength;
|
UINT32 capsDataLength;
|
||||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||||
|
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||||
pdu.capsSet = &capsSet;
|
pdu.capsSet = &capsSet;
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < 12)
|
if (Stream_GetRemainingLength(s) < 12)
|
||||||
|
@ -223,6 +250,12 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
gfx->ConnectionCaps = capsSet;
|
gfx->ConnectionCaps = capsSet;
|
||||||
WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%08"PRIX32" flags: 0x%08"PRIX32"",
|
WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%08"PRIX32" flags: 0x%08"PRIX32"",
|
||||||
capsSet.version, capsSet.flags);
|
capsSet.version, capsSet.flags);
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
IFCALL(context->CapsConfirm, context, &pdu);
|
||||||
|
}
|
||||||
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,13 +264,14 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
static UINT rdpgfx_send_frame_acknowledge_pdu(RdpgfxClientContext* context,
|
||||||
RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu)
|
RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu)
|
||||||
{
|
{
|
||||||
UINT error;
|
UINT error;
|
||||||
wStream* s;
|
wStream* s;
|
||||||
RDPGFX_HEADER header;
|
RDPGFX_HEADER header;
|
||||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
|
||||||
|
RDPGFX_CHANNEL_CALLBACK* callback = gfx->listener_callback->channel_callback;
|
||||||
header.flags = 0;
|
header.flags = 0;
|
||||||
header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
|
header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
|
||||||
header.pduLength = RDPGFX_HEADER_SIZE + 12;
|
header.pduLength = RDPGFX_HEADER_SIZE + 12;
|
||||||
|
@ -599,7 +633,6 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||||
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
BOOL sendAck = TRUE;
|
|
||||||
|
|
||||||
if (Stream_GetRemainingLength(s) < RDPGFX_END_FRAME_PDU_SIZE)
|
if (Stream_GetRemainingLength(s) < RDPGFX_END_FRAME_PDU_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -625,16 +658,15 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
gfx->TotalDecodedFrames++;
|
gfx->TotalDecodedFrames++;
|
||||||
ack.frameId = pdu.frameId;
|
ack.frameId = pdu.frameId;
|
||||||
ack.totalFramesDecoded = gfx->TotalDecodedFrames;
|
ack.totalFramesDecoded = gfx->TotalDecodedFrames;
|
||||||
IFCALLRET(context->PreFrameAck, sendAck, context, &ack);
|
|
||||||
|
|
||||||
if (sendAck)
|
if (gfx->sendFrameAcks)
|
||||||
{
|
{
|
||||||
if (gfx->suspendFrameAcks)
|
if (gfx->suspendFrameAcks)
|
||||||
{
|
{
|
||||||
ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT;
|
ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT;
|
||||||
|
|
||||||
if (gfx->TotalDecodedFrames == 1)
|
if (gfx->TotalDecodedFrames == 1)
|
||||||
if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack)))
|
if ((error = rdpgfx_send_frame_acknowledge_pdu(context, &ack)))
|
||||||
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"",
|
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
@ -642,7 +674,7 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
{
|
{
|
||||||
ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE;
|
ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE;
|
||||||
|
|
||||||
if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack)))
|
if ((error = rdpgfx_send_frame_acknowledge_pdu(context, &ack)))
|
||||||
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"",
|
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
@ -667,7 +699,8 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||||
qoe.timeDiffEDR = 1;
|
qoe.timeDiffEDR = 1;
|
||||||
|
|
||||||
if ((error = rdpgfx_send_qoe_frame_acknowledge_pdu(callback, &qoe)))
|
if ((error = rdpgfx_send_qoe_frame_acknowledge_pdu(callback, &qoe)))
|
||||||
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"",
|
WLog_Print(gfx->log, WLOG_ERROR,
|
||||||
|
"rdpgfx_send_qoe_frame_acknowledge_pdu failed with error %"PRIu32"",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,8 +1551,24 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
|
||||||
static UINT rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback)
|
static UINT rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback)
|
||||||
{
|
{
|
||||||
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
|
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
|
||||||
WLog_DBG(TAG, "OnOpen");
|
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||||
return rdpgfx_send_caps_advertise_pdu(callback);
|
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
BOOL do_caps_advertise = TRUE;
|
||||||
|
gfx->sendFrameAcks = TRUE;
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
IFCALLRET(context->OnOpen, error, context, &do_caps_advertise, &gfx->sendFrameAcks);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
WLog_Print(gfx->log, WLOG_ERROR, "context->OnOpen failed with error %"PRIu32"", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_caps_advertise)
|
||||||
|
error = rdpgfx_send_supported_caps(callback);
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1580,6 +1629,11 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
IFCALL(context->OnClose, context);
|
||||||
|
}
|
||||||
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1911,6 +1965,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||||
context->GetSurfaceData = rdpgfx_get_surface_data;
|
context->GetSurfaceData = rdpgfx_get_surface_data;
|
||||||
context->SetCacheSlotData = rdpgfx_set_cache_slot_data;
|
context->SetCacheSlotData = rdpgfx_set_cache_slot_data;
|
||||||
context->GetCacheSlotData = rdpgfx_get_cache_slot_data;
|
context->GetCacheSlotData = rdpgfx_get_cache_slot_data;
|
||||||
|
context->CapsAdvertise = rdpgfx_send_caps_advertise_pdu;
|
||||||
|
context->FrameAcknowledge = rdpgfx_send_frame_acknowledge_pdu;
|
||||||
gfx->iface.pInterface = (void*) context;
|
gfx->iface.pInterface = (void*) context;
|
||||||
gfx->zgfx = zgfx_context_new(FALSE);
|
gfx->zgfx = zgfx_context_new(FALSE);
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ struct _RDPGFX_PLUGIN
|
||||||
UINT32 TotalDecodedFrames;
|
UINT32 TotalDecodedFrames;
|
||||||
UINT32 StartDecodingTime;
|
UINT32 StartDecodingTime;
|
||||||
BOOL suspendFrameAcks;
|
BOOL suspendFrameAcks;
|
||||||
|
BOOL sendFrameAcks;
|
||||||
|
|
||||||
wHashTable* SurfaceTable;
|
wHashTable* SurfaceTable;
|
||||||
|
|
||||||
|
|
|
@ -83,8 +83,15 @@ typedef UINT(*pcRdpgfxUpdateSurfaces)(RdpgfxClientContext* context);
|
||||||
typedef UINT(*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId,
|
typedef UINT(*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId,
|
||||||
UINT32 nrRects, const RECTANGLE_16* rects);
|
UINT32 nrRects, const RECTANGLE_16* rects);
|
||||||
|
|
||||||
typedef BOOL(*pcRdpgfxPreFrameAck)(RdpgfxClientContext* context,
|
typedef UINT(*pcRdpgfxOnOpen)(RdpgfxClientContext* context, BOOL* do_caps_advertise,
|
||||||
RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge);
|
BOOL* do_frame_acks);
|
||||||
|
typedef UINT(*pcRdpgfxOnClose)(RdpgfxClientContext* context);
|
||||||
|
typedef UINT(*pcRdpgfxCapsAdvertise)(RdpgfxClientContext* context,
|
||||||
|
const RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise);
|
||||||
|
typedef UINT(*pcRdpgfxCapsConfirm)(RdpgfxClientContext* context,
|
||||||
|
const RDPGFX_CAPS_CONFIRM_PDU* capsConfirm);
|
||||||
|
typedef UINT(*pcRdpgfxFrameAcknowledge)(RdpgfxClientContext* context,
|
||||||
|
const RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge);
|
||||||
|
|
||||||
struct _rdpgfx_client_context
|
struct _rdpgfx_client_context
|
||||||
{
|
{
|
||||||
|
@ -117,12 +124,17 @@ struct _rdpgfx_client_context
|
||||||
pcRdpgfxSetCacheSlotData SetCacheSlotData;
|
pcRdpgfxSetCacheSlotData SetCacheSlotData;
|
||||||
pcRdpgfxGetCacheSlotData GetCacheSlotData;
|
pcRdpgfxGetCacheSlotData GetCacheSlotData;
|
||||||
|
|
||||||
|
/* Proxy callbacks */
|
||||||
|
pcRdpgfxOnOpen OnOpen;
|
||||||
|
pcRdpgfxOnClose OnClose;
|
||||||
|
pcRdpgfxCapsAdvertise CapsAdvertise;
|
||||||
|
pcRdpgfxCapsConfirm CapsConfirm;
|
||||||
|
pcRdpgfxFrameAcknowledge FrameAcknowledge;
|
||||||
|
|
||||||
/* No locking required */
|
/* No locking required */
|
||||||
pcRdpgfxUpdateSurfaces UpdateSurfaces;
|
pcRdpgfxUpdateSurfaces UpdateSurfaces;
|
||||||
pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea;
|
pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea;
|
||||||
|
|
||||||
pcRdpgfxPreFrameAck PreFrameAck;
|
|
||||||
|
|
||||||
CRITICAL_SECTION mux;
|
CRITICAL_SECTION mux;
|
||||||
PROFILER_DEFINE(SurfaceProfiler)
|
PROFILER_DEFINE(SurfaceProfiler)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue