From e8c8e7b6d0a6a6864c47597adb8c24608fec9961 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 27 Feb 2019 16:36:15 +0100 Subject: [PATCH] Updated EGFX support to 10.6 --- channels/rdpgfx/client/rdpgfx_main.c | 377 ++++++++++++++++++--------- channels/rdpgfx/rdpgfx_common.c | 6 +- channels/rdpgfx/server/rdpgfx_main.c | 44 ++++ include/freerdp/channels/rdpgfx.h | 46 +++- include/freerdp/client/rdpgfx.h | 7 +- include/freerdp/server/rdpgfx.h | 57 ++-- libfreerdp/gdi/gfx.c | 31 +++ server/shadow/shadow_client.c | 71 ++++- 8 files changed, 493 insertions(+), 146 deletions(-) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 6e93cb4d7..8abe21c64 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -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[RDPGFX_NUMBER_CAPSETS]; + RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 }; RDPGFX_CAPS_ADVERTISE_PDU pdu; gfx = (RDPGFX_PLUGIN*) callback->plugin; header.flags = 0; @@ -69,6 +69,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) pdu.capsSets = (RDPGFX_CAPSET*) capsSets; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_8; + capsSet->length = 4; capsSet->flags = 0; if (gfx->ThinClient) @@ -82,6 +83,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_81; + capsSet->length = 4; capsSet->flags = 0; if (gfx->ThinClient) @@ -91,30 +93,61 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; #ifdef WITH_GFX_H264 + if (gfx->H264) capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED; + #endif if (!gfx->H264 || gfx->AVC444) { + UINT32 caps10Flags = 0; capsSet = &capsSets[pdu.capsSetCount++]; capsSet->version = RDPGFX_CAPVERSION_10; - capsSet->flags = 0; + capsSet->length = 4; if (gfx->SmallCache) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + caps10Flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; #ifdef WITH_GFX_H264 - if (!gfx->AVC444) - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; -#else - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; -#endif - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; + if (!gfx->AVC444) + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + +#else + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#endif + capsSet->flags = caps10Flags; + /* + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_101; + capsSet->length = 0x10; + capsSet->flags = 0; + */ + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_102; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + + if (gfx->ThinClient) + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_THINCLIENT; + + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_103; + capsSet->length = 0x4; + capsSet->flags = caps10Flags & ~RDPGFX_CAPS_FLAG_SMALL_CACHE; + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_104; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_105; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_106; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; } header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); @@ -137,7 +170,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { capsSet = &(pdu.capsSets[index]); Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ - Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ + Stream_Write_UINT32(s, capsSet->length); /* capsDataLength (4 bytes) */ Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ } @@ -161,7 +194,6 @@ 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; - pdu.capsSet = &capsSet; if (Stream_GetRemainingLength(s) < 12) @@ -173,11 +205,9 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */ Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ - gfx->ConnectionCaps = capsSet; - WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%08"PRIX32" flags: 0x%08"PRIX32"", - capsSet.version, capsSet.flags); + capsSet.version, capsSet.flags); return CHANNEL_RC_OK; } @@ -193,13 +223,12 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s; RDPGFX_HEADER header; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - header.flags = 0; header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); - s = Stream_New(NULL, header.pduLength); + if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -222,19 +251,18 @@ fail: } static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, - const RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* pdu) + const RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* pdu) { UINT error; wStream* s; RDPGFX_HEADER header; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - header.flags = 0; header.cmdId = RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; WLog_Print(gfx->log, WLOG_DEBUG, "SendQoeFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); - s = Stream_New(NULL, header.pduLength); + if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -249,7 +277,6 @@ static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callb Stream_Write_UINT32(s, pdu->timestamp); Stream_Write_UINT16(s, pdu->timeDiffSE); Stream_Write_UINT16(s, pdu->timeDiffEDR); - error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); fail: @@ -291,6 +318,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF)); + if (!pdu.monitorDefArray) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -317,15 +345,16 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } Stream_Seek(s, pad); /* pad (total size is 340 bytes) */ - WLog_Print(gfx->log, WLOG_DEBUG, "RecvResetGraphicsPdu: width: %"PRIu32" height: %"PRIu32" count: %"PRIu32"", - pdu.width, pdu.height, pdu.monitorCount); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvResetGraphicsPdu: width: %"PRIu32" height: %"PRIu32" count: %"PRIu32"", + pdu.width, pdu.height, pdu.monitorCount); for (index = 0; index < pdu.monitorCount; index++) { monitor = &(pdu.monitorDefArray[index]); WLog_Print(gfx->log, WLOG_DEBUG, - "RecvResetGraphicsPdu: monitor left:%"PRIi32" top:%"PRIi32" right:%"PRIi32" left:%"PRIi32" flags:0x%"PRIx32"", - monitor->left, monitor->top, monitor->right, monitor->bottom, monitor->flags); + "RecvResetGraphicsPdu: monitor left:%"PRIi32" top:%"PRIi32" right:%"PRIi32" left:%"PRIi32" flags:0x%"PRIx32"", + monitor->left, monitor->top, monitor->right, monitor->bottom, monitor->flags); } if (context) @@ -341,7 +370,6 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, graphicsReset.width = pdu.width; graphicsReset.height = pdu.height; PubSub_OnGraphicsReset(gfx->rdpcontext->pubSub, gfx->rdpcontext, &graphicsReset); - free(pdu.monitorDefArray); return error; } @@ -408,6 +436,7 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback } pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16)); + if (!pdu.cacheSlots) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -420,7 +449,7 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback } WLog_Print(gfx->log, WLOG_DEBUG, "RecvCacheImportReplyPdu: importedEntriesCount: %"PRIu16"", - pdu.importedEntriesCount); + pdu.importedEntriesCount); if (context) { @@ -458,8 +487,8 @@ static UINT rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ WLog_Print(gfx->log, WLOG_DEBUG, - "RecvCreateSurfacePdu: surfaceId: %"PRIu16" width: %"PRIu16" height: %"PRIu16" pixelFormat: 0x%02"PRIX8"", - pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); + "RecvCreateSurfacePdu: surfaceId: %"PRIu16" width: %"PRIu16" height: %"PRIu16" pixelFormat: 0x%02"PRIX8"", + pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); if (context) { @@ -527,9 +556,9 @@ static UINT rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %"PRIu32" timestamp: 0x%08"PRIX32"", - pdu.frameId, pdu.timestamp); - + pdu.frameId, pdu.timestamp); gfx->StartDecodingTime = GetTickCountPrecise(); + if (context) { IFCALLRET(context->StartFrame, error, context, &pdu); @@ -587,39 +616,45 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, if (gfx->TotalDecodedFrames == 1) if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", + error); } else { ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack))) - WLog_Print(gfx->log, WLOG_DEBUG, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", error); + WLog_Print(gfx->log, WLOG_DEBUG, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", + error); } - switch(gfx->ConnectionCaps.version) + switch (gfx->ConnectionCaps.version) { - case RDPGFX_CAPVERSION_10: - case RDPGFX_CAPVERSION_102: - case RDPGFX_CAPVERSION_103: - if (gfx->SendQoeAck) - { - RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU qoe; - UINT32 diff = (GetTickCountPrecise() - gfx->StartDecodingTime); + case RDPGFX_CAPVERSION_10: + case RDPGFX_CAPVERSION_102: + case RDPGFX_CAPVERSION_103: + if (gfx->SendQoeAck) + { + RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU qoe; + UINT32 diff = (GetTickCountPrecise() - gfx->StartDecodingTime); - if (diff > 65000) - diff = 0; + if (diff > 65000) + diff = 0; - qoe.frameId = pdu.frameId; - qoe.timestamp = gfx->StartDecodingTime; - qoe.timeDiffSE = diff; - qoe.timeDiffEDR = 1; - if ((error = rdpgfx_send_qoe_frame_acknowledge_pdu(callback, &qoe))) - WLog_Print(gfx->log, WLOG_DEBUG, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", error); - } - break; - default: - break; + qoe.frameId = pdu.frameId; + qoe.timestamp = gfx->StartDecodingTime; + qoe.timeDiffSE = diff; + qoe.timeDiffEDR = 1; + + if ((error = rdpgfx_send_qoe_frame_acknowledge_pdu(callback, &qoe))) + WLog_Print(gfx->log, WLOG_DEBUG, "rdpgfx_send_frame_acknowledge_pdu failed with error %"PRIu32"", + error); + } + + break; + + default: + break; } return error; @@ -665,13 +700,13 @@ static UINT rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); WLog_Print(gfx->log, WLOG_DEBUG, - "RecvWireToSurface1Pdu: surfaceId: %"PRIu16" codecId: %s (0x%04"PRIX16") pixelFormat: 0x%02"PRIX8" " - "destRect: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16" bitmapDataLength: %"PRIu32"", - pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), - pdu.codecId, pdu.pixelFormat, - pdu.destRect.left, pdu.destRect.top, - pdu.destRect.right, pdu.destRect.bottom, - pdu.bitmapDataLength); + "RecvWireToSurface1Pdu: surfaceId: %"PRIu16" codecId: %s (0x%04"PRIX16") pixelFormat: 0x%02"PRIX8" " + "destRect: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16" bitmapDataLength: %"PRIu32"", + pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), + pdu.codecId, pdu.pixelFormat, + pdu.destRect.left, pdu.destRect.top, + pdu.destRect.right, pdu.destRect.bottom, + pdu.bitmapDataLength); cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; cmd.contextId = 0; @@ -733,10 +768,11 @@ static UINT rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ pdu.bitmapData = Stream_Pointer(s); Stream_Seek(s, pdu.bitmapDataLength); - WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface2Pdu: surfaceId: %"PRIu16" codecId: %s (0x%04"PRIX16") " - "codecContextId: %"PRIu32" pixelFormat: 0x%02"PRIX8" bitmapDataLength: %"PRIu32"", - pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, - pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvWireToSurface2Pdu: surfaceId: %"PRIu16" codecId: %s (0x%04"PRIX16") " + "codecContextId: %"PRIu32" pixelFormat: 0x%02"PRIX8" bitmapDataLength: %"PRIu32"", + pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, + pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); cmd.surfaceId = pdu.surfaceId; cmd.codecId = pdu.codecId; cmd.contextId = pdu.codecContextId; @@ -783,15 +819,17 @@ static UINT rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ - WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteEncodingContextPdu: surfaceId: %"PRIu16" codecContextId: %"PRIu32"", - pdu.surfaceId, pdu.codecContextId); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvDeleteEncodingContextPdu: surfaceId: %"PRIu16" codecContextId: %"PRIu32"", + pdu.surfaceId, pdu.codecContextId); if (context) { IFCALLRET(context->DeleteEncodingContext, error, context, &pdu); if (error) - WLog_Print(gfx->log, WLOG_ERROR, "context->DeleteEncodingContext failed with error %"PRIu32"", error); + WLog_Print(gfx->log, WLOG_ERROR, "context->DeleteEncodingContext failed with error %"PRIu32"", + error); } return error; @@ -834,6 +872,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea } pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16)); + if (!pdu.fillRects) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -853,7 +892,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea } WLog_Print(gfx->log, WLOG_DEBUG, "RecvSolidFillPdu: surfaceId: %"PRIu16" fillRectCount: %"PRIu16"", - pdu.surfaceId, pdu.fillRectCount); + pdu.surfaceId, pdu.fillRectCount); if (context) { @@ -906,6 +945,7 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* } pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + if (!pdu.destPts) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -924,11 +964,12 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* } } - WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToSurfacePdu: surfaceIdSrc: %"PRIu16" surfaceIdDest: %"PRIu16" " - "left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16" destPtsCount: %"PRIu16"", - pdu.surfaceIdSrc, pdu.surfaceIdDest, - pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, - pdu.destPtsCount); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvSurfaceToSurfacePdu: surfaceIdSrc: %"PRIu16" surfaceIdDest: %"PRIu16" " + "left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16" destPtsCount: %"PRIu16"", + pdu.surfaceIdSrc, pdu.surfaceIdDest, + pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, + pdu.destPtsCount); if (context) { @@ -972,11 +1013,11 @@ static UINT rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } WLog_Print(gfx->log, WLOG_DEBUG, - "RecvSurfaceToCachePdu: surfaceId: %"PRIu16" cacheKey: 0x%016"PRIX64" cacheSlot: %"PRIu16" " - "left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", - pdu.surfaceId, pdu.cacheKey, pdu.cacheSlot, - pdu.rectSrc.left, pdu.rectSrc.top, - pdu.rectSrc.right, pdu.rectSrc.bottom); + "RecvSurfaceToCachePdu: surfaceId: %"PRIu16" cacheKey: 0x%016"PRIX64" cacheSlot: %"PRIu16" " + "left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", + pdu.surfaceId, pdu.cacheKey, pdu.cacheSlot, + pdu.rectSrc.left, pdu.rectSrc.top, + pdu.rectSrc.right, pdu.rectSrc.bottom); if (context) { @@ -1021,6 +1062,7 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + if (!pdu.destPts) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1040,8 +1082,8 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } WLog_Print(gfx->log, WLOG_DEBUG, - "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %"PRIu16" surfaceId: %"PRIu16" destPtsCount: %"PRIu16"", - pdu.cacheSlot, pdu.surfaceId, pdu.destPtsCount); + "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %"PRIu16" surfaceId: %"PRIu16" destPtsCount: %"PRIu16"", + pdu.cacheSlot, pdu.surfaceId, pdu.destPtsCount); if (context) { @@ -1079,8 +1121,8 @@ static UINT rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, - "RecvMapSurfaceToOutputPdu: surfaceId: %"PRIu16" outputOriginX: %"PRIu32" outputOriginY: %"PRIu32"", - pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); + "RecvMapSurfaceToOutputPdu: surfaceId: %"PRIu16" outputOriginX: %"PRIu32" outputOriginY: %"PRIu32"", + pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); if (context) { @@ -1093,6 +1135,42 @@ static UINT rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* return error; } +static UINT rdpgfx_recv_map_surface_to_scaled_output_pdu(RDPGFX_CHANNEL_CALLBACK* + callback, wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + UINT error = CHANNEL_RC_OK; + + if (Stream_GetRemainingLength(s) < 12) + { + WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ + Stream_Read_UINT32(s, pdu.targetX); + Stream_Read_UINT32(s, pdu.targetY); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvMapSurfaceToOutputPdu: surfaceId: %"PRIu16" outputOriginX: %"PRIu32" outputOriginY: %"PRIu32" targetX: %"PRIu32" targetY: %"PRIu32, + pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY, pdu.targetX, pdu.targetY); + + if (context) + { + IFCALLRET(context->MapSurfaceToScaledOutput, error, context, &pdu); + + if (error) + WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToScaledOutput failed with error %"PRIu32"", + error); + } + + return error; +} + /** * Function description * @@ -1117,8 +1195,8 @@ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callb Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ WLog_Print(gfx->log, WLOG_DEBUG, - "RecvMapSurfaceToWindowPdu: surfaceId: %"PRIu16" windowId: 0x%016"PRIX64" mappedWidth: %"PRIu32" mappedHeight: %"PRIu32"", - pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + "RecvMapSurfaceToWindowPdu: surfaceId: %"PRIu16" windowId: 0x%016"PRIX64" mappedWidth: %"PRIu32" mappedHeight: %"PRIu32"", + pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); if (context && context->MapSurfaceToWindow) { @@ -1131,6 +1209,43 @@ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callb return error; } +static UINT rdpgfx_recv_map_surface_to_scaled_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, + wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + UINT error = CHANNEL_RC_OK; + + if (Stream_GetRemainingLength(s) < 18) + { + WLog_Print(gfx->log, WLOG_ERROR, "not enough data!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ + Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ + Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ + Stream_Read_UINT32(s, pdu.targetWidth); + Stream_Read_UINT32(s, pdu.targetHeight); + WLog_Print(gfx->log, WLOG_DEBUG, + "RecvMapSurfaceToWindowPdu: surfaceId: %"PRIu16" windowId: 0x%016"PRIX64" mappedWidth: %"PRIu32" mappedHeight: %"PRIu32"", + pdu.surfaceId, pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + + if (context && context->MapSurfaceToScaledWindow) + { + IFCALLRET(context->MapSurfaceToScaledWindow, error, context, &pdu); + + if (error) + WLog_Print(gfx->log, WLOG_ERROR, "context->MapSurfaceToScaledWindow failed with error %"PRIu32"", + error); + } + + return error; +} + + /** * Function description * @@ -1142,7 +1257,6 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) RDPGFX_HEADER header; UINT error; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - beg = Stream_GetPosition(s); if ((error = rdpgfx_read_header(s, &header))) @@ -1151,30 +1265,32 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) return error; } - WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"", - rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, - header.pduLength); + WLog_Print(gfx->log, WLOG_DEBUG, + "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"", + rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, + header.pduLength); switch (header.cmdId) { case RDPGFX_CMDID_WIRETOSURFACE_1: if ((error = rdpgfx_recv_wire_to_surface_1_pdu(callback, s))) WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_wire_to_surface_1_pdu failed with error %"PRIu32"!", - error); + error); break; case RDPGFX_CMDID_WIRETOSURFACE_2: if ((error = rdpgfx_recv_wire_to_surface_2_pdu(callback, s))) WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_wire_to_surface_2_pdu failed with error %"PRIu32"!", - error); + error); break; case RDPGFX_CMDID_DELETEENCODINGCONTEXT: if ((error = rdpgfx_recv_delete_encoding_context_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_delete_encoding_context_pdu failed with error %"PRIu32"!", - error); + WLog_Print(gfx->log, WLOG_ERROR, + "rdpgfx_recv_delete_encoding_context_pdu failed with error %"PRIu32"!", + error); break; @@ -1187,38 +1303,42 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) case RDPGFX_CMDID_SURFACETOSURFACE: if ((error = rdpgfx_recv_surface_to_surface_pdu(callback, s))) WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_surface_to_surface_pdu failed with error %"PRIu32"!", - error); + error); break; case RDPGFX_CMDID_SURFACETOCACHE: if ((error = rdpgfx_recv_surface_to_cache_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_surface_to_cache_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_surface_to_cache_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_CACHETOSURFACE: if ((error = rdpgfx_recv_cache_to_surface_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_cache_to_surface_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_cache_to_surface_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_EVICTCACHEENTRY: if ((error = rdpgfx_recv_evict_cache_entry_pdu(callback, s))) WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_evict_cache_entry_pdu failed with error %"PRIu32"!", - error); + error); break; case RDPGFX_CMDID_CREATESURFACE: if ((error = rdpgfx_recv_create_surface_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_create_surface_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_create_surface_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_DELETESURFACE: if ((error = rdpgfx_recv_delete_surface_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_delete_surface_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_delete_surface_pdu failed with error %"PRIu32"!", + error); break; @@ -1236,34 +1356,54 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) case RDPGFX_CMDID_RESETGRAPHICS: if ((error = rdpgfx_recv_reset_graphics_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_reset_graphics_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_reset_graphics_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_MAPSURFACETOOUTPUT: if ((error = rdpgfx_recv_map_surface_to_output_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_map_surface_to_output_pdu failed with error %"PRIu32"!", - error); + WLog_Print(gfx->log, WLOG_ERROR, + "rdpgfx_recv_map_surface_to_output_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_CACHEIMPORTREPLY: if ((error = rdpgfx_recv_cache_import_reply_pdu(callback, s))) WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_cache_import_reply_pdu failed with error %"PRIu32"!", - error); + error); break; case RDPGFX_CMDID_CAPSCONFIRM: if ((error = rdpgfx_recv_caps_confirm_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_caps_confirm_pdu failed with error %"PRIu32"!", error); + WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_caps_confirm_pdu failed with error %"PRIu32"!", + error); break; case RDPGFX_CMDID_MAPSURFACETOWINDOW: if ((error = rdpgfx_recv_map_surface_to_window_pdu(callback, s))) - WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_recv_map_surface_to_window_pdu failed with error %"PRIu32"!", - error); + WLog_Print(gfx->log, WLOG_ERROR, + "rdpgfx_recv_map_surface_to_window_pdu failed with error %"PRIu32"!", + error); + + break; + + case RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW: + if ((error = rdpgfx_recv_map_surface_to_scaled_window_pdu(callback, s))) + WLog_Print(gfx->log, WLOG_ERROR, + "rdpgfx_recv_map_surface_to_scaled_window_pdu failed with error %"PRIu32"!", + error); + + break; + + case RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT: + if ((error = rdpgfx_recv_map_surface_to_scaled_output_pdu(callback, s))) + WLog_Print(gfx->log, WLOG_ERROR, + "rdpgfx_recv_map_surface_to_scaled_output_pdu failed with error %"PRIu32"!", + error); break; @@ -1275,7 +1415,7 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) if (error) { WLog_Print(gfx->log, WLOG_ERROR, "Error while parsing GFX cmdId: %s (0x%04"PRIX16")", - rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId); + rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId); return error; } @@ -1284,7 +1424,7 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) if (end != (beg + header.pduLength)) { WLog_Print(gfx->log, WLOG_ERROR, "Unexpected gfx pdu end: Actual: %d, Expected: %"PRIu32"", - end, (beg + header.pduLength)); + end, (beg + header.pduLength)); Stream_SetPosition(s, (beg + header.pduLength)); } @@ -1307,7 +1447,7 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; UINT error = CHANNEL_RC_OK; status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data), - &pDstData, &DstSize, 0); + &pDstData, &DstSize, 0); if (status < 0) { @@ -1316,6 +1456,7 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* } s = Stream_New(pDstData, DstSize); + if (!s) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1360,7 +1501,6 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - WLog_Print(gfx->log, WLOG_DEBUG, "OnClose"); free(callback); gfx->UnacknowledgedFrames = 0; @@ -1421,8 +1561,8 @@ static UINT rdpgfx_on_new_channel_connection(IWTSListenerCallback* { RDPGFX_CHANNEL_CALLBACK* callback; RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)pListenerCallback; - callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); + if (!callback) { WLog_ERR(TAG, "calloc failed!"); @@ -1450,8 +1590,8 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, { UINT error; RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; - gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); + if (!gfx->listener_callback) { WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); @@ -1634,7 +1774,7 @@ static UINT rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, if (cacheSlot >= gfx->MaxCacheSlot) { WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__, - cacheSlot, gfx->MaxCacheSlot); + cacheSlot, gfx->MaxCacheSlot); return ERROR_INVALID_INDEX; } @@ -1650,7 +1790,7 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac if (cacheSlot >= gfx->MaxCacheSlot) { WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__, - cacheSlot, gfx->MaxCacheSlot); + cacheSlot, gfx->MaxCacheSlot); return NULL; } @@ -1687,6 +1827,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } gfx->log = WLog_Get(TAG); + if (!gfx->log) { free(gfx); @@ -1699,9 +1840,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->iface.Connected = NULL; gfx->iface.Disconnected = NULL; gfx->iface.Terminated = rdpgfx_plugin_terminated; - gfx->rdpcontext = ((freerdp *)gfx->settings->instance)->context; - + gfx->rdpcontext = ((freerdp*)gfx->settings->instance)->context; gfx->SurfaceTable = HashTable_New(TRUE); + if (!gfx->SurfaceTable) { free(gfx); @@ -1721,8 +1862,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->SmallCache = TRUE; gfx->MaxCacheSlot = gfx->SmallCache ? 4096 : 25600; + context = (RdpgfxClientContext*)calloc(1, sizeof(RdpgfxClientContext)); - context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext)); if (!context) { free(gfx); diff --git a/channels/rdpgfx/rdpgfx_common.c b/channels/rdpgfx/rdpgfx_common.c index 2a6243bc8..cb8379c2a 100644 --- a/channels/rdpgfx/rdpgfx_common.c +++ b/channels/rdpgfx/rdpgfx_common.c @@ -55,12 +55,14 @@ static const char* RDPGFX_CMDID_STRINGS[] = "RDPGFX_CMDID_CAPSCONFIRM", "RDPGFX_CMDID_UNUSED_0014", "RDPGFX_CMDID_MAPSURFACETOWINDOW", - "RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE" + "RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE", + "RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT", + "RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW" }; const char* rdpgfx_get_cmd_id_string(UINT16 cmdId) { - if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW) + if (cmdId <= RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW) return RDPGFX_CMDID_STRINGS[cmdId]; else return "RDPGFX_CMDID_UNKNOWN"; diff --git a/channels/rdpgfx/server/rdpgfx_main.c b/channels/rdpgfx/server/rdpgfx_main.c index e3e645c64..6397fd4de 100644 --- a/channels/rdpgfx/server/rdpgfx_main.c +++ b/channels/rdpgfx/server/rdpgfx_main.c @@ -1053,6 +1053,27 @@ static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context, return rdpgfx_server_single_packet_send(context, s); } +static UINT rdpgfx_send_map_surface_to_scaled_window_pdu(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* pdu) +{ + wStream* s = rdpgfx_server_single_packet_new( + RDPGFX_CMDID_MAPSURFACETOWINDOW, 18); + + if (!s) + { + WLog_ERR(TAG, "rdpgfx_server_single_packet_new failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write_UINT16(s, pdu->surfaceId); /* surfaceId (2 bytes) */ + Stream_Write_UINT64(s, pdu->windowId); /* windowId (8 bytes) */ + Stream_Write_UINT32(s, pdu->mappedWidth); /* mappedWidth (4 bytes) */ + Stream_Write_UINT32(s, pdu->mappedHeight); /* mappedHeight (4 bytes) */ + Stream_Write_UINT32(s, pdu->targetWidth); + Stream_Write_UINT32(s, pdu->targetHeight); + return rdpgfx_server_single_packet_send(context, s); +} + /** * Function description * @@ -1251,6 +1272,27 @@ static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context, return error; } +static UINT rdpgfx_send_map_surface_to_scaled_output_pdu(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* pdu) +{ + wStream* s = rdpgfx_server_single_packet_new( + RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT, 12); + + if (!s) + { + WLog_ERR(TAG, "rdpgfx_server_single_packet_new failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write_UINT16(s, pdu->surfaceId); /* surfaceId (2 bytes) */ + Stream_Write_UINT16(s, 0); /* reserved (2 bytes). Must be 0 */ + Stream_Write_UINT32(s, pdu->outputOriginX); /* outputOriginX (4 bytes) */ + Stream_Write_UINT32(s, pdu->outputOriginY); /* outputOriginY (4 bytes) */ + Stream_Write_UINT32(s, pdu->targetX); + Stream_Write_UINT32(s, pdu->targetY); + return rdpgfx_server_single_packet_send(context, s); +} + /** * Function description * @@ -1533,6 +1575,8 @@ RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm) context->EvictCacheEntry = rdpgfx_send_evict_cache_entry_pdu; context->MapSurfaceToOutput = rdpgfx_send_map_surface_to_output_pdu; context->MapSurfaceToWindow = rdpgfx_send_map_surface_to_window_pdu; + context->MapSurfaceToScaledOutput = rdpgfx_send_map_surface_to_scaled_output_pdu; + context->MapSurfaceToScaledWindow = rdpgfx_send_map_surface_to_scaled_window_pdu; context->CapsAdvertise = NULL; context->CapsConfirm = rdpgfx_send_caps_confirm_pdu; context->FrameAcknowledge = NULL; diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 03a44ab87..c0b450672 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -74,6 +74,8 @@ typedef BYTE RDPGFX_PIXELFORMAT; #define RDPGFX_CMDID_UNUSED_0014 0x0014 #define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015 #define RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE 0x0016 +#define RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT 0x0017 +#define RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW 0x0018 #define RDPGFX_HEADER_SIZE 8 @@ -92,15 +94,20 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER; #define RDPGFX_CAPVERSION_8 0x00080004 /** [MS-RDPEGFX] 2.2.3.1 */ #define RDPGFX_CAPVERSION_81 0x00080105 /** [MS-RDPEGFX] 2.2.3.2 */ #define RDPGFX_CAPVERSION_10 0x000A0002 /** [MS-RDPEGFX] 2.2.3.3 */ -#define RDPGFX_CAPVERSION_102 0x000A0200 /** [MS-RDPEGFX] 2.2.3.4 */ -#define RDPGFX_CAPVERSION_103 0x000A0301 /** [MS-RDPEGFX] 2.2.3.5 */ +#define RDPGFX_CAPVERSION_101 0x000A0100 /** [MS-RDPEGFX] 2.2.3.4 */ +#define RDPGFX_CAPVERSION_102 0x000A0200 /** [MS-RDPEGFX] 2.2.3.5 */ +#define RDPGFX_CAPVERSION_103 0x000A0301 /** [MS-RDPEGFX] 2.2.3.6 */ +#define RDPGFX_CAPVERSION_104 0x000A0400 /** [MS-RDPEGFX] 2.2.3.7 */ +#define RDPGFX_CAPVERSION_105 0x000A0502 /** [MS-RDPEGFX] 2.2.3.8 */ +#define RDPGFX_CAPVERSION_106 0x000A0601 /** [MS-RDPEGFX] 2.2.3.9 */ -#define RDPGFX_NUMBER_CAPSETS 5 +#define RDPGFX_NUMBER_CAPSETS 9 #define RDPGFX_CAPSET_SIZE 12 struct _RDPGFX_CAPSET { UINT32 version; + UINT32 length; UINT32 flags; }; typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; @@ -109,6 +116,7 @@ typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; #define RDPGFX_CAPS_FLAG_SMALL_CACHE 0x00000002U /* 8.0+ */ #define RDPGFX_CAPS_FLAG_AVC420_ENABLED 0x00000010U /* 8.1+ */ #define RDPGFX_CAPS_FLAG_AVC_DISABLED 0x00000020U /* 10.0+ */ +#define RDPGFX_CAPS_FLAG_AVC_THINCLIENT 0x00000040U /* 10.3+ */ struct _RDPGFX_CAPSET_VERSION8 { @@ -200,7 +208,7 @@ struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU UINT32 codecContextId; }; typedef struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU - RDPGFX_DELETE_ENCODING_CONTEXT_PDU; + RDPGFX_DELETE_ENCODING_CONTEXT_PDU; struct _RDPGFX_SOLID_FILL_PDU { @@ -305,7 +313,19 @@ struct _RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU UINT32 outputOriginY; }; typedef struct _RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU - RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU; + RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU; + +struct _RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU +{ + UINT16 surfaceId; + UINT16 reserved; + UINT32 outputOriginX; + UINT32 outputOriginY; + UINT32 targetX; + UINT32 targetY; +}; +typedef struct _RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU + RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU; struct _RDPGFX_CACHE_ENTRY_METADATA { @@ -349,7 +369,19 @@ struct _RDPGFX_MAP_SURFACE_TO_WINDOW_PDU UINT32 mappedHeight; }; typedef struct _RDPGFX_MAP_SURFACE_TO_WINDOW_PDU - RDPGFX_MAP_SURFACE_TO_WINDOW_PDU; + RDPGFX_MAP_SURFACE_TO_WINDOW_PDU; + +struct _RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU +{ + UINT16 surfaceId; + UINT64 windowId; + UINT32 mappedWidth; + UINT32 mappedHeight; + UINT32 targetWidth; + UINT32 targetHeight; +}; +typedef struct _RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU + RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU; /* H264 */ @@ -396,7 +428,7 @@ struct _RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU UINT16 timeDiffEDR; }; typedef struct _RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU - RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU; + RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU; #endif /* FREERDP_CHANNEL_RDPGFX_H */ diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index f3f93ed9a..84f521936 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -61,9 +61,12 @@ typedef UINT(*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, const RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry); typedef UINT(*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); +typedef UINT(*pcRdpgfxMapSurfaceToScaledOutput)(RdpgfxClientContext* context, + const RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToOutput); typedef UINT(*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, const RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); - +typedef UINT(*pcRdpgfxMapSurfaceToScaledWindow)(RdpgfxClientContext* context, + const RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* surfaceToWindow); typedef UINT(*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData); typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, @@ -101,7 +104,9 @@ struct _rdpgfx_client_context pcRdpgfxCacheImportReply CacheImportReply; pcRdpgfxEvictCacheEntry EvictCacheEntry; pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput; + pcRdpgfxMapSurfaceToScaledOutput MapSurfaceToScaledOutput; pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow; + pcRdpgfxMapSurfaceToScaledWindow MapSurfaceToScaledWindow; pcRdpgfxGetSurfaceIds GetSurfaceIds; pcRdpgfxSetSurfaceData SetSurfaceData; diff --git a/include/freerdp/server/rdpgfx.h b/include/freerdp/server/rdpgfx.h index dada58f93..e5c39170b 100644 --- a/include/freerdp/server/rdpgfx.h +++ b/include/freerdp/server/rdpgfx.h @@ -28,27 +28,48 @@ typedef struct _rdpgfx_server_private RdpgfxServerPrivate; typedef BOOL (*psRdpgfxServerOpen)(RdpgfxServerContext* context); typedef BOOL (*psRdpgfxServerClose)(RdpgfxServerContext* context); -typedef UINT(*psRdpgfxResetGraphics)(RdpgfxServerContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics); +typedef UINT(*psRdpgfxResetGraphics)(RdpgfxServerContext* context, + RDPGFX_RESET_GRAPHICS_PDU* resetGraphics); typedef UINT(*psRdpgfxStartFrame)(RdpgfxServerContext* context, RDPGFX_START_FRAME_PDU* startFrame); typedef UINT(*psRdpgfxEndFrame)(RdpgfxServerContext* context, RDPGFX_END_FRAME_PDU* endFrame); typedef UINT(*psRdpgfxSurfaceCommand)(RdpgfxServerContext* context, RDPGFX_SURFACE_COMMAND* cmd); -typedef UINT(*psRdpgfxSurfaceFrameCommand)(RdpgfxServerContext* context, RDPGFX_SURFACE_COMMAND* cmd, RDPGFX_START_FRAME_PDU* startFrame, RDPGFX_END_FRAME_PDU* endFrame); -typedef UINT(*psRdpgfxDeleteEncodingContext)(RdpgfxServerContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext); -typedef UINT(*psRdpgfxCreateSurface)(RdpgfxServerContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface); -typedef UINT(*psRdpgfxDeleteSurface)(RdpgfxServerContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface); +typedef UINT(*psRdpgfxSurfaceFrameCommand)(RdpgfxServerContext* context, + RDPGFX_SURFACE_COMMAND* cmd, RDPGFX_START_FRAME_PDU* startFrame, RDPGFX_END_FRAME_PDU* endFrame); +typedef UINT(*psRdpgfxDeleteEncodingContext)(RdpgfxServerContext* context, + RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext); +typedef UINT(*psRdpgfxCreateSurface)(RdpgfxServerContext* context, + RDPGFX_CREATE_SURFACE_PDU* createSurface); +typedef UINT(*psRdpgfxDeleteSurface)(RdpgfxServerContext* context, + RDPGFX_DELETE_SURFACE_PDU* deleteSurface); typedef UINT(*psRdpgfxSolidFill)(RdpgfxServerContext* context, RDPGFX_SOLID_FILL_PDU* solidFill); -typedef UINT(*psRdpgfxSurfaceToSurface)(RdpgfxServerContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface); -typedef UINT(*psRdpgfxSurfaceToCache)(RdpgfxServerContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache); -typedef UINT(*psRdpgfxCacheToSurface)(RdpgfxServerContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface); -typedef UINT(*psRdpgfxCacheImportOffer)(RdpgfxServerContext* context, RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer); -typedef UINT(*psRdpgfxCacheImportReply)(RdpgfxServerContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply); -typedef UINT(*psRdpgfxEvictCacheEntry)(RdpgfxServerContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry); -typedef UINT(*psRdpgfxMapSurfaceToOutput)(RdpgfxServerContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); -typedef UINT(*psRdpgfxMapSurfaceToWindow)(RdpgfxServerContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); -typedef UINT(*psRdpgfxCapsAdvertise)(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise); -typedef UINT(*psRdpgfxCapsConfirm)(RdpgfxServerContext* context, RDPGFX_CAPS_CONFIRM_PDU* capsConfirm); -typedef UINT(*psRdpgfxFrameAcknowledge)(RdpgfxServerContext* context, RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge); -typedef UINT(*psRdpgfxQoeFrameAcknowledge)(RdpgfxServerContext* context, RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* qoeFrameAcknowledge); +typedef UINT(*psRdpgfxSurfaceToSurface)(RdpgfxServerContext* context, + RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface); +typedef UINT(*psRdpgfxSurfaceToCache)(RdpgfxServerContext* context, + RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache); +typedef UINT(*psRdpgfxCacheToSurface)(RdpgfxServerContext* context, + RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface); +typedef UINT(*psRdpgfxCacheImportOffer)(RdpgfxServerContext* context, + RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer); +typedef UINT(*psRdpgfxCacheImportReply)(RdpgfxServerContext* context, + RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply); +typedef UINT(*psRdpgfxEvictCacheEntry)(RdpgfxServerContext* context, + RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry); +typedef UINT(*psRdpgfxMapSurfaceToOutput)(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); +typedef UINT(*psRdpgfxMapSurfaceToWindow)(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); +typedef UINT(*psRdpgfxMapSurfaceToScaledOutput)(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToOutput); +typedef UINT(*psRdpgfxMapSurfaceToScaledWindow)(RdpgfxServerContext* context, + RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* surfaceToWindow); +typedef UINT(*psRdpgfxCapsAdvertise)(RdpgfxServerContext* context, + RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise); +typedef UINT(*psRdpgfxCapsConfirm)(RdpgfxServerContext* context, + RDPGFX_CAPS_CONFIRM_PDU* capsConfirm); +typedef UINT(*psRdpgfxFrameAcknowledge)(RdpgfxServerContext* context, + RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge); +typedef UINT(*psRdpgfxQoeFrameAcknowledge)(RdpgfxServerContext* context, + RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* qoeFrameAcknowledge); struct _rdpgfx_server_context { @@ -75,6 +96,8 @@ struct _rdpgfx_server_context psRdpgfxEvictCacheEntry EvictCacheEntry; psRdpgfxMapSurfaceToOutput MapSurfaceToOutput; psRdpgfxMapSurfaceToWindow MapSurfaceToWindow; + psRdpgfxMapSurfaceToScaledOutput MapSurfaceToScaledOutput; + psRdpgfxMapSurfaceToScaledWindow MapSurfaceToScaledWindow; psRdpgfxCapsAdvertise CapsAdvertise; psRdpgfxCapsConfirm CapsConfirm; psRdpgfxFrameAcknowledge FrameAcknowledge; diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 4be8d5fee..cf7d4fa65 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -1231,6 +1231,29 @@ fail: return rc; } +static UINT gdi_MapSurfaceToScaledOutput(RdpgfxClientContext* context, + const RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToOutput) +{ + UINT rc = ERROR_INTERNAL_ERROR; + gdiGfxSurface* surface; + EnterCriticalSection(&context->mux); + surface = (gdiGfxSurface*) context->GetSurfaceData(context, + surfaceToOutput->surfaceId); + + if (!surface) + goto fail; + + surface->outputMapped = TRUE; + surface->outputOriginX = surfaceToOutput->outputOriginX; + surface->outputOriginY = surfaceToOutput->outputOriginY; + // TODO: Target x,y + region16_clear(&surface->invalidRegion); + rc = CHANNEL_RC_OK; +fail: + LeaveCriticalSection(&context->mux); + return rc; +} + /** * Function description * @@ -1242,6 +1265,12 @@ static UINT gdi_MapSurfaceToWindow(RdpgfxClientContext* context, return CHANNEL_RC_OK; } +static UINT gdi_MapSurfaceToScaledWindow(RdpgfxClientContext* context, + const RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU* surfaceToWindow) +{ + return CHANNEL_RC_OK; +} + BOOL gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx) { if (!gdi || !gfx) @@ -1264,6 +1293,8 @@ BOOL gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx) gfx->EvictCacheEntry = gdi_EvictCacheEntry; gfx->MapSurfaceToOutput = gdi_MapSurfaceToOutput; gfx->MapSurfaceToWindow = gdi_MapSurfaceToWindow; + gfx->MapSurfaceToScaledOutput = gdi_MapSurfaceToScaledOutput; + gfx->MapSurfaceToScaledWindow = gdi_MapSurfaceToScaledWindow; gfx->UpdateSurfaces = gdi_UpdateSurfaces; InitializeCriticalSection(&gfx->mux); PROFILER_CREATE(gfx->SurfaceProfiler, "GFX-PROFILER"); diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index a5ad68bff..149be18a8 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -630,7 +630,7 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, { const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; - if (currentCaps->version == RDPGFX_CAPVERSION_103) + if (currentCaps->version == RDPGFX_CAPVERSION_106) { RDPGFX_CAPSET caps = *currentCaps; RDPGFX_CAPS_CONFIRM_PDU pdu; @@ -640,6 +640,75 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, { flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_AVC_THINCLIENT); +#ifndef WITH_GFX_H264 + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; + pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = !(flags & + RDPGFX_CAPS_FLAG_AVC_DISABLED); +#endif + } + + return context->CapsConfirm(context, &pdu); + } + + if (currentCaps->version == RDPGFX_CAPVERSION_105) + { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + + if (settings) + { + flags = pdu.capsSet->flags; + settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_AVC_THINCLIENT); +#ifndef WITH_GFX_H264 + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; + pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = !(flags & + RDPGFX_CAPS_FLAG_AVC_DISABLED); +#endif + } + + return context->CapsConfirm(context, &pdu); + } + + if (currentCaps->version == RDPGFX_CAPVERSION_104) + { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + + if (settings) + { + flags = pdu.capsSet->flags; + settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_AVC_THINCLIENT); +#ifndef WITH_GFX_H264 + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; + pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else + settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = !(flags & + RDPGFX_CAPS_FLAG_AVC_DISABLED); +#endif + } + + return context->CapsConfirm(context, &pdu); + } + + if (currentCaps->version == RDPGFX_CAPVERSION_103) + { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + + if (settings) + { + flags = pdu.capsSet->flags; + settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_AVC_THINCLIENT); #ifndef WITH_GFX_H264 settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE; pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;