GFX: support 10.2 stack.
authorArmin Novak <armin.novak@gmail.com>
Sun, 16 Oct 2016 08:28:06 +0000 (10:28 +0200)
committerArmin Novak <armin.novak@gmail.com>
Sun, 16 Oct 2016 08:42:46 +0000 (10:42 +0200)
channels/rdpgfx/client/rdpgfx_main.c
channels/rdpgfx/server/rdpgfx_main.c
include/freerdp/channels/rdpgfx.h
server/shadow/shadow_client.c

index 23782db..e348e36 100644 (file)
@@ -60,7 +60,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
        RDPGFX_PLUGIN* gfx;
        RDPGFX_HEADER header;
        RDPGFX_CAPSET* capsSet;
-       RDPGFX_CAPSET capsSets[3];
+       RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS];
        RDPGFX_CAPS_ADVERTISE_PDU pdu;
        gfx = (RDPGFX_PLUGIN*) callback->plugin;
        header.flags = 0;
@@ -101,6 +101,9 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
 
                if (!gfx->H264)
                        capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
+
+               capsSets[pdu.capsSetCount] = *capsSet;
+               capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102;
        }
 
        header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount *
index 47d2bf4..4f64525 100644 (file)
@@ -572,6 +572,7 @@ static UINT rdpgfx_write_surface_command(wStream* s,
        UINT32 bitmapDataStart = 0;
        UINT32 bitmapDataLength = 0;
        UINT8 pixelFormat = 0;
+
        switch (cmd->format)
        {
                case PIXEL_FORMAT_BGRX32:
@@ -1156,8 +1157,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
         wStream* s)
 {
        UINT16 index;
-       RDPGFX_CAPSET* capsSet;
-       RDPGFX_CAPSET capsSets[3];
+       RDPGFX_CAPSET* capsSets;
        RDPGFX_CAPS_ADVERTISE_PDU pdu;
        UINT error = CHANNEL_RC_OK;
        UINT32 capsDataLength;
@@ -1170,24 +1170,22 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
 
        Stream_Read_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */
 
-       if (pdu.capsSetCount > 3)
-       {
-               /* According to the latest spec, capsSetCount <= 3 */
-               WLog_ERR(TAG, "capsSetCount is greater than 3: %u", pdu.capsSetCount);
-               return ERROR_INVALID_DATA;
-       }
-
-       if (Stream_GetRemainingLength(s) < (pdu.capsSetCount * 12))
+       if (Stream_GetRemainingLength(s) < (pdu.capsSetCount * RDPGFX_CAPSET_SIZE))
        {
                WLog_ERR(TAG, "not enough data!");
                return ERROR_INVALID_DATA;
        }
 
+       capsSets = calloc(pdu.capsSetCount, RDPGFX_CAPSET_SIZE);
+
+       if (!capsSets)
+               return ERROR_OUTOFMEMORY;
+
        pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
 
        for (index = 0; index < pdu.capsSetCount; index++)
        {
-               capsSet = &(pdu.capsSets[index]);
+               RDPGFX_CAPSET* capsSet = &(pdu.capsSets[index]);
                Stream_Read_UINT32(s, capsSet->version); /* version (4 bytes) */
                Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */
 
@@ -1195,6 +1193,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
                {
                        WLog_ERR(TAG, "capsDataLength does not equal to 4: %lu",
                                 capsDataLength);
+                       free(capsSets);
                        return ERROR_INVALID_DATA;
                }
 
@@ -1209,6 +1208,7 @@ static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
                        WLog_ERR(TAG, "context->CapsAdvertise failed with error %lu", error);
        }
 
+       free(capsSets);
        return error;
 }
 
index 97e863f..7f737a2 100644 (file)
@@ -92,7 +92,9 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER;
 #define RDPGFX_CAPVERSION_8                    0x00080004
 #define RDPGFX_CAPVERSION_81                   0x00080105
 #define RDPGFX_CAPVERSION_10                   0x000A0002
+#define RDPGFX_CAPVERSION_102                  0x000A0200
 
+#define RDPGFX_NUMBER_CAPSETS                  4
 #define RDPGFX_CAPSET_SIZE                     12
 
 struct _RDPGFX_CAPSET
index a536de9..3af9eaf 100644 (file)
@@ -617,19 +617,37 @@ static UINT shadow_client_rdpgfx_qoe_frame_acknowledge(RdpgfxServerContext*
  *
  * @return 0 on success, otherwise a Win32 error code
  */
-static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise)
+static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
+        RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise)
 {
        UINT16 index;
        RDPGFX_CAPS_CONFIRM_PDU pdu;
        rdpSettings* settings = context->rdpcontext->settings;
        UINT32 flags = 0;
-
        /* Request full screen update for new gfx channel */
-       shadow_client_refresh_rect((rdpShadowClient *)context->custom, 0, NULL);
+       shadow_client_refresh_rect((rdpShadowClient*)context->custom, 0, NULL);
+
+       for (index = 0; index < capsAdvertise->capsSetCount; index++)
+       {
+               pdu.capsSet = &(capsAdvertise->capsSets[index]);
+
+               if (pdu.capsSet->version == RDPGFX_CAPVERSION_102)
+               {
+                       if (settings)
+                       {
+                               flags = pdu.capsSet->flags;
+                               settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
+                               settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
+                       }
+
+                       return context->CapsConfirm(context, &pdu);
+               }
+       }
 
        for (index = 0; index < capsAdvertise->capsSetCount; index++)
        {
                pdu.capsSet = &(capsAdvertise->capsSets[index]);
+
                if (pdu.capsSet->version == RDPGFX_CAPVERSION_10)
                {
                        if (settings)
@@ -642,6 +660,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RD
                        return context->CapsConfirm(context, &pdu);
                }
        }
+
        for (index = 0; index < capsAdvertise->capsSetCount; index++)
        {
                if (pdu.capsSet->version == RDPGFX_CAPVERSION_81)
@@ -657,6 +676,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RD
                        return context->CapsConfirm(context, &pdu);
                }
        }
+
        for (index = 0; index < capsAdvertise->capsSetCount; index++)
        {
                if (pdu.capsSet->version == RDPGFX_CAPVERSION_8)