예제 #1
0
static int test_empty_rectangle(void)
{
	REGION16 region, intersection;
	int retCode = -1;
	int i;
	RECTANGLE_16 emptyRectangles[3] =
	{
		{   0,    0,    0,    0},
		{  10,   10,   10,   11},
		{  10,   10,   11,   10}
	};
	RECTANGLE_16 firstRect =
	{
		0, 0, 100, 100
	};
	RECTANGLE_16 anotherRect =
	{
		100, 100,  200,  200
	};
	RECTANGLE_16 expected_inter_extents =
	{
		0, 0, 0, 0
	};
	region16_init(&region);
	region16_init(&intersection);

	/* Check for empty rectangles */
	for (i = 0; i < 3; i++)
	{
		if (!rectangle_is_empty(&emptyRectangles[i]))
			goto out;
	}

	/* Check for non-empty rectangles */
	if (rectangle_is_empty(&firstRect))
		goto out;

	/* Intersect 2 non-intersect rectangle, result should be empty */
	if (!region16_union_rect(&region, &region, &firstRect))
		goto out;

	if (!region16_intersect_rect(&region, &region, &anotherRect))
		goto out;

	if (!compareRectangles(region16_extents(&region), &expected_inter_extents, 1))
		goto out;

	if (!region16_is_empty(&region))
		goto out;

	if (!rectangle_is_empty(region16_extents(&intersection)))
		goto out;

	retCode = 0;
out:
	region16_uninit(&intersection);
	region16_uninit(&region);
	return retCode;
}
예제 #2
0
파일: region.c 프로젝트: JozLes77/FreeRDP
BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2)
{
	const RECTANGLE_16 *rect, *endPtr, *srcExtents;
	int nbRects;

	assert(src);
	assert(src->data);

	rect = region16_rects(src, &nbRects);

	if (!nbRects)
		return FALSE;

	srcExtents = region16_extents(src);

	if (nbRects == 1)
		return rectangles_intersects(srcExtents, arg2);

	if (!rectangles_intersects(srcExtents, arg2))
		return FALSE;

	endPtr = rect + nbRects;

	for (endPtr = rect + nbRects; (rect < endPtr) && (arg2->bottom > rect->top); rect++)
	{
		if (rectangles_intersects(rect, arg2))
			return TRUE;
	}

	return FALSE;
}
예제 #3
0
파일: gfx.c 프로젝트: apprisi/FreeRDP
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;
}
예제 #4
0
파일: gfx.c 프로젝트: Graf3x/FreeRDP
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;
}
예제 #5
0
파일: xf_gfx.c 프로젝트: davidleake/FreeRDP
int xf_OutputUpdate(xfContext* xfc)
{
	UINT16 width, height;
	xfGfxSurface* surface;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16* extents;

	if (!xfc->graphicsReset)
		return 1;

	surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId);

	if (!surface)
		return -1;

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = xfc->width;
	surfaceRect.bottom = xfc->height;

	region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect);

	XSetClipMask(xfc->display, xfc->gc, None);
	XSetFunction(xfc->display, xfc->gc, GXcopy);
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);

	if (!region16_is_empty(&(xfc->invalidRegion)))
	{
		extents = region16_extents(&(xfc->invalidRegion));

		width = extents->right - extents->left;
		height = extents->bottom - extents->top;

		if (width > xfc->width)
			width = xfc->width;

		if (height > xfc->height)
			height = xfc->height;

		XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
				extents->left, extents->top,
				extents->left, extents->top, width, height);
	}

	region16_clear(&(xfc->invalidRegion));

	XSetClipMask(xfc->display, xfc->gc, None);
	XSync(xfc->display, True);

	return 1;
}
예제 #6
0
파일: xf_rail.c 프로젝트: bceverly/FreeRDP
void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
{
	int index;
	int count;
	RECTANGLE_16 updateRect;
	RECTANGLE_16 windowRect;
	ULONG_PTR* pKeys = NULL;
	xfAppWindow* appWindow;
	const RECTANGLE_16* extents;
	REGION16 windowInvalidRegion;

	region16_init(&windowInvalidRegion);

	count = HashTable_GetKeys(xfc->railWindows, &pKeys);

	for (index = 0; index < count; index++)
	{
		appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);

		if (appWindow)
		{
			windowRect.left = MAX(appWindow->x, 0);
			windowRect.top = MAX(appWindow->y, 0);
			windowRect.right = MAX(appWindow->x + appWindow->width, 0);
			windowRect.bottom = MAX(appWindow->y + appWindow->height, 0);

			region16_clear(&windowInvalidRegion);
			region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);

			if (!region16_is_empty(&windowInvalidRegion))
			{
				extents = region16_extents(&windowInvalidRegion);

				updateRect.left = extents->left - appWindow->x;
				updateRect.top = extents->top - appWindow->y;
				updateRect.right = extents->right - appWindow->x;
				updateRect.bottom = extents->bottom - appWindow->y;

				if (appWindow)
				{
					xf_UpdateWindowArea(xfc, appWindow, updateRect.left, updateRect.top,
							updateRect.right - updateRect.left,
							updateRect.bottom - updateRect.top);
				}
			}
		}
	}

	region16_uninit(&windowInvalidRegion);
}
예제 #7
0
파일: wf_client.c 프로젝트: C4rt/FreeRDP
BOOL wf_sw_end_paint(wfContext* wfc)
{
	int i;
	rdpGdi* gdi;
	int ninvalid;
	RECT updateRect;
	HGDI_RGN cinvalid;
	REGION16 invalidRegion;
	RECTANGLE_16 invalidRect;
	const RECTANGLE_16* extents;
	rdpContext* context = (rdpContext*) wfc;

	gdi = context->gdi;

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

	if (ninvalid < 1)
		return TRUE;

	region16_init(&invalidRegion);

	for (i = 0; i < ninvalid; i++)
	{
		invalidRect.left = cinvalid[i].x;
		invalidRect.top = cinvalid[i].y;
		invalidRect.right = cinvalid[i].x + cinvalid[i].w;
		invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;

		region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
	}

	if (!region16_is_empty(&invalidRegion))
	{
		extents = region16_extents(&invalidRegion);

		updateRect.left = extents->left;
		updateRect.top = extents->top;
		updateRect.right = extents->right;
		updateRect.bottom = extents->bottom;

		InvalidateRect(wfc->hwnd, &updateRect, FALSE);

		if (wfc->rail)
			wf_rail_invalidate_region(wfc, &invalidRegion);
	}

	region16_uninit(&invalidRegion);
	return TRUE;
}
예제 #8
0
파일: wf_rail.c 프로젝트: AMV007/FreeRDP
void wf_rail_invalidate_region(wfContext* wfc, REGION16* invalidRegion)
{
	int index;
	int count;
	RECT updateRect;
	RECTANGLE_16 windowRect;
	ULONG_PTR* pKeys = NULL;
	wfRailWindow* railWindow;
	const RECTANGLE_16* extents;
	REGION16 windowInvalidRegion;

	region16_init(&windowInvalidRegion);

	count = HashTable_GetKeys(wfc->railWindows, &pKeys);

	for (index = 0; index < count; index++)
	{
		railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows, (void*) pKeys[index]);

		if (railWindow)
		{
			windowRect.left = railWindow->x;
			windowRect.top = railWindow->y;
			windowRect.right = railWindow->x + railWindow->width;
			windowRect.bottom = railWindow->y + railWindow->height;

			region16_clear(&windowInvalidRegion);
			region16_intersect_rect(&windowInvalidRegion, invalidRegion, &windowRect);

			if (!region16_is_empty(&windowInvalidRegion))
			{
				extents = region16_extents(&windowInvalidRegion);

				updateRect.left = extents->left - railWindow->x;
				updateRect.top = extents->top - railWindow->y;
				updateRect.right = extents->right - railWindow->x;
				updateRect.bottom = extents->bottom - railWindow->y;

				InvalidateRect(railWindow->hWnd, &updateRect, FALSE);
			}
		}
	}

	region16_uninit(&windowInvalidRegion);
}
예제 #9
0
static int test_norbert_case() {
	REGION16 region, intersection;
	int retCode = -1;
	const RECTANGLE_16 *rects;
	int nbRects, i;

	RECTANGLE_16 inRectangles[5] = {
			{1680,    0, 1920,  242},
			{ 294,  242,  971,  776},
			{1680,  242, 1920,  776},
			{1680,  776, 1920, 1036},
			{   2, 1040,   53, 1078}
	};

	RECTANGLE_16 screenRect = {
		0, 0, 1920, 1080
	};
	RECTANGLE_16 expected_inter_extents = {
		0, 0, 1920, 1078
	};

	region16_init(&region);
	region16_init(&intersection);

	for (i = 0; i < 5; i++)
	{
		if (!region16_union_rect(&region, &region, &inRectangles[i]))
			goto out;
	}

	if (!region16_intersect_rect(&intersection, &region, &screenRect))
		goto out;
	rects = region16_rects(&intersection, &nbRects);
	if (!rects || nbRects != 5 || !compareRectangles(rects, inRectangles, nbRects))
		goto out;

	if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1) )
		goto out;

	retCode = 0;
