Example #1
0
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
	int count;
	int index;
	xfGfxSurface* surface;
	UINT16* pSurfaceIds = NULL;
	xfContext* xfc = (xfContext*) context->custom;

	freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);

	count = context->GetSurfaceIds(context, &pSurfaceIds);

	for (index = 0; index < count; index++)
	{
		surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);

		if (!surface || !surface->outputMapped)
			continue;

		region16_clear(&surface->invalidRegion);
	}

	free(pSurfaceIds);

	xfc->graphicsReset = TRUE;

	return 1;
}
Example #2
0
static int test_r1_r3(void)
{
	REGION16 region;
	int retCode = -1;
	const RECTANGLE_16* rects;
	UINT32 nbRects;
	RECTANGLE_16 r1 = {  0, 101, 200, 201};
	RECTANGLE_16 r3 = {150, 151, 250, 251};
	RECTANGLE_16 r1_r3[] =
	{
		{  0, 101, 200, 151},
		{  0, 151, 250, 201},
		{150, 201, 250, 251}
	};
	region16_init(&region);
	/*
	 * +===============================================================
	 * |
	 * |+-----+                +-----+
	 * || r1  |                |     |
	 * ||   +-+------+         +-----+--------+
	 * ||   |    r3  |         |              |
	 * |+---+        | ====>   +-----+--------+
	 * |    |        |               |        |
	 * |    +--------+               +--------+
	 */

	/* R1 + R3  */
	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	if (!region16_union_rect(&region, &region, &r3))
		goto out;

	rects = region16_rects(&region, &nbRects);

	if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects))
		goto out;

	/* R3 + R1  */
	region16_clear(&region);

	if (!region16_union_rect(&region, &region, &r3))
		goto out;

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	rects = region16_rects(&region, &nbRects);

	if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r3, nbRects))
		goto out;

	retCode = 0;
out:
	region16_uninit(&region);
	return retCode;
}
Example #3
0
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;
}
Example #4
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT gdi_ResetGraphics(RdpgfxClientContext* context,
                              const RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
	UINT32 index;
	UINT16 count;
	UINT32 DesktopWidth;
	UINT32 DesktopHeight;
	gdiGfxSurface* surface;
	UINT16* pSurfaceIds = NULL;
	rdpGdi* gdi = (rdpGdi*) context->custom;
	rdpUpdate* update = gdi->context->update;
	rdpSettings* settings = gdi->context->settings;
	DesktopWidth = resetGraphics->width;
	DesktopHeight = resetGraphics->height;

	if ((DesktopWidth != settings->DesktopWidth)
	    || (DesktopHeight != settings->DesktopHeight))
	{
		settings->DesktopWidth = DesktopWidth;
		settings->DesktopHeight = DesktopHeight;

		if (update)
			update->DesktopResize(gdi->context);
	}

	context->GetSurfaceIds(context, &pSurfaceIds, &count);

	for (index = 0; index < count; index++)
	{
		surface = (gdiGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);

		if (!surface || !surface->outputMapped)
			continue;

		if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
		                                 surface->width, surface->height))
		{
			free(pSurfaceIds);
			return ERROR_INTERNAL_ERROR;
		}

		region16_clear(&surface->invalidRegion);
	}

	free(pSurfaceIds);

	if (!freerdp_client_codecs_reset(gdi->context->codecs, FREERDP_CODEC_ALL,
	                                 gdi->width, gdi->height))
		return ERROR_INTERNAL_ERROR;

	gdi->graphicsReset = TRUE;
	return CHANNEL_RC_OK;
}
Example #5
0
File: gfx.c Project: 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;
}
Example #6
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;

		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;
}
Example #7
0
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
{
	xfGfxSurface* surface;

	surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId);

	surface->outputMapped = TRUE;
	surface->outputOriginX = surfaceToOutput->outputOriginX;
	surface->outputOriginY = surfaceToOutput->outputOriginY;

	region16_clear(&surface->invalidRegion);

	return 1;
}
Example #8
0
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);
}
Example #9
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* 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;
}
Example #10
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT gdi_MapSurfaceToOutput(RdpgfxClientContext* context,
                                   const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
{
	gdiGfxSurface* surface;
	surface = (gdiGfxSurface*) context->GetSurfaceData(context,
	          surfaceToOutput->surfaceId);

	if (!surface)
		return ERROR_INTERNAL_ERROR;

	surface->outputMapped = TRUE;
	surface->outputOriginX = surfaceToOutput->outputOriginX;
	surface->outputOriginY = surfaceToOutput->outputOriginY;
	region16_clear(&surface->invalidRegion);
	return CHANNEL_RC_OK;
}
Example #11
0
static int test_basic(void)
{
	REGION16 region;
	int retCode = -1;
	const RECTANGLE_16* rects;
	UINT32 nbRects;
	/* R1 + R2 ==> disjointed rects */
	RECTANGLE_16 r1 = {  0, 101, 200, 201};
	RECTANGLE_16 r2 = {150, 301, 250, 401};
	RECTANGLE_16 r1_r2[] =
	{
		{0,   101, 200, 201},
		{150, 301, 250, 401}
	};
	/* r1 */
	region16_init(&region);

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	rects = region16_rects(&region, &nbRects);

	if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16)))
		goto out;

	/* r1 + r2 */
	if (!region16_union_rect(&region, &region, &r2))
		goto out;

	rects = region16_rects(&region, &nbRects);

	if (!rects || nbRects != 2 || !compareRectangles(rects, r1_r2, nbRects))
		goto out;

	/* clear region */
	region16_clear(&region);
	region16_rects(&region, &nbRects);

	if (nbRects)
		goto out;

	retCode = 0;
