Fix remoteFx encoder with topleft and bottomright rectangle
This patch fixes the case where with a topleft and a bottomright rectangle, the encoder would send the full screen instead of only the intersected tiles.
This commit is contained in:
parent
d1e75efb8c
commit
2d16d929b6
@ -39,6 +39,7 @@
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/utils/region.h>
|
||||
|
||||
#include "rfx_constants.h"
|
||||
#include "rfx_types.h"
|
||||
@ -51,6 +52,15 @@
|
||||
#include "rfx_sse2.h"
|
||||
#include "rfx_neon.h"
|
||||
|
||||
void *zmalloc(int size) {
|
||||
void *ret;
|
||||
ret = malloc(size);
|
||||
if (ret)
|
||||
ZeroMemory(ret, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifndef RFX_INIT_SIMD
|
||||
#define RFX_INIT_SIMD(_rfx_context) do { } while (0)
|
||||
#endif
|
||||
@ -183,24 +193,13 @@ void rfx_decoder_tile_free(RFX_TILE* tile)
|
||||
|
||||
RFX_TILE* rfx_encoder_tile_new()
|
||||
{
|
||||
RFX_TILE* tile = NULL;
|
||||
|
||||
tile = (RFX_TILE*) malloc(sizeof(RFX_TILE));
|
||||
|
||||
if (tile)
|
||||
{
|
||||
ZeroMemory(tile, sizeof(RFX_TILE));
|
||||
}
|
||||
|
||||
return tile;
|
||||
return (RFX_TILE *)zmalloc( sizeof(RFX_TILE) );
|
||||
}
|
||||
|
||||
void rfx_encoder_tile_free(RFX_TILE* tile)
|
||||
{
|
||||
if (tile)
|
||||
{
|
||||
free(tile);
|
||||
}
|
||||
}
|
||||
|
||||
RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
@ -212,36 +211,42 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
DWORD dwValue;
|
||||
SYSTEM_INFO sysinfo;
|
||||
RFX_CONTEXT* context;
|
||||
wObject *pool;
|
||||
RFX_CONTEXT_PRIV *priv;
|
||||
|
||||
context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT));
|
||||
ZeroMemory(context, sizeof(RFX_CONTEXT));
|
||||
context = (RFX_CONTEXT*) zmalloc(sizeof(RFX_CONTEXT));
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
context->encoder = encoder;
|
||||
|
||||
context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV));
|
||||
ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV));
|
||||
context->priv = priv = (RFX_CONTEXT_PRIV *)zmalloc( sizeof(RFX_CONTEXT_PRIV) );
|
||||
if (!priv)
|
||||
goto error_priv;
|
||||
|
||||
WLog_Init();
|
||||
|
||||
context->priv->log = WLog_Get("com.freerdp.codec.rfx");
|
||||
WLog_OpenAppender(context->priv->log);
|
||||
priv->log = WLog_Get("com.freerdp.codec.rfx");
|
||||
WLog_OpenAppender(priv->log);
|
||||
|
||||
#ifdef WITH_DEBUG_RFX
|
||||
WLog_SetLogLevel(context->priv->log, WLOG_DEBUG);
|
||||
WLog_SetLogLevel(priv->log, WLOG_DEBUG);
|
||||
#endif
|
||||
|
||||
context->priv->TilePool = ObjectPool_New(TRUE);
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init;
|
||||
priv->TilePool = ObjectPool_New(TRUE);
|
||||
if (!priv->TilePool)
|
||||
goto error_tilePool;
|
||||
pool = ObjectPool_Object(priv->TilePool);
|
||||
pool->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init;
|
||||
|
||||
if (context->encoder)
|
||||
{
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free;
|
||||
pool->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new;
|
||||
pool->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free;
|
||||
pool->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new;
|
||||
pool->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -258,7 +263,9 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
* We then multiply by 3 to use a single, partioned buffer for all 3 channels.
|
||||
*/
|
||||
|
||||
context->priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
|
||||
priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
|
||||
if (!priv->BufferPool)
|
||||
goto error_BufferPool;
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
@ -271,16 +278,16 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
GetVersionExA(&verinfo);
|
||||
isVistaOrLater = ((verinfo.dwMajorVersion >= 6) && (verinfo.dwMinorVersion >= 0)) ? TRUE : FALSE;
|
||||
|
||||
context->priv->UseThreads = isVistaOrLater;
|
||||
priv->UseThreads = isVistaOrLater;
|
||||
}
|
||||
#else
|
||||
context->priv->UseThreads = TRUE;
|
||||
priv->UseThreads = TRUE;
|
||||
#endif
|
||||
|
||||
GetNativeSystemInfo(&sysinfo);
|
||||
|
||||
context->priv->MinThreadCount = sysinfo.dwNumberOfProcessors;
|
||||
context->priv->MaxThreadCount = 0;
|
||||
priv->MinThreadCount = sysinfo.dwNumberOfProcessors;
|
||||
priv->MaxThreadCount = 0;
|
||||
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\FreeRDP\\RemoteFX"), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
|
||||
|
||||
@ -289,33 +296,35 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
dwSize = sizeof(dwValue);
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("UseThreads"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
context->priv->UseThreads = dwValue ? 1 : 0;
|
||||
priv->UseThreads = dwValue ? 1 : 0;
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("MinThreadCount"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
context->priv->MinThreadCount = dwValue;
|
||||
priv->MinThreadCount = dwValue;
|
||||
|
||||
if (RegQueryValueEx(hKey, _T("MaxThreadCount"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
|
||||
context->priv->MaxThreadCount = dwValue;
|
||||
priv->MaxThreadCount = dwValue;
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
if (priv->UseThreads)
|
||||
{
|
||||
/* Call primitives_get here in order to avoid race conditions when using primitives_get */
|
||||
/* from multiple threads. This call will initialize all function pointers correctly */
|
||||
/* before any decoding threads are started */
|
||||
primitives_get();
|
||||
|
||||
context->priv->ThreadPool = CreateThreadpool(NULL);
|
||||
InitializeThreadpoolEnvironment(&context->priv->ThreadPoolEnv);
|
||||
SetThreadpoolCallbackPool(&context->priv->ThreadPoolEnv, context->priv->ThreadPool);
|
||||
priv->ThreadPool = CreateThreadpool(NULL);
|
||||
if (!priv->ThreadPool)
|
||||
goto error_threadPool;
|
||||
InitializeThreadpoolEnvironment(&priv->ThreadPoolEnv);
|
||||
SetThreadpoolCallbackPool(&priv->ThreadPoolEnv, priv->ThreadPool);
|
||||
|
||||
if (context->priv->MinThreadCount)
|
||||
SetThreadpoolThreadMinimum(context->priv->ThreadPool, context->priv->MinThreadCount);
|
||||
if (priv->MinThreadCount)
|
||||
SetThreadpoolThreadMinimum(priv->ThreadPool, priv->MinThreadCount);
|
||||
|
||||
if (context->priv->MaxThreadCount)
|
||||
SetThreadpoolThreadMaximum(context->priv->ThreadPool, context->priv->MaxThreadCount);
|
||||
if (priv->MaxThreadCount)
|
||||
SetThreadpoolThreadMaximum(priv->ThreadPool, priv->MaxThreadCount);
|
||||
}
|
||||
|
||||
/* initialize the default pixel format */
|
||||
@ -335,29 +344,47 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
RFX_INIT_SIMD(context);
|
||||
|
||||
context->state = RFX_STATE_SEND_HEADERS;
|
||||
|
||||
return context;
|
||||
|
||||
error_threadPool:
|
||||
BufferPool_Free(priv->BufferPool);
|
||||
error_BufferPool:
|
||||
ObjectPool_Free(priv->TilePool);
|
||||
error_tilePool:
|
||||
free(priv);
|
||||
error_priv:
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rfx_context_free(RFX_CONTEXT* context)
|
||||
{
|
||||
RFX_CONTEXT_PRIV *priv;
|
||||
|
||||
assert(NULL != context);
|
||||
assert(NULL != context->priv);
|
||||
assert(NULL != context->priv->TilePool);
|
||||
assert(NULL != context->priv->BufferPool);
|
||||
|
||||
priv = context->priv;
|
||||
if (context->quants)
|
||||
free(context->quants);
|
||||
|
||||
ObjectPool_Free(context->priv->TilePool);
|
||||
ObjectPool_Free(priv->TilePool);
|
||||
|
||||
rfx_profiler_print(context);
|
||||
rfx_profiler_free(context);
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
if (priv->UseThreads)
|
||||
{
|
||||
CloseThreadpool(context->priv->ThreadPool);
|
||||
DestroyThreadpoolEnvironment(&context->priv->ThreadPoolEnv);
|
||||
|
||||
if (priv->workObjects)
|
||||
free(priv->workObjects);
|
||||
if (priv->tileWorkParams)
|
||||
free(priv->tileWorkParams);
|
||||
|
||||
#ifdef WITH_PROFILER
|
||||
fprintf(stderr, "\nWARNING: Profiling results probably unusable with multithreaded RemoteFX codec!\n");
|
||||
#endif
|
||||
@ -610,10 +637,7 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (message->rects)
|
||||
message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT));
|
||||
else
|
||||
message->rects = (RFX_RECT*) malloc(message->numRects * sizeof(RFX_RECT));
|
||||
message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT));
|
||||
|
||||
/* rects */
|
||||
for (i = 0; i < message->numRects; i++)
|
||||
@ -624,8 +648,9 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag
|
||||
Stream_Read_UINT16(s, message->rects[i].width); /* width (2 bytes) */
|
||||
Stream_Read_UINT16(s, message->rects[i].height); /* height (2 bytes) */
|
||||
|
||||
WLog_Print(context->priv->log, WLOG_DEBUG, "rect %d (%d %d %d %d).",
|
||||
i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height);
|
||||
WLog_Print(context->priv->log, WLOG_DEBUG, "rect %d (x,y=%d,%d w,h=%d %d).", i,
|
||||
message->rects[i].x, message->rects[i].y,
|
||||
message->rects[i].width, message->rects[i].height);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -695,10 +720,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa
|
||||
|
||||
Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */
|
||||
|
||||
if (context->quants != NULL)
|
||||
context->quants = (UINT32*) realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32));
|
||||
else
|
||||
context->quants = (UINT32*) malloc(context->numQuant * 10 * sizeof(UINT32));
|
||||
context->quants = (UINT32 *)realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32));
|
||||
|
||||
quants = context->quants;
|
||||
|
||||
@ -1127,37 +1149,84 @@ void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta
|
||||
rfx_encode_rgb(param->context, param->tile);
|
||||
}
|
||||
|
||||
RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
|
||||
int numRects, BYTE* data, int width, int height, int scanline)
|
||||
#define ALIGN_DOWN(value, alignto) ((value) - ((value) % (alignto)))
|
||||
#define ALIGN_UP(value, alignto) ( (((value) + (alignto) - 1) / (alignto) ) * (alignto) )
|
||||
|
||||
static BOOL computeRegion(const RFX_RECT* rects, int numRects, REGION16 *region)
|
||||
{
|
||||
int i, close_cnt;
|
||||
int xIdx;
|
||||
int yIdx;
|
||||
int numTilesX;
|
||||
int numTilesY;
|
||||
UINT16 ax, ay;
|
||||
int i;
|
||||
const RFX_RECT *rect = rects;
|
||||
|
||||
for(i = 0; i < numRects; i++, rect++) {
|
||||
RECTANGLE_16 rect16;
|
||||
|
||||
rect16.left = rect->x;
|
||||
rect16.top = rect->y;
|
||||
rect16.right = rect->x + rect->width;
|
||||
rect16.bottom = rect->y + rect->height;
|
||||
|
||||
if (!region16_union_rect(region, region, &rect16))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL setupWorkers(RFX_CONTEXT *context, int nbTiles)
|
||||
{
|
||||
RFX_CONTEXT_PRIV *priv = context->priv;
|
||||
|
||||
if (!context->priv->UseThreads)
|
||||
return TRUE;
|
||||
|
||||
priv->workObjects = (PTP_WORK *)realloc(priv->workObjects, sizeof(PTP_WORK) * nbTiles);
|
||||
if (!priv->workObjects)
|
||||
return FALSE;
|
||||
|
||||
priv->tileWorkParams = (RFX_TILE_COMPOSE_WORK_PARAM *)
|
||||
realloc(priv->tileWorkParams, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * nbTiles);
|
||||
if (!priv->tileWorkParams)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects,
|
||||
BYTE* data, int width, int height, int scanline)
|
||||
{
|
||||
int i, maxNbTiles, maxTilesX, maxTilesY;
|
||||
int xIdx, yIdx, regionNbRects;
|
||||
int gridRelX, gridRelY, ax, ay, bytesPerPixel;
|
||||
RFX_TILE* tile;
|
||||
RFX_RECT* rect;
|
||||
int BytesPerPixel;
|
||||
RFX_RECT* rfxRect;
|
||||
RFX_MESSAGE* message = NULL;
|
||||
PTP_WORK* work_objects = NULL;
|
||||
RFX_TILE_COMPOSE_WORK_PARAM* params = NULL;
|
||||
PTP_WORK* workObject;
|
||||
RFX_TILE_COMPOSE_WORK_PARAM *workParam;
|
||||
|
||||
message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE));
|
||||
REGION16 rectsRegion, tilesRegion;
|
||||
RECTANGLE_16 currentTileRect;
|
||||
const RECTANGLE_16 *regionRect;
|
||||
const RECTANGLE_16 *extents;
|
||||
|
||||
#if 0
|
||||
const RFX_RECT *tt = rects;
|
||||
fprintf(stderr, "input with %d rect(s)\n", numRects);
|
||||
for (i = 0; i < numRects; i++, tt++)
|
||||
fprintf(stderr, "%d: %d,%d -> %d,%d (w=%d h=%d)\n", i,
|
||||
tt->x, tt->y, tt->x + tt->width, tt->y + tt->height,
|
||||
tt->width, tt->height
|
||||
);
|
||||
#endif
|
||||
|
||||
message = (RFX_MESSAGE *)zmalloc(sizeof(RFX_MESSAGE));
|
||||
if (!message)
|
||||
return NULL;
|
||||
|
||||
ZeroMemory(message, sizeof(RFX_MESSAGE));
|
||||
|
||||
if (context->state == RFX_STATE_SEND_HEADERS)
|
||||
rfx_update_context_properties(context);
|
||||
|
||||
message->frameIdx = context->frameIdx++;
|
||||
|
||||
message->numRects = numRects;
|
||||
message->rects = (RFX_RECT*) rects;
|
||||
|
||||
if (!context->numQuant)
|
||||
{
|
||||
context->numQuant = 1;
|
||||
@ -1167,133 +1236,210 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
|
||||
context->quantIdxCb = 0;
|
||||
context->quantIdxCr = 0;
|
||||
}
|
||||
|
||||
rect = (RFX_RECT*) &rects[0];
|
||||
BytesPerPixel = (context->bits_per_pixel / 8);
|
||||
|
||||
message->numQuant = context->numQuant;
|
||||
message->quantVals = context->quants;
|
||||
|
||||
numTilesX = (width + 63) / 64;
|
||||
numTilesY = (height + 63) / 64;
|
||||
rfxRect = (RFX_RECT*) &rects[0];
|
||||
bytesPerPixel = (context->bits_per_pixel / 8);
|
||||
|
||||
message->numTiles = numTilesX * numTilesY;
|
||||
if (message->numTiles)
|
||||
{
|
||||
message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles);
|
||||
ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->numTiles);
|
||||
}
|
||||
region16_init(&rectsRegion);
|
||||
if (!computeRegion(rects, numRects, &rectsRegion))
|
||||
goto out_free_message;
|
||||
extents = region16_extents(&rectsRegion);
|
||||
/* fprintf(stderr, "\n\n%s: nrects(in/simplified)=%d/%d width=%d height=%d bounds=(%d,%d-%d,%d)\n", __FUNCTION__,
|
||||
numRects, region16_n_rects(&rectsRegion),
|
||||
width, height,
|
||||
extents->left, extents->top,
|
||||
extents->right, extents->bottom);*/
|
||||
|
||||
WLog_Print(context->priv->log, WLOG_DEBUG, "x: %d y: %d width: %d height: %d scanline: %d BytesPerPixel: %d",
|
||||
rect->x, rect->y, width, height, scanline, BytesPerPixel);
|
||||
maxTilesX = ALIGN_UP(extents->right - extents->left, 64) / 64;
|
||||
maxTilesY = ALIGN_UP(extents->bottom - extents->top, 64) / 64;
|
||||
maxNbTiles = maxTilesX * maxTilesY;
|
||||
|
||||
message->tiles = zmalloc(maxNbTiles * sizeof(RFX_TILE*));
|
||||
if (!message->tiles)
|
||||
goto out_free_message;
|
||||
|
||||
if (!setupWorkers(context, maxNbTiles))
|
||||
goto out_clean_tiles;
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
{
|
||||
if (message->numTiles)
|
||||
work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles);
|
||||
if (!work_objects)
|
||||
{
|
||||
free(message);
|
||||
return NULL;
|
||||
}
|
||||
params = (RFX_TILE_COMPOSE_WORK_PARAM*)
|
||||
malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * message->numTiles);
|
||||
if (!params)
|
||||
{
|
||||
if (message->tiles)
|
||||
free(message->tiles);
|
||||
free(message);
|
||||
free(work_objects);
|
||||
return NULL;
|
||||
}
|
||||
ZeroMemory(work_objects, sizeof(PTP_WORK) * message->numTiles);
|
||||
ZeroMemory(params, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * message->numTiles);
|
||||
workObject = context->priv->workObjects;
|
||||
workParam = context->priv->tileWorkParams;
|
||||
}
|
||||
|
||||
close_cnt = 0;
|
||||
for (yIdx = 0; yIdx < numTilesY; yIdx++)
|
||||
regionRect = region16_rects(&rectsRegion, ®ionNbRects);
|
||||
message->rects = rfxRect = zmalloc(regionNbRects * sizeof(RFX_RECT));
|
||||
if (!message->rects)
|
||||
goto out_clean_tiles;
|
||||
message->numRects = regionNbRects;
|
||||
|
||||
region16_init(&tilesRegion);
|
||||
|
||||
for (i = 0; i < regionNbRects; i++, regionRect++, rfxRect++)
|
||||
{
|
||||
for (xIdx = 0; xIdx < numTilesX; xIdx++)
|
||||
int startTileX = regionRect->left / 64;
|
||||
int endTileX = (regionRect->right - 1) / 64;
|
||||
|
||||
int startTileY = regionRect->top / 64;
|
||||
int endTileY = (regionRect->bottom - 1) / 64;
|
||||
|
||||
rfxRect->x = regionRect->left;
|
||||
rfxRect->y = regionRect->top;
|
||||
rfxRect->width = (regionRect->right - regionRect->left);
|
||||
rfxRect->height = (regionRect->bottom - regionRect->top);
|
||||
|
||||
/*fprintf(stderr, "%s: rect[%d,%d->%d,%d] start=(%d,%d) end=(%d,%d)\n",
|
||||
__FUNCTION__,
|
||||
regionRect->left, regionRect->top, regionRect->right, regionRect->bottom,
|
||||
startTileX, startTileY,
|
||||
endTileX, endTileY
|
||||
);
|
||||
fprintf(stderr, "rfxRect=%d,%d w/h=%d,%d\n", rfxRect->x, rfxRect->y, rfxRect->width, rfxRect->height);*/
|
||||
|
||||
for (yIdx = startTileY, gridRelY = startTileY * 64; yIdx <= endTileY; yIdx++, gridRelY += 64 )
|
||||
{
|
||||
i = yIdx * numTilesX + xIdx;
|
||||
int tileHeight = 64;
|
||||
if ((yIdx == endTileY) && (gridRelY + 64 > height))
|
||||
tileHeight = height - gridRelY;
|
||||
|
||||
tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool);
|
||||
currentTileRect.top = gridRelY;
|
||||
currentTileRect.bottom = gridRelY + tileHeight;
|
||||
|
||||
tile->xIdx = xIdx;
|
||||
tile->yIdx = yIdx;
|
||||
tile->x = tile->xIdx * 64;
|
||||
tile->y = tile->yIdx * 64;
|
||||
tile->scanline = scanline;
|
||||
tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64;
|
||||
tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64;
|
||||
|
||||
ax = rect->x + tile->x;
|
||||
ay = rect->y + tile->y;
|
||||
if (tile->data && tile->allocated)
|
||||
for (xIdx = startTileX, gridRelX = startTileX * 64; xIdx <= endTileX; xIdx++, gridRelX += 64)
|
||||
{
|
||||
free(tile->data);
|
||||
tile->allocated = FALSE;
|
||||
}
|
||||
tile->data = &data[(ay * scanline) + (ax * BytesPerPixel)];
|
||||
int tileWidth = 64;
|
||||
if ((xIdx == endTileX) && (gridRelX + 64 > width))
|
||||
tileWidth = width - gridRelX;
|
||||
|
||||
tile->quantIdxY = context->quantIdxY;
|
||||
tile->quantIdxCb = context->quantIdxCb;
|
||||
tile->quantIdxCr = context->quantIdxCr;
|
||||
currentTileRect.left = gridRelX;
|
||||
currentTileRect.right = gridRelX + tileWidth;
|
||||
|
||||
tile->YLen = 0;
|
||||
tile->CbLen = 0;
|
||||
tile->CrLen = 0;
|
||||
/* checks if this tile is already treated */
|
||||
if (region16_intersects_rect(&tilesRegion, ¤tTileRect)) {
|
||||
/*fprintf(stderr, "skipping %d,%d -> %d,%d\n",
|
||||
currentTileRect.left, currentTileRect.top,
|
||||
currentTileRect.right, currentTileRect.bottom
|
||||
);*/
|
||||
continue;
|
||||
}
|
||||
|
||||
tile->YCbCrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
tile = (RFX_TILE *)ObjectPool_Take(context->priv->TilePool);
|
||||
if (!tile)
|
||||
goto out_clean_rects;;
|
||||
|
||||
tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]);
|
||||
tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]);
|
||||
tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]);
|
||||
tile->xIdx = xIdx;
|
||||
tile->yIdx = yIdx;
|
||||
tile->x = gridRelX;
|
||||
tile->y = gridRelY;
|
||||
tile->scanline = scanline;
|
||||
tile->width = tileWidth;
|
||||
tile->height = tileHeight;
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
{
|
||||
assert(params);
|
||||
/*fprintf(stderr, "tile(%d,%d) - %d,%d->%d,%d (x=%d,y=%d,w=%d,h=%d),\n",
|
||||
tile->xIdx, tile->yIdx,
|
||||
currentTileRect.left, currentTileRect.top,
|
||||
currentTileRect.right, currentTileRect.bottom,
|
||||
tile->x, tile->y,
|
||||
tile->width, tile->height
|
||||
);*/
|
||||
|
||||
params[i].context = context;
|
||||
params[i].tile = tile;
|
||||
ax = gridRelX;
|
||||
ay = gridRelY;
|
||||
if (tile->data && tile->allocated)
|
||||
{
|
||||
free(tile->data);
|
||||
tile->allocated = FALSE;
|
||||
}
|
||||
tile->data = &data[(ay * scanline) + (ax * bytesPerPixel)];
|
||||
|
||||
work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback,
|
||||
(void*) ¶ms[i], &context->priv->ThreadPoolEnv);
|
||||
tile->quantIdxY = context->quantIdxY;
|
||||
tile->quantIdxCb = context->quantIdxCb;
|
||||
tile->quantIdxCr = context->quantIdxCr;
|
||||
|
||||
SubmitThreadpoolWork(work_objects[i]);
|
||||
close_cnt = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfx_encode_rgb(context, tile);
|
||||
}
|
||||
}
|
||||
tile->YLen = tile->CbLen = tile->CrLen = 0;
|
||||
|
||||
tile->YCbCrData = (BYTE *)BufferPool_Take(context->priv->BufferPool, -1);
|
||||
if (!tile->YCbCrData)
|
||||
goto out_clean_rects;
|
||||
|
||||
tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]);
|
||||
tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]);
|
||||
tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]);
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
{
|
||||
workParam->context = context;
|
||||
workParam->tile = tile;
|
||||
|
||||
*workObject = CreateThreadpoolWork(
|
||||
(PTP_WORK_CALLBACK)rfx_compose_message_tile_work_callback,
|
||||
(void *)workParam,
|
||||
&context->priv->ThreadPoolEnv
|
||||
);
|
||||
|
||||
SubmitThreadpoolWork(*workObject);
|
||||
|
||||
workObject++;
|
||||
workParam++;
|
||||
}
|
||||
else
|
||||
{
|
||||
rfx_encode_rgb(context, tile);
|
||||
}
|
||||
|
||||
message->tiles[message->numTiles] = tile;
|
||||
message->numTiles++;
|
||||
|
||||
if (!region16_union_rect(&tilesRegion, &tilesRegion, ¤tTileRect))
|
||||
goto out_clean_rects;
|
||||
} /* xIdx */
|
||||
} /* yIdx */
|
||||
} /* rects */
|
||||
|
||||
if (message->numTiles != maxNbTiles)
|
||||
{
|
||||
message->tiles = realloc(message->tiles, sizeof(RFX_TILE *) * message->numTiles);
|
||||
if (!message->tiles)
|
||||
goto out_clean_rects;
|
||||
}
|
||||
|
||||
message->tilesDataSize = 0;
|
||||
region16_uninit(&tilesRegion);
|
||||
|
||||
for (i = 0; i < close_cnt; i++)
|
||||
/* when using threads ensure all computations are done */
|
||||
message->tilesDataSize = 0;
|
||||
workObject = context->priv->workObjects;
|
||||
for (i = 0; i < message->numTiles; i++)
|
||||
{
|
||||
tile = message->tiles[i];
|
||||
|
||||
if (context->priv->UseThreads && work_objects)
|
||||
if (context->priv->UseThreads)
|
||||
{
|
||||
WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE);
|
||||
CloseThreadpoolWork(work_objects[i]);
|
||||
WaitForThreadpoolWorkCallbacks(*workObject, FALSE);
|
||||
CloseThreadpoolWork(*workObject);
|
||||
workObject++;
|
||||
}
|
||||
|
||||
message->tilesDataSize += rfx_tile_length(tile);
|
||||
}
|
||||
|
||||
if (work_objects)
|
||||
free(work_objects);
|
||||
|
||||
if (params)
|
||||
free(params);
|
||||
|
||||
region16_uninit(&rectsRegion);
|
||||
return message;
|
||||
|
||||
out_clean_rects:
|
||||
free(message->rects);
|
||||
out_clean_tiles:
|
||||
free(message->tiles);
|
||||
region16_uninit(&tilesRegion);
|
||||
out_free_message:
|
||||
fprintf(stderr, "remoteFx error\n");
|
||||
region16_uninit(&rectsRegion);
|
||||
free(message);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* numMessages, int maxDataSize)
|
||||
{
|
||||
int i, j;
|
||||
@ -1432,14 +1578,8 @@ void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* mes
|
||||
{
|
||||
/* Clipping rectangles are relative to destLeft, destTop */
|
||||
|
||||
#if 1
|
||||
Stream_Write_UINT16(s, 0); /* x (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* y (2 bytes) */
|
||||
#else
|
||||
Stream_Write_UINT16(s, message->rects[i].x); /* x (2 bytes) */
|
||||
Stream_Write_UINT16(s, message->rects[i].y); /* y (2 bytes) */
|
||||
#endif
|
||||
|
||||
Stream_Write_UINT16(s, message->rects[i].width); /* width (2 bytes) */
|
||||
Stream_Write_UINT16(s, message->rects[i].height); /* height (2 bytes) */
|
||||
}
|
||||
@ -1483,3 +1623,4 @@ void rfx_compose_message(RFX_CONTEXT* context, wStream* s,
|
||||
|
||||
rfx_message_free(context, message);
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,18 @@
|
||||
#define DEBUG_RFX(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
struct _RFX_TILE_COMPOSE_WORK_PARAM;
|
||||
typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM;
|
||||
|
||||
struct _RFX_CONTEXT_PRIV
|
||||
{
|
||||
wLog* log;
|
||||
wObjectPool* TilePool;
|
||||
|
||||
BOOL UseThreads;
|
||||
PTP_WORK* workObjects;
|
||||
RFX_TILE_COMPOSE_WORK_PARAM* tileWorkParams;
|
||||
|
||||
DWORD MinThreadCount;
|
||||
DWORD MaxThreadCount;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user