out:
	region16_uninit(&intersection);
	region16_uninit(&region);
	return retCode;
}
예제 #10
0
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;
}
예제 #11
0
static int test_norbert_case(void)
{
	REGION16 region, intersection;
	int retCode = -1;
	const RECTANGLE_16* rects;
	UINT32 nbRects, i;
	RECTANGLE_16 inRectangles[5] =
	{
		{1680,    0, 1920,  242},
		{ 294,  242,  971,  776},
		{1680,  242, 1920,  776},
		{1680,  776, 1920, 1036},
		{   2, 1040,   53, 1078}
	};
	RECTANGLE_16 screenRect =
	{
		0, 0, 1920, 1080
	};
	RECTANGLE_16 expected_inter_extents =
	{
		2, 0, 1920, 1078
	};
	region16_init(&region);
	region16_init(&intersection);

	/*
	 * Consider following as a screen with resolution 1920*1080
	 *      | |    |     |           |               |      |
	 *      | |2   |53   |294        |971            |1680  |
	 *      | |    |     |           |               |      |
	 *    0 +=+======================================+======+
	 *      | |                                      |      |
	 *      |                                        |  R[0]|
	 *  242 |            +-----------+               +------+
	 *      | |          |           |               |      |
	 *      |            |           |               |      |
	 *      |            |       R[1]|               |  R[2]|
	 *  776 | |          +-----------+               +------+
	 *      |                                        |      |
	 *      |                                        |  R[3]|
	 * 1036 | |                                      +------+
	 * 1040 | +----+
	 *      | |R[4]|                         Union of R[0-4]|
	 * 1078 | +----+    -    -    -    -    -    -    -    -+
	 * 1080 |
	 *
	 *
	 * The result is union of R[0] - R[4].
	 * After intersected with the full screen rect, the
	 * result should keep the same.
	 */
	for (i = 0; i < 5; i++)
	{
		if (!region16_union_rect(&region, &region, &inRectangles[i]))
			goto out;
	}

	if (!compareRectangles(region16_extents(&region), &expected_inter_extents, 1))
		goto out;

	if (!region16_intersect_rect(&intersection, &region, &screenRect))
		goto out;

	rects = region16_rects(&intersection, &nbRects);

	if (!rects || nbRects != 5 || !compareRectangles(rects, inRectangles, nbRects))
		goto out;

	if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1))
		goto out;

	retCode = 0;
