diff --git a/include/freerdp/gdi/bitmap.h b/include/freerdp/gdi/bitmap.h index 42caf0b13..d1165e0e6 100644 --- a/include/freerdp/gdi/bitmap.h +++ b/include/freerdp/gdi/bitmap.h @@ -38,7 +38,10 @@ FREERDP_API UINT32* gdi_GetPointer_32bpp(HGDI_BITMAP hBmp, int X, int Y); FREERDP_API void gdi_SetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y, BYTE pixel); FREERDP_API void gdi_SetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y, UINT16 pixel); FREERDP_API void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, UINT32 pixel); -FREERDP_API HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, BYTE* data); +FREERDP_API HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, + BYTE* data); +FREERDP_API HGDI_BITMAP gdi_CreateBitmapEx(int nWidth, int nHeight, int cBitsPerPixel, + BYTE* data, void (*fkt_free)(void*)); FREERDP_API HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight); FREERDP_API BOOL gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, DWORD rop); diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index 9736ba724..804fb802e 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -178,6 +178,7 @@ struct _GDI_BITMAP int height; int scanline; BYTE* data; + void (*free)(void *); }; typedef struct _GDI_BITMAP GDI_BITMAP; typedef GDI_BITMAP* HGDI_BITMAP; diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index cc3ee84ed..03486d8f6 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -130,10 +130,17 @@ INLINE void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, UINT32 pixel) * @param nHeight height * @param cBitsPerPixel bits per pixel * @param data pixel buffer + * @param fkt_free The function used for deallocation of the buffer, NULL for none. * @return new bitmap */ HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, BYTE* data) +{ + return gdi_CreateBitmapEx(nWidth, nHeight, cBitsPerPixel, data, _aligned_free); +} + +HGDI_BITMAP gdi_CreateBitmapEx(int nWidth, int nHeight, int cBitsPerPixel, BYTE* data, + void (*fkt_free)(void*)) { HGDI_BITMAP hBitmap = (HGDI_BITMAP) calloc(1, sizeof(GDI_BITMAP)); @@ -147,6 +154,7 @@ HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, BYTE* d hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = data; + hBitmap->free = fkt_free; return hBitmap; } @@ -162,7 +170,7 @@ HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, BYTE* d HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight) { - HGDI_BITMAP hBitmap = (HGDI_BITMAP) malloc(sizeof(GDI_BITMAP)); + HGDI_BITMAP hBitmap = (HGDI_BITMAP) calloc(1, sizeof(GDI_BITMAP)); if (!hBitmap) return NULL; @@ -173,6 +181,7 @@ HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight) hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = _aligned_malloc(nWidth * nHeight * hBitmap->bytesPerPixel, 16); + hBitmap->free = _aligned_free; if (!hBitmap->data) { free(hBitmap); diff --git a/libfreerdp/gdi/dc.c b/libfreerdp/gdi/dc.c index b816a77b5..f1032bef8 100644 --- a/libfreerdp/gdi/dc.c +++ b/libfreerdp/gdi/dc.c @@ -201,8 +201,11 @@ BOOL gdi_DeleteObject(HGDIOBJECT hgdiobject) { HGDI_BITMAP hBitmap = (HGDI_BITMAP) hgdiobject; - if (hBitmap->data) - _aligned_free(hBitmap->data); + if (hBitmap->data && hBitmap->free) + { + hBitmap->free(hBitmap->data); + hBitmap->data = NULL; + } free(hBitmap); } diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index fd7236dc7..eb6c3d727 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -399,7 +399,7 @@ gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, BYTE* { gdiBitmap* bitmap; - bitmap = (gdiBitmap*) malloc(sizeof(gdiBitmap)); + bitmap = (gdiBitmap*) calloc(1, sizeof(gdiBitmap)); if (!bitmap) goto fail_bitmap; @@ -1107,11 +1107,9 @@ static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) freerdp_image_copy(pDstData, gdi->format, -1, 0, 0, cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0, gdi->palette); - gdi->image->bitmap->width = cmd->width; - gdi->image->bitmap->height = cmd->height; - gdi->image->bitmap->bitsPerPixel = cmd->bpp; - gdi->image->bitmap->bytesPerPixel = cmd->bpp / 8; - gdi->image->bitmap->data = gdi->bitmap_buffer; + gdi_DeleteObject((HGDIOBJECT)gdi->image->bitmap); + gdi->image->bitmap = gdi_CreateBitmapEx(cmd->width, cmd->height, cmd->bpp, gdi->bitmap_buffer, NULL); + gdi_SelectObject(gdi->image->hdc, (HGDIOBJECT) gdi->image->bitmap); gdi_BitBlt(gdi->primary->hdc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY); } @@ -1132,11 +1130,9 @@ static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) freerdp_image_copy(pDstData, gdi->format, -1, 0, 0, cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0, gdi->palette); - gdi->image->bitmap->width = cmd->width; - gdi->image->bitmap->height = cmd->height; - gdi->image->bitmap->bitsPerPixel = cmd->bpp; - gdi->image->bitmap->bytesPerPixel = cmd->bpp / 8; - gdi->image->bitmap->data = gdi->bitmap_buffer; + gdi_DeleteObject((HGDIOBJECT)gdi->image->bitmap); + gdi->image->bitmap = gdi_CreateBitmapEx(cmd->width, cmd->height, cmd->bpp, gdi->bitmap_buffer, NULL); + gdi_SelectObject(gdi->image->hdc, (HGDIOBJECT) gdi->image->bitmap); gdi_BitBlt(gdi->primary->hdc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY); } @@ -1202,7 +1198,8 @@ BOOL gdi_init_primary(rdpGdi* gdi) if (!gdi->primary_buffer) gdi->primary->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, gdi->width, gdi->height); else - gdi->primary->bitmap = gdi_CreateBitmap(gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer); + gdi->primary->bitmap = gdi_CreateBitmapEx(gdi->width, gdi->height, gdi->dstBpp, + gdi->primary_buffer, NULL); if (!gdi->primary->bitmap) goto fail_bitmap; diff --git a/libfreerdp/gdi/test/TestGdiClip.c b/libfreerdp/gdi/test/TestGdiClip.c index 0bc95258b..627d36919 100644 --- a/libfreerdp/gdi/test/TestGdiClip.c +++ b/libfreerdp/gdi/test/TestGdiClip.c @@ -28,7 +28,7 @@ int test_gdi_ClipCoords(void) hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; - bmp = gdi_CreateBitmap(1024, 768, 4, NULL); + bmp = gdi_CreateBitmapEx(1024, 768, 4, NULL, NULL); gdi_SelectObject(hdc, (HGDIOBJECT) bmp); gdi_SetNullClipRgn(hdc); @@ -186,7 +186,7 @@ int test_gdi_InvalidateRegion(void) hdc->bytesPerPixel = 4; hdc->bitsPerPixel = 32; - bmp = gdi_CreateBitmap(1024, 768, 4, NULL); + bmp = gdi_CreateBitmapEx(1024, 768, 4, NULL, NULL); gdi_SelectObject(hdc, (HGDIOBJECT) bmp); gdi_SetNullClipRgn(hdc);