out:
	region16_uninit(&region);
	return retCode;
}
Example #12
0
/**
 * Function description
 * Notify client for resize. The new desktop width/height
 * should have already been updated in rdpSettings.
 *
 * @return TRUE on success
 */
static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
{
	rdpContext* context;
	rdpSettings* settings;
	rdpShadowServer* server;
	freerdp_peer* peer;

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

	/**
	 * Unset client activated flag to avoid sending update message during
	 * resize. DesktopResize will reactive the client and
	 * shadow_client_activate would be invoked later.
	 */
	client->activated = FALSE;

	/* Close Gfx surfaces */
	if (pStatus->gfxSurfaceCreated)
	{
		if (!shadow_client_rdpgfx_release_surface(client))
			return FALSE;

		pStatus->gfxSurfaceCreated = FALSE;
	}

	/* Send Resize */
	if (!peer->update->DesktopResize(peer->update->context))
	{
		WLog_ERR(TAG, "DesktopResize failed");
		return FALSE;
	}

	/* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */
	EnterCriticalSection(&(client->lock));
	region16_clear(&(client->invalidRegion));
	LeaveCriticalSection(&(client->lock));

	WLog_INFO(TAG, "Client from %s is resized (%dx%d@%d)",
			peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);

	return TRUE;
}
Example #13
0
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);
}
Example #14
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;
}
Example #15
0
static int test_r1_r6(void)
{
	REGION16 region;
	int retCode = -1;
	const RECTANGLE_16* rects;
	UINT32 nbRects;
	RECTANGLE_16 r1 = {  0, 101, 200, 201};
	RECTANGLE_16 r6 = {150, 121, 170, 131};
	region16_init(&region);
	/*
	 * +===============================================================
	 * |
	 * |+--------+           +--------+
	 * || r1     |           |        |
	 * ||   +--+ |           |        |
	 * ||   |r6| |  =====>   |        |
	 * ||   +--+ |           |        |
	 * ||        |           |        |
	 * |+--------+           +--------+
	 * |
	 */
	region16_clear(&region);

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	if (!region16_union_rect(&region, &region, &r6))
		goto out;

	rects = region16_rects(&region, &nbRects);

	if (!rects || nbRects != 1 || !compareRectangles(rects, &r1, nbRects))
		goto out;

	retCode = 0;
out:
	region16_uninit(&region);
	return retCode;
}
Example #16
0
/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
	int index;
	UINT16 count;
	xfGfxSurface* surface;
	UINT16* pSurfaceIds = NULL;
	xfContext* xfc = (xfContext*) context->custom;

	context->GetSurfaceIds(context, &pSurfaceIds, &count);

	for (index = 0; index < count; index++)
	{
		surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);

		if (!surface || !surface->outputMapped)
			continue;

		if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
						 surface->width, surface->height))
		{
			free(pSurfaceIds);
			return ERROR_INTERNAL_ERROR;
		}

		region16_clear(&surface->invalidRegion);
	}

	free(pSurfaceIds);

	if (!freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL,
					 xfc->settings->DesktopWidth,
					 xfc->settings->DesktopHeight))
		return ERROR_INTERNAL_ERROR;

	xfc->graphicsReset = TRUE;

	return CHANNEL_RC_OK;
}
Example #17
0
static void UwacSubmitBufferPtr(UwacWindow* window, UwacBuffer* buffer)
{
	UINT32 nrects, i;
#ifdef HAVE_PIXMAN_REGION
	const pixman_box32_t* box;
#else
	const RECTANGLE_16* box;
#endif
	wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0);