out:
	region16_uninit(&intersection);
	region16_uninit(&region);
	return retCode;
}
예제 #12
0
파일: xf_gfx.c 프로젝트: DavBfr/FreeRDP
static int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
{
	UINT16 width, height;
	UINT32 surfaceX, surfaceY;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16* extents;

	surfaceX = surface->outputOriginX;
	surfaceY = surface->outputOriginY;

	surfaceRect.left = surfaceX;
	surfaceRect.top = surfaceY;
	surfaceRect.right = surfaceX + surface->width;
	surfaceRect.bottom = surfaceY + surface->height;

	XSetClipMask(xfc->display, xfc->gc, None);
	XSetFunction(xfc->display, xfc->gc, GXcopy);
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);

	if (!region16_is_empty(&surface->invalidRegion))
	{
		extents = region16_extents(&surface->invalidRegion);

		width = extents->right - extents->left;
		height = extents->bottom - extents->top;

		if (width > surface->width)
			width = surface->width;

		if (height > surface->height)
			height = surface->height;

		if (surface->stage)
		{
			freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0,
				surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL);
		}

#ifdef WITH_XRENDER
		if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
		{
			XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
				extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);

			xf_draw_screen(xfc, extents->left, extents->top, width, height);
		}
		else
#endif
		{
			XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
				extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);
		}
	}

	region16_clear(&surface->invalidRegion);

	XSetClipMask(xfc->display, xfc->gc, None);
	XSync(xfc->display, False);

	return 1;
}
예제 #13
0
파일: rfx.c 프로젝트: C4rt/FreeRDP
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* rfxRect;
	RFX_MESSAGE* message = NULL;
	PTP_WORK* workObject = NULL;
	RFX_TILE_COMPOSE_WORK_PARAM *workParam = NULL;
	BOOL success = FALSE;

	REGION16 rectsRegion, tilesRegion;
	RECTANGLE_16 currentTileRect;
	const RECTANGLE_16 *regionRect;
	const RECTANGLE_16 *extents;

	assert(data);
	assert(rects);
	assert(numRects > 0);
	assert(width > 0);
	assert(height > 0);
	assert(scanline > 0);

	if (!(message = (RFX_MESSAGE*)calloc(1, sizeof(RFX_MESSAGE))))
		return NULL;

	region16_init(&tilesRegion);
	region16_init(&rectsRegion);

	if (context->state == RFX_STATE_SEND_HEADERS)
		rfx_update_context_properties(context);

	message->frameIdx = context->frameIdx++;

	if (!context->numQuant)
	{
		if (!(context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values))))
			goto skip_encoding_loop;

		CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values));
		context->numQuant = 1;
		context->quantIdxY = 0;
		context->quantIdxCb = 0;
		context->quantIdxCr = 0;
	}

	message->numQuant = context->numQuant;
	message->quantVals = context->quants;

	bytesPerPixel = (context->bits_per_pixel / 8);

	if (!computeRegion(rects, numRects, &rectsRegion, width, height))
		goto skip_encoding_loop;

	extents = region16_extents(&rectsRegion);
	assert(extents->right - extents->left > 0);
	assert(extents->bottom - extents->top > 0);

	maxTilesX = 1 + TILE_NO(extents->right - 1) - TILE_NO(extents->left);
	maxTilesY = 1 + TILE_NO(extents->bottom - 1) - TILE_NO(extents->top);
	maxNbTiles = maxTilesX * maxTilesY;

	if (!(message->tiles = calloc(maxNbTiles, sizeof(RFX_TILE*))))
		goto skip_encoding_loop;

	if (!setupWorkers(context, maxNbTiles))
		goto skip_encoding_loop;

	if (context->priv->UseThreads)
	{
		workObject = context->priv->workObjects;
		workParam = context->priv->tileWorkParams;
	}

	regionRect = region16_rects(&rectsRegion, &regionNbRects);

	if (!(message->rects = calloc(regionNbRects, sizeof(RFX_RECT))))
		goto skip_encoding_loop;

	message->numRects = regionNbRects;

	for (i = 0, rfxRect = message->rects; i < regionNbRects; i++, regionRect++, rfxRect++)
	{
		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);


		for (yIdx = startTileY, gridRelY = startTileY * 64; yIdx <= endTileY; yIdx++, gridRelY += 64 )
		{
			int tileHeight = 64;

			if ((yIdx == endTileY) && (gridRelY + 64 > height))
				tileHeight = height - gridRelY;

			currentTileRect.top = gridRelY;
			currentTileRect.bottom = gridRelY + tileHeight;

			for (xIdx = startTileX, gridRelX = startTileX * 64; xIdx <= endTileX; xIdx++, gridRelX += 64)
			{
				int tileWidth = 64;

				if ((xIdx == endTileX) && (gridRelX + 64 > width))
					tileWidth = width - gridRelX;

				currentTileRect.left = gridRelX;
				currentTileRect.right = gridRelX + tileWidth;

				/* checks if this tile is already treated */
				if (region16_intersects_rect(&tilesRegion, &currentTileRect))
					continue;

				if (!(tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool)))
					goto skip_encoding_loop;

				tile->xIdx = xIdx;
				tile->yIdx = yIdx;
				tile->x = gridRelX;
				tile->y = gridRelY;
				tile->scanline = scanline;
				tile->width = tileWidth;
				tile->height = tileHeight;

				ax = gridRelX;
				ay = gridRelY;

				if (tile->data && tile->allocated)
				{
					free(tile->data);
					tile->allocated = FALSE;
				}
				tile->data = &data[(ay * scanline) + (ax * bytesPerPixel)];

				tile->quantIdxY = context->quantIdxY;
				tile->quantIdxCb = context->quantIdxCb;
				tile->quantIdxCr = context->quantIdxCr;

				tile->YLen = tile->CbLen = tile->CrLen = 0;

				if (!(tile->YCbCrData = (BYTE *)BufferPool_Take(context->priv->BufferPool, -1)))
					goto skip_encoding_loop;

				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]);

				message->tiles[message->numTiles] = tile;
				message->numTiles++;

				if (context->priv->UseThreads)
				{
					workParam->context = context;
					workParam->tile = tile;

					if (!(*workObject = CreateThreadpoolWork(
							(PTP_WORK_CALLBACK)rfx_compose_message_tile_work_callback,
							(void*) workParam,
							&context->priv->ThreadPoolEnv)))
					{
						goto skip_encoding_loop;
					}

					SubmitThreadpoolWork(*workObject);

					workObject++;
					workParam++;
				}
				else
				{
					rfx_encode_rgb(context, tile);
				}

				if (!region16_union_rect(&tilesRegion, &tilesRegion, &currentTileRect))
					goto skip_encoding_loop;
			} /* xIdx */
		}  /* yIdx */
	}  /* rects */

	success = TRUE;

