diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 2b50e9ce8..b6d9f3b2f 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -854,11 +854,41 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) zgfx_context_free(gfx->zgfx); + HashTable_Free(gfx->SurfaceTable); + free(gfx); return 0; } +int rdpgfx_set_surface_data(RdpgfxClientContext* context, UINT16 surfaceId, void* pData) +{ + ULONG_PTR key; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + if (pData) + HashTable_Add(gfx->SurfaceTable, (void*) key, pData); + else + HashTable_Remove(gfx->SurfaceTable, (void*) key); + + return 1; +} + +void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId) +{ + ULONG_PTR key; + void* pData = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + pData = HashTable_GetItemValue(gfx->SurfaceTable, (void*) key); + + return pData; +} + #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpgfx_DVCPluginEntry #endif @@ -885,6 +915,11 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) gfx->iface.Disconnected = NULL; gfx->iface.Terminated = rdpgfx_plugin_terminated; + gfx->SurfaceTable = HashTable_New(TRUE); + + if (!gfx->SurfaceTable) + return -1; + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); if (!context) @@ -892,6 +927,9 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) context->handle = (void*) gfx; + context->SetSurfaceData = rdpgfx_set_surface_data; + context->GetSurfaceData = rdpgfx_get_surface_data; + gfx->iface.pInterface = (void*) context; gfx->zgfx = zgfx_context_new(FALSE); diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index ace81bef3..da0e64822 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -66,6 +67,8 @@ struct _RDPGFX_PLUGIN ZGFX_CONTEXT* zgfx; UINT32 UnacknowledgedFrames; UINT32 TotalDecodedFrames; + + wHashTable* SurfaceTable; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index b068c5d54..8cea5027e 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -306,16 +306,52 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) { + xfGfxSurface* surface; + xfContext* xfc = (xfContext*) context->custom; + printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n", createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat); + surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface)); + + if (!surface) + return -1; + + surface->surfaceId = createSurface->surfaceId; + surface->width = (UINT32) createSurface->width; + surface->height = (UINT32) createSurface->height; + surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; + + surface->data = (BYTE*) calloc(1, surface->width * surface->height * 4); + + if (!surface->data) + return -1; + + surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, + (char*) surface->data, surface->width, surface->height, 32, 0); + + context->SetSurfaceData(context, surface->surfaceId, (void*) surface); + return 1; } int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) { + xfGfxSurface* surface = NULL; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId); + printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId); + if (surface) + { + XFree(surface->image); + free(surface->data); + free(surface); + } + + context->SetSurfaceData(context, deleteSurface->surfaceId, NULL); + return 1; } diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 01a61b9db..efc7c46dd 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -23,6 +23,17 @@ #include "xf_client.h" #include "xfreerdp.h" +struct xf_gfx_surface +{ + UINT16 surfaceId; + UINT32 width; + UINT32 height; + BOOL alpha; + BYTE* data; + XImage* image; +}; +typedef struct xf_gfx_surface xfGfxSurface; + void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx); #endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index b2c0dda70..64c1155a1 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -45,6 +45,9 @@ typedef int (*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, RDPGFX_EVIC typedef int (*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); +typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData); +typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId); + struct _rdpgfx_client_context { void* handle; @@ -66,6 +69,9 @@ struct _rdpgfx_client_context pcRdpgfxEvictCacheEntry EvictCacheEntry; pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput; pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow; + + pcRdpgfxSetSurfaceData SetSurfaceData; + pcRdpgfxGetSurfaceData GetSurfaceData; }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */