wfreerdp: fix gdi usage
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 12 Sep 2014 15:34:30 +0000 (11:34 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Fri, 12 Sep 2014 15:34:30 +0000 (11:34 -0400)
client/Windows/cli/wfreerdp.c
client/Windows/wf_gdi.c
client/Windows/wf_gdi.h
client/Windows/wf_graphics.c
client/Windows/wf_graphics.h
client/Windows/wf_interface.c
client/Windows/wf_interface.h

index c5f5fa0..a661ce7 100644 (file)
@@ -63,6 +63,8 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
        settings = context->settings;
        wfc = (wfContext*) context;
 
+       settings->SoftwareGdi = TRUE;
+
        context->argc = __argc;
        context->argv = (char**) malloc(sizeof(char*) * __argc);
 
index d02c369..e41b59a 100644 (file)
@@ -339,6 +339,106 @@ void wf_toggle_fullscreen(wfContext* wfc)
        }
 }
 
+void wf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
+{
+       HDC hdc;
+       int status;
+       int nXDst;
+       int nYDst;
+       int nXSrc;
+       int nYSrc;
+       int nWidth;
+       int nHeight;
+       HBITMAP dib;
+       UINT32 index;
+       BYTE* pSrcData;
+       BYTE* pDstData;
+       UINT32 SrcSize;
+       BOOL compressed;
+       UINT32 SrcFormat;
+       UINT32 bitsPerPixel;
+       UINT32 bytesPerPixel;
+       BITMAP_DATA* bitmap;
+       rdpCodecs* codecs = context->codecs;
+       wfContext* wfc = (wfContext*) context;
+
+       hdc = CreateCompatibleDC(GetDC(NULL));
+
+       for (index = 0; index < bitmapUpdate->number; index++)
+       {
+               bitmap = &(bitmapUpdate->rectangles[index]);
+
+               nXSrc = 0;
+               nYSrc = 0;
+
+               nXDst = bitmap->destLeft;
+               nYDst = bitmap->destTop;
+
+               nWidth = bitmap->width;
+               nHeight = bitmap->height;
+
+               pSrcData = bitmap->bitmapDataStream;
+               SrcSize = bitmap->bitmapLength;
+
+               compressed = bitmap->compressed;
+               bitsPerPixel = bitmap->bitsPerPixel;
+               bytesPerPixel = (bitsPerPixel + 7) / 8;
+
+               SrcFormat = gdi_get_pixel_format(bitsPerPixel, TRUE);
+
+               if (wfc->bitmap_size < (nWidth * nHeight * 4))
+               {
+                       wfc->bitmap_size = nWidth * nHeight * 4;
+                       wfc->bitmap_buffer = (BYTE*) _aligned_realloc(wfc->bitmap_buffer, wfc->bitmap_size, 16);
+
+                       if (!wfc->bitmap_buffer)
+                               return;
+               }
+
+               if (compressed)
+               {
+                       pDstData = wfc->bitmap_buffer;
+
+                       if (bitsPerPixel < 32)
+                       {
+                               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);
+                       }
+                       else
+                       {
+                               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);
+                       }
+
+                       if (status < 0)
+                       {
+                               DEBUG_WARN("wf_gdi_bitmap_update: bitmap decompression failure\n");
+                               return;
+                       }
+
+                       pSrcData = wfc->bitmap_buffer;
+               }
+
+               dib = wf_create_dib(wfc, nWidth, nHeight, 32, pSrcData, NULL);
+               SelectObject(hdc, dib);
+
+               nWidth = bitmap->destRight - bitmap->destLeft + 1; /* clip width */
+               nHeight = bitmap->destBottom - bitmap->destTop + 1; /* clip height */
+
+               BitBlt(wfc->primary->hdc, nXDst, nYDst, nWidth, nHeight, hdc, 0, 0, SRCCOPY);
+
+               gdi_InvalidateRegion(wfc->hdc, nXDst, nYDst, nWidth, nHeight);
+
+               DeleteObject(dib);
+       }
+
+       ReleaseDC(NULL, hdc);
+}
+
 void wf_gdi_palette_update(wfContext* wfc, PALETTE_UPDATE* palette)
 {
 
@@ -453,12 +553,12 @@ void wf_gdi_multi_opaque_rect(wfContext* wfc, MULTI_OPAQUE_RECT_ORDER* multi_opa
        UINT32 brush_color;
        DELTA_RECT* rectangle;
 
+       brush_color = freerdp_color_convert_var_rgb(multi_opaque_rect->color, wfc->srcBpp, wfc->dstBpp, wfc->clrconv);
+
        for (i = 1; i < (int) multi_opaque_rect->numRectangles + 1; i++)
        {
                rectangle = &multi_opaque_rect->rectangles[i];
 
-               brush_color = freerdp_color_convert_var_bgr(multi_opaque_rect->color, wfc->srcBpp, wfc->dstBpp, wfc->clrconv);
-
                rect.left = rectangle->left;
                rect.top = rectangle->top;
                rect.right = rectangle->left + rectangle->width;
index b7ab1cf..bc966f0 100644 (file)
@@ -31,6 +31,7 @@ void wf_update_offset(wfContext* wfc);
 void wf_resize_window(wfContext* wfc);
 void wf_toggle_fullscreen(wfContext* wfc);
 
+void wf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate);
 void wf_gdi_register_update_callbacks(rdpUpdate* update);
 
 void wf_update_canvas_diff(wfContext* wfc);
index 67a44d0..2ca2b24 100644 (file)
@@ -146,55 +146,58 @@ void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap,
 {
        int status;
        UINT16 size;
+       BYTE* pSrcData;
+       BYTE* pDstData;
+       UINT32 SrcSize;
+       UINT32 SrcFormat;
+       UINT32 bytesPerPixel;
 
-       size = width * height * (bpp / 8);
+       bytesPerPixel = (bpp + 7) / 8;
+       size = width * height * 4;
 
        if (!bitmap->data)
                bitmap->data = (BYTE*) _aligned_malloc(size, 16);
        else
                bitmap->data = (BYTE*) _aligned_realloc(bitmap->data, size, 16);
 
+       pSrcData = data;
+       SrcSize = (UINT32) length;
+       pDstData = bitmap->data;
+
        if (compressed)
        {
-               BYTE* pDstData;
-               UINT32 SrcSize;
-
-               SrcSize = (UINT32) length;
-               pDstData = bitmap->data;
-
                if (bpp < 32)
                {
                        freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_INTERLEAVED);
 
-                       status = interleaved_decompress(wfc->codecs->interleaved, data, SrcSize, bpp,
-                                       &pDstData, PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
-
-                       if (status < 0)
-                       {
-                               DEBUG_WARN("wf_Bitmap_Decompress: Bitmap Decompression Failed\n");
-                       }
+                       status = interleaved_decompress(wfc->codecs->interleaved, pSrcData, SrcSize, bpp,
+                                       &pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height);
                }
                else
                {
                        freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR);
 
-                       status = planar_decompress(wfc->codecs->planar, data, SrcSize, &pDstData,
+                       status = planar_decompress(wfc->codecs->planar, pSrcData, SrcSize, &pDstData,
                                        PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
+               }
 
-                       if (status < 0)
-                       {
-                               DEBUG_WARN("wf_Bitmap_Decompress: Bitmap Decompression Failed\n");
-                       }
+               if (status < 0)
+               {
+                       DEBUG_WARN("wf_Bitmap_Decompress: Bitmap Decompression Failed\n");
+                       return;
                }
        }
        else
        {
-               freerdp_image_flip(data, bitmap->data, width, height, bpp);
+               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);
        }
 
        bitmap->compressed = FALSE;
        bitmap->length = size;
-       bitmap->bpp = bpp;
+       bitmap->bpp = 32;
 }
 
 void wf_Bitmap_SetSurface(wfContext* wfc, rdpBitmap* bitmap, BOOL primary)
@@ -277,30 +280,13 @@ void wf_Pointer_SetDefault(wfContext* wfc)
 
 }
 
-/* Graphics Module */
-
-void wf_register_graphics(rdpGraphics* graphics)
+void wf_register_pointer(rdpGraphics* graphics)
 {
        wfContext* wfc;
        rdpPointer pointer;
 
        wfc = (wfContext*) graphics->context;
 
-       if (wfc->sw_gdi == FALSE)
-       {
-               rdpBitmap bitmap;
-
-               ZeroMemory(&bitmap, sizeof(rdpBitmap));
-               bitmap.size = sizeof(wfBitmap);
-               bitmap.New = (pBitmap_New) wf_Bitmap_New;
-               bitmap.Free = (pBitmap_Free) wf_Bitmap_Free;
-               bitmap.Paint = (pBitmap_Paint) wf_Bitmap_Paint;
-               bitmap.Decompress = (pBitmap_Decompress) wf_Bitmap_Decompress;
-               bitmap.SetSurface = (pBitmap_SetSurface) wf_Bitmap_SetSurface;
-
-               graphics_register_bitmap(graphics, &bitmap);
-       }
-
        ZeroMemory(&pointer, sizeof(rdpPointer));
        pointer.size = sizeof(wfPointer);
        pointer.New = (pPointer_New) wf_Pointer_New;
@@ -311,3 +297,23 @@ void wf_register_graphics(rdpGraphics* graphics)
 
        graphics_register_pointer(graphics, &pointer);
 }
+
+/* Graphics Module */
+
+void wf_register_graphics(rdpGraphics* graphics)
+{
+       wfContext* wfc;
+       rdpBitmap bitmap;
+
+       wfc = (wfContext*) graphics->context;
+
+       ZeroMemory(&bitmap, sizeof(rdpBitmap));
+       bitmap.size = sizeof(wfBitmap);
+       bitmap.New = (pBitmap_New) wf_Bitmap_New;
+       bitmap.Free = (pBitmap_Free) wf_Bitmap_Free;
+       bitmap.Paint = (pBitmap_Paint) wf_Bitmap_Paint;
+       bitmap.Decompress = (pBitmap_Decompress) wf_Bitmap_Decompress;
+       bitmap.SetSurface = (pBitmap_SetSurface) wf_Bitmap_SetSurface;
+
+       graphics_register_bitmap(graphics, &bitmap);
+}
index a27c6a6..cfc2a96 100644 (file)
@@ -26,6 +26,7 @@ HBITMAP wf_create_dib(wfContext* wfc, int width, int height, int bpp, BYTE* data
 wfBitmap* wf_image_new(wfContext* wfc, int width, int height, int bpp, BYTE* data);
 void wf_image_free(wfBitmap* image);
 
+void wf_register_pointer(rdpGraphics* graphics);
 void wf_register_graphics(rdpGraphics* graphics);
 
 #endif /* WF_GRAPHICS */
index 1b5caeb..1d11ebd 100644 (file)
 #include <assert.h>
 #include <sys/types.h>
 
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-
 #include <freerdp/freerdp.h>
 #include <freerdp/constants.h>
 #include <freerdp/utils/event.h>
@@ -104,8 +100,8 @@ void wf_sw_end_paint(wfContext* wfc)
 
                update_rect.left = x;
                update_rect.top = y;
-               update_rect.right = x + w - 1;
-               update_rect.bottom = y + h - 1;
+               update_rect.right = x + w;
+               update_rect.bottom = y + h;
 
                InvalidateRect(wfc->hwnd, &update_rect, FALSE);
        }
@@ -237,9 +233,9 @@ BOOL wf_pre_connect(freerdp* instance)
        settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE;
 
        wfc->fullscreen = settings->Fullscreen;
+
        if (wfc->fullscreen)
                wfc->fs_toggle = 1;
-       wfc->sw_gdi = settings->SoftwareGdi;
 
        wfc->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV));
        ZeroMemory(wfc->clrconv, sizeof(CLRCONV));