skip_encoding_loop:

	if (success && message->numTiles != maxNbTiles)
	{
		void* pmem = realloc((void*) message->tiles, sizeof(RFX_TILE*) * message->numTiles);

		if (pmem)
			message->tiles = (RFX_TILE**) pmem;
		else
			success = FALSE;
	}

	/* 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)
		{
			if (*workObject)
			{
				WaitForThreadpoolWorkCallbacks(*workObject, FALSE);
				CloseThreadpoolWork(*workObject);
			}
			workObject++;
		}

		message->tilesDataSize += rfx_tile_length(tile);
	}

	region16_uninit(&tilesRegion);
	region16_uninit(&rectsRegion);

	if (success)
		return message;

	WLog_ERR(TAG, "%s: failed", __FUNCTION__);

	message->freeRects = TRUE;
	rfx_message_free(context, message);
	return NULL;
}
예제 #14
0
파일: region.c 프로젝트: JozLes77/FreeRDP
BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect)
{
	REGION16_DATA *newItems;
	const RECTANGLE_16 *srcPtr, *endPtr, *srcExtents;
	RECTANGLE_16 *dstPtr;
	int nbRects, usedRects;
	RECTANGLE_16 common, newExtents;

	assert(src);
	assert(src->data);

	srcPtr = region16_rects(src, &nbRects);

	if (!nbRects)
	{
		region16_clear(dst);
		return TRUE;
	}

	srcExtents = region16_extents(src);

	if (nbRects == 1)
	{
		BOOL intersects = rectangles_intersection(srcExtents, rect, &common);

		region16_clear(dst);

		if (intersects)
			return region16_union_rect(dst, dst, &common);

		return TRUE;
	}

	newItems = allocateRegion(nbRects);

	if (!newItems)
		return FALSE;

	dstPtr = (RECTANGLE_16*) (&newItems[1]);
	usedRects = 0;
	ZeroMemory(&newExtents, sizeof(newExtents));

	/* accumulate intersecting rectangles, the final region16_simplify_bands() will
	 * do all the bad job to recreate correct rectangles
	 */
	for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++)
	{
		if (rectangles_intersection(srcPtr, rect, &common))
		{
			*dstPtr = common;
			usedRects++;
			dstPtr++;

			newExtents.top = MIN(common.top, newExtents.top);
			newExtents.left = MIN(common.left, newExtents.left);
			newExtents.bottom = MAX(common.bottom, newExtents.bottom);
			newExtents.right = MAX(common.right, newExtents.right);
		}
	}

	newItems->nbRects = usedRects;
	newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));

	if (dst->data->size)
		free(dst->data);

	dst->data = realloc(newItems, newItems->size);

	if (!dst->data)
	{
		free(newItems);
		return FALSE;
	}

	dst->extents = newExtents;
	return region16_simplify_bands(dst);
}
예제 #15
0
파일: region.c 프로젝트: JozLes77/FreeRDP
BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect)
{
	const RECTANGLE_16* srcExtents;
	RECTANGLE_16* dstExtents;
	const RECTANGLE_16 *currentBand, *endSrcRect, *nextBand;
	REGION16_DATA* newItems = NULL;
	RECTANGLE_16* dstRect = NULL;
	int usedRects, srcNbRects;
	UINT16 topInterBand;

	assert(src);
	assert(src->data);
	assert(dst);

	srcExtents = region16_extents(src);
	dstExtents = region16_extents_noconst(dst);

	if (!region16_n_rects(src))
	{
		/* source is empty, so the union is rect */
		dst->extents = *rect;
		dst->data = allocateRegion(1);

		if (!dst->data)
			return FALSE;

		dstRect = region16_rects_noconst(dst);

		dstRect->top = rect->top;
		dstRect->left = rect->left;
		dstRect->right = rect->right;
		dstRect->bottom = rect->bottom;

		return TRUE;
	}

	newItems = allocateRegion((1 + region16_n_rects(src)) * 4);

	if (!newItems)
		return FALSE;

	dstRect = (RECTANGLE_16*) (&newItems[1]);
	usedRects = 0;

	/* adds the piece of rect that is on the top of src */
	if (rect->top < srcExtents->top)
	{
		dstRect->top = rect->top;
		dstRect->left = rect->left;
		dstRect->right = rect->right;
		dstRect->bottom = srcExtents->top;

		usedRects++;
		dstRect++;
	}

	/* treat possibly overlapping region */
	currentBand = region16_rects(src, &srcNbRects);
	endSrcRect = currentBand + srcNbRects;

	while (currentBand < endSrcRect)
	{
		if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) ||
			rectangle_contained_in_band(currentBand, endSrcRect, rect))
		{
			/* no overlap between rect and the band, rect is totally below or totally above
			 * the current band, or rect is already covered by an item of the band.
			 * let's copy all the rectangles from this band
						+----+
						|    |   rect (case 1)
						+----+

			   =================
                   band of srcRect
			   =================
						+----+
						|    |   rect (case 2)
						+----+
			 */
			region16_copy_band_with_union(dstRect,
					currentBand, endSrcRect,
					currentBand->top, currentBand->bottom,
					NULL, &usedRects,
					&nextBand, &dstRect);
			topInterBand = rect->top;
		}
		else
		{

			/* rect overlaps the band:
		                           |    |  |    |
             ====^=================|    |==|    |=========================== band
                 |   top split     |    |  |    |
                 v                 | 1  |  | 2  |
                 ^                 |    |  |    |  +----+   +----+
                 |   merge zone    |    |  |    |  |    |   | 4  |
                 v                 +----+  |    |  |    |   +----+
                 ^                         |    |  | 3  |
                 |   bottom split          |    |  |    |
             ====v=========================|    |==|    |===================
                                           |    |  |    |

			 possible cases:
			 1) no top split, merge zone then a bottom split. The band will be splitted
			  in two
			 2) not band split, only the merge zone, band merged with rect but not splitted
			 3) a top split, the merge zone and no bottom split. The band will be split
			 in two
			 4) a top split, the merge zone and also a bottom split. The band will be
			 splitted in 3, but the coalesce algorithm may merge the created bands
			 */
			UINT16 mergeTop = currentBand->top;
			UINT16 mergeBottom = currentBand->bottom;

			/* test if we need a top split, case 3 and 4 */
			if (rect->top > currentBand->top)
			{
				region16_copy_band_with_union(dstRect,
						currentBand, endSrcRect,
						currentBand->top, rect->top,
						NULL, &usedRects,
						&nextBand, &dstRect);
				mergeTop = rect->top;
			}

			/* do the merge zone (all cases) */
			if (rect->bottom < currentBand->bottom)
				mergeBottom = rect->bottom;

			region16_copy_band_with_union(dstRect,
					currentBand, endSrcRect,
					mergeTop, mergeBottom,
					rect, &usedRects,
					&nextBand, &dstRect);

			/* test if we need a bottom split, case 1 and 4 */
			if (rect->bottom < currentBand->bottom)
			{
				region16_copy_band_with_union(dstRect,
						currentBand, endSrcRect,
						mergeBottom, currentBand->bottom,
						NULL, &usedRects,
						&nextBand, &dstRect);
			}
			topInterBand = currentBand->bottom;
		}

		/* test if a piece of rect should be inserted as a new band between
		 * the current band and the next one. band n and n+1 shouldn't touch.
		 *
		 * ==============================================================
		 *                                                        band n
		 *            +------+                    +------+
		 * ===========| rect |====================|      |===============
		 *            |      |    +------+        |      |
		 *            +------+    | rect |        | rect |
		 *                        +------+        |      |
		 * =======================================|      |================
		 *                                        +------+         band n+1
		 * ===============================================================
		 *
		 */
		if ((nextBand < endSrcRect) && (nextBand->top != currentBand->bottom) &&
				(rect->bottom > currentBand->bottom) && (rect->top < nextBand->top))
		{
			dstRect->right = rect->right;
			dstRect->left = rect->left;
			dstRect->top = topInterBand;
			dstRect->bottom = MIN(nextBand->top, rect->bottom);
			dstRect++; usedRects++;
		}

		currentBand = nextBand;
	}

	/* adds the piece of rect that is below src */
	if (srcExtents->bottom < rect->bottom)
	{
		dstRect->top = MAX(srcExtents->bottom, rect->top);
		dstRect->left = rect->left;
		dstRect->right = rect->right;
		dstRect->bottom = rect->bottom;

		usedRects++;
		dstRect++;
	}

	if ((src == dst) && (src->data->size))
		free(src->data);

	dstExtents->top = MIN(rect->top, srcExtents->top);
	dstExtents->left = MIN(rect->left, srcExtents->left);
	dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom);
	dstExtents->right = MAX(rect->right, srcExtents->right);

	newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));
	dst->data = realloc(newItems, newItems->size);

	if (!dst->data)
	{
		free(newItems);
		return FALSE;
	}

	dst->data->nbRects = usedRects;

	return region16_simplify_bands(dst);
}
예제 #16
0
파일: x11_shadow.c 프로젝트: AMV007/FreeRDP
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
{
	int count;
	int status;
	int x, y;
	int width, height;
	XImage* image;
	rdpShadowScreen* screen;
	rdpShadowServer* server;
	rdpShadowSurface* surface;
	RECTANGLE_16 invalidRect;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16 *extents;

	server = subsystem->server;
	surface = server->surface;
	screen = server->screen;

	count = ArrayList_Count(server->clients);

	if (count < 1)
		return 1;

	if ((count == 1) && subsystem->suppressOutput)
		return 1;

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = surface->width;
	surfaceRect.bottom = surface->height;

	XLockDisplay(subsystem->display);

	if (subsystem->use_xshm)
	{
		image = subsystem->fb_image;

		XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
				subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);

		status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
				(BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect);
	}
	else
	{
		image = XGetImage(subsystem->display, subsystem->root_window,
					surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);

		status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
				(BYTE*) image->data, image->bytes_per_line, &invalidRect);
	}

	XSync(subsystem->display, False);

	XUnlockDisplay(subsystem->display);

	region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
	region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);

	if (!region16_is_empty(&(subsystem->invalidRegion)))
	{
		extents = region16_extents(&(subsystem->invalidRegion));

		x = extents->left;
		y = extents->top;
		width = extents->right - extents->left;
		height = extents->bottom - extents->top;

		freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
				surface->scanline, x, y, width, height,
				(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
				image->bytes_per_line, x, y, NULL);

		//x11_shadow_blend_cursor(subsystem);

		count = ArrayList_Count(server->clients);

		InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);

		SetEvent(subsystem->updateEvent);

		EnterSynchronizationBarrier(&(subsystem->barrier), 0);

		DeleteSynchronizationBarrier(&(subsystem->barrier));

		if (count == 1)
		{
			rdpShadowClient* client;

			client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);

			if (client)
			{
				subsystem->captureFrameRate = client->encoder->fps;
			}
		}

		ResetEvent(subsystem->updateEvent);

		region16_clear(&(subsystem->invalidRegion));
	}

	if (!subsystem->use_xshm)
		XDestroyImage(image);

	return 1;
}
예제 #17
0
int freerds_message_server_queue_pack(rdsBackendConnector* connector)
{
	RDS_RECT rect;
	int ChainedMode;
	REGION16 region;
	wLinkedList* list;
	RECTANGLE_16 rect16;
	RDS_MSG_COMMON* node;
	rdsConnection* connection;
	const RECTANGLE_16* extents;

	ChainedMode = 0;
	connection = connector->connection;

	list = connector->ServerList;

	region16_init(&region);

	LinkedList_Enumerator_Reset(list);

	while (LinkedList_Enumerator_MoveNext(list))
	{
		node = (RDS_MSG_COMMON*) LinkedList_Enumerator_Current(list);

		if ((!ChainedMode) && (node->msgFlags & RDS_MSG_FLAG_RECT))
		{
			rect16.left = node->rect.x;
			rect16.top = node->rect.y;
			rect16.right = node->rect.x + node->rect.width;
			rect16.bottom = node->rect.y + node->rect.height;

			region16_union_rect(&region, &region, &rect16);
		}
		else
		{
			MessageQueue_Post(connector->ServerQueue, (void*) connector, node->type, (void*) node, NULL);
		}
	}

	LinkedList_Clear(list);

	if (!ChainedMode)
	{
		extents = region16_extents(&region);

		rect.x = extents->left;
		rect.y = extents->top;
		rect.width = extents->right - extents->left;
		rect.height = extents->bottom - extents->top;

		freerds_message_server_align_rect(connector, &rect);

		if (connector->framebuffer.fbAttached && (rect.width * rect.height))
		{
			RDS_MSG_COMMON* msg;
			RDS_MSG_PAINT_RECT paintRect;

			paintRect.type = RDS_SERVER_PAINT_RECT;

			paintRect.nXSrc = 0;
			paintRect.nYSrc = 0;
			paintRect.bitmapData = NULL;
			paintRect.bitmapDataLength = 0;
			paintRect.framebuffer = &(connector->framebuffer);
			paintRect.fbSegmentId = connector->framebuffer.fbSegmentId;

			paintRect.nLeftRect = rect.x;
			paintRect.nTopRect = rect.y;
			paintRect.nWidth = rect.width;
			paintRect.nHeight = rect.height;

			msg = freerds_server_message_copy((RDS_MSG_COMMON*) &paintRect);

			MessageQueue_Post(connector->ServerQueue, (void*) connector, msg->type, (void*) msg, NULL);
		}
	}

	region16_uninit(&region);

	return 0;
}
예제 #18
0
int shadow_client_send_surface_update(rdpShadowClient* client)
{
	int status = -1;
	int nXSrc, nYSrc;
	int nWidth, nHeight;
	rdpContext* context;
	rdpSettings* settings;
	rdpShadowServer* server;
	rdpShadowSurface* surface;
	rdpShadowEncoder* encoder;
	REGION16 invalidRegion;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16* extents;

	context = (rdpContext*) client;
	settings = context->settings;
	server = client->server;
	encoder = client->encoder;

	surface = client->inLobby ? server->lobby : server->surface;

	EnterCriticalSection(&(client->lock));

	region16_init(&invalidRegion);
	region16_copy(&invalidRegion, &(client->invalidRegion));
	region16_clear(&(client->invalidRegion));

	LeaveCriticalSection(&(client->lock));

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = surface->width;
	surfaceRect.bottom = surface->height;

	region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);

	if (server->shareSubRect)
	{
		region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
	}

	if (region16_is_empty(&invalidRegion))
	{
		region16_uninit(&invalidRegion);
		return 1;
	}

	extents = region16_extents(&invalidRegion);

	nXSrc = extents->left - 0;
	nYSrc = extents->top - 0;
	nWidth = extents->right - extents->left;
	nHeight = extents->bottom - extents->top;

	//WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
	//	nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);

	if (settings->RemoteFxCodec || settings->NSCodec)
	{
		status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
	}
	else
	{
		status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
	}

	region16_uninit(&invalidRegion);

	return status;
}
예제 #19
0
파일: win_shadow.c 프로젝트: BUGgs/FreeRDP
int win_shadow_surface_copy(winShadowSubsystem* subsystem)
{
	int x, y;
	int width;
	int height;
	int count;
	int status = 1;
	int nDstStep = 0;
	BYTE* pDstData = NULL;
	rdpShadowServer* server;
	rdpShadowSurface* surface;
	RECTANGLE_16 surfaceRect;
	RECTANGLE_16 invalidRect;
	const RECTANGLE_16* extents;

	server = subsystem->server;
	surface = server->surface;

	if (ArrayList_Count(server->clients) < 1)
	{
		region16_clear(&(subsystem->invalidRegion));
		return 1;
	}

	surfaceRect.left = surface->x;
	surfaceRect.top = surface->y;
	surfaceRect.right = surface->x + surface->width;
	surfaceRect.bottom = surface->y + surface->height;

	region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);

	if (region16_is_empty(&(subsystem->invalidRegion)))
		return 1;

	extents = region16_extents(&(subsystem->invalidRegion));
	CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16));

	shadow_capture_align_clip_rect(&invalidRect, &surfaceRect);

	x = invalidRect.left;
	y = invalidRect.top;
	width = invalidRect.right - invalidRect.left;
	height = invalidRect.bottom - invalidRect.top;

	if (0)
	{
		x = 0;
		y = 0;
		width = surface->width;
		height = surface->height;
	}

	WLog_INFO(TAG, "SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d",
		x, y, width, height, x + width, y + height);

