libfreerdp-gdi: start optimizing gdi bitmap update
This commit is contained in:
parent
938e2abcd4
commit
5b2a465ee6
@ -108,56 +108,101 @@
|
||||
|
||||
/* 24bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_R8G8B8 PIXEL_FORMAT_R8G8B8_F(0)
|
||||
#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8
|
||||
#define PIXEL_FORMAT_R8G8B8_VF PIXEL_FORMAT_R8G8B8_F(1)
|
||||
#define PIXEL_FORMAT_RGB24_VF PIXEL_FORMAT_R8G8B8_VF
|
||||
|
||||
#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
|
||||
#define PIXEL_FORMAT_B8G8R8 PIXEL_FORMAT_B8G8R8_F(0)
|
||||
#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8
|
||||
#define PIXEL_FORMAT_B8G8R8_VF PIXEL_FORMAT_B8G8R8_F(1)
|
||||
#define PIXEL_FORMAT_BGR24_VF PIXEL_FORMAT_B8G8R8_VF
|
||||
|
||||
/* 16bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_R5G6B5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_R5G6B5 PIXEL_FORMAT_R5G6B5_F(0)
|
||||
#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5
|
||||
#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5
|
||||
#define PIXEL_FORMAT_R5G6B5_VF PIXEL_FORMAT_R5G6B5_F(1)
|
||||
#define PIXEL_FORMAT_RGB565_VF PIXEL_FORMAT_R5G6B5_VF
|
||||
#define PIXEL_FORMAT_RGB16_VF PIXEL_FORMAT_R5G6B5_VF
|
||||
|
||||
#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_B5G6R5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5)
|
||||
#define PIXEL_FORMAT_B5G6R5 PIXEL_FORMAT_B5G6R5_F(0)
|
||||
#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5
|
||||
#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5
|
||||
#define PIXEL_FORMAT_B5G6R5_VF PIXEL_FORMAT_B5G6R5_F(1)
|
||||
#define PIXEL_FORMAT_BGR565_VF PIXEL_FORMAT_B5G6R5_VF
|
||||
#define PIXEL_FORMAT_BGR16_VF PIXEL_FORMAT_B5G6R5_VF
|
||||
|
||||
#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_A1R5G5B5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_A1R5G5B5 PIXEL_FORMAT_A1R5G5B5_F(0)
|
||||
#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5
|
||||
#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5
|
||||
#define PIXEL_FORMAT_A1R5G5B5_VF PIXEL_FORMAT_A1R5G5B5_F(1)
|
||||
#define PIXEL_FORMAT_ARGB555_VF PIXEL_FORMAT_A1R5G5B5_VF
|
||||
#define PIXEL_FORMAT_ARGB15_VF PIXEL_FORMAT_A1R5G5B5_VF
|
||||
|
||||
#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_X1R5G5B5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_X1R5G5B5 PIXEL_FORMAT_X1R5G5B5_F(0)
|
||||
#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5
|
||||
#define PIXEL_FORMAT_X1R5G5B5_VF PIXEL_FORMAT_X1R5G5B5_F(1)
|
||||
#define PIXEL_FORMAT_XRGB555_VF PIXEL_FORMAT_X1R5G5B5_VF
|
||||
#define PIXEL_FORMAT_RGB555_VF PIXEL_FORMAT_X1R5G5B5_VF
|
||||
#define PIXEL_FORMAT_RGB15_VF PIXEL_FORMAT_X1R5G5B5_VF
|
||||
|
||||
#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_A1B5G5R5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_A1B5G5R5 PIXEL_FORMAT_A1B5G5R5_F(0)
|
||||
#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5
|
||||
#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5
|
||||
#define PIXEL_FORMAT_A1B5G5R5_VF PIXEL_FORMAT_A1B5G5R5_F(1)
|
||||
#define PIXEL_FORMAT_ABGR555_VF PIXEL_FORMAT_A1B5G5R5_VF
|
||||
#define PIXEL_FORMAT_ABGR15_VF PIXEL_FORMAT_A1B5G5R5_VF
|
||||
|
||||
#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_X1B5G5R5_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5)
|
||||
#define PIXEL_FORMAT_X1B5G5R5 PIXEL_FORMAT_X1B5G5R5_F(0)
|
||||
#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5
|
||||
#define PIXEL_FORMAT_X1B5G5R5_VF PIXEL_FORMAT_X1B5G5R5_F(1)
|
||||
#define PIXEL_FORMAT_XBGR555_VF PIXEL_FORMAT_X1B5G5R5_VF
|
||||
#define PIXEL_FORMAT_BGR555_VF PIXEL_FORMAT_X1B5G5R5_VF
|
||||
#define PIXEL_FORMAT_BGR15_VF PIXEL_FORMAT_X1B5G5R5_VF
|
||||
|
||||
/* 8bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(0, 8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A8 PIXEL_FORMAT_A8_F(0)
|
||||
#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_RGB8 PIXEL_FORMAT_A8
|
||||
#define PIXEL_FORMAT_A8_VF PIXEL_FORMAT_A8_F(1)
|
||||
#define PIXEL_FORMAT_8BPP_VF PIXEL_FORMAT_A8_VF
|
||||
#define PIXEL_FORMAT_256_VF PIXEL_FORMAT_A8_VF
|
||||
#define PIXEL_FORMAT_RGB8_VF PIXEL_FORMAT_A8_VF
|
||||
|
||||
/* 4 bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(0, 4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A4_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A4 PIXEL_FORMAT_A4_F(0)
|
||||
#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4
|
||||
#define PIXEL_FORMAT_A4_VF PIXEL_FORMAT_A4_F(1)
|
||||
#define PIXEL_FORMAT_4BPP_VF PIXEL_FORMAT_A4_VF
|
||||
|
||||
/* 1bpp formats */
|
||||
|
||||
#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(0, 1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A1_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0)
|
||||
#define PIXEL_FORMAT_A1 PIXEL_FORMAT_A1_F(0)
|
||||
#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1
|
||||
#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1
|
||||
#define PIXEL_FORMAT_A1_VF PIXEL_FORMAT_A1_F(1)
|
||||
#define PIXEL_FORMAT_1BPP_VF PIXEL_FORMAT_A1_VF
|
||||
#define PIXEL_FORMAT_MONO_VF PIXEL_FORMAT_A1_VF
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
52
libfreerdp/cache/bitmap.c
vendored
52
libfreerdp/cache/bitmap.c
vendored
@ -41,8 +41,9 @@ void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
||||
bitmap = offscreen_cache_get(cache->offscreen, memblt->cacheIndex);
|
||||
else
|
||||
bitmap = bitmap_cache_get(cache->bitmap, (BYTE) memblt->cacheId, memblt->cacheIndex);
|
||||
/* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
|
||||
if (bitmap == NULL) return;
|
||||
|
||||
if (!bitmap)
|
||||
return; /* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
|
||||
|
||||
memblt->bitmap = bitmap;
|
||||
IFCALL(cache->bitmap->MemBlt, context, memblt);
|
||||
@ -60,9 +61,8 @@ void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
||||
else
|
||||
bitmap = bitmap_cache_get(cache->bitmap, (BYTE) mem3blt->cacheId, mem3blt->cacheIndex);
|
||||
|
||||
/* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
|
||||
if (!bitmap)
|
||||
return;
|
||||
return; /* XP-SP2 servers sometimes ask for cached bitmaps they've never defined. */
|
||||
|
||||
style = brush->style;
|
||||
|
||||
@ -96,7 +96,7 @@ void update_gdi_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cacheBitma
|
||||
|
||||
prevBitmap = bitmap_cache_get(cache->bitmap, cacheBitmap->cacheId, cacheBitmap->cacheIndex);
|
||||
|
||||
if (prevBitmap != NULL)
|
||||
if (prevBitmap)
|
||||
Bitmap_Free(context, prevBitmap);
|
||||
|
||||
bitmap_cache_put(cache->bitmap, cacheBitmap->cacheId, cacheBitmap->cacheIndex, bitmap);
|
||||
@ -112,11 +112,8 @@ void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cach
|
||||
|
||||
Bitmap_SetDimensions(context, bitmap, cacheBitmapV2->bitmapWidth, cacheBitmapV2->bitmapHeight);
|
||||
|
||||
if (cacheBitmapV2->bitmapBpp == 0)
|
||||
{
|
||||
/* Workaround for Windows 8 bug where bitmapBpp is not set */
|
||||
cacheBitmapV2->bitmapBpp = context->instance->settings->ColorDepth;
|
||||
}
|
||||
if (!cacheBitmapV2->bitmapBpp)
|
||||
cacheBitmapV2->bitmapBpp = context->settings->ColorDepth;
|
||||
|
||||
bitmap->Decompress(context, bitmap,
|
||||
cacheBitmapV2->bitmapDataStream, cacheBitmapV2->bitmapWidth, cacheBitmapV2->bitmapHeight,
|
||||
@ -145,11 +142,8 @@ void update_gdi_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cach
|
||||
|
||||
Bitmap_SetDimensions(context, bitmap, bitmapData->width, bitmapData->height);
|
||||
|
||||
if (cacheBitmapV3->bitmapData.bpp == 0)
|
||||
{
|
||||
/* Workaround for Windows 8 bug where bitmapBpp is not set */
|
||||
cacheBitmapV3->bitmapData.bpp = context->instance->settings->ColorDepth;
|
||||
}
|
||||
if (!cacheBitmapV3->bpp)
|
||||
cacheBitmapV3->bpp = context->settings->ColorDepth;
|
||||
|
||||
/* According to http://msdn.microsoft.com/en-us/library/gg441209.aspx
|
||||
* CACHE_BITMAP_REV3_ORDER::bitmapData::codecID = 0x00 (uncompressed) */
|
||||
@ -173,9 +167,9 @@ void update_gdi_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cach
|
||||
void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
|
||||
{
|
||||
int i;
|
||||
rdpBitmap* bitmap;
|
||||
BITMAP_DATA* bitmap_data;
|
||||
BOOL reused = TRUE;
|
||||
rdpBitmap* bitmap;
|
||||
BITMAP_DATA* bitmapData;
|
||||
rdpCache* cache = context->cache;
|
||||
|
||||
if (!cache->bitmap->bitmap)
|
||||
@ -189,22 +183,22 @@ void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
|
||||
|
||||
for (i = 0; i < (int) bitmapUpdate->number; i++)
|
||||
{
|
||||
bitmap_data = &bitmapUpdate->rectangles[i];
|
||||
bitmapData = &bitmapUpdate->rectangles[i];
|
||||
|
||||
bitmap->bpp = bitmap_data->bitsPerPixel;
|
||||
bitmap->length = bitmap_data->bitmapLength;
|
||||
bitmap->compressed = bitmap_data->compressed;
|
||||
bitmap->bpp = bitmapData->bitsPerPixel;
|
||||
bitmap->length = bitmapData->bitmapLength;
|
||||
bitmap->compressed = bitmapData->compressed;
|
||||
|
||||
Bitmap_SetRectangle(context, bitmap,
|
||||
bitmap_data->destLeft, bitmap_data->destTop,
|
||||
bitmap_data->destRight, bitmap_data->destBottom);
|
||||
bitmapData->destLeft, bitmapData->destTop,
|
||||
bitmapData->destRight, bitmapData->destBottom);
|
||||
|
||||
Bitmap_SetDimensions(context, bitmap, bitmap_data->width, bitmap_data->height);
|
||||
Bitmap_SetDimensions(context, bitmap, bitmapData->width, bitmapData->height);
|
||||
|
||||
bitmap->Decompress(context, bitmap,
|
||||
bitmap_data->bitmapDataStream, bitmap_data->width, bitmap_data->height,
|
||||
bitmap_data->bitsPerPixel, bitmap_data->bitmapLength,
|
||||
bitmap_data->compressed, RDP_CODEC_ID_NONE);
|
||||
bitmapData->bitmapDataStream, bitmapData->width, bitmapData->height,
|
||||
bitmapData->bitsPerPixel, bitmapData->bitmapLength,
|
||||
bitmapData->compressed, RDP_CODEC_ID_NONE);
|
||||
|
||||
if (reused)
|
||||
bitmap->Free(context, bitmap);
|
||||
@ -324,10 +318,8 @@ void bitmap_cache_free(rdpBitmapCache* bitmapCache)
|
||||
{
|
||||
bitmap = bitmapCache->cells[i].entries[j];
|
||||
|
||||
if (bitmap != NULL)
|
||||
{
|
||||
if (bitmap)
|
||||
Bitmap_Free(bitmapCache->context, bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmapCache->cells[i].entries);
|
||||
|
@ -1299,6 +1299,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
int x, y;
|
||||
int srcFlip;
|
||||
int dstFlip;
|
||||
int nSrcPad;
|
||||
int nDstPad;
|
||||
BYTE a, r, g, b;
|
||||
int beg, end, inc;
|
||||
int srcBitsPerPixel;
|
||||
@ -1312,10 +1314,19 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8);
|
||||
srcFlip = FREERDP_PIXEL_FORMAT_FLIP(dwSrcFormat);
|
||||
|
||||
if (nSrcStep < 0)
|
||||
nSrcStep = srcBytesPerPixel * nWidth;
|
||||
|
||||
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat);
|
||||
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8);
|
||||
dstFlip = FREERDP_PIXEL_FORMAT_FLIP(dwDstFormat);
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
nSrcPad = (nSrcStep - (nWidth * srcBytesPerPixel));
|
||||
nDstPad = (nDstStep - (nWidth * dstBytesPerPixel));
|
||||
|
||||
if (srcFlip != dstFlip)
|
||||
vFlip = TRUE;
|
||||
|
||||
@ -1327,9 +1338,6 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
|
||||
if (srcBytesPerPixel == 4)
|
||||
{
|
||||
if (nSrcStep < 0)
|
||||
nSrcStep = srcBytesPerPixel * nWidth;
|
||||
|
||||
if (srcBitsPerPixel == 24)
|
||||
{
|
||||
if (dstBytesPerPixel == 4) /* srcBytesPerPixel == dstBytesPerPixel */
|
||||
@ -1339,11 +1347,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
UINT32* pSrcPixel;
|
||||
UINT32* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
@ -1356,18 +1361,17 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (dstBitsPerPixel == 24) /* srcBitsPerPixel == dstBitsPerPixel */
|
||||
{
|
||||
UINT32* pSrcPixel;
|
||||
UINT32* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
if (overlap && (nYSrc < nYDst))
|
||||
{
|
||||
beg = nHeight - 1;
|
||||
@ -1385,8 +1389,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
{
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
|
||||
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
|
||||
}
|
||||
}
|
||||
@ -1394,11 +1398,13 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
{
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + (nHeight - y - 1)) * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (UINT32*) &pDstData[((nYDst + (nHeight - y - 1)) * nDstStep) + (nXDst * 4)];
|
||||
MoveMemory(pDstPixel, pSrcPixel, nWidth * 4);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (dstBytesPerPixel == 3)
|
||||
@ -1406,11 +1412,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
UINT32* pSrcPixel;
|
||||
BYTE* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * 3)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
@ -1425,9 +1428,11 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pSrcPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))];
|
||||
pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcStep];
|
||||
pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[nDstStep];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (dstBytesPerPixel == 2)
|
||||
{
|
||||
@ -1436,11 +1441,8 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
UINT32* pSrcPixel;
|
||||
UINT16* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
@ -1454,20 +1456,19 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))];
|
||||
pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (dstBitsPerPixel == 15)
|
||||
{
|
||||
UINT32* pSrcPixel;
|
||||
UINT16* pDstPixel;
|
||||
|
||||
if (nDstStep < 0)
|
||||
nDstStep = dstBytesPerPixel * nWidth;
|
||||
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)];
|
||||
pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
|
||||
pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * 2)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
@ -1481,15 +1482,182 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))];
|
||||
pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))];
|
||||
pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (UINT16*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (srcBytesPerPixel == 3)
|
||||
{
|
||||
if (dstBytesPerPixel == 4)
|
||||
{
|
||||
if ((dstBitsPerPixel == 32) || (dstBitsPerPixel == 24))
|
||||
{
|
||||
BYTE* pSrcPixel;
|
||||
BYTE* pDstPixel;
|
||||
|
||||
if (!vFlip)
|
||||
{
|
||||
pSrcPixel = (BYTE*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 3)];
|
||||
pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = 0xFF;
|
||||
}
|
||||
|
||||
pSrcPixel = (BYTE*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrcPixel = (BYTE*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 3)];
|
||||
pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = *pSrcPixel++;
|
||||
*pDstPixel++ = 0xFF;
|
||||
}
|
||||
|
||||
pSrcPixel = (BYTE*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)];
|
||||
pDstPixel = (BYTE*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (srcBytesPerPixel == 2)
|
||||
{
|
||||
if (srcBitsPerPixel == 16)
|
||||
{
|
||||
if (dstBytesPerPixel == 4)
|
||||
{
|
||||
if ((dstBitsPerPixel == 32) || (dstBitsPerPixel == 24))
|
||||
{
|
||||
UINT16* pSrcPixel;
|
||||
UINT32* pDstPixel;
|
||||
|
||||
if (!vFlip)
|
||||
{
|
||||
pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB16(r, g, b, *pSrcPixel);
|
||||
*pDstPixel = ARGB32(0xFF, r, g, b);
|
||||
|
||||
pSrcPixel++;
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB16(r, g, b, *pSrcPixel);
|
||||
*pDstPixel = ARGB32(0xFF, r, g, b);
|
||||
|
||||
pSrcPixel++;
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (srcBitsPerPixel == 15)
|
||||
{
|
||||
if (dstBytesPerPixel == 4)
|
||||
{
|
||||
if ((dstBitsPerPixel == 32) || (dstBitsPerPixel == 24))
|
||||
{
|
||||
UINT16* pSrcPixel;
|
||||
UINT32* pDstPixel;
|
||||
|
||||
if (!vFlip)
|
||||
{
|
||||
pSrcPixel = (UINT16*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 2)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB15(r, g, b, *pSrcPixel);
|
||||
*pDstPixel = ARGB32(0xFF, r, g, b);
|
||||
|
||||
pSrcPixel++;
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[nSrcPad];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrcPixel = (UINT16*) &pSrcData[((nYSrc + nHeight - 1) * nSrcStep) + (nXSrc * 2)];
|
||||
pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
GetRGB15(r, g, b, *pSrcPixel);
|
||||
*pDstPixel = ARGB32(0xFF, r, g, b);
|
||||
|
||||
pSrcPixel++;
|
||||
pDstPixel++;
|
||||
}
|
||||
|
||||
pSrcPixel = (UINT16*) &((BYTE*) pSrcPixel)[-((nSrcStep - nSrcPad) + nSrcStep)];
|
||||
pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[nDstPad];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (srcBytesPerPixel == 1)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length)
|
||||
|
@ -267,8 +267,15 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress24to24(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
if (vFlip)
|
||||
{
|
||||
RleDecompress24to24(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
RleDecompress24to24(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
|
||||
}
|
||||
}
|
||||
else if ((bpp == 16) || (bpp == 15))
|
||||
{
|
||||
@ -284,8 +291,15 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress16to16(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
if (vFlip)
|
||||
{
|
||||
RleDecompress16to16(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
RleDecompress16to16(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
|
||||
}
|
||||
}
|
||||
else if (bpp == 8)
|
||||
{
|
||||
@ -301,8 +315,15 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress8to8(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
if (vFlip)
|
||||
{
|
||||
RleDecompress8to8(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
RleDecompress8to8(pSrcData, SrcSize, pDstData, scanline, nWidth, nHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -454,6 +454,123 @@ void gdi_bitmap_free_ex(gdiBitmap* bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
|
||||
{
|
||||
int status;
|
||||
int nXDst;
|
||||
int nYDst;
|
||||
int nXSrc;
|
||||
int nYSrc;
|
||||
int nWidth;
|
||||
int nHeight;
|
||||
int nSrcStep;
|
||||
int nDstStep;
|
||||
UINT32 index;
|
||||
BYTE* buffer;
|
||||
BYTE* pSrcData;
|
||||
BYTE* pDstData;
|
||||
UINT32 SrcSize;
|
||||
BOOL compressed;
|
||||
UINT32 SrcFormat;
|
||||
UINT32 bitsPerPixel;
|
||||
UINT32 bytesPerPixel;
|
||||
BITMAP_DATA* bitmap;
|
||||
rdpGdi* gdi = context->gdi;
|
||||
rdpCodecs* codecs = context->codecs;
|
||||
|
||||
buffer = (BYTE*) _aligned_malloc(256 * 256 * 4, 16);
|
||||
|
||||
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;
|
||||
|
||||
pDstData = buffer;
|
||||
|
||||
pSrcData = bitmap->bitmapDataStream;
|
||||
SrcSize = bitmap->bitmapLength;
|
||||
|
||||
compressed = bitmap->compressed;
|
||||
bitsPerPixel = bitmap->bitsPerPixel;
|
||||
bytesPerPixel = (bitsPerPixel + 7) / 8;
|
||||
|
||||
SrcFormat = PIXEL_FORMAT_XRGB32_VF;
|
||||
|
||||
switch (bitsPerPixel)
|
||||
{
|
||||
case 8:
|
||||
SrcFormat = PIXEL_FORMAT_RGB8_VF;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
SrcFormat = PIXEL_FORMAT_RGB15_VF;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
SrcFormat = PIXEL_FORMAT_RGB16_VF;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
SrcFormat = PIXEL_FORMAT_RGB24_VF;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
SrcFormat = PIXEL_FORMAT_XRGB32_VF;
|
||||
break;
|
||||
}
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
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_VF, nWidth * 4, 0, 0, nWidth, nHeight);
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("gdi_bitmap_update: bitmap decompression failure\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pSrcData = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nSrcStep = nWidth * bytesPerPixel;
|
||||
|
||||
pDstData = gdi->primary_buffer;
|
||||
nDstStep = gdi->width * 4;
|
||||
|
||||
status = freerdp_image_copy(pDstData, PIXEL_FORMAT_XRGB32, nDstStep, nXDst, nYDst,
|
||||
nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc);
|
||||
|
||||
gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, nWidth, nHeight);
|
||||
}
|
||||
|
||||
_aligned_free(buffer);
|
||||
}
|
||||
|
||||
void gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
||||
{
|
||||
rdpGdi* gdi = context->gdi;
|
||||
@ -1100,6 +1217,8 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer)
|
||||
|
||||
gdi_register_graphics(instance->context->graphics);
|
||||
|
||||
instance->update->BitmapUpdate = gdi_bitmap_update;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -371,15 +371,15 @@ INLINE int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h)
|
||||
HGDI_RGN invalid;
|
||||
HGDI_RGN cinvalid;
|
||||
|
||||
if (hdc->hwnd == NULL)
|
||||
if (!hdc->hwnd)
|
||||
return 0;
|
||||
|
||||
if (hdc->hwnd->invalid == NULL)
|
||||
if (!hdc->hwnd->invalid)
|
||||
return 0;
|
||||
|
||||
cinvalid = hdc->hwnd->cinvalid;
|
||||
|
||||
if (hdc->hwnd->ninvalid + 1 > hdc->hwnd->count)
|
||||
if ((hdc->hwnd->ninvalid + 1) > hdc->hwnd->count)
|
||||
{
|
||||
hdc->hwnd->count *= 2;
|
||||
cinvalid = (HGDI_RGN) realloc(cinvalid, sizeof(GDI_RGN) * (hdc->hwnd->count));
|
||||
|
Loading…
Reference in New Issue
Block a user