rdpgfx/client: Add callbacks for manual caps sending and frame acking
authorMati Shabtay <matishabtay@gmail.com>
Sun, 5 May 2019 12:31:18 +0000 (15:31 +0300)
committerMati Shabtay <matishabtay@gmail.com>
Sun, 5 May 2019 12:56:35 +0000 (15:56 +0300)
channels/rdpgfx/client/rdpgfx_main.c
channels/rdpgfx/client/rdpgfx_main.h
include/freerdp/client/rdpgfx.h

index 987c787..c7b17e2 100644 (file)
  *
  * @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;
-       UINT32 x;
-       wStream* s;
+       UINT error = CHANNEL_RC_OK;
        UINT16 index;
-       RDPGFX_PLUGIN* gfx;
        RDPGFX_HEADER header;
        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_CAPS_ADVERTISE_PDU pdu;
        gfx = (RDPGFX_PLUGIN*) callback->plugin;
-       header.flags = 0;
-       header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
+       context = (RdpgfxClientContext*) gfx->iface.pInterface;
        pdu.capsSetCount = 0;
        pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
        capsSet = &capsSets[pdu.capsSetCount++];
@@ -160,40 +215,11 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
 #endif
        }
 
-       header.pduLength = RDPGFX_HEADER_SIZE + 2;
-
-       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!");
-               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++)
+       if (context)
        {
-               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);
+               IFCALLRET(context->CapsAdvertise, error, context, &pdu);
        }
 
-       Stream_SealLength(s);
-       error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
-                                        Stream_Buffer(s), NULL);
-fail:
-       Stream_Free(s, TRUE);
        return error;
 }
 
@@ -209,6 +235,7 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
        UINT32 capsDataLength;
        RDPGFX_CAPS_CONFIRM_PDU pdu;
        RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
+       RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
        pdu.capsSet = &capsSet;
 
        if (Stream_GetRemainingLength(s) < 12)
@@ -223,6 +250,12 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
        gfx->ConnectionCaps = capsSet;
        WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%08"PRIX32" flags: 0x%08"PRIX32"",
                   capsSet.version, capsSet.flags);
+
+       if (context)
+       {
+               IFCALL(context->CapsConfirm, context, &pdu);
+       }
+
        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
  */
-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)
 {
        UINT error;
        wStream* s;
        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.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
        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;
        RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
        UINT error = CHANNEL_RC_OK;
-       BOOL sendAck = TRUE;
 
        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++;
        ack.frameId = pdu.frameId;
        ack.totalFramesDecoded = gfx->TotalDecodedFrames;
-       IFCALLRET(context->PreFrameAck, sendAck, context, &ack);
 
-       if (sendAck)
+       if (gfx->sendFrameAcks)
        {
                if (gfx->suspendFrameAcks)
                {
                        ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT;
 
                        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"",
                                                   error);
                }
@@ -642,7 +674,7 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
                {
                        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"",
                                           error);
                }
@@ -667,7 +699,8 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
                                qoe.timeDiffEDR = 1;
 
                                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);
                        }
 
@@ -1518,8 +1551,24 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
 static UINT rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback)
 {
        RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
-       WLog_DBG(TAG, "OnOpen");
-       return rdpgfx_send_caps_advertise_pdu(callback);
+       RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
+       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;
 }
 
@@ -1911,6 +1965,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
                context->GetSurfaceData = rdpgfx_get_surface_data;
                context->SetCacheSlotData = rdpgfx_set_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->zgfx = zgfx_context_new(FALSE);
 
index 7efe298..0b09839 100644 (file)
@@ -73,6 +73,7 @@ struct _RDPGFX_PLUGIN
        UINT32 TotalDecodedFrames;
        UINT32 StartDecodingTime;
        BOOL suspendFrameAcks;
+    BOOL sendFrameAcks;
 
        wHashTable* SurfaceTable;
 
index 7de72ed..ea2120e 100644 (file)
@@ -83,8 +83,15 @@ typedef UINT(*pcRdpgfxUpdateSurfaces)(RdpgfxClientContext* context);
 typedef UINT(*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId,
         UINT32 nrRects, const RECTANGLE_16* rects);
 
-typedef BOOL(*pcRdpgfxPreFrameAck)(RdpgfxClientContext* context,
-                                   RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge);
+typedef UINT(*pcRdpgfxOnOpen)(RdpgfxClientContext* context, BOOL* do_caps_advertise,
+                              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
 {
@@ -117,12 +124,17 @@ struct _rdpgfx_client_context
        pcRdpgfxSetCacheSlotData SetCacheSlotData;
        pcRdpgfxGetCacheSlotData GetCacheSlotData;
 
+       /* Proxy callbacks */
+       pcRdpgfxOnOpen OnOpen;
+       pcRdpgfxOnClose OnClose;
+       pcRdpgfxCapsAdvertise CapsAdvertise;
+       pcRdpgfxCapsConfirm CapsConfirm;
+       pcRdpgfxFrameAcknowledge FrameAcknowledge;
+
        /* No locking required */
        pcRdpgfxUpdateSurfaces UpdateSurfaces;
        pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea;
 
-       pcRdpgfxPreFrameAck PreFrameAck;
-
        CRITICAL_SECTION mux;
        PROFILER_DEFINE(SurfaceProfiler)
 };