mirror of https://github.com/FreeRDP/FreeRDP
xfreerdp: fix egfx multimonitor support
This commit is contained in:
parent
9b9fbd2ab1
commit
22ac46957a
|
@ -1020,6 +1020,35 @@ int rdpgfx_set_surface_data(RdpgfxClientContext* context, UINT16 surfaceId, void
|
|||
return 1;
|
||||
}
|
||||
|
||||
int rdpgfx_get_surface_ids(RdpgfxClientContext* context, UINT16** ppSurfaceIds)
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
UINT16* pSurfaceIds;
|
||||
ULONG_PTR* pKeys = NULL;
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
|
||||
|
||||
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
|
||||
|
||||
if (count < 1)
|
||||
return 0;
|
||||
|
||||
pSurfaceIds = (UINT16*) malloc(count * sizeof(UINT16));
|
||||
|
||||
if (!pSurfaceIds)
|
||||
return -1;
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
pSurfaceIds[index] = pKeys[index] - 1;
|
||||
}
|
||||
|
||||
free(pKeys);
|
||||
*ppSurfaceIds = pSurfaceIds;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId)
|
||||
{
|
||||
ULONG_PTR key;
|
||||
|
@ -1117,6 +1146,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
|||
|
||||
context->handle = (void*) gfx;
|
||||
|
||||
context->GetSurfaceIds = rdpgfx_get_surface_ids;
|
||||
context->SetSurfaceData = rdpgfx_set_surface_data;
|
||||
context->GetSurfaceData = rdpgfx_get_surface_data;
|
||||
context->SetCacheSlotData = rdpgfx_set_cache_slot_data;
|
||||
|
|
|
@ -26,50 +26,30 @@
|
|||
|
||||
#define TAG CLIENT_TAG("x11")
|
||||
|
||||
static int xf_call_for_each_surface(xfContext* xfc, wArrayList* surfaceList, int (*processSurface)(xfContext*, xfGfxSurface*, void*), void* param)
|
||||
{
|
||||
int status = 1;
|
||||
int surfaceIndex;
|
||||
RdpgfxClientContext* context = xfc->gfx;
|
||||
|
||||
/* Iterating backwards to be able to remove surfaces from the list */
|
||||
surfaceIndex = ArrayList_Count(surfaceList) - 1;
|
||||
|
||||
for (; surfaceIndex >= 0; surfaceIndex--)
|
||||
{
|
||||
UINT32 surfaceId;
|
||||
xfGfxSurface* surface;
|
||||
|
||||
surfaceId = (UINT32) (ULONG_PTR) ArrayList_GetItem(xfc->gfxMappedSurfaceIds, surfaceIndex);
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceId);
|
||||
|
||||
if (!surface)
|
||||
{
|
||||
ArrayList_RemoveAt(surfaceList, surfaceIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (processSurface(xfc, surface, param) < 0)
|
||||
status = -1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int do_clearInvalidRegion(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||
{
|
||||
region16_clear(&surface->invalidRegion);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
int status = 1;
|
||||
xfGfxSurface* surface;
|
||||
UINT16* pSurfaceIds = NULL;
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);
|
||||
|
||||
xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_clearInvalidRegion, NULL);
|
||||
count = context->GetSurfaceIds(context, &pSurfaceIds);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);
|
||||
|
||||
if (!surface || !surface->outputMapped)
|
||||
continue;
|
||||
|
||||
region16_clear(&surface->invalidRegion);
|
||||
}
|
||||
|
||||
free(pSurfaceIds);
|
||||
|
||||
xfc->graphicsReset = TRUE;
|
||||
|
||||
|
@ -83,8 +63,8 @@ int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
|
|||
RECTANGLE_16 surfaceRect;
|
||||
const RECTANGLE_16* extents;
|
||||
|
||||
surfaceX = surface->mapping.output.originX;
|
||||
surfaceY = surface->mapping.output.originY;
|
||||
surfaceX = surface->outputOriginX;
|
||||
surfaceY = surface->outputOriginY;
|
||||
|
||||
surfaceRect.left = surfaceX;
|
||||
surfaceRect.top = surfaceY;
|
||||
|
@ -138,87 +118,82 @@ int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int xf_UpdateSurface(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||
int xf_UpdateSurfaces(xfContext* xfc)
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
int status = 1;
|
||||
xfGfxSurface* surface;
|
||||
UINT16* pSurfaceIds = NULL;
|
||||
RdpgfxClientContext* context = xfc->gfx;
|
||||
|
||||
switch (surface->mapping.mode)
|
||||
if (!xfc->graphicsReset)
|
||||
return 1;
|
||||
|
||||
count = context->GetSurfaceIds(context, &pSurfaceIds);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
case GFX_MAP_OUTPUT:
|
||||
status = xf_OutputUpdate(xfc, surface);
|
||||
break;
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);
|
||||
|
||||
case GFX_MAP_NONE:
|
||||
if (!surface || !surface->outputMapped)
|
||||
continue;
|
||||
|
||||
status = xf_OutputUpdate(xfc, surface);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
free(pSurfaceIds);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int xf_UpdateSurfaces(xfContext* xfc)
|
||||
{
|
||||
if (!xfc->graphicsReset)
|
||||
return 1;
|
||||
|
||||
return xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, xf_UpdateSurface, NULL);
|
||||
}
|
||||
|
||||
BOOL xf_MappedSurfaceRect(xfContext* xfc, xfGfxSurface* surface, RECTANGLE_16* rect)
|
||||
{
|
||||
BOOL mapped = FALSE;
|
||||
|
||||
switch (surface->mapping.mode)
|
||||
{
|
||||
case GFX_MAP_OUTPUT:
|
||||
mapped = TRUE;
|
||||
rect->left = surface->mapping.output.originX;
|
||||
rect->top = surface->mapping.output.originY;
|
||||
rect->right = surface->mapping.output.originX + surface->width;
|
||||
rect->bottom = surface->mapping.output.originY + surface->height;
|
||||
break;
|
||||
|
||||
case GFX_MAP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
return mapped;
|
||||
}
|
||||
|
||||
static int do_OutputExpose(xfContext* xfc, xfGfxSurface* surface, void* param)
|
||||
{
|
||||
RECTANGLE_16 surfaceRect;
|
||||
RECTANGLE_16 intersection;
|
||||
RECTANGLE_16* invalidRect = param;
|
||||
|
||||
if (!xf_MappedSurfaceRect(xfc, surface, &surfaceRect))
|
||||
return -1;
|
||||
|
||||
if (rectangles_intersection(invalidRect, &surfaceRect, &intersection))
|
||||
{
|
||||
/* Invalid rects are specified relative to surface origin */
|
||||
intersection.left -= surfaceRect.left;
|
||||
intersection.top -= surfaceRect.top;
|
||||
intersection.right -= surfaceRect.left;
|
||||
intersection.bottom -= surfaceRect.top;
|
||||
|
||||
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &intersection);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
int status = 1;
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
RECTANGLE_16 intersection;
|
||||
UINT16* pSurfaceIds = NULL;
|
||||
RdpgfxClientContext* context = xfc->gfx;
|
||||
|
||||
invalidRect.left = x;
|
||||
invalidRect.top = y;
|
||||
invalidRect.right = x + width;
|
||||
invalidRect.bottom = y + height;
|
||||
|
||||
if (xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_OutputExpose, &invalidRect) < 0)
|
||||
status = -1;
|
||||
count = context->GetSurfaceIds(context, &pSurfaceIds);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);
|
||||
|
||||
if (!surface || !surface->outputMapped)
|
||||
continue;
|
||||
|
||||
surfaceRect.left = surface->outputOriginX;
|
||||
surfaceRect.top = surface->outputOriginY;
|
||||
surfaceRect.right = surface->outputOriginX + surface->width;
|
||||
surfaceRect.bottom = surface->outputOriginY + surface->height;
|
||||
|
||||
if (rectangles_intersection(&invalidRect, &surfaceRect, &intersection))
|
||||
{
|
||||
/* Invalid rects are specified relative to surface origin */
|
||||
intersection.left -= surfaceRect.left;
|
||||
intersection.top -= surfaceRect.top;
|
||||
intersection.right -= surfaceRect.left;
|
||||
intersection.bottom -= surfaceRect.top;
|
||||
|
||||
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &intersection);
|
||||
}
|
||||
}
|
||||
|
||||
free(pSurfaceIds);
|
||||
|
||||
if (xf_UpdateSurfaces(xfc) < 0)
|
||||
status = -1;
|
||||
|
@ -708,7 +683,7 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr
|
|||
(char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep);
|
||||
}
|
||||
|
||||
surface->mapping.mode = GFX_MAP_NONE;
|
||||
surface->outputMapped = FALSE;
|
||||
|
||||
region16_init(&surface->invalidRegion);
|
||||
|
||||
|
@ -733,7 +708,6 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de
|
|||
free(surface);
|
||||
}
|
||||
|
||||
ArrayList_Remove(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) deleteSurface->surfaceId);
|
||||
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
|
||||
|
||||
if (xfc->codecs->progressive)
|
||||
|
@ -959,18 +933,15 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD
|
|||
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
|
||||
{
|
||||
xfGfxSurface* surface;
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId);
|
||||
|
||||
surface->mapping.mode = GFX_MAP_OUTPUT;
|
||||
surface->mapping.output.originX = surfaceToOutput->outputOriginX;
|
||||
surface->mapping.output.originY = surfaceToOutput->outputOriginY;
|
||||
surface->outputMapped = TRUE;
|
||||
surface->outputOriginX = surfaceToOutput->outputOriginX;
|
||||
surface->outputOriginY = surfaceToOutput->outputOriginY;
|
||||
|
||||
region16_clear(&surface->invalidRegion);
|
||||
|
||||
ArrayList_Add(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) surfaceToOutput->surfaceId);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -999,15 +970,9 @@ void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
|
|||
gfx->EvictCacheEntry = xf_EvictCacheEntry;
|
||||
gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput;
|
||||
gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow;
|
||||
|
||||
xfc->gfxMappedSurfaceIds = ArrayList_New(FALSE);
|
||||
}
|
||||
|
||||
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
|
||||
{
|
||||
if (xfc->gfxMappedSurfaceIds)
|
||||
{
|
||||
ArrayList_Free(xfc->gfxMappedSurfaceIds);
|
||||
xfc->gfxMappedSurfaceIds = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
|
||||
#include <freerdp/gdi/gfx.h>
|
||||
|
||||
enum xf_gfx_mapping_mode
|
||||
{
|
||||
GFX_MAP_NONE,
|
||||
GFX_MAP_OUTPUT
|
||||
};
|
||||
typedef enum xf_gfx_mapping_mode xfGfxMappingMode;
|
||||
|
||||
struct xf_gfx_surface
|
||||
{
|
||||
UINT16 surfaceId;
|
||||
|
@ -44,18 +37,9 @@ struct xf_gfx_surface
|
|||
int scanline;
|
||||
int stageStep;
|
||||
UINT32 format;
|
||||
struct
|
||||
{
|
||||
xfGfxMappingMode mode;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
UINT32 originX;
|
||||
UINT32 originY;
|
||||
} output;
|
||||
};
|
||||
} mapping;
|
||||
BOOL outputMapped;
|
||||
UINT32 outputOriginX;
|
||||
UINT32 outputOriginY;
|
||||
REGION16 invalidRegion;
|
||||
};
|
||||
typedef struct xf_gfx_surface xfGfxSurface;
|
||||
|
|
|
@ -125,7 +125,6 @@ struct xf_context
|
|||
BYTE* primary_buffer;
|
||||
BOOL inGfxFrame;
|
||||
BOOL graphicsReset;
|
||||
wArrayList* gfxMappedSurfaceIds;
|
||||
|
||||
BOOL frame_begin;
|
||||
UINT16 frame_x1;
|
||||
|
|
|
@ -47,6 +47,7 @@ typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_M
|
|||
|
||||
typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData);
|
||||
typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId);
|
||||
typedef int (*pcRdpgfxGetSurfaceIds)(RdpgfxClientContext* context, UINT16** ppSurfaceIds);
|
||||
typedef int (*pcRdpgfxSetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData);
|
||||
typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot);
|
||||
|
||||
|
@ -72,6 +73,7 @@ struct _rdpgfx_client_context
|
|||
pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput;
|
||||
pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow;
|
||||
|
||||
pcRdpgfxGetSurfaceIds GetSurfaceIds;
|
||||
pcRdpgfxSetSurfaceData SetSurfaceData;
|
||||
pcRdpgfxGetSurfaceData GetSurfaceData;
|
||||
pcRdpgfxSetCacheSlotData SetCacheSlotData;
|
||||
|
|
|
@ -99,9 +99,9 @@ rdpChannels* freerdp_channels_new(void)
|
|||
void freerdp_channels_free(rdpChannels* channels)
|
||||
{
|
||||
int index;
|
||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||
ULONG_PTR* pKeys;
|
||||
int nkeys;
|
||||
ULONG_PTR* pKeys = NULL;
|
||||
CHANNEL_OPEN_DATA* pChannelOpenData;
|
||||
|
||||
if (channels->queue)
|
||||
{
|
||||
|
@ -126,12 +126,15 @@ void freerdp_channels_free(rdpChannels* channels)
|
|||
if (g_OpenHandles)
|
||||
{
|
||||
nkeys = HashTable_GetKeys(g_OpenHandles, &pKeys);
|
||||
free(pKeys);
|
||||
if ( nkeys == 0 ) {
|
||||
|
||||
if (nkeys == 0)
|
||||
{
|
||||
HashTable_Free(g_OpenHandles);
|
||||
DeleteCriticalSection(&g_channels_lock);
|
||||
g_OpenHandles = NULL;
|
||||
}
|
||||
|
||||
free(pKeys);
|
||||
}
|
||||
|
||||
free(channels);
|
||||
|
|
|
@ -457,6 +457,14 @@ int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
|
|||
iKey = 0;
|
||||
count = table->numOfElements;
|
||||
|
||||
if (count < 1)
|
||||
{
|
||||
if (table->synchronized)
|
||||
LeaveCriticalSection(&table->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR));
|
||||
|
||||
if (!pKeys)
|
||||
|
|
Loading…
Reference in New Issue