/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, const RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { UINT status = CHANNEL_RC_OK; UINT16 index; BOOL sameSurface; UINT32 nWidth, nHeight; const RECTANGLE_16* rectSrc; RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; gdiGfxSurface* surfaceSrc; gdiGfxSurface* surfaceDst; rdpGdi* gdi = (rdpGdi*) context->custom; rectSrc = &(surfaceToSurface->rectSrc); surfaceSrc = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE; if (!sameSurface) surfaceDst = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); else surfaceDst = surfaceSrc; if (!surfaceSrc || !surfaceDst) return ERROR_INTERNAL_ERROR; nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { destPt = &surfaceToSurface->destPts[index]; if (!freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL, FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + rectSrc->right; invalidRect.bottom = destPt->y + rectSrc->bottom; region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect); IFCALL(context->UpdateSurfaceArea, context, surfaceDst->surfaceId, 1, &invalidRect); } if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { xfGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return -1; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); return 1; }
void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap, BYTE* data, int width, int height, int bpp, int length, BOOL compressed, int codecId) { int status; UINT16 size; BYTE* pSrcData; BYTE* pDstData; UINT32 SrcSize; UINT32 SrcFormat; UINT32 bytesPerPixel; 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) { if (bpp < 32) { if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_INTERLEAVED)) return; status = interleaved_decompress(wfc->codecs->interleaved, pSrcData, SrcSize, bpp, &pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, NULL); } else { if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR)) return; status = planar_decompress(wfc->codecs->planar, pSrcData, SrcSize, &pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, TRUE); } if (status < 0) { WLog_ERR(TAG, "Bitmap Decompression Failed"); return; } } else { 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, NULL); } bitmap->compressed = FALSE; bitmap->length = size; bitmap->bpp = 32; }
Pixmap xf_brush_new(xfContext* xfc, int width, int height, int bpp, BYTE* data) { GC gc; Pixmap bitmap; BYTE* cdata; XImage* image; UINT32 brushFormat; bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, xfc->depth); if (data) { brushFormat = gdi_get_pixel_format(bpp, FALSE); cdata = (BYTE*) _aligned_malloc(width * height * 4, 16); freerdp_image_copy(cdata, xfc->format, -1, 0, 0, width, height, data, brushFormat, -1, 0, 0, xfc->palette); image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) cdata, width, height, xfc->scanline_pad, 0); gc = XCreateGC(xfc->display, xfc->drawable, 0, NULL); XPutImage(xfc->display, bitmap, gc, image, 0, 0, 0, 0, width, height); XFree(image); if (cdata != data) _aligned_free(cdata); XFreeGC(xfc->display, gc); } return bitmap; }
HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, UINT32 nWidth, UINT32 nHeight, UINT32 SrcFormat, BYTE* data) { UINT32 nSrcStep; UINT32 nDstStep; BYTE* pSrcData; BYTE* pDstData; HGDI_BITMAP bitmap; if (!gdi) return NULL; nDstStep = nWidth * GetBytesPerPixel(gdi->dstFormat); pDstData = _aligned_malloc(nHeight * nDstStep, 16); if (!pDstData) return NULL; pSrcData = data; nSrcStep = nWidth * GetBytesPerPixel(SrcFormat); if (!freerdp_image_copy(pDstData, gdi->dstFormat, nDstStep, 0, 0, nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, 0, 0, &gdi->palette, FREERDP_FLIP_NONE)) { _aligned_free(pDstData); return NULL; } bitmap = gdi_CreateBitmap(nWidth, nHeight, gdi->dstFormat, pDstData); return bitmap; }
static Pixmap xf_brush_new(xfContext* xfc, UINT32 width, UINT32 height, UINT32 bpp, BYTE* data) { GC gc; Pixmap bitmap; BYTE* cdata; XImage* image; rdpGdi* gdi; UINT32 brushFormat; gdi = xfc->context.gdi; bitmap = XCreatePixmap(xfc->display, xfc->drawable, width, height, xfc->depth); if (data) { brushFormat = gdi_get_pixel_format(bpp); cdata = (BYTE*) _aligned_malloc(width * height * 4, 16); freerdp_image_copy(cdata, gdi->dstFormat, 0, 0, 0, width, height, data, brushFormat, 0, 0, 0, &xfc->context.gdi->palette, FREERDP_FLIP_NONE); image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) cdata, width, height, xfc->scanline_pad, 0); gc = XCreateGC(xfc->display, xfc->drawable, 0, NULL); XPutImage(xfc->display, bitmap, gc, image, 0, 0, 0, 0, width, height); XFree(image); if (cdata != data) _aligned_free(cdata); XFreeGC(xfc->display, gc); } return bitmap; }
HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, int nWidth, int nHeight, int bpp, BYTE* data) { int nSrcStep; int nDstStep; BYTE* pSrcData; BYTE* pDstData; UINT32 SrcFormat; int bytesPerPixel; HGDI_BITMAP bitmap; nDstStep = nWidth * gdi->bytesPerPixel; pDstData = _aligned_malloc(nHeight * nDstStep, 16); if (!pDstData) return NULL; pSrcData = data; switch (bpp) { case 32: bytesPerPixel = 4; SrcFormat = PIXEL_FORMAT_XRGB32; break; case 24: bytesPerPixel = 3; SrcFormat = PIXEL_FORMAT_RGB24; break; case 16: bytesPerPixel = 2; SrcFormat = PIXEL_FORMAT_RGB565; break; case 15: bytesPerPixel = 2; SrcFormat = PIXEL_FORMAT_RGB555; break; case 8: bytesPerPixel = 1; SrcFormat = PIXEL_FORMAT_RGB8; break; default: SrcFormat = PIXEL_FORMAT_RGB565; bytesPerPixel = 2; break; } nSrcStep = nWidth * bytesPerPixel; freerdp_image_copy(pDstData, gdi->format, nDstStep, 0, 0, nWidth, nHeight, pSrcData, SrcFormat, nSrcStep, 0, 0, gdi->palette); bitmap = gdi_CreateBitmap(nWidth, nHeight, gdi->dstBpp, pDstData); return bitmap; }
BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, BYTE* data, int width, int height, int bpp, int length, BOOL compressed, int codecId) { int status; UINT16 size; BYTE* pSrcData; BYTE* pDstData; UINT32 SrcSize; UINT32 SrcFormat; UINT32 bytesPerPixel; rdpGdi* gdi = context->gdi; bytesPerPixel = (bpp + 7) / 8; size = width * height * 4; bitmap->data = (BYTE*) _aligned_malloc(size, 16); pSrcData = data; SrcSize = (UINT32) length; pDstData = bitmap->data; if (compressed) { if (bpp < 32) { if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_INTERLEAVED)) return FALSE; status = interleaved_decompress(gdi->codecs->interleaved, pSrcData, SrcSize, bpp, &pDstData, gdi->format, -1, 0, 0, width, height, gdi->palette); } else { if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR)) return FALSE; status = planar_decompress(gdi->codecs->planar, pSrcData, SrcSize, &pDstData, gdi->format, -1, 0, 0, width, height, TRUE); } if (status < 0) { WLog_ERR(TAG, "Bitmap Decompression Failed"); return FALSE; } } else { SrcFormat = gdi_get_pixel_format(bpp, TRUE); status = freerdp_image_copy(pDstData, gdi->format, -1, 0, 0, width, height, pSrcData, SrcFormat, -1, 0, 0, gdi->palette); } bitmap->compressed = FALSE; bitmap->length = size; bitmap->bpp = gdi->dstBpp; return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->data, cmd->format, 0, 0, 0, NULL, FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { xfGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; freerdp_image_copy(surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, -1, 0, 0, NULL); invalidRect.left = cmd->left; invalidRect.top = cmd->top; invalidRect.right = cmd->right; invalidRect.bottom = cmd->bottom; region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect); if (!xfc->inGfxFrame) xf_UpdateSurfaces(xfc); return CHANNEL_RC_OK; }
int gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { UINT16 index; BOOL sameSurface; int nWidth, nHeight; RDPGFX_RECT16* rectSrc; RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; gdiGfxSurface* surfaceSrc; gdiGfxSurface* surfaceDst; rdpGdi* gdi = (rdpGdi*) context->custom; rectSrc = &(surfaceToSurface->rectSrc); destPt = &surfaceToSurface->destPts[0]; surfaceSrc = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE; if (!sameSurface) surfaceDst = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); else surfaceDst = surfaceSrc; if (!surfaceSrc || !surfaceDst) return -1; nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { destPt = &surfaceToSurface->destPts[index]; if (sameSurface) { freerdp_image_move(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top); } else { freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL); } invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + rectSrc->right; invalidRect.bottom = destPt->y + rectSrc->bottom; region16_union_rect(&(gdi->invalidRegion), &(gdi->invalidRegion), &invalidRect); } if (!gdi->inGfxFrame) gdi_OutputUpdate(gdi); return 1; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { UINT16 index; BOOL sameSurface; int nWidth, nHeight; RECTANGLE_16* rectSrc; RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; xfGfxSurface* surfaceSrc; xfGfxSurface* surfaceDst; xfContext* xfc = (xfContext*) context->custom; rectSrc = &(surfaceToSurface->rectSrc); destPt = &surfaceToSurface->destPts[0]; surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); sameSurface = (surfaceToSurface->surfaceIdSrc == surfaceToSurface->surfaceIdDest) ? TRUE : FALSE; if (!sameSurface) surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); else surfaceDst = surfaceSrc; if (!surfaceSrc || !surfaceDst) return ERROR_INTERNAL_ERROR; nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { destPt = &surfaceToSurface->destPts[index]; if (sameSurface) { freerdp_image_move(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, rectSrc->left, rectSrc->top); } else { freerdp_image_copy(surfaceDst->data, surfaceDst->format, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, surfaceSrc->format, surfaceSrc->scanline, rectSrc->left, rectSrc->top, NULL); } invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + rectSrc->right; invalidRect.bottom = destPt->y + rectSrc->bottom; region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect); } if (!xfc->inGfxFrame) xf_UpdateSurfaces(xfc); return CHANNEL_RC_OK; }
int gdi_OutputUpdate(rdpGdi* gdi) { int nDstStep; BYTE* pDstData; int nXDst, nYDst; int nXSrc, nYSrc; int nWidth, nHeight; gdiGfxSurface* surface; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; if (!gdi->graphicsReset) return 1; pDstData = gdi->primary_buffer; nDstStep = gdi->bytesPerPixel * gdi->width; surface = (gdiGfxSurface*) gdi->gfx->GetSurfaceData(gdi->gfx, gdi->outputSurfaceId); if (!surface) return -1; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = gdi->width; surfaceRect.bottom = gdi->height; region16_intersect_rect(&(gdi->invalidRegion), &(gdi->invalidRegion), &surfaceRect); if (!region16_is_empty(&(gdi->invalidRegion))) { extents = region16_extents(&(gdi->invalidRegion)); nXDst = extents->left; nYDst = extents->top; nXSrc = extents->left; nYSrc = extents->top; nWidth = extents->right - extents->left; nHeight = extents->bottom - extents->top; update->BeginPaint(gdi->context); freerdp_image_copy(pDstData, gdi->format, nDstStep, nXDst, nYDst, nWidth, nHeight, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL); gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, nWidth, nHeight); update->EndPaint(gdi->context); } region16_clear(&(gdi->invalidRegion)); return 1; }
int gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { int nDstStep; BYTE* pDstData; int nXDst, nYDst; int nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; pDstData = gdi->primary_buffer; nDstStep = gdi->bytesPerPixel * gdi->width; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!region16_is_empty(&(surface->invalidRegion))) { extents = region16_extents(&(surface->invalidRegion)); nXSrc = extents->left; nYSrc = extents->top; nXDst = surfaceX + extents->left; nYDst = surfaceY + extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; update->BeginPaint(gdi->context); freerdp_image_copy(pDstData, gdi->format, nDstStep, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL); gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); update->EndPaint(gdi->context); } region16_clear(&(surface->invalidRegion)); return 1; }
static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const BYTE* pSrcData, UINT32 DstWidth, UINT32 DstHeight, UINT32 bpp, UINT32 length, BOOL compressed, UINT32 codecId) { UINT32 SrcSize = length; UINT32 SrcFormat; UINT32 bytesPerPixel; rdpGdi* gdi = context->gdi; bitmap->compressed = FALSE; bitmap->format = gdi->dstFormat; bitmap->length = DstWidth * DstHeight * GetBytesPerPixel(bitmap->format); bytesPerPixel = GetBytesPerPixel(bpp); bitmap->data = (BYTE*) _aligned_malloc(bitmap->length, 16); if (!bitmap->data) return FALSE; if (compressed) { if (bpp < 32) { if (!interleaved_decompress(context->codecs->interleaved, pSrcData, SrcSize, DstWidth, DstHeight, bpp, bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, &gdi->palette)) return FALSE; } else { if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight, bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, TRUE)) return FALSE; } } else { SrcFormat = gdi_get_pixel_format(bpp); if (!freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, pSrcData, SrcFormat, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL)) return FALSE; } return TRUE; }
BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { int depth; BYTE* data; Pixmap pixmap; XImage* image; UINT32 SrcFormat; xfContext* xfc = (xfContext*) context; xf_lock_x11(xfc, FALSE); data = bitmap->data; depth = (bitmap->bpp >= 24) ? 24 : bitmap->bpp; pixmap = XCreatePixmap(xfc->display, xfc->drawable, bitmap->width, bitmap->height, xfc->depth); if (bitmap->data) { XSetFunction(xfc->display, xfc->gc, GXcopy); if (depth != xfc->depth) { if (!(data = _aligned_malloc(bitmap->width * bitmap->height * 4, 16))) { xf_unlock_x11(xfc, FALSE); return FALSE; } SrcFormat = gdi_get_pixel_format(bitmap->bpp, TRUE); freerdp_image_copy(data, xfc->format, -1, 0, 0, bitmap->width, bitmap->height, bitmap->data, SrcFormat, -1, 0, 0, xfc->palette); _aligned_free(bitmap->data); bitmap->data = data; bitmap->bpp = (xfc->depth >= 24) ? 32 : xfc->depth; } image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfc->scanline_pad, 0); XPutImage(xfc->display, pixmap, xfc->gc, image, 0, 0, 0, 0, bitmap->width, bitmap->height); XFree(image); } ((xfBitmap*) bitmap)->pixmap = pixmap; xf_unlock_x11(xfc, FALSE); return TRUE; }
int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) { UINT16 index; int nWidth, nHeight; RDPGFX_RECT16* rectSrc; RDPGFX_POINT16* destPt; RECTANGLE_16 invalidRect; xfGfxSurface* surfaceSrc; xfGfxSurface* surfaceDst; xfContext* xfc = (xfContext*) context->custom; rectSrc = &(surfaceToSurface->rectSrc); destPt = &surfaceToSurface->destPts[0]; /**not needed?*/ surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); else surfaceDst = surfaceSrc; if (!surfaceSrc || !surfaceDst) return -1; nWidth = rectSrc->right - rectSrc->left; nHeight = rectSrc->bottom - rectSrc->top; for (index = 0; index < surfaceToSurface->destPtsCount; index++) { destPt = &surfaceToSurface->destPts[index]; freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32, surfaceSrc->scanline, rectSrc->left, rectSrc->top); invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + rectSrc->right; invalidRect.bottom = destPt->y + rectSrc->bottom; /**width,height?*/ region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); return 1; }
/* Bitmap Class */ static BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap) { int depth; BYTE* data; Pixmap pixmap; XImage* image; UINT32 SrcFormat; rdpGdi* gdi; xfContext* xfc = (xfContext*) context; gdi = context->gdi; xf_lock_x11(xfc, FALSE); data = bitmap->data; depth = GetBitsPerPixel(bitmap->format); pixmap = XCreatePixmap(xfc->display, xfc->drawable, bitmap->width, bitmap->height, xfc->depth); if (bitmap->data) { XSetFunction(xfc->display, xfc->gc, GXcopy); if (depth != xfc->depth) { if (!(data = _aligned_malloc(bitmap->width * bitmap->height * 4, 16))) { xf_unlock_x11(xfc, FALSE); return FALSE; } SrcFormat = bitmap->format; freerdp_image_copy(data, gdi->dstFormat, 0, 0, 0, bitmap->width, bitmap->height, bitmap->data, SrcFormat, 0, 0, 0, &context->gdi->palette, FREERDP_FLIP_NONE); _aligned_free(bitmap->data); bitmap->data = data; bitmap->format = gdi->dstFormat; } image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*) bitmap->data, bitmap->width, bitmap->height, xfc->scanline_pad, 0); XPutImage(xfc->display, pixmap, xfc->gc, image, 0, 0, 0, 0, bitmap->width, bitmap->height); XFree(image); } ((xfBitmap*) bitmap)->pixmap = pixmap; xf_unlock_x11(xfc, FALSE); return TRUE; }
static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { UINT32 nXDst, nYDst; UINT32 nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* rects; UINT32 i, nbRects; rdpUpdate* update = gdi->context->update; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!(rects = region16_rects(&surface->invalidRegion, &nbRects)) || !nbRects) return CHANNEL_RC_OK; update->BeginPaint(gdi->context); for (i = 0; i < nbRects; i++) { nXSrc = rects[i].left; nYSrc = rects[i].top; nXDst = surfaceX + nXSrc; nYDst = surfaceY + nYSrc; width = rects[i].right - rects[i].left; height = rects[i].bottom - rects[i].top; if (!freerdp_image_copy(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) return CHANNEL_RC_NULL_DATA; gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); } update->EndPaint(gdi->context); region16_clear(&(surface->invalidRegion)); return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { size_t size; RECTANGLE_16* rect; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; xfContext* xfc = (xfContext*) context->custom; rect = &(surfaceToCache->rectSrc); surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry)); if (!cacheEntry) return CHANNEL_RC_NO_MEMORY; cacheEntry->width = (UINT32) (rect->right - rect->left); cacheEntry->height = (UINT32) (rect->bottom - rect->top); cacheEntry->alpha = surface->alpha; cacheEntry->format = surface->format; cacheEntry->scanline = cacheEntry->width * 4; cacheEntry->scanline += (cacheEntry->scanline % (xfc->scanline_pad / 8)); size = cacheEntry->scanline * cacheEntry->height; cacheEntry->data = (BYTE*) _aligned_malloc(size, 16); if (!cacheEntry->data) { free(cacheEntry); return CHANNEL_RC_NO_MEMORY; } ZeroMemory(cacheEntry->data, size); freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, cacheEntry->width, cacheEntry->height, surface->data, surface->format, surface->scanline, rect->left, rect->top, NULL); context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_CacheToSurface(RdpgfxClientContext* context, const RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { UINT status = CHANNEL_RC_OK; UINT16 index; RDPGFX_POINT16* destPt; gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; rdpGdi* gdi = (rdpGdi*) context->custom; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return ERROR_INTERNAL_ERROR; for (index = 0; index < cacheToSurface->destPtsCount; index++) { destPt = &cacheToSurface->destPts[index]; if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, NULL, FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + cacheEntry->width; invalidRect.bottom = destPt->y + cacheEntry->height; region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect); IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); } if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }
static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) { UINT32 nXDst, nYDst; UINT32 nXSrc, nYSrc; UINT16 width, height; UINT32 surfaceX, surfaceY; RECTANGLE_16 surfaceRect; const RECTANGLE_16* extents; rdpUpdate* update = gdi->context->update; surfaceX = surface->outputOriginX; surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; surfaceRect.right = surface->width; surfaceRect.bottom = surface->height; region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); if (!region16_is_empty(&(surface->invalidRegion))) { extents = region16_extents(&(surface->invalidRegion)); nXSrc = extents->left; nYSrc = extents->top; nXDst = surfaceX + extents->left; nYDst = surfaceY + extents->top; width = extents->right - extents->left; height = extents->bottom - extents->top; update->BeginPaint(gdi->context); if (!freerdp_image_copy(gdi->primary_buffer, gdi->primary->hdc->format, gdi->stride, nXDst, nYDst, width, height, surface->data, surface->format, surface->scanline, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) return CHANNEL_RC_NULL_DATA; gdi_InvalidateRegion(gdi->primary->hdc, nXDst, nYDst, width, height); update->EndPaint(gdi->context); } region16_clear(&(surface->invalidRegion)); return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT gdi_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { RDPGFX_RECT16* rect; gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; rdpGdi* gdi = (rdpGdi*) context->custom; rect = &(surfaceToCache->rectSrc); surface = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; cacheEntry = (gdiGfxCacheEntry*) calloc(1, sizeof(gdiGfxCacheEntry)); if (!cacheEntry) return ERROR_INTERNAL_ERROR; cacheEntry->width = (UINT32) (rect->right - rect->left); cacheEntry->height = (UINT32) (rect->bottom - rect->top); cacheEntry->alpha = surface->alpha; cacheEntry->format = (!gdi->invert) ? PIXEL_FORMAT_XRGB32 : PIXEL_FORMAT_XBGR32; cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height); if (!cacheEntry->data) { free(cacheEntry); return ERROR_INTERNAL_ERROR; } freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, cacheEntry->width, cacheEntry->height, surface->data, surface->format, surface->scanline, rect->left, rect->top, NULL); context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context, const RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { const RECTANGLE_16* rect; gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; rect = &(surfaceToCache->rectSrc); surface = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; cacheEntry = (gdiGfxCacheEntry*) calloc(1, sizeof(gdiGfxCacheEntry)); if (!cacheEntry) return ERROR_NOT_ENOUGH_MEMORY; cacheEntry->width = (UINT32)(rect->right - rect->left); cacheEntry->height = (UINT32)(rect->bottom - rect->top); cacheEntry->format = surface->format; cacheEntry->scanline = gfx_align_scanline(cacheEntry->width * 4, 16); cacheEntry->data = (BYTE*) calloc(cacheEntry->height, cacheEntry->scanline); if (!cacheEntry->data) { free(cacheEntry); return ERROR_NOT_ENOUGH_MEMORY; } if (!freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, cacheEntry->width, cacheEntry->height, surface->data, surface->format, surface->scanline, rect->left, rect->top, NULL, FREERDP_FLIP_NONE)) { free(cacheEntry); return ERROR_INTERNAL_ERROR; } return context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { UINT16 index; RDPGFX_POINT16* destPt; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; xfContext* xfc = (xfContext*) context->custom; surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return ERROR_INTERNAL_ERROR; for (index = 0; index < cacheToSurface->destPtsCount; index++) { destPt = &cacheToSurface->destPts[index]; freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, NULL); invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + cacheEntry->width - 1; invalidRect.bottom = destPt->y + cacheEntry->height - 1; region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect); } if (!xfc->inGfxFrame) xf_UpdateSurfaces(xfc); return CHANNEL_RC_OK; }
HBITMAP wf_create_dib(wfContext* wfc, UINT32 width, UINT32 height, UINT32 srcFormat, const BYTE* data, BYTE** pdata) { HDC hdc; int negHeight; HBITMAP bitmap; BITMAPINFO bmi; BYTE* cdata = NULL; UINT32 dstFormat = srcFormat; /** * See: http://msdn.microsoft.com/en-us/library/dd183376 * if biHeight is positive, the bitmap is bottom-up * if biHeight is negative, the bitmap is top-down * Since we get top-down bitmaps, let's keep it that way */ negHeight = (height < 0) ? height : height * (-1); hdc = GetDC(NULL); bmi.bmiHeader.biSize = sizeof(BITMAPINFO); bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = negHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = GetBitsPerPixel(dstFormat); bmi.bmiHeader.biCompression = BI_RGB; bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &cdata, NULL, 0); if (data) freerdp_image_copy(cdata, dstFormat, 0, 0, 0, width, height, data, srcFormat, 0, 0, 0, &wfc->context.gdi->palette); if (pdata) *pdata = cdata; ReleaseDC(NULL, hdc); GdiFlush(); return bitmap; }
int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { UINT16 index; RDPGFX_POINT16* destPt; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; xfContext* xfc = (xfContext*) context->custom; surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return -1; for (index = 0; index < cacheToSurface->destPtsCount; index++) { destPt = &cacheToSurface->destPts[index]; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0); invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + cacheEntry->width - 1; invalidRect.bottom = destPt->y + cacheEntry->height - 1; region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); } if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); return 1; }
int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) { RDPGFX_RECT16* rect; xfGfxSurface* surface; xfGfxCacheEntry* cacheEntry; rect = &(surfaceToCache->rectSrc); surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); if (!surface) return -1; cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry)); if (!cacheEntry) return -1; cacheEntry->width = (UINT32) (rect->right - rect->left); cacheEntry->height = (UINT32) (rect->bottom - rect->top); cacheEntry->alpha = surface->alpha; cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height); if (!cacheEntry->data) return -1; freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0, cacheEntry->width, cacheEntry->height, surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top); context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); return 1; }
int gdi_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) { UINT16 index; RDPGFX_POINT16* destPt; gdiGfxSurface* surface; gdiGfxCacheEntry* cacheEntry; RECTANGLE_16 invalidRect; rdpGdi* gdi = (rdpGdi*) context->custom; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); if (!surface || !cacheEntry) return -1; for (index = 0; index < cacheToSurface->destPtsCount; index++) { destPt = &cacheToSurface->destPts[index]; freerdp_image_copy(surface->data, surface->format, surface->scanline, destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, cacheEntry->data, cacheEntry->format, cacheEntry->scanline, 0, 0, NULL); invalidRect.left = destPt->x; invalidRect.top = destPt->y; invalidRect.right = destPt->x + cacheEntry->width - 1; invalidRect.bottom = destPt->y + cacheEntry->height - 1; region16_union_rect(&(gdi->invalidRegion), &(gdi->invalidRegion), &invalidRect); } if (!gdi->inGfxFrame) gdi_OutputUpdate(gdi); return 1; }
static void 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) { freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX); message = rfx_process_message(gdi->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength); /* 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) { freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC); 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; } 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->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_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; } 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->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_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); } }