/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { INT32 rc; UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; RECTANGLE_16 invalidRect; surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; rc = progressive_create_surface_context(surface->codecs->progressive, cmd->surfaceId, surface->width, surface->height); if (rc < 0) { WLog_ERR(TAG, "progressive_create_surface_context failure: %d", rc); return ERROR_INTERNAL_ERROR; } rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId); if (rc < 0) { WLog_ERR(TAG, "progressive_decompress failure: %d", rc); 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_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { int i, j; int status; BYTE* DstData; RFX_RECT* rect; int nXDst, nYDst; int nXSrc, nYSrc; int nWidth, nHeight; int nbUpdateRects; xfGfxSurface* surface; REGION16 updateRegion; RECTANGLE_16 updateRect; RECTANGLE_16* updateRects; REGION16 clippingRects; RECTANGLE_16 clippingRect; RFX_PROGRESSIVE_TILE* tile; PROGRESSIVE_BLOCK_REGION* region; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) return ERROR_INTERNAL_ERROR; if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_PROGRESSIVE, surface->width, surface->height)) return ERROR_INTERNAL_ERROR; progressive_create_surface_context(surface->codecs->progressive, cmd->surfaceId, surface->width, surface->height); DstData = surface->data; status = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, &DstData, surface->format, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId); if (status < 0) { WLog_ERR(TAG, "progressive_decompress failure: %d", status); return ERROR_INTERNAL_ERROR; } region = &(surface->codecs->progressive->region); region16_init(&clippingRects); for (i = 0; i < region->numRects; i++) { rect = &(region->rects[i]); clippingRect.left = cmd->left + rect->x; clippingRect.top = cmd->top + rect->y; clippingRect.right = clippingRect.left + rect->width; clippingRect.bottom = clippingRect.top + rect->height; region16_union_rect(&clippingRects, &clippingRects, &clippingRect); } for (i = 0; i < region->numTiles; i++) { tile = region->tiles[i]; updateRect.left = cmd->left + tile->x; updateRect.top = cmd->top + tile->y; updateRect.right = updateRect.left + 64; updateRect.bottom = updateRect.top + 64; region16_init(&updateRegion); region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects); for (j = 0; j < nbUpdateRects; j++) { nXDst = updateRects[j].left; nYDst = updateRects[j].top; nWidth = updateRects[j].right - updateRects[j].left; nHeight = updateRects[j].bottom - updateRects[j].top; nXSrc = nXDst - (cmd->left + tile->x); nYSrc = nYDst - (cmd->top + tile->y); freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, nXDst, nYDst, nWidth, nHeight, tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc, NULL); region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &updateRects[j]); } region16_uninit(&updateRegion); } region16_uninit(&clippingRects); if (!xfc->inGfxFrame) xf_UpdateSurfaces(xfc); return CHANNEL_RC_OK; }
int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count) { int cnt; int pass; int size; int index; int status; int nXSrc, nYSrc; int nXDst, nYDst; int nWidth, nHeight; RECTANGLE_16 tileRect; RECTANGLE_16 updateRect; RECTANGLE_16 clippingRect; RFX_PROGRESSIVE_TILE* tile; PROGRESSIVE_BLOCK_REGION* region; clippingRect.left = 0; clippingRect.top = 0; clippingRect.right = g_Width; clippingRect.bottom = g_Height; for (pass = 0; pass < count; pass++) { status = progressive_decompress(progressive, files[pass].buffer, files[pass].size, &g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, g_Width, g_Height, 0); printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1); region = &(progressive->region); switch (quarter) { case 0: clippingRect.left = 0; clippingRect.top = 0; clippingRect.right = g_Width / 2; clippingRect.bottom = g_Height /2; break; case 1: clippingRect.left = g_Width / 2; clippingRect.top = g_Height / 2; clippingRect.right = g_Width; clippingRect.bottom = g_Height; break; case 2: clippingRect.left = 0; clippingRect.top = g_Height / 2; clippingRect.right = g_Width / 2; clippingRect.bottom = g_Height; break; case 3: clippingRect.left = g_Width / 2; clippingRect.top = 0; clippingRect.right = g_Width; clippingRect.bottom = g_Height / 2; break; } for (index = 0; index < region->numTiles; index++) { tile = region->tiles[index]; tileRect.left = tile->x; tileRect.top = tile->y; tileRect.right = tile->x + tile->width; tileRect.bottom = tile->y + tile->height; rectangles_intersection(&tileRect, &clippingRect, &updateRect); nXDst = updateRect.left; nYDst = updateRect.top; nWidth = updateRect.right - updateRect.left; nHeight = updateRect.bottom - updateRect.top; if ((nWidth <= 0) || (nHeight <= 0)) continue; nXSrc = nXDst - tile->x; nYSrc = nYDst - tile->y; freerdp_image_copy(g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, nXDst, nYDst, nWidth, nHeight, tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc); } size = bitmaps[pass].size; cnt = test_memcmp_count(g_DstData, bitmaps[pass].buffer, size, 1); if (cnt) { float rate = ((float) cnt) / ((float) size) * 100.0f; printf("Progressive RemoteFX decompression failure\n"); printf("Actual, Expected (%d/%d = %.3f%%):\n", cnt, size, rate); } //WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); } return 1; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* context, const RDPGFX_SURFACE_COMMAND* cmd) { INT32 rc; UINT status = CHANNEL_RC_OK; gdiGfxSurface* surface; REGION16 invalidRegion; const RECTANGLE_16* rects; UINT32 nrRects, x; /** * Note: Since this comes via a Wire-To-Surface-2 PDU the * cmd's top/left/right/bottom/width/height members are always zero! * The update region is determined during decompression. */ surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); if (!surface) { WLog_ERR(TAG, "%s: unable to retrieve surfaceData for surfaceId=%"PRIu32"", __FUNCTION__, cmd->surfaceId); return ERROR_NOT_FOUND; } rc = progressive_create_surface_context(surface->codecs->progressive, cmd->surfaceId, surface->width, surface->height); if (rc < 0) { WLog_ERR(TAG, "progressive_create_surface_context failure: %"PRId32"", rc); return ERROR_INTERNAL_ERROR; } region16_init(&invalidRegion); rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data, surface->format, surface->scanline, cmd->left, cmd->top, &invalidRegion, cmd->surfaceId); if (rc < 0) { WLog_ERR(TAG, "progressive_decompress failure: %"PRId32"", rc); region16_uninit(&invalidRegion); return ERROR_INTERNAL_ERROR; } rects = region16_rects(&invalidRegion, &nrRects); IFCALL(context->UpdateSurfaceArea, context, surface->surfaceId, nrRects, rects); for (x=0; x<nrRects; x++) region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &rects[x]); region16_uninit(&invalidRegion); if (!gdi->inGfxFrame) { status = CHANNEL_RC_NOT_INITIALIZED; IFCALLRET(context->UpdateSurfaces, status, context); } return status; }