Added gfx capability filter option.
With this new option it is possible to selectively disable certain GFX capability versions. This way buggy behaviour can be addressed at runtime.
This commit is contained in:
parent
3d1cec894c
commit
7b2608a938
@ -106,6 +106,32 @@ fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
static BOOL rdpgfx_is_capability_filtered(RDPGFX_PLUGIN* gfx, UINT32 caps)
|
||||
{
|
||||
const UINT32 filter = gfx->capsFilter;
|
||||
const UINT32 capList[] =
|
||||
{
|
||||
RDPGFX_CAPVERSION_8,
|
||||
RDPGFX_CAPVERSION_81,
|
||||
RDPGFX_CAPVERSION_10,
|
||||
RDPGFX_CAPVERSION_101,
|
||||
RDPGFX_CAPVERSION_102,
|
||||
RDPGFX_CAPVERSION_103,
|
||||
RDPGFX_CAPVERSION_104,
|
||||
RDPGFX_CAPVERSION_105,
|
||||
RDPGFX_CAPVERSION_106
|
||||
};
|
||||
UINT32 x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(capList); x++)
|
||||
{
|
||||
if (caps == capList[x])
|
||||
return (filter & (1 << x)) != 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@ -113,54 +139,69 @@ fail:
|
||||
*/
|
||||
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;
|
||||
|
||||
if (!callback)
|
||||
return ERROR_BAD_ARGUMENTS;
|
||||
|
||||
gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
|
||||
if (!gfx)
|
||||
return ERROR_BAD_CONFIGURATION;
|
||||
|
||||
context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||
|
||||
if (!context)
|
||||
return ERROR_BAD_CONFIGURATION;
|
||||
|
||||
pdu.capsSetCount = 0;
|
||||
pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_8;
|
||||
capsSet->length = 4;
|
||||
capsSet->flags = 0;
|
||||
|
||||
if (gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_8))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_8;
|
||||
capsSet->length = 4;
|
||||
capsSet->flags = 0;
|
||||
|
||||
/* in CAPVERSION_8 the spec says that we should not have both
|
||||
* thinclient and smallcache (and thinclient implies a small cache)
|
||||
*/
|
||||
if (gfx->SmallCache && !gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
if (gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
|
||||
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_81;
|
||||
capsSet->length = 4;
|
||||
capsSet->flags = 0;
|
||||
/* in CAPVERSION_8 the spec says that we should not have both
|
||||
* thinclient and smallcache (and thinclient implies a small cache)
|
||||
*/
|
||||
if (gfx->SmallCache && !gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
}
|
||||
|
||||
if (gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_81))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_81;
|
||||
capsSet->length = 4;
|
||||
capsSet->flags = 0;
|
||||
|
||||
if (gfx->SmallCache)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
if (gfx->ThinClient)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
|
||||
|
||||
if (gfx->SmallCache)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
|
||||
#ifdef WITH_GFX_H264
|
||||
|
||||
if (gfx->H264)
|
||||
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;
|
||||
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->length = 4;
|
||||
|
||||
if (gfx->SmallCache)
|
||||
caps10Flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
@ -173,43 +214,68 @@ static UINT rdpgfx_send_supported_caps(RDPGFX_CHANNEL_CALLBACK* callback)
|
||||
#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 (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_10))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_10;
|
||||
capsSet->length = 4;
|
||||
capsSet->flags = caps10Flags;
|
||||
}
|
||||
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_101))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_101;
|
||||
capsSet->length = 0x10;
|
||||
capsSet->flags = 0;
|
||||
}
|
||||
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_102))
|
||||
{
|
||||
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;
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_103))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_103;
|
||||
capsSet->length = 0x4;
|
||||
capsSet->flags = caps10Flags & ~RDPGFX_CAPS_FLAG_SMALL_CACHE;
|
||||
}
|
||||
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_104))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_104;
|
||||
capsSet->length = 0x4;
|
||||
capsSet->flags = caps10Flags;
|
||||
}
|
||||
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_105))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_105;
|
||||
capsSet->length = 0x4;
|
||||
capsSet->flags = caps10Flags;
|
||||
}
|
||||
|
||||
if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_106))
|
||||
{
|
||||
capsSet = &capsSets[pdu.capsSetCount++];
|
||||
capsSet->version = RDPGFX_CAPVERSION_106;
|
||||
capsSet->length = 0x4;
|
||||
capsSet->flags = caps10Flags;
|
||||
}
|
||||
}
|
||||
|
||||
if (context)
|
||||
{
|
||||
IFCALLRET(context->CapsAdvertise, error, context, &pdu);
|
||||
}
|
||||
|
||||
return error;
|
||||
return IFCALLRESULT(ERROR_BAD_CONFIGURATION, context->CapsAdvertise, context, &pdu);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1949,6 +2015,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
gfx->H264 = gfx->settings->GfxH264;
|
||||
gfx->AVC444 = gfx->settings->GfxAVC444;
|
||||
gfx->SendQoeAck = gfx->settings->GfxSendQoeAck;
|
||||
gfx->capsFilter = gfx->settings->GfxCapsFilter;
|
||||
|
||||
if (gfx->H264)
|
||||
gfx->SmallCache = TRUE;
|
||||
|
@ -67,6 +67,7 @@ struct _RDPGFX_PLUGIN
|
||||
BOOL ProgressiveV2;
|
||||
BOOL H264;
|
||||
BOOL AVC444;
|
||||
UINT32 capsFilter;
|
||||
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 UnacknowledgedFrames;
|
||||
|
@ -835,6 +835,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
||||
#define FreeRDP_GfxAVC444 (3845)
|
||||
#define FreeRDP_GfxSendQoeAck (3846)
|
||||
#define FreeRDP_GfxAVC444v2 (3847)
|
||||
#define FreeRDP_GfxCapsFilter (3848)
|
||||
#define FreeRDP_BitmapCacheV3CodecId (3904)
|
||||
#define FreeRDP_DrawNineGridEnabled (3968)
|
||||
#define FreeRDP_DrawNineGridCacheSize (3969)
|
||||
@ -1419,7 +1420,8 @@ struct rdp_settings
|
||||
ALIGN64 BOOL GfxAVC444; /* 3845 */
|
||||
ALIGN64 BOOL GfxSendQoeAck; /* 3846 */
|
||||
ALIGN64 BOOL GfxAVC444v2; /* 3847 */
|
||||
UINT64 padding3904[3904 - 3848]; /* 3848 */
|
||||
ALIGN64 UINT32 GfxCapsFilter; /* 3848 */
|
||||
UINT64 padding3904[3904 - 3849]; /* 3849 */
|
||||
|
||||
/**
|
||||
* Caches
|
||||
|
@ -613,6 +613,32 @@ static UINT shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static BOOL shadow_are_caps_filtered(const rdpSettings* settings, UINT32 caps)
|
||||
{
|
||||
const UINT32 filter = settings->GfxCapsFilter;
|
||||
const UINT32 capList[] =
|
||||
{
|
||||
RDPGFX_CAPVERSION_8,
|
||||
RDPGFX_CAPVERSION_81,
|
||||
RDPGFX_CAPVERSION_10,
|
||||
RDPGFX_CAPVERSION_101,
|
||||
RDPGFX_CAPVERSION_102,
|
||||
RDPGFX_CAPVERSION_103,
|
||||
RDPGFX_CAPVERSION_104,
|
||||
RDPGFX_CAPVERSION_105,
|
||||
RDPGFX_CAPVERSION_106
|
||||
};
|
||||
UINT32 x;
|
||||
|
||||
for (x = 0; x < ARRAYSIZE(capList); x++)
|
||||
{
|
||||
if (caps == capList[x])
|
||||
return (filter & (1 << x)) != 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context,
|
||||
const RDPGFX_CAPSET* capsSets,
|
||||
UINT32 capsSetCount,
|
||||
@ -623,6 +649,9 @@ static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context,
|
||||
rdpSettings* settings;
|
||||
settings = context->rdpcontext->settings;
|
||||
|
||||
if (shadow_are_caps_filtered(settings, capsVersion))
|
||||
return FALSE;
|
||||
|
||||
for (index = 0; index < capsSetCount; index++)
|
||||
{
|
||||
const RDPGFX_CAPSET* currentCaps = &capsSets[index];
|
||||
@ -697,52 +726,58 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
|
||||
RDPGFX_CAPVERSION_10, &rc))
|
||||
return rc;
|
||||
|
||||
for (index = 0; index < capsAdvertise->capsSetCount; index++)
|
||||
if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_81))
|
||||
{
|
||||
const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
|
||||
|
||||
if (currentCaps->version == RDPGFX_CAPVERSION_81)
|
||||
for (index = 0; index < capsAdvertise->capsSetCount; index++)
|
||||
{
|
||||
RDPGFX_CAPSET caps = *currentCaps;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
pdu.capsSet = ∩︀
|
||||
const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
|
||||
|
||||
if (settings)
|
||||
if (currentCaps->version == RDPGFX_CAPVERSION_81)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxAVC444v2 = settings->GfxAVC444 = FALSE;
|
||||
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
#ifndef WITH_GFX_H264
|
||||
settings->GfxH264 = FALSE;
|
||||
pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
|
||||
#else
|
||||
settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED);
|
||||
#endif
|
||||
}
|
||||
RDPGFX_CAPSET caps = *currentCaps;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
pdu.capsSet = ∩︀
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
if (settings)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxAVC444v2 = settings->GfxAVC444 = FALSE;
|
||||
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
#ifndef WITH_GFX_H264
|
||||
settings->GfxH264 = FALSE;
|
||||
pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
|
||||
#else
|
||||
settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED);
|
||||
#endif
|
||||
}
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; index < capsAdvertise->capsSetCount; index++)
|
||||
if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_8))
|
||||
{
|
||||
const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
|
||||
|
||||
if (currentCaps->version == RDPGFX_CAPVERSION_8)
|
||||
for (index = 0; index < capsAdvertise->capsSetCount; index++)
|
||||
{
|
||||
RDPGFX_CAPSET caps = *currentCaps;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
pdu.capsSet = ∩︀
|
||||
const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
|
||||
|
||||
if (settings)
|
||||
if (currentCaps->version == RDPGFX_CAPVERSION_8)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
}
|
||||
RDPGFX_CAPSET caps = *currentCaps;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
pdu.capsSet = ∩︀
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
if (settings)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
}
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user