#ifdef HAVE_PIXMAN_REGION
	box = pixman_region32_rectangles(&buffer->damage, &nrects);

	for (i = 0; i < nrects; i++, box++)
		wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1));

#else
	box = region16_rects(&buffer->damage, &nrects);

	for (i = 0; i < nrects; i++, box++)
		wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left),
		                  (box->bottom - box->top));

#endif

	if (window->frame_callback)
		wl_callback_destroy(window->frame_callback);

	window->frame_callback = wl_surface_frame(window->surface);
	wl_callback_add_listener(window->frame_callback, &frame_listener, window);
	wl_surface_commit(window->surface);
#ifdef HAVE_PIXMAN_REGION
	pixman_region32_clear(&buffer->damage);
#else
	region16_clear(&buffer->damage);
#endif
}
Example #18
0
static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
{
	UINT rc = ERROR_INTERNAL_ERROR;
	UINT32 surfaceX, surfaceY;
	RECTANGLE_16 surfaceRect;
	rdpGdi* gdi;
	UINT32 nbRects, x;
	const RECTANGLE_16* rects;
	gdi = xfc->context.gdi;
	surfaceX = surface->gdi.outputOriginX;
	surfaceY = surface->gdi.outputOriginY;
	surfaceRect.left = 0;
	surfaceRect.top = 0;
	surfaceRect.right = surface->gdi.width;
	surfaceRect.bottom = surface->gdi.height;
	XSetClipMask(xfc->display, xfc->gc, None);
	XSetFunction(xfc->display, xfc->gc, GXcopy);
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
	region16_intersect_rect(&(surface->gdi.invalidRegion),
	                        &(surface->gdi.invalidRegion), &surfaceRect);

	if (!(rects = region16_rects(&surface->gdi.invalidRegion, &nbRects)))
		return CHANNEL_RC_OK;

	for (x = 0; x < nbRects; x++)
	{
		const UINT32 nXSrc = rects[x].left;
		const UINT32 nYSrc = rects[x].top;
		const UINT32 width = rects[x].right - nXSrc;
		const UINT32 height = rects[x].bottom - nYSrc;
		const UINT32 nXDst = surfaceX + nXSrc;
		const UINT32 nYDst = surfaceY + nYSrc;

		if (surface->stage)
		{
			if (!freerdp_image_copy(surface->stage, gdi->dstFormat,
			                        surface->stageScanline, nXSrc, nYSrc,
			                        width, height,
			                        surface->gdi.data, surface->gdi.format,
			                        surface->gdi.scanline, nXSrc, nYSrc,
			                        NULL, FREERDP_FLIP_NONE))
				goto fail;
		}

		if (xfc->remote_app)
		{
			XPutImage(xfc->display, xfc->primary, xfc->gc,
			          surface->image, nXSrc, nYSrc,
			          nXDst, nYDst, width, height);
			xf_lock_x11(xfc, FALSE);
			xf_rail_paint(xfc, nXDst, nYDst, nXDst + width, nYDst + height);
			xf_unlock_x11(xfc, FALSE);
		}
		else
#ifdef WITH_XRENDER
			if (xfc->context.settings->SmartSizing
			    || xfc->context.settings->MultiTouchGestures)
			{
				XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
				          nXSrc, nYSrc, nXDst, nYDst, width, height);
				xf_draw_screen(xfc, nXDst, nYDst, width, height);
			}
			else
#endif
			{
				XPutImage(xfc->display, xfc->drawable, xfc->gc,
				          surface->image, nXSrc, nYSrc,
				          nXDst, nYDst, width, height);
			}
	}

	rc = CHANNEL_RC_OK;