#if defined(WITH_WDS_API)
	{
		rdpGdi* gdi;
		shwContext* shw;
		rdpContext* context;

		shw = subsystem->shw;
		context = (rdpContext*) shw;
		gdi = context->gdi;

		pDstData = gdi->primary_buffer;
		nDstStep = gdi->width * 4;
	}
#elif defined(WITH_DXGI_1_2)
	status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height);
#endif

	if (status <= 0)
		return status;

	freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
			surface->scanline, x - surface->x, y - surface->y, width, height,
			pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0, NULL);

	ArrayList_Lock(server->clients);

	count = ArrayList_Count(server->clients);

	shadow_multiclient_publish_and_wait(subsystem->updateEvent);

	ArrayList_Unlock(server->clients);

	region16_clear(&(subsystem->invalidRegion));

	return 1;
}
예제 #20
0
int xf_OutputUpdate(xfContext* xfc)
{
	UINT16 width, height;
	xfGfxSurface* surface;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16* extents;

	if (!xfc->graphicsReset)
		return 1;

	surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId);

	if (!surface)
		return -1;

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = xfc->width;
	surfaceRect.bottom = xfc->height;

	region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect);

	XSetClipMask(xfc->display, xfc->gc, None);
	XSetFunction(xfc->display, xfc->gc, GXcopy);
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);

	if (!region16_is_empty(&(xfc->invalidRegion)))
	{
		extents = region16_extents(&(xfc->invalidRegion));

		width = extents->right - extents->left;
		height = extents->bottom - extents->top;

		if (width > xfc->width)
			width = xfc->width;

		if (height > xfc->height)
			height = xfc->height;

		if (surface->stage)
		{
			freerdp_image_copy(surface->stage, xfc->format, surface->stageStep, 0, 0,
				surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL);
		}

#ifdef WITH_XRENDER
		if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
		{
			XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
				extents->left, extents->top, extents->left, extents->top, width, height);

			xf_draw_screen(xfc, extents->left, extents->top, width, height);
		}
		else
