Пример #1
0
BOOL gdi_init_primary(rdpGdi* gdi)
{
	gdi->primary = (gdiBitmap*) calloc(1, sizeof(gdiBitmap));

	if (!gdi->primary)
		goto fail_primary;

	if (!(gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
		goto fail_hdc;

	if (!gdi->primary_buffer)
		gdi->primary->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, gdi->width, gdi->height);
	else
		gdi->primary->bitmap = gdi_CreateBitmapEx(gdi->width, gdi->height, gdi->dstBpp,
												gdi->primary_buffer, NULL);

	if (!gdi->primary->bitmap)
		goto fail_bitmap;

	gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap);
	gdi->primary->org_bitmap = NULL;

	gdi->primary_buffer = gdi->primary->bitmap->data;

	if (!(gdi->primary->hdc->hwnd = (HGDI_WND) calloc(1, sizeof(GDI_WND))))
		goto fail_hwnd;
	if (!(gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
		goto fail_hwnd;
	gdi->primary->hdc->hwnd->invalid->null = 1;

	gdi->primary->hdc->hwnd->count = 32;
	if (!(gdi->primary->hdc->hwnd->cinvalid = (HGDI_RGN) calloc(gdi->primary->hdc->hwnd->count, sizeof(GDI_RGN))))
		goto fail_hwnd;
	gdi->primary->hdc->hwnd->ninvalid = 0;

	if (!gdi->drawing)
		gdi->drawing = gdi->primary;

	return TRUE;

fail_hwnd:
	gdi_DeleteObject((HGDIOBJECT) gdi->primary->bitmap);
fail_bitmap:
	gdi_DeleteDC(gdi->primary->hdc);
fail_hdc:
	free(gdi->primary);
	gdi->primary = NULL;
fail_primary:
	return FALSE;
}
Пример #2
0
static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
{
	const rdpBrush* brush = &patblt->brush;
	UINT32 foreColor;
	UINT32 backColor;
	UINT32 originalColor;
	HGDI_BRUSH originalBrush, hbrush = NULL;
	rdpGdi* gdi = context->gdi;
	BOOL ret = FALSE;
	const DWORD rop = gdi_rop3_code(patblt->bRop);
	UINT32 nXSrc = 0;
	UINT32 nYSrc = 0;
	BYTE data[8 * 8 * 4];
	HGDI_BITMAP hBmp = NULL;

	if (!gdi_decode_color(gdi, patblt->foreColor, &foreColor, NULL))
		return FALSE;

	if (!gdi_decode_color(gdi, patblt->backColor, &backColor, NULL))
		return FALSE;

	originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor);
	originalBrush = gdi->drawing->hdc->brush;

	switch (brush->style)
	{
		case GDI_BS_SOLID:
			hbrush = gdi_CreateSolidBrush(foreColor);
			break;

		case GDI_BS_HATCHED:
			{
				const BYTE* hatched;
				hatched = GDI_BS_HATCHED_PATTERNS + (8 * brush->hatch);

				if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0,
				                                        0, 8, 8,
				                                        hatched, backColor, foreColor, &gdi->palette))
					goto out_error;

				hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);

				if (!hBmp)
					goto out_error;

				hbrush = gdi_CreateHatchBrush(hBmp);
			}
			break;

		case GDI_BS_PATTERN:
			{
				UINT32 brushFormat;

				if (brush->bpp > 1)
				{
					brushFormat = gdi_get_pixel_format(brush->bpp);

					if (!freerdp_image_copy(data, gdi->drawing->hdc->format, 0, 0, 0,
					                        8, 8, brush->data, brushFormat, 0, 0, 0,
					                        &gdi->palette, FREERDP_FLIP_NONE))
						goto out_error;
				}
				else
				{
					if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0,
					                                        0, 8, 8,
					                                        brush->data, backColor, foreColor, &gdi->palette))
						goto out_error;
				}

				hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);

				if (!hBmp)
					goto out_error;

				hbrush = gdi_CreatePatternBrush(hBmp);
			}
			break;

		default:
			WLog_ERR(TAG,  "unimplemented brush style:%"PRIu32"", brush->style);
			break;
	}

	if (!hbrush)
		gdi_DeleteObject((HGDIOBJECT) hBmp);
	else
	{
		hbrush->nXOrg = brush->x;
		hbrush->nYOrg = brush->y;
		gdi->drawing->hdc->brush = hbrush;
		ret = gdi_BitBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect,
		                 patblt->nWidth, patblt->nHeight,
		                 gdi->primary->hdc, nXSrc, nYSrc, rop, &gdi->palette);
	}

