xfreerdp: fix X11 16bpp mode

This commit is contained in:
Marc-André Moreau 2014-09-17 14:29:56 -04:00
parent fb4e5d352b
commit 48b35be953
6 changed files with 145 additions and 87 deletions

View File

@ -946,9 +946,9 @@ BOOL xf_post_connect(freerdp *instance)
XSetForeground(xfc->display, xfc->gc, BlackPixelOfScreen(xfc->screen));
XFillRectangle(xfc->display, xfc->primary, xfc->gc, 0, 0, xfc->width, xfc->height);
XFlush(xfc->display);
xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0);
xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4);
if (settings->SoftwareGdi)
{
@ -1641,9 +1641,6 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
{
xf_window_free(xfc);
if (xfc->bmp_codec_none)
free(xfc->bmp_codec_none);
if (xfc->bitmap_buffer)
_aligned_free(xfc->bitmap_buffer);

View File

@ -1139,6 +1139,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
{
int i, tx, ty;
XImage* image;
BYTE* pSrcData;
BYTE* pDstData;
RFX_MESSAGE* message;
xfContext* xfc = (xfContext*) context;
@ -1148,21 +1150,39 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX);
message = rfx_process_message(xfc->codecs->rfx,
cmd->bitmapData, cmd->bitmapDataLength);
message = rfx_process_message(xfc->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetClipRectangles(xfc->display, xfc->gc,
cmd->destLeft, cmd->destTop,
XSetClipRectangles(xfc->display, xfc->gc, cmd->destLeft, cmd->destTop,
(XRectangle*) message->rects, message->numRects, YXBanded);
if (xfc->bitmap_size < (64 * 64 * 4))
{
xfc->bitmap_size = 64 * 64 * 4;
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
if (!xfc->bitmap_buffer)
return;
}
/* Draw the tiles to primary surface, each is 64x64. */
for (i = 0; i < message->numTiles; i++)
{
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) message->tiles[i]->data, 64, 64, 32, 0);
pSrcData = message->tiles[i]->data;
pDstData = pSrcData;
if ((xfc->depth != 24) || (xfc->depth != 32))
{
pDstData = xfc->bitmap_buffer;
freerdp_image_copy(pDstData, xfc->format, -1, 0, 0,
64, 64, pSrcData, PIXEL_FORMAT_XRGB32, -1, 0, 0);
}
image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) pDstData, 64, 64, xfc->scanline_pad, 0);
tx = message->tiles[i]->x + cmd->destLeft;
ty = message->tiles[i]->y + cmd->destTop;
@ -1176,9 +1196,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
{
tx = message->rects[i].x + cmd->destLeft;
ty = message->rects[i].y + cmd->destTop;
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, tx, ty, message->rects[i].width, message->rects[i].height, tx, ty);
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc,
tx, ty, message->rects[i].width, message->rects[i].height, tx, ty);
}
xf_gdi_surface_update_frame(xfc, tx, ty, message->rects[i].width, message->rects[i].height);
@ -1191,39 +1213,42 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_NSCODEC);
nsc_process_message(xfc->codecs->nsc, cmd->bpp, cmd->width, cmd->height,
cmd->bitmapData, cmd->bitmapDataLength);
nsc_process_message(xfc->codecs->nsc, cmd->bpp, cmd->width, cmd->height, cmd->bitmapData, cmd->bitmapDataLength);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc,
cmd->width * cmd->height * 4);
if (xfc->bitmap_size < (cmd->width * cmd->height * 4))
{
xfc->bitmap_size = cmd->width * cmd->height * 4;
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
freerdp_image_flip(xfc->codecs->nsc->BitmapData, xfc->bmp_codec_nsc,
cmd->width, cmd->height, 32);
if (!xfc->bitmap_buffer)
return;
}
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) xfc->bmp_codec_nsc, cmd->width, cmd->height, 32, 0);
pSrcData = xfc->codecs->nsc->BitmapData;
pDstData = xfc->bitmap_buffer;
freerdp_image_copy(pDstData, xfc->format, -1, 0, 0,
cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0);
image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) pDstData, cmd->width, cmd->height, xfc->scanline_pad, 0);
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height);
cmd->destLeft, cmd->destTop, cmd->width, cmd->height);
XFree(image);
free(xfc->bmp_codec_nsc);
xfc->bmp_codec_nsc = NULL;
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height,
cmd->destLeft, cmd->destTop, cmd->width, cmd->height,
cmd->destLeft, cmd->destTop);
}
xf_gdi_surface_update_frame(xfc,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height);
xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height);
XSetClipMask(xfc->display, xfc->gc, None);
}
@ -1232,43 +1257,39 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
/* Validate that the data received is large enough */
if ((cmd->width * cmd->height * cmd->bpp / 8) <= (cmd->bitmapDataLength))
if (xfc->bitmap_size < (cmd->width * cmd->height * 4))
{
xfc->bmp_codec_none = (BYTE*) realloc(xfc->bmp_codec_none,
cmd->width * cmd->height * 4);
xfc->bitmap_size = cmd->width * cmd->height * 4;
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
freerdp_image_flip(cmd->bitmapData, xfc->bmp_codec_none,
cmd->width, cmd->height, 32);
if (!xfc->bitmap_buffer)
return;
}
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) xfc->bmp_codec_none, cmd->width, cmd->height, 32, 0);
pSrcData = cmd->bitmapData;
pDstData = xfc->bitmap_buffer;
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height);
XFree(image);
free(xfc->bmp_codec_none);
xfc->bmp_codec_none = NULL;
freerdp_image_copy(pDstData, xfc->format, -1, 0, 0,
cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0);
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height,
cmd->destLeft, cmd->destTop);
}
xf_gdi_surface_update_frame(xfc,
image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) pDstData, cmd->width, cmd->height, xfc->scanline_pad, 0);
XPutImage(xfc->display, xfc->primary, xfc->gc, image, 0, 0,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height);
XFree(image);
XSetClipMask(xfc->display, xfc->gc, None);
}
else
if (!xfc->remote_app)
{
DEBUG_WARN("Invalid bitmap size - data is %d bytes for %dx%d\n update",
cmd->bitmapDataLength, cmd->width, cmd->height);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height, cmd->destLeft, cmd->destTop);
}
xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height);
XSetClipMask(xfc->display, xfc->gc, None);
}
else
{

View File

@ -75,9 +75,17 @@ int xf_OutputUpdate(xfContext* xfc)
if (height > xfc->height)
height = xfc->height;
if (surface->stage)
{
freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0,
surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0);
//freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, extents->left, extents->top,
// width, height, surface->data, surface->format, surface->scanline, extents->left, extents->top);
}
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
extents->left, extents->top,
extents->left, extents->top, width, height);
extents->left, extents->top, extents->left, extents->top, width, height);
}
region16_clear(&(xfc->invalidRegion));
@ -90,9 +98,6 @@ int xf_OutputUpdate(xfContext* xfc)
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
{
/** *********************************
* to be improved?
* *********************************/
RECTANGLE_16 invalidRect;
invalidRect.left = x;
@ -137,7 +142,7 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context,
if (!surface)
return -1;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top,
freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top,
cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0);
invalidRect.left = cmd->left;
@ -216,7 +221,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
nWidth = updateRects[j].right - updateRects[j].left;
nHeight = updateRects[j].bottom - updateRects[j].top;
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_copy(surface->data, surface->format, surface->scanline,
nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0);
@ -251,7 +256,7 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
DstData = surface->data;
status = clear_decompress(xfc->codecs->clear, cmd->data, cmd->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
if (status < 0)
{
@ -266,7 +271,6 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
@ -290,7 +294,7 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
DstData = surface->data;
status = planar_decompress(xfc->codecs->planar, cmd->data, cmd->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE);
surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE);
invalidRect.left = cmd->left;
invalidRect.top = cmd->top;
@ -334,7 +338,7 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
DstData = surface->data;
status = h264_decompress(xfc->codecs->h264, bs->data, bs->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects);
surface->format, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects);
if (status < 0)
{
@ -417,7 +421,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
DstData = surface->data;
status = progressive_decompress(xfc->codecs->progressive, cmd->data, cmd->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId);
surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId);
if (status < 0)
{
@ -529,6 +533,8 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN
int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
{
size_t size;
UINT32 bytesPerPixel;
xfGfxSurface* surface;
xfContext* xfc = (xfContext*) context->custom;
@ -541,16 +547,41 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr
surface->width = (UINT32) createSurface->width;
surface->height = (UINT32) createSurface->height;
surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE;
surface->format = xfc->format;
surface->format = PIXEL_FORMAT_XRGB32;
surface->scanline = (surface->width + (surface->width % 4)) * 4;
surface->data = (BYTE*) calloc(1, surface->scanline * surface->height);
surface->scanline = surface->width * 4;
surface->scanline += (surface->scanline % (xfc->scanline_pad / 8));
size = surface->scanline * surface->height;
surface->data = (BYTE*) _aligned_malloc(size, 16);
if (!surface->data)
return -1;
surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
(char*) surface->data, surface->width, surface->height, 32, surface->scanline);
ZeroMemory(surface->data, size);
if ((xfc->depth == 24) || (xfc->depth == 32))
{
surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) surface->data, surface->width, surface->height, xfc->scanline_pad, surface->scanline);
}
else
{
bytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(xfc->format) / 8);
surface->stageStep = surface->width * bytesPerPixel;
surface->stageStep += (surface->stageStep % (xfc->scanline_pad / 8));
size = surface->stageStep * surface->height;
surface->stage = (BYTE*) _aligned_malloc(size, 16);
if (!surface->stage)
return -1;
ZeroMemory(surface->stage, size);
surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
(char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep);
}
context->SetSurfaceData(context, surface->surfaceId, (void*) surface);
@ -567,7 +598,8 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de
if (surface)
{
XFree(surface->image);
free(surface->data);
_aligned_free(surface->data);
_aligned_free(surface->stage);
free(surface);
}
@ -614,7 +646,7 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
invalidRect.right = rect->right;
invalidRect.bottom = rect->bottom;
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_fill(surface->data, surface->format, surface->scanline,
rect->left, rect->top, nWidth, nHeight, color);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
@ -662,13 +694,13 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
if (sameSurface)
{
freerdp_image_move(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
freerdp_image_move(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top);
}
else
{
freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32,
freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline,
destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format,
surfaceSrc->scanline, rectSrc->left, rectSrc->top);
}
@ -688,6 +720,7 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
{
size_t size;
RDPGFX_RECT16* rect;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
@ -708,17 +741,22 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU*
cacheEntry->width = (UINT32) (rect->right - rect->left);
cacheEntry->height = (UINT32) (rect->bottom - rect->top);
cacheEntry->alpha = surface->alpha;
cacheEntry->format = xfc->format;
cacheEntry->format = surface->format;
cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4;
cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height);
cacheEntry->scanline = cacheEntry->width * 4;
cacheEntry->scanline += (cacheEntry->scanline % (xfc->scanline_pad / 8));
size = cacheEntry->scanline * cacheEntry->height;
cacheEntry->data = (BYTE*) _aligned_malloc(size, 16);
if (!cacheEntry->data)
return -1;
freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline,
ZeroMemory(cacheEntry->data, size);
freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
0, 0, cacheEntry->width, cacheEntry->height, surface->data,
PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top);
surface->format, surface->scanline, rect->left, rect->top);
context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry);
@ -744,9 +782,9 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU*
{
destPt = &cacheToSurface->destPts[index];
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
freerdp_image_copy(surface->data, surface->format, surface->scanline,
destPt->x, destPt->y, cacheEntry->width, cacheEntry->height,
cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0);
cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0);
invalidRect.left = destPt->x;
invalidRect.top = destPt->y;
@ -775,7 +813,7 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD
if (cacheEntry)
{
free(cacheEntry->data);
_aligned_free(cacheEntry->data);
free(cacheEntry);
}

View File

@ -32,8 +32,10 @@ struct xf_gfx_surface
UINT32 height;
BOOL alpha;
BYTE* data;
BYTE* stage;
XImage* image;
int scanline;
int stageStep;
UINT32 format;
};
typedef struct xf_gfx_surface xfGfxSurface;

View File

@ -155,8 +155,6 @@ struct xf_context
XSetWindowAttributes attribs;
BOOL complex_regions;
VIRTUAL_SCREEN vscreen;
BYTE* bmp_codec_none;
BYTE* bmp_codec_nsc;
void* xv_context;
void* clipboard_context;

View File

@ -603,6 +603,8 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS
if (useTempBuffer)
{
pDstData = *ppDstData;
status = freerdp_image_copy(pDstData, DstFormat, -1, 0, 0, nWidth, nHeight,
planar->TempBuffer, PIXEL_FORMAT_XRGB32, -1, 0, 0);
}