From 1b7a84419c0096d002ce0ea7d92e99d3e0f09af0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 16 Sep 2014 19:12:26 -0400 Subject: [PATCH] xfreerdp: partial fix for X11 16bpp mode --- client/Windows/wf_gdi.c | 2 +- client/Windows/wf_graphics.c | 2 +- client/X11/xf_client.c | 112 +++++--- client/X11/xf_gdi.c | 41 ++- client/X11/xf_gfx.c | 5 +- client/X11/xf_gfx.h | 2 + client/X11/xf_graphics.c | 12 +- client/X11/xfreerdp.h | 2 + include/freerdp/codec/planar.h | 2 +- libfreerdp/codec/color.c | 369 +++++++++++++++++++++++++ libfreerdp/codec/planar.c | 5 +- libfreerdp/codec/test/TestFreeRDPCodecPlanar.c | 10 +- libfreerdp/gdi/gdi.c | 2 +- libfreerdp/gdi/gfx.c | 2 +- libfreerdp/gdi/graphics.c | 2 +- 15 files changed, 502 insertions(+), 68 deletions(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index ab9329e..07cb52b 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -411,7 +411,7 @@ void wf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR); status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData, - PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight); + PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight, TRUE); } if (status < 0) diff --git a/client/Windows/wf_graphics.c b/client/Windows/wf_graphics.c index 2ca2b24..28cec4c 100644 --- a/client/Windows/wf_graphics.c +++ b/client/Windows/wf_graphics.c @@ -178,7 +178,7 @@ void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap, freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR); status = planar_decompress(wfc->codecs->planar, pSrcData, SrcSize, &pDstData, - PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height); + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, TRUE); } if (status < 0) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 2a4d4cc..82c1b56 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -239,7 +239,6 @@ void xf_sw_end_paint(rdpContext *context) w = cinvalid[i].w; h = cinvalid[i].h; - //combine xfc->primary with xfc->image XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) @@ -270,25 +269,24 @@ void xf_sw_end_paint(rdpContext *context) } } -void xf_sw_desktop_resize(rdpContext *context) +void xf_sw_desktop_resize(rdpContext* context) { - rdpSettings *settings; - xfContext *xfc = (xfContext *) context; - settings = xfc->instance->settings; + rdpGdi* gdi = context->gdi; + xfContext* xfc = (xfContext*) context; xf_lock_x11(xfc, TRUE); if (!xfc->fullscreen) { - rdpGdi *gdi = context->gdi; gdi_resize(gdi, xfc->width, xfc->height); if (xfc->image) { xfc->image->data = NULL; XDestroyImage(xfc->image); + xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, - (char *) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0); + (char*) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0); } } @@ -297,7 +295,7 @@ void xf_sw_desktop_resize(rdpContext *context) void xf_hw_begin_paint(rdpContext *context) { - xfContext *xfc = (xfContext *) context; + xfContext* xfc = (xfContext*) context; xfc->hdc->hwnd->invalid->null = 1; xfc->hdc->hwnd->ninvalid = 0; } @@ -306,19 +304,23 @@ void xf_hw_end_paint(rdpContext *context) { INT32 x, y; UINT32 w, h; - xfContext *xfc = (xfContext *) context; - if(!xfc->remote_app) + xfContext* xfc = (xfContext*) context; + + if (!xfc->remote_app) { - if(!xfc->complex_regions) + if (!xfc->complex_regions) { - if(xfc->hdc->hwnd->invalid->null) + if (xfc->hdc->hwnd->invalid->null) return; + x = xfc->hdc->hwnd->invalid->x; y = xfc->hdc->hwnd->invalid->y; w = xfc->hdc->hwnd->invalid->w; h = xfc->hdc->hwnd->invalid->h; + xf_lock_x11(xfc, FALSE); - if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) + + if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) { xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); } @@ -326,6 +328,7 @@ void xf_hw_end_paint(rdpContext *context) { XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y); } + xf_unlock_x11(xfc, FALSE); } else @@ -333,18 +336,23 @@ void xf_hw_end_paint(rdpContext *context) int i; int ninvalid; HGDI_RGN cinvalid; - if(xfc->hdc->hwnd->ninvalid < 1) + + if (xfc->hdc->hwnd->ninvalid < 1) return; + ninvalid = xfc->hdc->hwnd->ninvalid; cinvalid = xfc->hdc->hwnd->cinvalid; + xf_lock_x11(xfc, FALSE); - for(i = 0; i < ninvalid; i++) + + for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; - if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) + + if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) { xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); } @@ -353,20 +361,26 @@ void xf_hw_end_paint(rdpContext *context) XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, x, y, w, h, x, y); } } + XFlush(xfc->display); + xf_unlock_x11(xfc, FALSE); } } else { - if(xfc->hdc->hwnd->invalid->null) + if (xfc->hdc->hwnd->invalid->null) return; + x = xfc->hdc->hwnd->invalid->x; y = xfc->hdc->hwnd->invalid->y; w = xfc->hdc->hwnd->invalid->w; h = xfc->hdc->hwnd->invalid->h; + xf_lock_x11(xfc, FALSE); + xf_rail_paint(xfc, context->rail, x, y, x + w - 1, y + h - 1); + xf_unlock_x11(xfc, FALSE); } } @@ -377,19 +391,24 @@ void xf_hw_desktop_resize(rdpContext *context) rdpSettings *settings; xfContext *xfc = (xfContext *) context; settings = xfc->instance->settings; + xf_lock_x11(xfc, TRUE); - if(!xfc->fullscreen) + + if (!xfc->fullscreen) { xfc->width = settings->DesktopWidth; xfc->height = settings->DesktopHeight; - if(xfc->window) + + if (xfc->window) xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight); - if(xfc->primary) + + if (xfc->primary) { same = (xfc->primary == xfc->drawing) ? TRUE : FALSE; XFreePixmap(xfc->display, xfc->primary); - xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, - xfc->width, xfc->height, xfc->depth); + + xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); + if(same) xfc->drawing = xfc->primary; } @@ -401,6 +420,7 @@ void xf_hw_desktop_resize(rdpContext *context) XSetForeground(xfc->display, xfc->gc, 0); XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, xfc->width, xfc->height); } + xf_unlock_x11(xfc, TRUE); } @@ -736,8 +756,10 @@ BOOL xf_pre_connect(freerdp* instance) settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; + xfc->UseXThreads = TRUE; - if(xfc->UseXThreads) + + if (xfc->UseXThreads) { if(!XInitThreads()) { @@ -745,43 +767,53 @@ BOOL xf_pre_connect(freerdp* instance) xfc->UseXThreads = FALSE; } } + xfc->display = XOpenDisplay(NULL); - if(!xfc->display) + + if (!xfc->display) { DEBUG_WARN( "xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL)); DEBUG_WARN( "Please check that the $DISPLAY environment variable is properly set.\n"); return FALSE; } - if(xfc->debug) + + if (xfc->debug) { DEBUG_WARN( "Enabling X11 debug mode.\n"); XSynchronize(xfc->display, TRUE); _def_error_handler = XSetErrorHandler(_xf_error_handler); } + xfc->mutex = CreateMutex(NULL, FALSE, NULL); + PubSub_SubscribeChannelConnected(instance->context->pubSub, - (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler); + (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler); + (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler); + freerdp_client_load_addins(channels, instance->settings); freerdp_channels_pre_connect(channels, instance); - if(settings->AuthenticationOnly) + + if (settings->AuthenticationOnly) { /* Check --authonly has a username and password. */ - if(settings->Username == NULL) + if (!settings->Username) { DEBUG_WARN( "--authonly, but no -u username. Please provide one.\n"); return FALSE; } - if(settings->Password == NULL) + + if (!settings->Password) { DEBUG_WARN( "--authonly, but no -p password. Please provide one.\n"); return FALSE; } - DEBUG_WARN( "Authentication only. Don't connect to X.\n"); + + DEBUG_WARN("Authentication only. Don't connect to X.\n"); /* Avoid XWindows initialization and configuration below. */ return TRUE; } + xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False); xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False); xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP", False); @@ -801,21 +833,39 @@ BOOL xf_pre_connect(freerdp* instance) xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False); xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False); xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False); + xf_keyboard_init(xfc); + xfc->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA); instance->context->cache = cache_new(instance->settings); + xfc->xfds = ConnectionNumber(xfc->display); xfc->screen_number = DefaultScreen(xfc->display); xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number); xfc->depth = DefaultDepthOfScreen(xfc->screen); xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst); + xfc->invert = (ImageByteOrder(xfc->display) == MSBFirst) ? TRUE : FALSE; xfc->complex_regions = TRUE; xfc->fullscreen = settings->Fullscreen; xfc->grab_keyboard = settings->GrabKeyboard; xfc->fullscreen_toggle = settings->ToggleFullscreen; + xf_detect_monitors(xfc, settings); xfc->colormap = DefaultColormap(xfc->display, xfc->screen_number); + xfc->format = PIXEL_FORMAT_XRGB32; + + if (xfc->depth == 32) + xfc->format = (!xfc->invert) ? PIXEL_FORMAT_XRGB32 : PIXEL_FORMAT_XBGR32; + else if (xfc->depth == 24) + xfc->format = (!xfc->invert) ? PIXEL_FORMAT_XRGB32 : PIXEL_FORMAT_XBGR32; + else if (xfc->depth == 16) + xfc->format = (!xfc->invert) ? PIXEL_FORMAT_RGB565 : PIXEL_FORMAT_BGR565; + else if (xfc->depth == 15) + xfc->format = (!xfc->invert) ? PIXEL_FORMAT_RGB555 : PIXEL_FORMAT_BGR555; + else + xfc->format = PIXEL_FORMAT_XRGB32; + return TRUE; } diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 0ba5d58..2bcc0dd 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -244,7 +244,7 @@ Pixmap xf_brush_new(xfContext* xfc, int width, int height, int bpp, BYTE* data) bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, xfc->depth); - if (data != NULL) + if (data) { GC gc; @@ -347,14 +347,14 @@ void xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED); status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel, - &pDstData, PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight); + &pDstData, xfc->format, -1, 0, 0, nWidth, nHeight); } else { freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR); status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData, - PIXEL_FORMAT_XRGB32_VF, nWidth * 4, 0, 0, nWidth, nHeight); + xfc->format, -1, 0, 0, nWidth, nHeight, TRUE); } if (status < 0) @@ -365,6 +365,15 @@ void xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) pSrcData = xfc->bitmap_buffer; } + else + { + pDstData = xfc->bitmap_buffer; + + status = freerdp_image_copy(pDstData, xfc->format, -1, 0, 0, + nWidth, nHeight, pSrcData, SrcFormat, -1, 0, 0); + + pSrcData = xfc->bitmap_buffer; + } xf_lock_x11(xfc, FALSE); @@ -405,7 +414,7 @@ void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds) xf_lock_x11(xfc, FALSE); - if (bounds != NULL) + if (bounds) { clip.x = bounds->left; clip.y = bounds->top; @@ -436,7 +445,7 @@ void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XFillRectangle(xfc->display, xfc->drawable, xfc->gc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight); } @@ -530,7 +539,7 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) if (xfc->drawing == xfc->primary) { XSetFunction(xfc->display, xfc->gc, GXcopy); - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect); } @@ -555,7 +564,7 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { if (xfc->unobscured) { @@ -596,12 +605,13 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XFillRectangle(xfc->display, xfc->drawable, xfc->gc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); } + gdi_InvalidateRegion(xfc->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect, opaque_rect->nWidth, opaque_rect->nHeight); } @@ -635,7 +645,7 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XFillRectangle(xfc->display, xfc->drawable, xfc->gc, rectangle->left, rectangle->top, @@ -672,7 +682,7 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XDrawLine(xfc->display, xfc->drawable, xfc->gc, line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd); @@ -734,7 +744,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XDrawLines(xfc->display, xfc->drawable, xfc->gc, points, npoints, CoordModePrevious); } @@ -781,12 +791,13 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc, memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight, memblt->nLeftRect, memblt->nTopRect); } + gdi_InvalidateRegion(xfc->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight); } @@ -854,7 +865,7 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) if (xfc->drawing == xfc->primary) { - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc, mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight, @@ -1165,7 +1176,7 @@ 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 != TRUE) + 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); } @@ -1240,7 +1251,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) free(xfc->bmp_codec_none); xfc->bmp_codec_none = NULL; - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, cmd->destLeft, cmd->destTop, diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index c749dfb..9e24086 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -290,7 +290,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); + PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE); invalidRect.left = cmd->left; invalidRect.top = cmd->top; @@ -541,6 +541,7 @@ 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->scanline = (surface->width + (surface->width % 4)) * 4; surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); @@ -690,6 +691,7 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* RDPGFX_RECT16* rect; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; + xfContext* xfc = (xfContext*) context->custom; rect = &(surfaceToCache->rectSrc); @@ -706,6 +708,7 @@ 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->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height); diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h index 4b65025..9d0661f 100644 --- a/client/X11/xf_gfx.h +++ b/client/X11/xf_gfx.h @@ -34,6 +34,7 @@ struct xf_gfx_surface BYTE* data; XImage* image; int scanline; + UINT32 format; }; typedef struct xf_gfx_surface xfGfxSurface; @@ -45,6 +46,7 @@ struct xf_gfx_cache_entry BOOL alpha; BYTE* data; int scanline; + UINT32 format; }; typedef struct xf_gfx_cache_entry xfGfxCacheEntry; diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index a12eff4..8dafff0 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -135,14 +135,14 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_INTERLEAVED); status = interleaved_decompress(xfc->codecs->interleaved, pSrcData, SrcSize, bpp, - &pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height); + &pDstData, xfc->format, -1, 0, 0, width, height); } else { freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR); - status = planar_decompress(xfc->codecs->planar, pSrcData, SrcSize, &pDstData, - PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height); + status = planar_decompress(xfc->codecs->planar, pSrcData, SrcSize, + &pDstData, xfc->format, -1, 0, 0, width, height, TRUE); } if (status < 0) @@ -155,13 +155,13 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, { SrcFormat = gdi_get_pixel_format(bpp, TRUE); - status = freerdp_image_copy(pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, - width, height, pSrcData, SrcFormat, width * bytesPerPixel, 0, 0); + status = freerdp_image_copy(pDstData, xfc->format, -1, 0, 0, + width, height, pSrcData, SrcFormat, -1, 0, 0); } bitmap->compressed = FALSE; bitmap->length = size; - bitmap->bpp = 32; + bitmap->bpp = (xfc->depth >= 24) ? 32 : xfc->depth; } void xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 3b07e50..f538a2b 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -85,6 +85,8 @@ struct xf_context int height; int srcBpp; GC gc_mono; + BOOL invert; + UINT32 format; Screen* screen; XImage* image; Pixmap primary; diff --git a/include/freerdp/codec/planar.h b/include/freerdp/codec/planar.h index 218295c..fddcdfb 100644 --- a/include/freerdp/codec/planar.h +++ b/include/freerdp/codec/planar.h @@ -108,7 +108,7 @@ FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context); FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, - BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BOOL vFlip); #endif /* FREERDP_CODEC_PLANAR_H */ diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 0933aa4..a3c7e9b 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1770,6 +1770,181 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, return 1; } } + else if (dstBytesPerPixel == 2) + { + if (dstBitsPerPixel == 16) + { + UINT16* pSrcPixel; + UINT16* pDstPixel; + + if (!invert) + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + CopyMemory(pDstPixel, pSrcPixel, nWidth * 2); + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcStep]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstStep]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + CopyMemory(pDstPixel, pSrcPixel, nWidth * 2); + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-nSrcStep]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstStep]; + } + } + } + else + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = BGR16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = BGR16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + + return 1; + } + else if (dstBitsPerPixel == 15) + { + UINT16* pSrcPixel; + UINT16* pDstPixel; + + if (!invert) + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = RGB15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = RGB15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + else + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = BGR15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB16(r, g, b, *pSrcPixel); + *pDstPixel = BGR15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + + return 1; + } + } } else if (srcBitsPerPixel == 15) { @@ -1868,6 +2043,197 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, } } } + else if (dstBytesPerPixel == 2) + { + if (dstBitsPerPixel == 16) + { + UINT16* pSrcPixel; + UINT16* pDstPixel; + + if (!invert) + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = RGB16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = RGB16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + else + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = BGR16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = BGR16(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + + return 1; + } + else if (dstBitsPerPixel == 15) + { + UINT16* pSrcPixel; + UINT16* pDstPixel; + + if (!invert) + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = RGB15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = RGB15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + else + { + if (!vFlip) + { + pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = BGR15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + else + { + pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)]; + pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)]; + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + GetRGB15(r, g, b, *pSrcPixel); + *pDstPixel = BGR15(r, g, b); + + pSrcPixel++; + pDstPixel++; + } + + pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)]; + pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad]; + } + } + } + + return 1; + } + } } } else if (srcBytesPerPixel == 1) @@ -1875,6 +2241,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, } + fprintf(stderr, "freerdp_image_copy failure: src: %d/%d dst: %d/%d\n", + srcBitsPerPixel, srcBytesPerPixel, dstBitsPerPixel, dstBytesPerPixel); + return -1; } diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 5f8187b..da662f9 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -275,7 +275,7 @@ static int planar_decompress_planes_raw(const BYTE* pSrcData[4], int nSrcStep, B } int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, - BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BOOL vFlip) { BOOL cs; BOOL rle; @@ -283,7 +283,6 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS BOOL alpha; int status; BYTE* srcp; - BOOL vFlip; int subSize; int subWidth; int subHeight; @@ -301,8 +300,6 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS if ((nWidth * nHeight) <= 0) return -1; - vFlip = FREERDP_PIXEL_FORMAT_FLIP(DstFormat) ? TRUE : FALSE; - srcp = pSrcData; UncompressedSize = nWidth * nHeight * 4; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c index a0be4bb..b234af3 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c @@ -3110,7 +3110,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) pDstData = decompressedBitmap; if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0) + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE) < 0) { printf("failed to decompress white bitmap: width: %d height: %d\n", width, height); return -1; @@ -3148,7 +3148,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) pDstData = decompressedBitmap; if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0) + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE) < 0) { printf("failed to decompress black bitmap: width: %d height: %d\n", width, height); return -1; @@ -3185,7 +3185,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) pDstData = decompressedBitmap; if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0) + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE) < 0) { printf("failed to decompress experimental bitmap 01: width: %d height: %d\n", width, height); return -1; @@ -3223,7 +3223,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) pDstData = decompressedBitmap; if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0) + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE) < 0) { printf("failed to decompress experimental bitmap 02: width: %d height: %d\n", width, height); return -1; @@ -3268,7 +3268,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[]) pDstData = decompressedBitmap; if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData, - PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0) + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE) < 0) { printf("failed to decompress experimental bitmap 03: width: %d height: %d\n", width, height); return -1; diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 41263f9..ee24968 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -554,7 +554,7 @@ void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR); status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData, - gdi->format, nWidth * 4, 0, 0, nWidth, nHeight); + gdi->format, nWidth * 4, 0, 0, nWidth, nHeight, TRUE); } if (status < 0) diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 8694b62..fc7cd41 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -294,7 +294,7 @@ int gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_ DstData = surface->data; status = planar_decompress(gdi->codecs->planar, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); + PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, FALSE); invalidRect.left = cmd->left; invalidRect.top = cmd->top; diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 8f1ddbc..454b2a5 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -183,7 +183,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR); status = planar_decompress(gdi->codecs->planar, pSrcData, SrcSize, &pDstData, - PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height); + PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, FALSE); } if (status < 0) -- 2.7.4