xfreerdp: initial egfx bitmap caching

This commit is contained in:
Marc-André Moreau 2014-06-13 08:36:09 -04:00
parent 27b1e76dbb
commit eeb7cd2cb2
7 changed files with 187 additions and 33 deletions

View File

@ -60,6 +60,8 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
gfx->SmallCache = FALSE;
gfx->H264 = FALSE;
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
header.flags = 0;
header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
@ -892,6 +894,31 @@ void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId)
return pData;
}
int rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData)
{
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
return -1;
gfx->CacheSlots[cacheSlot] = pData;
return 1;
}
void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot)
{
void* pData = NULL;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
return NULL;
pData = gfx->CacheSlots[cacheSlot];
return pData;
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry rdpgfx_DVCPluginEntry
#endif
@ -923,6 +950,9 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (!gfx->SurfaceTable)
return -1;
gfx->ThinClient = TRUE;
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
if (!context)
@ -932,6 +962,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
context->SetSurfaceData = rdpgfx_set_surface_data;
context->GetSurfaceData = rdpgfx_get_surface_data;
context->SetCacheSlotData = rdpgfx_set_cache_slot_data;
context->GetCacheSlotData = rdpgfx_get_cache_slot_data;
gfx->iface.pInterface = (void*) context;

View File

@ -69,6 +69,9 @@ struct _RDPGFX_PLUGIN
UINT32 TotalDecodedFrames;
wHashTable* SurfaceTable;
UINT16 MaxCacheSlot;
void* CacheSlots[25600];
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;

View File

@ -167,9 +167,6 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context,
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
printf("xf_SurfaceCommand_Uncompressed: x: %d y: %d w: %d h: %d r: %d b: %d\n",
cmd->left, cmd->top, cmd->width, cmd->height, cmd->right, cmd->bottom);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
@ -382,13 +379,19 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
UINT16 index;
UINT32 color;
BYTE a, r, g, b;
XRectangle* xrects;
int nWidth, nHeight;
RDPGFX_RECT16* rect;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
xfContext* xfc = (xfContext*) context->custom;
surface = (xfGfxSurface*) context->GetSurfaceData(context, solidFill->surfaceId);
printf("xf_SolidFill\n");
if (!surface)
return -1;
b = solidFill->fillPixel.B;
g = solidFill->fillPixel.G;
r = solidFill->fillPixel.R;
@ -396,36 +399,24 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
color = ARGB32(a, r, g, b);
xrects = (XRectangle*) malloc(solidFill->fillRectCount * sizeof(XRectangle));
if (!xrects)
return -1;
for (index = 0; index < solidFill->fillRectCount; index++)
{
rect = &(solidFill->fillRects[index]);
xrects[index].x = rect->left;
xrects[index].y = rect->top;
xrects[index].width = rect->right - rect->left + 1;
xrects[index].height = rect->bottom - rect->top + 1;
nWidth = rect->right - rect->left;
nHeight = rect->bottom - rect->top;
invalidRect.left = rect->left;
invalidRect.top = rect->top;
invalidRect.right = rect->right;
invalidRect.bottom = rect->bottom;
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
rect->left, rect->top, nWidth, nHeight, color);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
}
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, color);
XFillRectangles(xfc->display, xfc->drawing, xfc->gc, xrects, solidFill->fillRectCount);
free(xrects);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
@ -446,12 +437,6 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
rectSrc = &(surfaceToSurface->rectSrc);
destPt = &surfaceToSurface->destPts[0];
printf("xf_SurfaceToSurface: srcId: %d dstId: %d rect: x: %d y: %d w: %d h: %d ptsCount: %d x: %d y: %d\n",
(int) surfaceToSurface->surfaceIdSrc, (int) surfaceToSurface->surfaceIdDest,
rectSrc->left, rectSrc->top, rectSrc->right - rectSrc->left,
rectSrc->bottom - rectSrc->top, (int) surfaceToSurface->destPtsCount,
destPt->x, destPt->y);
surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest)
@ -489,14 +474,80 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
{
printf("xf_SurfaceToCache\n");
RDPGFX_RECT16* rect;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
rect = &(surfaceToCache->rectSrc);
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId);
printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n",
surfaceToCache->cacheKey, surfaceToCache->cacheSlot);
if (!surface)
return -1;
cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry));
if (!cacheEntry)
return -1;
cacheEntry->width = (UINT32) (rect->right - rect->left);
cacheEntry->height = (UINT32) (rect->bottom - rect->top);
cacheEntry->alpha = surface->alpha;
cacheEntry->scanline = cacheEntry->width * 4;
cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height);
if (!cacheEntry->data)
return -1;
freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height, surface->data,
PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top);
context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry);
return 1;
}
int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
{
printf("xf_CacheToSurface\n");
UINT16 index;
RDPGFX_POINT16* destPt;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
RECTANGLE_16 invalidRect;
xfContext* xfc = (xfContext*) context->custom;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId);
cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot);
printf("xf_CacheToSurface: cacheEntry: %d\n",
cacheToSurface->cacheSlot);
if (!surface || !cacheEntry)
return -1;
for (index = 0; index < cacheToSurface->destPtsCount; index++)
{
destPt = &cacheToSurface->destPts[index];
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
destPt->x, destPt->y, cacheEntry->width, cacheEntry->height,
cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0);
invalidRect.left = destPt->x;
invalidRect.top = destPt->y;
invalidRect.right = destPt->x + cacheEntry->width - 1;
invalidRect.bottom = destPt->y + cacheEntry->height - 1;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
return 1;
}
@ -517,9 +568,6 @@ int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OU
{
xfContext* xfc = (xfContext*) context->custom;
printf("xf_MapSurfaceToOutput: surfaceId: %d outputOriginX: %d outputOriginY: %d\n",
surfaceToOutput->surfaceId, surfaceToOutput->outputOriginX, surfaceToOutput->outputOriginY);
xfc->outputSurfaceId = surfaceToOutput->surfaceId;
return 1;

View File

@ -35,6 +35,18 @@ struct xf_gfx_surface
};
typedef struct xf_gfx_surface xfGfxSurface;
struct xf_gfx_cache_entry
{
UINT64 cacheKey;
UINT32 width;
UINT32 height;
BOOL alpha;
BYTE* data;
XImage* image;
int scanline;
};
typedef struct xf_gfx_cache_entry xfGfxCacheEntry;
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height);
void xf_register_graphics_pipeline(xfContext* xfc, RdpgfxClientContext* gfx);

