int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight) { BYTE* data; BYTE* buffer; int yIdx, xIdx, k; int rows, cols; int nSrcStep; BYTE* pSrcData; UINT32 DstSize; UINT32 SrcFormat; BITMAP_DATA* bitmap; rdpUpdate* update; rdpContext* context; rdpSettings* settings; UINT32 maxUpdateSize; UINT32 totalBitmapSize; UINT32 updateSizeEstimate; BITMAP_DATA* bitmapData; BITMAP_UPDATE bitmapUpdate; rdpShadowServer* server; rdpShadowEncoder* encoder; context = (rdpContext*) client; update = context->update; settings = context->settings; server = client->server; encoder = client->encoder; maxUpdateSize = settings->MultifragMaxRequestSize; if (settings->ColorDepth < 32) shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED); else shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR); pSrcData = surface->data; nSrcStep = surface->scanline; SrcFormat = PIXEL_FORMAT_RGB32; if (server->shareSubRect) { int subX, subY; int subWidth, subHeight; subX = server->subRect.left; subY = server->subRect.top; subWidth = server->subRect.right - server->subRect.left; subHeight = server->subRect.bottom - server->subRect.top; nXSrc -= subX; nYSrc -= subY; pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)]; } if ((nXSrc % 4) != 0) { nWidth += (nXSrc % 4); nXSrc -= (nXSrc % 4); } if ((nYSrc % 4) != 0) { nHeight += (nYSrc % 4); nYSrc -= (nYSrc % 4); } rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0); cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0); k = 0; totalBitmapSize = 0; bitmapUpdate.count = bitmapUpdate.number = rows * cols; if (!(bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number))) return -1; bitmapUpdate.rectangles = bitmapData; if ((nWidth % 4) != 0) { nWidth += (4 - (nWidth % 4)); } if ((nHeight % 4) != 0) { nHeight += (4 - (nHeight % 4)); } for (yIdx = 0; yIdx < rows; yIdx++) { for (xIdx = 0; xIdx < cols; xIdx++) { bitmap = &bitmapData[k]; bitmap->width = 64; bitmap->height = 64; bitmap->destLeft = nXSrc + (xIdx * 64); bitmap->destTop = nYSrc + (yIdx * 64); if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth)) bitmap->width = (nXSrc + nWidth) - bitmap->destLeft; if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight)) bitmap->height = (nYSrc + nHeight) - bitmap->destTop; bitmap->destRight = bitmap->destLeft + bitmap->width - 1; bitmap->destBottom = bitmap->destTop + bitmap->height - 1; bitmap->compressed = TRUE; if ((bitmap->width < 4) || (bitmap->height < 4)) continue; if (settings->ColorDepth < 32) { int bitsPerPixel = settings->ColorDepth; int bytesPerPixel = (bitsPerPixel + 7) / 8; DstSize = 64 * 64 * 4; buffer = encoder->grid[k]; interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height, pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel); bitmap->bitmapDataStream = buffer; bitmap->bitmapLength = DstSize; bitmap->bitsPerPixel = bitsPerPixel; bitmap->cbScanWidth = bitmap->width * bytesPerPixel; bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel; } else { int dstSize; buffer = encoder->grid[k]; data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)]; buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize); bitmap->bitmapDataStream = buffer; bitmap->bitmapLength = dstSize; bitmap->bitsPerPixel = 32; bitmap->cbScanWidth = bitmap->width * 4; bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4; } bitmap->cbCompFirstRowSize = 0; bitmap->cbCompMainBodySize = bitmap->bitmapLength; totalBitmapSize += bitmap->bitmapLength; k++; } } bitmapUpdate.count = bitmapUpdate.number = k; updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16; if (updateSizeEstimate > maxUpdateSize) { UINT32 i, j; UINT32 updateSize; UINT32 newUpdateSize; BITMAP_DATA* fragBitmapData = NULL; if (k > 0) fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k); if (!fragBitmapData) { free(bitmapData); return -1; } bitmapUpdate.rectangles = fragBitmapData; i = j = 0; updateSize = 1024; while (i < k) { newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16); if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k)) { CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); updateSize = newUpdateSize; } else { if ((i + 1) >= k) { CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); updateSize = newUpdateSize; } bitmapUpdate.count = bitmapUpdate.number = j; IFCALL(update->BitmapUpdate, context, &bitmapUpdate); updateSize = 1024; j = 0; } } free(fragBitmapData); } else { IFCALL(update->BitmapUpdate, context, &bitmapUpdate); } free(bitmapData); return 1; }
int freerds_send_bitmap_update(rdsConnection* connection, int bpp, RDS_MSG_PAINT_RECT* msg) { int nXSrc; int nYSrc; int nWidth; int nHeight; BYTE* data; BYTE* buffer; int yIdx, xIdx, k; int rows, cols, extra; int nSrcStep; BYTE* pSrcData; UINT32 DstSize; UINT32 SrcFormat; BITMAP_DATA* bitmap; rdpUpdate* update; rdsEncoder* encoder; rdpContext* context; rdpSettings* settings; UINT32 maxUpdateSize; UINT32 totalBitmapSize; UINT32 updateSizeEstimate; BITMAP_DATA* bitmapData; BITMAP_UPDATE bitmapUpdate; WLog_VRB(TAG, "%s", __FUNCTION__); nXSrc = msg->nLeftRect; nYSrc = msg->nTopRect; nWidth = msg->nWidth; nHeight = msg->nHeight; context = (rdpContext*) connection; update = context->update; settings = connection->settings; encoder = connection->encoder; maxUpdateSize = settings->MultifragMaxRequestSize; if (settings->ColorDepth < 32) freerds_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED); else freerds_encoder_prepare(encoder, FREERDP_CODEC_PLANAR); pSrcData = msg->framebuffer->fbSharedMemory; nSrcStep = msg->framebuffer->fbScanline; SrcFormat = PIXEL_FORMAT_RGB32; if ((nXSrc % 4) != 0) { nWidth += (nXSrc % 4); nXSrc -= (nXSrc % 4); } if ((nYSrc % 4) != 0) { nHeight += (nYSrc % 4); nYSrc -= (nYSrc % 4); } rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0); cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0); k = 0; totalBitmapSize = 0; bitmapUpdate.count = bitmapUpdate.number = rows * cols; bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number); bitmapUpdate.rectangles = bitmapData; if (!bitmapData) return -1; if ((nWidth % 4) != 0) { nXSrc -= (nWidth % 4); nWidth += (nWidth % 4); } if ((nHeight % 4) != 0) { nYSrc -= (nHeight % 4); nHeight += (nHeight % 4); } /* Clip the rectangle to the confines of the frame buffer. */ if (nXSrc < 0) { nWidth += nXSrc; nXSrc = 0; } if (nYSrc < 0) { nHeight += nYSrc; nYSrc = 0; } extra = (nXSrc + nWidth) - msg->framebuffer->fbWidth; if (extra > 0) { nWidth -= extra; } extra = (nYSrc + nHeight) - msg->framebuffer->fbHeight; if (extra > 0) { nHeight -= extra; } if ((nWidth <= 0) || (nHeight <= 0)) { /* Nothing to do. */ return 1; } for (yIdx = 0; yIdx < rows; yIdx++) { for (xIdx = 0; xIdx < cols; xIdx++) { bitmap = &bitmapData[k]; bitmap->width = 64; bitmap->height = 64; bitmap->destLeft = nXSrc + (xIdx * 64); bitmap->destTop = nYSrc + (yIdx * 64); if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth)) bitmap->width = (nXSrc + nWidth) - bitmap->destLeft; if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight)) bitmap->height = (nYSrc + nHeight) - bitmap->destTop; bitmap->destRight = bitmap->destLeft + bitmap->width - 1; bitmap->destBottom = bitmap->destTop + bitmap->height - 1; bitmap->compressed = TRUE; if ((bitmap->width < 4) || (bitmap->height < 4)) continue; if (settings->ColorDepth < 32) { int bitsPerPixel = settings->ColorDepth; int bytesPerPixel = (bitsPerPixel + 7) / 8; DstSize = 64 * 64 * 4; buffer = encoder->grid[k]; interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height, pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel); bitmap->bitmapDataStream = buffer; bitmap->bitmapLength = DstSize; bitmap->bitsPerPixel = bitsPerPixel; bitmap->cbScanWidth = bitmap->width * bytesPerPixel; bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel; } else { int dstSize; buffer = encoder->grid[k]; data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)]; buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize); bitmap->bitmapDataStream = buffer; bitmap->bitmapLength = dstSize; bitmap->bitsPerPixel = 32; bitmap->cbScanWidth = bitmap->width * 4; bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4; } bitmap->cbCompFirstRowSize = 0; bitmap->cbCompMainBodySize = bitmap->bitmapLength; totalBitmapSize += bitmap->bitmapLength; k++; } } bitmapUpdate.count = bitmapUpdate.number = k; updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16; if (updateSizeEstimate > maxUpdateSize) { UINT32 i, j; UINT32 updateSize; UINT32 newUpdateSize; BITMAP_DATA* fragBitmapData; fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k); bitmapUpdate.rectangles = fragBitmapData; i = j = 0; updateSize = 1024; while (i < k) { newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16); if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k)) { CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); updateSize = newUpdateSize; } else { if ((i + 1) >= k) { CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); updateSize = newUpdateSize; } bitmapUpdate.count = bitmapUpdate.number = j; IFCALL(update->BitmapUpdate, context, &bitmapUpdate); updateSize = 1024; j = 0; } } free(fragBitmapData); } else { IFCALL(update->BitmapUpdate, context, &bitmapUpdate); } free(bitmapData); return 1; }