@@ -345,7 +341,7 @@ BOOL wf_post_connect(freerdp* instance)
        wfc->width = settings->DesktopWidth;
        wfc->height = settings->DesktopHeight;
 
-       if (wfc->sw_gdi)
+       if (settings->SoftwareGdi)
        {
                wfc->primary = wf_image_new(wfc, wfc->width, wfc->height, wfc->dstBpp, NULL);
 
@@ -421,7 +417,7 @@ BOOL wf_post_connect(freerdp* instance)
        ShowWindow(wfc->hwnd, SW_SHOWNORMAL);
        UpdateWindow(wfc->hwnd);
 
-       if (wfc->sw_gdi)
+       if (settings->SoftwareGdi)
        {                                                                                       
                instance->update->BeginPaint = (pBeginPaint) wf_sw_begin_paint;
                instance->update->EndPaint = (pEndPaint) wf_sw_end_paint;
@@ -435,19 +431,21 @@ BOOL wf_post_connect(freerdp* instance)
        }
 
        pointer_cache_register_callbacks(instance->update);
+       wf_register_pointer(context->graphics);
 
-       if (wfc->sw_gdi != TRUE)
+       if (!settings->SoftwareGdi)
        {
                brush_cache_register_callbacks(instance->update);
                bitmap_cache_register_callbacks(instance->update);
                offscreen_cache_register_callbacks(instance->update);
+               wf_register_graphics(context->graphics);
+               instance->update->BitmapUpdate = wf_gdi_bitmap_update;
        }
 
-       wf_register_graphics(instance->context->graphics);
+       freerdp_channels_post_connect(context->channels, instance);
 
-       freerdp_channels_post_connect(instance->context->channels, instance);
+       wf_cliprdr_init(wfc, context->channels);
 
-       wf_cliprdr_init(wfc, instance->context->channels);
        if (wfc->fullscreen)
                floatbar_window_create(wfc);
 
@@ -1142,9 +1140,13 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
 
 void wfreerdp_client_free(freerdp* instance, rdpContext* context)
 {
+       wfContext* wfc = (wfContext*) context;
+
        if (context->cache)
                cache_free(context->cache);
 
+       _aligned_free(wfc->bitmap_buffer);
+
        freerdp_channels_free(context->channels);
 }
 
index feb0846..05e56a0 100644 (file)
@@ -82,6 +82,8 @@ struct wf_context
        int client_y;
        int client_width;
        int client_height;
+       UINT32 bitmap_size;
+       BYTE* bitmap_buffer;
 
        HANDLE keyboardThread;
 
@@ -112,7 +114,7 @@ struct wf_context
        DWORD mainThreadId;
        DWORD keyboardThreadId;
 
-       BOOL sw_gdi;
+       //BOOL sw_gdi;
 
        rdpFile* connectionRdpFile;