View File

@ -47,6 +47,8 @@ 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 (*pcRdpgfxSetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData);
typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot);
struct _rdpgfx_client_context
{
@ -72,6 +74,8 @@ struct _rdpgfx_client_context
pcRdpgfxSetSurfaceData SetSurfaceData;
pcRdpgfxGetSurfaceData GetSurfaceData;
pcRdpgfxSetCacheSlotData SetCacheSlotData;
pcRdpgfxGetCacheSlotData GetCacheSlotData;
};
#endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */

View File

@ -398,6 +398,8 @@ FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv);
FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc);
FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, UINT32 color);
#ifdef __cplusplus
}

View File

@ -1175,7 +1175,7 @@ void freerdp_clrconv_free(HCLRCONV clrconv)
int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc)
{
int y, x;
int x, y;
BYTE a, r, g, b;
int beg, end, inc;
int srcBitsPerPixel;
@ -1350,3 +1350,56 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
return 0;
}
void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length)
{
while (length--)
{
*ptr++ = fill;
}
return (void*) ptr;
}
int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, UINT32 color)
{
int y;
int dstBitsPerPixel;
int dstBytesPerPixel;
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat);
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8);
if (dstBytesPerPixel == 4)
{
UINT32* pDstPixel;
if (nDstStep < 0)
nDstStep = dstBytesPerPixel * nWidth;
for (y = 0; y < nHeight; y++)
{
pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)];
freerdp_image_memset32(pDstPixel, color, nWidth);
}
}
else if (dstBytesPerPixel == 3)
{
}
else if (dstBytesPerPixel == 2)
{
if (dstBitsPerPixel == 16)
{
}
else if (dstBitsPerPixel == 15)
{
}
}
return 0;
}