From 94c6473250bea85f8c392d806394bee6c8efaa43 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 10 Oct 2016 11:09:06 +0200 Subject: [PATCH 1/4] Inlined heavily used functions. --- include/freerdp/gdi/gdi.h | 2 - libfreerdp/gdi/bitmap.c | 1 + libfreerdp/gdi/brush.c | 6 -- libfreerdp/gdi/brush.h | 9 ++- libfreerdp/gdi/gdi.c | 59 ------------------- libfreerdp/gdi/gdi.h | 60 +++++++++++++++++++ libfreerdp/gdi/shape.c | 117 ++++++++++++++++++++------------------ 7 files changed, 132 insertions(+), 122 deletions(-) diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index a674777f9..5562bce0c 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -532,8 +532,6 @@ FREERDP_API DWORD gdi_rop3_code(BYTE code); FREERDP_API UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel, BOOL vFlip); FREERDP_API BOOL gdi_decode_color(rdpGdi* gdi, const UINT32 srcColor, UINT32* color, UINT32* format); -FREERDP_API BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, UINT32 x, UINT32 y); -FREERDP_API BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, UINT32 x, UINT32 y); FREERDP_API BOOL gdi_resize(rdpGdi* gdi, UINT32 width, UINT32 height); FREERDP_API BOOL gdi_resize_ex(rdpGdi* gdi, UINT32 width, UINT32 height, UINT32 stride, UINT32 format, BYTE* buffer, diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index db284e2c3..6028da9db 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -39,6 +39,7 @@ #include "brush.h" #include "clipping.h" +#include "../gdi/gdi.h" #define TAG FREERDP_TAG("gdi.bitmap") diff --git a/libfreerdp/gdi/brush.c b/libfreerdp/gdi/brush.c index 9118aad0b..db904954b 100644 --- a/libfreerdp/gdi/brush.c +++ b/libfreerdp/gdi/brush.c @@ -866,10 +866,4 @@ HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp) hBrush->pattern = hbmp; return hBrush; } -UINT32 gdi_GetBrushStyle(HGDI_DC hdc) -{ - if (!hdc || !hdc->brush) - return GDI_BS_NULL; - return hdc->brush->style; -} diff --git a/libfreerdp/gdi/brush.h b/libfreerdp/gdi/brush.h index 4966aa24f..a9dd30fde 100644 --- a/libfreerdp/gdi/brush.h +++ b/libfreerdp/gdi/brush.h @@ -34,7 +34,14 @@ FREERDP_LOCAL const char* gdi_rop_to_string(UINT32 code); FREERDP_LOCAL HGDI_BRUSH gdi_CreateSolidBrush(UINT32 crColor); FREERDP_LOCAL HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp); FREERDP_LOCAL HGDI_BRUSH gdi_CreateHatchBrush(HGDI_BITMAP hbmp); -FREERDP_LOCAL UINT32 gdi_GetBrushStyle(HGDI_DC hdc); + +static INLINE UINT32 gdi_GetBrushStyle(HGDI_DC hdc) +{ + if (!hdc || !hdc->brush) + return GDI_BS_NULL; + + return hdc->brush->style; +} #ifdef __cplusplus } diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 719a16067..4f093662b 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -369,65 +369,6 @@ UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel, BOOL vFlip) return format; } -BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, UINT32 x, UINT32 y) -{ - BYTE* p; - HGDI_BITMAP hBmp = (HGDI_BITMAP) hdcBmp->selectedObject; - - if (x < hBmp->width && y < hBmp->height) - { - p = hBmp->data + (y * hBmp->scanline) + (x * GetBytesPerPixel(hdcBmp->format)); - return p; - } - else - { - WLog_ERR(TAG, - "gdi_get_bitmap_pointer: requesting invalid pointer: (%d,%d) in %dx%d", - x, y, hBmp->width, hBmp->height); - return 0; - } -} - -/** - * Get current color in brush bitmap according to dest coordinates.\n - * @msdn{dd183396} - * @param x dest x-coordinate - * @param y dest y-coordinate - * @return color - */ -BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, UINT32 x, UINT32 y) -{ - BYTE* p; - UINT32 brushStyle = gdi_GetBrushStyle(hdcBrush); - - switch (brushStyle) - { - case GDI_BS_PATTERN: - case GDI_BS_HATCHED: - { - HGDI_BITMAP hBmpBrush = hdcBrush->brush->pattern; - /* According to @msdn{dd183396}, the system always positions a brush bitmap - * at the brush origin and copy across the client area. - * Calculate the offset of the mapped pixel in the brush bitmap according to - * brush origin and dest coordinates */ - x = (x + hBmpBrush->width - (hdcBrush->brush->nXOrg % hBmpBrush->width)) % - hBmpBrush->width; - y = (y + hBmpBrush->height - (hdcBrush->brush->nYOrg % hBmpBrush->height)) % - hBmpBrush->height; - p = hBmpBrush->data + (y * hBmpBrush->scanline) + (x * GetBytesPerPixel( - hBmpBrush->format)); - return p; - } - break; - - default: - break; - } - - p = (BYTE*) & (hdcBrush->textColor); - return p; -} - gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, BYTE* data) { diff --git a/libfreerdp/gdi/gdi.h b/libfreerdp/gdi/gdi.h index 71ef7af87..329d8e95e 100644 --- a/libfreerdp/gdi/gdi.h +++ b/libfreerdp/gdi/gdi.h @@ -21,6 +21,7 @@ #define __GDI_CORE_H #include "graphics.h" +#include "brush.h" #include @@ -32,4 +33,63 @@ FREERDP_LOCAL gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, BYTE* data); FREERDP_LOCAL void gdi_bitmap_free_ex(gdiBitmap* gdi_bmp); +static INLINE BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, UINT32 x, UINT32 y) +{ + BYTE* p; + HGDI_BITMAP hBmp = (HGDI_BITMAP) hdcBmp->selectedObject; + + if (x < hBmp->width && y < hBmp->height) + { + p = hBmp->data + (y * hBmp->scanline) + (x * GetBytesPerPixel(hdcBmp->format)); + return p; + } + else + { + WLog_ERR(FREERDP_TAG("gdi"), + "gdi_get_bitmap_pointer: requesting invalid pointer: (%d,%d) in %dx%d", + x, y, hBmp->width, hBmp->height); + return 0; + } +} + +/** + * Get current color in brush bitmap according to dest coordinates.\n + * @msdn{dd183396} + * @param x dest x-coordinate + * @param y dest y-coordinate + * @return color + */ +static INLINE BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, UINT32 x, UINT32 y) +{ + BYTE* p; + UINT32 brushStyle = gdi_GetBrushStyle(hdcBrush); + + switch (brushStyle) + { + case GDI_BS_PATTERN: + case GDI_BS_HATCHED: + { + HGDI_BITMAP hBmpBrush = hdcBrush->brush->pattern; + /* According to @msdn{dd183396}, the system always positions a brush bitmap + * at the brush origin and copy across the client area. + * Calculate the offset of the mapped pixel in the brush bitmap according to + * brush origin and dest coordinates */ + x = (x + hBmpBrush->width - (hdcBrush->brush->nXOrg % hBmpBrush->width)) % + hBmpBrush->width; + y = (y + hBmpBrush->height - (hdcBrush->brush->nYOrg % hBmpBrush->height)) % + hBmpBrush->height; + p = hBmpBrush->data + (y * hBmpBrush->scanline) + (x * GetBytesPerPixel( + hBmpBrush->format)); + return p; + } + break; + + default: + break; + } + + p = (BYTE*) & (hdcBrush->textColor); + return p; +} + #endif /* __GDI_CORE_H */ diff --git a/libfreerdp/gdi/shape.c b/libfreerdp/gdi/shape.c index b81c89d2c..050e4a325 100644 --- a/libfreerdp/gdi/shape.c +++ b/libfreerdp/gdi/shape.c @@ -37,6 +37,7 @@ #include #include "clipping.h" +#include "../gdi/gdi.h" #define TAG FREERDP_TAG("gdi.shape") @@ -108,7 +109,7 @@ static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2) * @return nonzero if successful, 0 otherwise */ BOOL gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, - int nBottomRect) + int nBottomRect) { Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); return TRUE; @@ -138,60 +139,68 @@ BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr) if (!gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL)) return TRUE; - switch(hbr->style) + switch (hbr->style) { - case GDI_BS_SOLID: - color = hbr->color; + case GDI_BS_SOLID: + color = hbr->color; - for (y = 0; y < nHeight; y++) - { - for (x = 0; x < nWidth; x++) - { - BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, - nYDest + y); - - if (dstp) - WriteColor(dstp, hdc->format, color); - } - } - - break; - case GDI_BS_HATCHED: - case GDI_BS_PATTERN: - monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO); - for (y = 0; y < nHeight; y++) - { - for (x = 0; x < nWidth; x++) + for (y = 0; y < nHeight; y++) { - const UINT32 yOffset = ((nYDest + y) * hbr->pattern->width % hbr->pattern->height) * GetBytesPerPixel(hbr->pattern->format); - const UINT32 xOffset = ((nXDest + x) % hbr->pattern->width) * GetBytesPerPixel(hbr->pattern->format); - const BYTE* patp = &hbr->pattern->data[yOffset + xOffset]; - BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, - nYDest + y); - - if (!patp) - return FALSE; - if (monochrome) + for (x = 0; x < nWidth; x++) { - if (*patp == 0) - dstColor = hdc->bkColor; - else - dstColor = hdc->textColor; - } - else - { - dstColor = ReadColor(patp, hbr->pattern->format); - dstColor = ConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL); - } + BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, + nYDest + y); - if (dstp) - WriteColor(dstp, hdc->format, dstColor); + if (dstp) + WriteColor(dstp, hdc->format, color); + } } - } - break; - default: - break; + + break; + + case GDI_BS_HATCHED: + case GDI_BS_PATTERN: + monochrome = (hbr->pattern->format == PIXEL_FORMAT_MONO); + + for (y = 0; y < nHeight; y++) + { + for (x = 0; x < nWidth; x++) + { + const UINT32 yOffset = ((nYDest + y) * hbr->pattern->width % + hbr->pattern->height) * GetBytesPerPixel(hbr->pattern->format); + const UINT32 xOffset = ((nXDest + x) % hbr->pattern->width) * GetBytesPerPixel( + hbr->pattern->format); + const BYTE* patp = &hbr->pattern->data[yOffset + xOffset]; + BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, + nYDest + y); + + if (!patp) + return FALSE; + + if (monochrome) + { + if (*patp == 0) + dstColor = hdc->bkColor; + else + dstColor = hdc->textColor; + } + else + { + dstColor = ReadColor(patp, hbr->pattern->format); + dstColor = ConvertColor(dstColor, hbr->pattern->format, hdc->format, NULL); + } + + if (dstp) + WriteColor(dstp, hdc->format, dstColor); + } + } + + break; + + default: + break; } + if (!gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight)) return FALSE; @@ -223,14 +232,14 @@ BOOL gdi_Polygon(HGDI_DC hdc, GDI_POINT* lpPoints, int nCount) * @return nonzero if successful, 0 otherwise */ BOOL gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT* lpPoints, int* lpPolyCounts, - int nCount) + int nCount) { WLog_ERR(TAG, "Not implemented!"); return FALSE; } BOOL gdi_Rectangle(HGDI_DC hdc, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, - UINT32 nHeight) + UINT32 nHeight) { UINT32 x, y; UINT32 color; @@ -244,9 +253,9 @@ BOOL gdi_Rectangle(HGDI_DC hdc, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, for (y = 0; y < nHeight; y++) { BYTE* dstLeft = gdi_get_bitmap_pointer(hdc, nXDst, - nYDst + y); + nYDst + y); BYTE* dstRight = gdi_get_bitmap_pointer(hdc, nXDst + nWidth - 1, - nYDst + y); + nYDst + y); if (dstLeft) WriteColor(dstLeft, hdc->format, color); @@ -258,9 +267,9 @@ BOOL gdi_Rectangle(HGDI_DC hdc, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, for (x = 0; x < nWidth; x++) { BYTE* dstTop = gdi_get_bitmap_pointer(hdc, nXDst + x, - nYDst); + nYDst); BYTE* dstBottom = gdi_get_bitmap_pointer(hdc, nXDst + x, - nYDst + nHeight - 1); + nYDst + nHeight - 1); if (dstTop) WriteColor(dstTop, hdc->format, color); From c405e1515ea9c371809ed1f1e9138d8ba0f57dbb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 10 Oct 2016 11:25:47 +0200 Subject: [PATCH 2/4] Inlined heavily used function. --- libfreerdp/gdi/bitmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 6028da9db..6f0d3787b 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -273,10 +273,10 @@ static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, const char* rop, return stack[0]; } -static BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest, - UINT32 nYDest, UINT32 nXSrc, UINT32 nYSrc, UINT32 x, UINT32 y, - BOOL useSrc, BOOL usePat, UINT32 style, - const char* rop, const gdiPalette* palette) +static INLINE BOOL BitBlt_write(HGDI_DC hdcDest, HGDI_DC hdcSrc, UINT32 nXDest, + UINT32 nYDest, UINT32 nXSrc, UINT32 nYSrc, UINT32 x, UINT32 y, + BOOL useSrc, BOOL usePat, UINT32 style, + const char* rop, const gdiPalette* palette) { UINT32 dstColor; UINT32 colorA; From c2787d7c5fc115c7b44caacc085f66284a4f677f Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 11 Oct 2016 12:14:52 +0200 Subject: [PATCH 3/4] Optimized gdi_FillRect --- libfreerdp/gdi/shape.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libfreerdp/gdi/shape.c b/libfreerdp/gdi/shape.c index 050e4a325..9fde0ec4c 100644 --- a/libfreerdp/gdi/shape.c +++ b/libfreerdp/gdi/shape.c @@ -131,6 +131,7 @@ BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr) BOOL monochrome = FALSE; UINT32 nXDest, nYDest; UINT32 nWidth, nHeight; + const BYTE* srcp; gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight); if (!hdc || !hbr) @@ -144,16 +145,21 @@ BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr) case GDI_BS_SOLID: color = hbr->color; - for (y = 0; y < nHeight; y++) + for (x = 0; x < nWidth; x++) { - for (x = 0; x < nWidth; x++) - { - BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, - nYDest + y); + BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest + x, + nYDest); - if (dstp) - WriteColor(dstp, hdc->format, color); - } + if (dstp) + WriteColor(dstp, hdc->format, color); + } + + srcp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest); + + for (y = 1; y < nHeight; y++) + { + BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); + memcpy(dstp, srcp, nWidth * GetBytesPerPixel(hdc->format)); } break; From c3058ba580dda44e2b3ec10c7c37a343cb6007da Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 11 Oct 2016 13:10:54 +0200 Subject: [PATCH 4/4] Optimized ROP for GDI_SRCCOPY and GDI_DSTCOPY. --- libfreerdp/gdi/bitmap.c | 44 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 6f0d3787b..0eaa9b8c2 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -462,6 +462,8 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc, UINT32 nXSrc, UINT32 nYSrc, DWORD rop, const gdiPalette* palette) { + HGDI_BITMAP hSrcBmp, hDstBmp; + if (!hdcDest) return FALSE; @@ -469,10 +471,44 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, &nYSrc)) return TRUE; - if (!BitBlt_process(hdcDest, nXDest, nYDest, - nWidth, nHeight, hdcSrc, - nXSrc, nYSrc, gdi_rop_to_string(rop), palette)) - return FALSE; + /* Check which ROP should be performed. + * Some specific ROP are used heavily and are resource intensive, + * add optimized versions for these here. + * + * For all others fall back to the generic implementation. + */ + switch (rop) + { + case GDI_SRCCOPY: + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; + hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; + + if (!freerdp_image_copy(hDstBmp->data, hdcDest->format, hDstBmp->scanline, + nXDest, nYDest, nWidth, nHeight, + hSrcBmp->data, hdcSrc->format, hSrcBmp->scanline, nXSrc, nYSrc, palette)) + return FALSE; + + break; + + case GDI_DSTCOPY: + hSrcBmp = (HGDI_BITMAP) hdcDest->selectedObject; + hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; + + if (!freerdp_image_copy(hDstBmp->data, hdcDest->format, hDstBmp->scanline, + nXDest, nYDest, nWidth, nHeight, + hSrcBmp->data, hdcSrc->format, hSrcBmp->scanline, nXSrc, nYSrc, palette)) + return FALSE; + + break; + + default: + if (!BitBlt_process(hdcDest, nXDest, nYDest, + nWidth, nHeight, hdcSrc, + nXSrc, nYSrc, gdi_rop_to_string(rop), palette)) + return FALSE; + + break; + } if (!gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight)) return FALSE;