#endif
		{
			XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
				extents->left, extents->top, extents->left, extents->top, width, height);
		}
	}

	region16_clear(&(xfc->invalidRegion));

	XSetClipMask(xfc->display, xfc->gc, None);
	XSync(xfc->display, True);

	return 1;
}
예제 #21
0
파일: x11_shadow.c 프로젝트: DavBfr/FreeRDP
int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
{
	int count;
	int status;
	int x, y;
	int width, height;
	XImage* image;
	rdpShadowScreen* screen;
	rdpShadowServer* server;
	rdpShadowSurface* surface;
	RECTANGLE_16 invalidRect;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16 *extents;

	server = subsystem->server;
	surface = server->surface;
	screen = server->screen;

	count = ArrayList_Count(server->clients);

	if (count < 1)
		return 1;

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = surface->width;
	surfaceRect.bottom = surface->height;

	XLockDisplay(subsystem->display);

	/*
	 * Ignore BadMatch error during image capture. The screen size may be 
	 * changed outside. We will resize to correct resolution at next frame
	 */
	XSetErrorHandler(x11_shadow_error_handler_for_capture);

	if (subsystem->use_xshm)
	{
		image = subsystem->fb_image;

		XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
				subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);

		status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
				(BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect);
	}
	else
	{
		image = XGetImage(subsystem->display, subsystem->root_window,
					surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);

		if (!image)
		{
			/*
			 * BadMatch error happened. The size may have been changed again.
			 * Give up this frame and we will resize again in next frame 
			 */
			goto fail_capture;
		}

		status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
				(BYTE*) image->data, image->bytes_per_line, &invalidRect);
	}

	/* Restore the default error handler */
	XSetErrorHandler(NULL);

	XSync(subsystem->display, False);

	XUnlockDisplay(subsystem->display);

	region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
	region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);

	if (!region16_is_empty(&(surface->invalidRegion)))
	{
		extents = region16_extents(&(surface->invalidRegion));

		x = extents->left;
		y = extents->top;
		width = extents->right - extents->left;
		height = extents->bottom - extents->top;

		freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
				surface->scanline, x, y, width, height,
				(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
				image->bytes_per_line, x, y, NULL);

		//x11_shadow_blend_cursor(subsystem);

		count = ArrayList_Count(server->clients);

		shadow_subsystem_frame_update((rdpShadowSubsystem *)subsystem);

		if (count == 1)
		{
			rdpShadowClient* client;

			client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);

			if (client)
			{
				subsystem->captureFrameRate = shadow_encoder_preferred_fps(client->encoder);
			}
		}

		region16_clear(&(surface->invalidRegion));
	}

	if (!subsystem->use_xshm)
		XDestroyImage(image);

	return 1;

