mirror of https://github.com/FreeRDP/FreeRDP
xfreerdp: initial egfx bitmap caching
This commit is contained in:
parent
27b1e76dbb
commit
eeb7cd2cb2
|
@ -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;
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@ struct _RDPGFX_PLUGIN
|
|||
UINT32 TotalDecodedFrames;
|
||||
|
||||
wHashTable* SurfaceTable;
|
||||
|
||||
UINT16 MaxCacheSlot;
|
||||
void* CacheSlots[25600];
|
||||
};
|
||||
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue