[server,shadow] readd multi rect BitmapUpdate support

* Partially revert 1f83198bb1
* Introduce new /bitmap-compat command line option for shadow-server
* Default to send multi rectangle BitmapUpdate
This commit is contained in:
akallabeth
2025-02-28 11:04:03 +01:00
parent 2d4fcf145b
commit 5faf0149c2
4 changed files with 48 additions and 15 deletions

View File

@@ -174,6 +174,7 @@ extern "C"
freerdp_listener* listener;
size_t maxClientsConnected;
BOOL SupportMultiRectBitmapUpdates; /** @since version 3.13.0 */
};
struct rdp_shadow_surface

View File

@@ -95,6 +95,8 @@ int main(int argc, char** argv)
"Allow GFX AVC420 codec" },
{ "gfx-avc444", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX AVC444 codec" },
{ "bitmap-compat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
"Limit BitmapUpdate to 1 rectangle (fixes broken windows 11 24H2 clients)" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1,
NULL, "Print version" },
{ "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL,

View File

@@ -50,23 +50,25 @@ typedef struct
*
* So send all updates only with a single rectangle.
*/
#define BitmapUpdateProxy(update, context, bitmap) \
BitmapUpdateProxyEx((update), (context), (bitmap), __FILE__, __LINE__, __func__)
static BOOL BitmapUpdateProxyEx(rdpUpdate* update, rdpContext* context, const BITMAP_UPDATE* bitmap,
#define BitmapUpdateProxy(client, bitmap) \
BitmapUpdateProxyEx((client), (bitmap), __FILE__, __LINE__, __func__)
static BOOL BitmapUpdateProxyEx(rdpShadowClient* client, const BITMAP_UPDATE* bitmap,
const char* file, size_t line, const char* fkt)
{
WINPR_ASSERT(update);
WINPR_ASSERT(context);
WINPR_ASSERT(client);
WINPR_ASSERT(bitmap);
for (UINT32 x = 0; x < bitmap->number; x++)
rdpShadowServer* server = client->server;
WINPR_ASSERT(server);
rdpContext* context = (rdpContext*)client;
rdpUpdate* update = context->update;
WINPR_ASSERT(update);
if (server->SupportMultiRectBitmapUpdates)
{
BITMAP_UPDATE cur = { 0 };
BITMAP_DATA* bmp = &bitmap->rectangles[x];
cur.rectangles = bmp;
cur.number = 1;
cur.skipCompression = bitmap->skipCompression;
const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap);
if (!rc)
{
const DWORD log_level = WLOG_ERROR;
@@ -74,11 +76,34 @@ static BOOL BitmapUpdateProxyEx(rdpUpdate* update, rdpContext* context, const BI
if (WLog_IsLevelActive(log, log_level))
{
WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
"BitmapUpdate[%" PRIu32 "] failed", x);
"BitmapUpdate[count %" PRIu32 "] failed", bitmap->number);
}
return FALSE;
}
}
else
{
for (UINT32 x = 0; x < bitmap->number; x++)
{
BITMAP_UPDATE cur = { 0 };
BITMAP_DATA* bmp = &bitmap->rectangles[x];
cur.rectangles = bmp;
cur.number = 1;
cur.skipCompression = bitmap->skipCompression;
const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
if (!rc)
{
const DWORD log_level = WLOG_ERROR;
wLog* log = WLog_Get(TAG);
if (WLog_IsLevelActive(log, log_level))
{
WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
"BitmapUpdate[count 1, at %" PRIu32 "] failed", x);
}
return FALSE;
}
}
}
return TRUE;
}
@@ -1813,7 +1838,7 @@ static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrc
if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
{
bitmapUpdate.number = j;
ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
ret = BitmapUpdateProxy(client, &bitmapUpdate);
if (!ret)
break;
@@ -1827,7 +1852,7 @@ static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrc
}
else
{
ret = BitmapUpdateProxy(update, context, &bitmapUpdate);
ret = BitmapUpdateProxy(client, &bitmapUpdate);
}
out:

View File

@@ -236,6 +236,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
{
server->mayView = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "bitmap-compat")
{
server->SupportMultiRectBitmapUpdates = arg->Value ? FALSE : TRUE;
}
CommandLineSwitchCase(arg, "may-interact")
{
server->mayInteract = arg->Value ? TRUE : FALSE;
@@ -1001,6 +1005,7 @@ rdpShadowServer* shadow_server_new(void)
if (!server)
return NULL;
server->SupportMultiRectBitmapUpdates = TRUE;
server->port = 3389;
server->mayView = TRUE;
server->mayInteract = TRUE;