fail_capture:
	XSetErrorHandler(NULL);
	XSync(subsystem->display, False);
	XUnlockDisplay(subsystem->display);
	return 0;
}
예제 #22
0
/**
 * Function description
 *
 * @return TRUE on success (or nothing need to be updated)
 */
static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
{
	BOOL ret = TRUE;
	int nXSrc, nYSrc;
	int nWidth, nHeight;
	rdpContext* context;
	rdpSettings* settings;
	rdpShadowServer* server;
	rdpShadowSurface* surface;
	rdpShadowEncoder* encoder;
	REGION16 invalidRegion;
	RECTANGLE_16 surfaceRect;
	const RECTANGLE_16* extents;
	BYTE* pSrcData;
	int nSrcStep;
	int index;
	int numRects = 0;
	const RECTANGLE_16* rects;

	context = (rdpContext*) client;
	settings = context->settings;
	server = client->server;
	encoder = client->encoder;

	surface = client->inLobby ? server->lobby : server->surface;

	EnterCriticalSection(&(client->lock));

	region16_init(&invalidRegion);
	region16_copy(&invalidRegion, &(client->invalidRegion));
	region16_clear(&(client->invalidRegion));

	LeaveCriticalSection(&(client->lock));

	rects = region16_rects(&(surface->invalidRegion), &numRects);
	for (index = 0; index < numRects; index++)
	{
		region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
	}

	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = surface->width;
	surfaceRect.bottom = surface->height;

	region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);

	if (server->shareSubRect)
	{
		region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
	}

	if (region16_is_empty(&invalidRegion))
	{
		/* No image region need to be updated. Success */
		goto out;
	}

	extents = region16_extents(&invalidRegion);

	nXSrc = extents->left;
	nYSrc = extents->top;
	nWidth = extents->right - extents->left;
	nHeight = extents->bottom - extents->top;

	pSrcData = surface->data;
	nSrcStep = surface->scanline;

	/* Move to new pSrcData / nXSrc / nYSrc according to sub rect */
	if (server->shareSubRect)
	{
		int subX, subY;

		subX = server->subRect.left;
		subY = server->subRect.top;

		nXSrc -= subX;
		nYSrc -= subY;
		pSrcData = &pSrcData[(subY * nSrcStep) + (subX * 4)];
	}

	//WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
	//	nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);

	if (settings->SupportGraphicsPipeline && 
	    settings->GfxH264 &&
	    pStatus->gfxOpened)
	{
		/* GFX/h264 always full screen encoded */
		nWidth = settings->DesktopWidth;
		nHeight = settings->DesktopHeight;

		/* Create primary surface if have not */
		if (!pStatus->gfxSurfaceCreated)
		{
			/* Only init surface when we have h264 supported */
			if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
				goto out;

			if (!(ret = shadow_client_rdpgfx_new_surface(client)))
				goto out;

			pStatus->gfxSurfaceCreated = TRUE;
		}

		ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, 0, 0, nWidth, nHeight);
	}
	else if (settings->RemoteFxCodec || settings->NSCodec)
	{
		ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth, nHeight);
	}
	else
	{
		ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, nXSrc, nYSrc, nWidth, nHeight);
	}

out:
	region16_uninit(&invalidRegion);

	return ret;
}