out_error:
	gdi_DeleteObject((HGDIOBJECT) hbrush);
	gdi->drawing->hdc->brush = originalBrush;
	gdi_SetTextColor(gdi->drawing->hdc, originalColor);
	return ret;
}
Пример #3
0
static BOOL gdi_init_primary(rdpGdi* gdi, UINT32 stride, UINT32 format,
                             BYTE* buffer, void (*pfree)(void*))
{
	gdi->primary = (gdiBitmap*) calloc(1, sizeof(gdiBitmap));

	if (format > 0)
		gdi->dstFormat = format;

	if (stride > 0)
		gdi->stride = stride;
	else
		gdi->stride = gdi->width * GetBytesPerPixel(gdi->dstFormat);

	if (!gdi->primary)
		goto fail_primary;

	if (!(gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
		goto fail_hdc;

	if (!buffer)
	{
		gdi->primary->bitmap = gdi_CreateCompatibleBitmap(
		                           gdi->hdc, gdi->width, gdi->height);
	}
	else
	{
		gdi->primary->bitmap = gdi_CreateBitmapEx(gdi->width, gdi->height,
		                       gdi->dstFormat,
		                       gdi->stride,
		                       buffer, pfree);
	}

	gdi->stride = gdi->primary->bitmap->scanline;

	if (!gdi->primary->bitmap)
		goto fail_bitmap;

	gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap);
	gdi->primary->org_bitmap = NULL;
	gdi->primary_buffer = gdi->primary->bitmap->data;

	if (!(gdi->primary->hdc->hwnd = (HGDI_WND) calloc(1, sizeof(GDI_WND))))
		goto fail_hwnd;

	if (!(gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
		goto fail_hwnd;

	gdi->primary->hdc->hwnd->invalid->null = TRUE;
	gdi->primary->hdc->hwnd->count = 32;

	if (!(gdi->primary->hdc->hwnd->cinvalid = (HGDI_RGN) calloc(
	            gdi->primary->hdc->hwnd->count, sizeof(GDI_RGN))))
		goto fail_hwnd;

	gdi->primary->hdc->hwnd->ninvalid = 0;

	if (!gdi->drawing)
		gdi->drawing = gdi->primary;

	return TRUE;
fail_hwnd:
	gdi_DeleteObject((HGDIOBJECT) gdi->primary->bitmap);
fail_bitmap:
	gdi_DeleteDC(gdi->primary->hdc);
fail_hdc:
	free(gdi->primary);
	gdi->primary = NULL;
fail_primary:
	return FALSE;
}
Пример #4
0
int test_gdi_InvalidateRegion(void)
{
	HGDI_DC hdc;
	HGDI_RGN rgn1;
	HGDI_RGN rgn2;
	HGDI_RGN invalid;
	HGDI_BITMAP bmp;

	if (!(hdc = gdi_GetDC()))
	{
		printf("failed to get gdi device context\n");
		return -1;
	}

	hdc->bytesPerPixel = 4;
	hdc->bitsPerPixel = 32;
	bmp = gdi_CreateBitmapEx(1024, 768, 4, NULL, NULL);
	gdi_SelectObject(hdc, (HGDIOBJECT) bmp);
	gdi_SetNullClipRgn(hdc);

	hdc->hwnd = (HGDI_WND) calloc(1, sizeof(GDI_WND));
	hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0);
	hdc->hwnd->invalid->null = 1;
	invalid = hdc->hwnd->invalid;

	hdc->hwnd->count = 16;
	hdc->hwnd->cinvalid = (HGDI_RGN) calloc(hdc->hwnd->count, sizeof(GDI_RGN));

	rgn1 = gdi_CreateRectRgn(0, 0, 0, 0);
	rgn2 = gdi_CreateRectRgn(0, 0, 0, 0);
	rgn1->null = 1;
	rgn2->null = 1;

	/* no previous invalid region */
	invalid->null = 1;
	gdi_SetRgn(rgn1, 300, 300, 100, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* region same as invalid region */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 100, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* left outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 300, 300, 100);
	gdi_SetRgn(rgn2, 100, 300, 300, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* right outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 300, 100);
	gdi_SetRgn(rgn2, 300, 300, 300, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* top outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 100, 100, 300);
	gdi_SetRgn(rgn2, 300, 100, 100, 300);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* bottom outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 100, 300);
	gdi_SetRgn(rgn2, 300, 300, 100, 300);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* left outside, right outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 300, 600, 300);
	gdi_SetRgn(rgn2, 100, 300, 600, 300);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* top outside, bottom outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 100, 100, 500);
	gdi_SetRgn(rgn2, 300, 100, 100, 500);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* all outside, left */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 300, 100, 100);
	gdi_SetRgn(rgn2, 100, 300, 300, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* all outside, right */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 700, 300, 100, 100);
	gdi_SetRgn(rgn2, 300, 300, 500, 100);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* all outside, top */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 100, 100, 100);
	gdi_SetRgn(rgn2, 300, 100, 100, 300);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* all outside, bottom */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 500, 100, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 300);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* all outside */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 100, 600, 600);
	gdi_SetRgn(rgn2, 100, 100, 600, 600);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	/* everything */
	gdi_SetRgn(invalid, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 0, 0, 1024, 768);
	gdi_SetRgn(rgn2, 0, 0, 1024, 768);

	gdi_InvalidateRegion(hdc, rgn1->x, rgn1->y, rgn1->w, rgn1->h);

	if (!gdi_EqualRgn(invalid, rgn2))
		return -1;

	return 0;
}
Пример #5
0
int test_gdi_ClipCoords(void)
{
	BOOL draw;
	HGDI_DC hdc;
	HGDI_RGN rgn1;
	HGDI_RGN rgn2;
	HGDI_BITMAP bmp;

	if (!(hdc = gdi_GetDC()))
	{
		printf("failed to get gdi device context\n");
		return -1;
	}

	hdc->bytesPerPixel = 4;
	hdc->bitsPerPixel = 32;
	bmp = gdi_CreateBitmapEx(1024, 768, 4, NULL, NULL);
	gdi_SelectObject(hdc, (HGDIOBJECT) bmp);
	gdi_SetNullClipRgn(hdc);

	rgn1 = gdi_CreateRectRgn(0, 0, 0, 0);
	rgn2 = gdi_CreateRectRgn(0, 0, 0, 0);
	rgn1->null = 1;
	rgn2->null = 1;

	/* null clipping region */
	gdi_SetNullClipRgn(hdc);
	gdi_SetRgn(rgn1, 20, 20, 100, 100);
	gdi_SetRgn(rgn2, 20, 20, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* region all inside clipping region */
	gdi_SetClipRgn(hdc, 0, 0, 1024, 768);
	gdi_SetRgn(rgn1, 20, 20, 100, 100);
	gdi_SetRgn(rgn2, 20, 20, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* region all outside clipping region, on the left */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 20, 20, 100, 100);
	gdi_SetRgn(rgn2, 0, 0, 0, 0);

	draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (draw)
		return -1;

	/* region all outside clipping region, on the right */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 420, 420, 100, 100);
	gdi_SetRgn(rgn2, 0, 0, 0, 0);

	draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (draw)
		return -1;

	/* region all outside clipping region, on top */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 20, 100, 100);
	gdi_SetRgn(rgn2, 0, 0, 0, 0);

	draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (draw)
		return -1;

	/* region all outside clipping region, at the bottom */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 420, 100, 100);
	gdi_SetRgn(rgn2, 0, 0, 0, 0);

	draw = gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (draw)
		return -1;

	/* left outside, right = clip, top = clip, bottom = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 300, 300, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* left outside, right inside, top = clip, bottom = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 100, 300, 250, 100);
	gdi_SetRgn(rgn2, 300, 300, 50, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* left = clip, right outside, top = clip, bottom = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 300, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* left inside, right outside, top = clip, bottom = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 350, 300, 200, 100);
	gdi_SetRgn(rgn2, 350, 300, 50, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* top outside, bottom = clip, left = clip, right = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 100, 300, 300);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* top = clip, bottom outside, left = clip, right = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 100, 200);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	/* top = clip, bottom = clip, top = clip, bottom = clip */
	gdi_SetClipRgn(hdc, 300, 300, 100, 100);
	gdi_SetRgn(rgn1, 300, 300, 100, 100);
	gdi_SetRgn(rgn2, 300, 300, 100, 100);

	gdi_ClipCoords(hdc, &(rgn1->x), &(rgn1->y), &(rgn1->w), &(rgn1->h), NULL, NULL);

	if (!gdi_EqualRgn(rgn1, rgn2))
		return -1;

	return 0;
}
Пример #6
0
HGDI_BITMAP gdi_CreateBitmap(UINT32 nWidth, UINT32 nHeight, UINT32 format,
                             BYTE* data)
{
	return gdi_CreateBitmapEx(nWidth, nHeight, format, 0, data, _aligned_free);
}
Пример #7
0
static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
{
	int i, j;
	int tx, ty;
	BYTE* pSrcData;
	BYTE* pDstData;
	RFX_MESSAGE* message;
	rdpGdi* gdi = context->gdi;

	DEBUG_GDI("destLeft %d destTop %d destRight %d destBottom %d "
		"bpp %d codecID %d width %d height %d length %d",
		cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom,
		cmd->bpp, cmd->codecID, cmd->width, cmd->height, cmd->bitmapDataLength);

	if (cmd->codecID == RDP_CODEC_ID_REMOTEFX)
	{
		if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX))
			return FALSE;

		if (!(message = rfx_process_message(gdi->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength)))
		{
			WLog_ERR(TAG, "Failed to process RemoteFX message");
			return FALSE;
		}

		/* blit each tile */
		for (i = 0; i < message->numTiles; i++)
		{
			tx = message->tiles[i]->x + cmd->destLeft;
			ty = message->tiles[i]->y + cmd->destTop;

			pSrcData = message->tiles[i]->data;
			pDstData = gdi->tile->bitmap->data;

			if (!gdi->invert && (gdi->dstBpp == 32))
			{
				gdi->tile->bitmap->data = pSrcData;
			}
			else
			{
				freerdp_image_copy(pDstData, gdi->format, -1, 0, 0,
						64, 64, pSrcData, PIXEL_FORMAT_XRGB32, -1, 0, 0, gdi->palette);
			}

			for (j = 0; j < message->numRects; j++)
			{
				gdi_SetClipRgn(gdi->primary->hdc,
					cmd->destLeft + message->rects[j].x,
					cmd->destTop + message->rects[j].y,
					message->rects[j].width, message->rects[j].height);

				gdi_BitBlt(gdi->primary->hdc, tx, ty, 64, 64, gdi->tile->hdc, 0, 0, GDI_SRCCOPY);
			}

			gdi->tile->bitmap->data = pDstData;
		}

		gdi_SetNullClipRgn(gdi->primary->hdc);
		rfx_message_free(gdi->codecs->rfx, message);
	}
	else if (cmd->codecID == RDP_CODEC_ID_NSCODEC)
	{
		if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC))
			return FALSE;

		nsc_process_message(gdi->codecs->nsc, cmd->bpp, cmd->width, cmd->height, cmd->bitmapData, cmd->bitmapDataLength);

		if (gdi->bitmap_size < (cmd->width * cmd->height * 4))
		{
			gdi->bitmap_size = cmd->width * cmd->height * 4;
			gdi->bitmap_buffer = (BYTE*) _aligned_realloc(gdi->bitmap_buffer, gdi->bitmap_size, 16);

			if (!gdi->bitmap_buffer)
				return FALSE;
		}

		pDstData = gdi->bitmap_buffer;
		pSrcData = gdi->codecs->nsc->BitmapData;

		freerdp_image_copy(pDstData, gdi->format, -1, 0, 0,
				cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0, gdi->palette);

		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);
	} 
	else if (cmd->codecID == RDP_CODEC_ID_NONE)
	{
		if (gdi->bitmap_size < (cmd->width * cmd->height * 4))
		{
			gdi->bitmap_size = cmd->width * cmd->height * 4;
			gdi->bitmap_buffer = (BYTE*) _aligned_realloc(gdi->bitmap_buffer, gdi->bitmap_size, 16);

			if (!gdi->bitmap_buffer)
				return FALSE;
		}

		pDstData = gdi->bitmap_buffer;
		pSrcData = cmd->bitmapData;

		freerdp_image_copy(pDstData, gdi->format, -1, 0, 0,
				cmd->width, cmd->height, pSrcData, PIXEL_FORMAT_XRGB32_VF, -1, 0, 0, gdi->palette);

		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);
	}
	else
	{
		WLog_ERR(TAG, "Unsupported codecID %d", cmd->codecID);
	}
	return TRUE;
}