fail:
	region16_clear(&surface->gdi.invalidRegion);
	XSetClipMask(xfc->display, xfc->gc, None);
	XSync(xfc->display, False);
	return rc;
}
Example #19
0
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;

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

	count = ArrayList_Count(server->clients);

	if (count < 1)
		return 1;

	if (subsystem->use_xshm)
	{
		XLockDisplay(subsystem->display);

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

		XSync(subsystem->display, False);

		XUnlockDisplay(subsystem->display);

		image = subsystem->fb_image;

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

		if (status > 0)
		{
			x = invalidRect.left;
			y = invalidRect.top;
			width = invalidRect.right - invalidRect.left;
			height = invalidRect.bottom - invalidRect.top;

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

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

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

			ResetEvent(subsystem->updateEvent);

			region16_clear(&(subsystem->invalidRegion));
		}
	}
	else
	{
		XLockDisplay(subsystem->display);

		image = XGetImage(subsystem->display, subsystem->root_window,
				surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);

		XUnlockDisplay(subsystem->display);

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

		if (status > 0)
		{
			x = invalidRect.left;
			y = invalidRect.top;
			width = invalidRect.right - invalidRect.left;
			height = invalidRect.bottom - invalidRect.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);

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

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

			ResetEvent(subsystem->updateEvent);

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

		XDestroyImage(image);
	}

	return 1;
}
Example #20
0
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);
}
Example #21
0
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;
}
Example #22
0
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;
}
Example #23
0
static int test_r1_r7_r8(void)
{
	REGION16 region;
	int retCode = -1;
	const RECTANGLE_16* rects;
	UINT32 nbRects;
	RECTANGLE_16 r1 = {  0, 101, 200, 201};
	RECTANGLE_16 r7 = {300, 101, 500, 201};
	RECTANGLE_16 r8 = {150, 121, 400, 131};
	RECTANGLE_16 r1_r7_r8[] =
	{
		{  0, 101, 200, 121},
		{300, 101, 500, 121},
		{  0, 121, 500, 131},
		{  0, 131, 200, 201},
		{300, 131, 500, 201},
	};
	/*
	 * +===============================================================
	 * |
	 * |+--------+   +--------+           +--------+   +--------+
	 * || r1     |   | r7     |           |        |   |        |
	 * ||   +------------+    |           +--------+---+--------+
	 * ||   |   r8       |    |   =====>  |                     |
	 * ||   +------------+    |           +--------+---+--------+
	 * ||        |   |        |           |        |   |        |
	 * |+--------+   +--------+           +--------+   +--------+
	 * |
	 */
	region16_init(&region);

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	if (!region16_union_rect(&region, &region, &r7))
		goto out;

	if (!region16_union_rect(&region, &region, &r8))
		goto out;

	rects = region16_rects(&region, &nbRects);

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

	region16_clear(&region);

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	if (!region16_union_rect(&region, &region, &r8))
		goto out;

	if (!region16_union_rect(&region, &region, &r7))
		goto out;

	rects = region16_rects(&region, &nbRects);

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

	region16_clear(&region);

	if (!region16_union_rect(&region, &region, &r8))
		goto out;

	if (!region16_union_rect(&region, &region, &r7))
		goto out;

	if (!region16_union_rect(&region, &region, &r1))
		goto out;

	rects = region16_rects(&region, &nbRects);

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

	retCode = 0;
out:
	region16_uninit(&region);
	return retCode;
}
Example #24
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;
}
Example #25
0
void* shadow_client_thread(rdpShadowClient* client)
{
	DWORD status;
	DWORD nCount;
	wMessage message;
	wMessage pointerPositionMsg;
	wMessage pointerAlphaMsg;
	wMessage audioVolumeMsg;
	HANDLE events[32];
	HANDLE ClientEvent;
	HANDLE ChannelEvent;
	void* UpdateSubscriber;
	HANDLE UpdateEvent;
	freerdp_peer* peer;
	rdpContext* context;
	rdpSettings* settings;
	rdpShadowServer* server;
	rdpShadowScreen* screen;
	rdpShadowEncoder* encoder;
	rdpShadowSubsystem* subsystem;
	wMessageQueue* MsgQueue = client->MsgQueue;

	server = client->server;
	screen = server->screen;
	encoder = client->encoder;
	subsystem = server->subsystem;

	context = (rdpContext*) client;
	peer = context->peer;
	settings = peer->settings;

	peer->Capabilities = shadow_client_capabilities;
	peer->PostConnect = shadow_client_post_connect;
	peer->Activate = shadow_client_activate;

	shadow_input_register_callbacks(peer->input);

	peer->Initialize(peer);

	peer->update->RefreshRect = (pRefreshRect)shadow_client_refresh_rect;
	peer->update->SuppressOutput = (pSuppressOutput)shadow_client_suppress_output;
	peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)shadow_client_surface_frame_acknowledge;

	if ((!client->vcm) || (!subsystem->updateEvent))
		goto out;

	UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
	if (!UpdateSubscriber)
		goto out;

	UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
	ClientEvent = peer->GetEventHandle(peer);
	ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);

	while (1)
	{
		nCount = 0;
		events[nCount++] = UpdateEvent;
		events[nCount++] = ClientEvent;
		events[nCount++] = ChannelEvent;
		events[nCount++] = MessageQueue_Event(MsgQueue);

		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);

		if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
		{
			if (client->activated)
			{
				int index;
				int numRects = 0;
				const RECTANGLE_16* rects;
				int width, height;

				/* Check resize */
				shadow_client_calc_desktop_size(server, &width, &height);
				if (settings->DesktopWidth != (UINT32)width || settings->DesktopHeight != (UINT32)height)
				{
					/* Screen size changed, do resize */
					settings->DesktopWidth = width;
					settings->DesktopHeight = height;

					/**
					 * Unset client activated flag to avoid sending update message during
					 * resize. DesktopResize will reactive the client and 
					 * shadow_client_activate would be invoked later.
					 */
					client->activated = FALSE;

					/* Send Resize */
					peer->update->DesktopResize(peer->update->context); // update_send_desktop_resize

					/* Clear my invalidRegion. shadow_client_activate refreshes fullscreen */
					region16_clear(&(client->invalidRegion));

					WLog_ERR(TAG, "Client from %s is resized (%dx%d@%d)",
							peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
				}
				else 
				{
					/* Send frame */
					rects = region16_rects(&(subsystem->invalidRegion), &numRects);

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

					shadow_client_send_surface_update(client);
				}
			}

			/* 
			 * The return value of shadow_multiclient_consume is whether or not the subscriber really consumes the event.
			 * It's not cared currently.
			 */
			(void)shadow_multiclient_consume(UpdateSubscriber);
		}

		if (WaitForSingleObject(ClientEvent, 0) == WAIT_OBJECT_0)
		{
			if (!peer->CheckFileDescriptor(peer))
			{
				WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
				break;
			}
		}

		if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
		{
			if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
			{
				WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
				break;
			}
		}

		if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
		{
			/* Drain messages. Pointer update could be accumulated. */
			pointerPositionMsg.id = 0;
			pointerPositionMsg.Free= NULL;
			pointerAlphaMsg.id = 0;
			pointerAlphaMsg.Free = NULL;
			audioVolumeMsg.id = 0;
			audioVolumeMsg.Free = NULL;
			while (MessageQueue_Peek(MsgQueue, &message, TRUE))
			{
				if (message.id == WMQ_QUIT)
				{
					break;
				}

				switch(message.id)
				{
					case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
						/* Abandon previous message */
						shadow_client_free_queued_message(&pointerPositionMsg);
						CopyMemory(&pointerPositionMsg, &message, sizeof(wMessage));
						break;

					case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
						/* Abandon previous message */
						shadow_client_free_queued_message(&pointerAlphaMsg);
						CopyMemory(&pointerAlphaMsg, &message, sizeof(wMessage));
						break;

					case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
						/* Abandon previous message */
						shadow_client_free_queued_message(&audioVolumeMsg);
						CopyMemory(&audioVolumeMsg, &message, sizeof(wMessage));
						break;

					default:
						shadow_client_subsystem_process_message(client, &message);
						break;
				}
			}

			if (message.id == WMQ_QUIT)
			{
				/* Release stored message */
				shadow_client_free_queued_message(&pointerPositionMsg);
				shadow_client_free_queued_message(&pointerAlphaMsg);
				shadow_client_free_queued_message(&audioVolumeMsg);
				break;
			}
			else
			{
				/* Process accumulated messages if needed */
				if (pointerPositionMsg.id)
				{
					shadow_client_subsystem_process_message(client, &pointerPositionMsg);
				}
				if (pointerAlphaMsg.id)
				{
					shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
				}
				if (audioVolumeMsg.id)
				{
					shadow_client_subsystem_process_message(client, &audioVolumeMsg);
				}
			}
		}
	}

	/* Free channels early because we establish channels in post connect */
	shadow_client_channels_free(client);

	if (UpdateSubscriber)
	{
		shadow_multiclient_release_subscriber(UpdateSubscriber);
		UpdateSubscriber = NULL;
	}

	if (peer->connected && subsystem->ClientDisconnect)
	{
		subsystem->ClientDisconnect(subsystem, client);
	}

out:
	peer->Disconnect(peer);
	
	freerdp_peer_context_free(peer);
	freerdp_peer_free(peer);
	ExitThread(0);
	return NULL;
}
Example #26
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;
}
Example #27
0
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;
}
Example #28
0
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;
}
Example #29
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;
}