Blame client/X11/xf_gfx.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * X11 Graphics Pipeline
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2016 Armin Novak <armin.novak@thincast.com>
Packit Service fa4841
 * Copyright 2016 Thincast Technologies GmbH
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
#include "xf_gfx.h"
Packit Service fa4841
#include "xf_rail.h"
Packit Service fa4841
Packit Service fa4841
#include <X11/Xutil.h>
Packit Service fa4841
Packit Service fa4841
#define TAG CLIENT_TAG("x11")
Packit Service fa4841
Packit Service fa4841
static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
Packit Service fa4841
{
Packit Service fa4841
	UINT rc = ERROR_INTERNAL_ERROR;
Packit Service fa4841
	UINT32 surfaceX, surfaceY;
Packit Service fa4841
	RECTANGLE_16 surfaceRect;
Packit Service fa4841
	rdpGdi* gdi;
Packit Service fa4841
	UINT32 nbRects, x;
Packit Service b1ea74
	double sx, sy;
Packit Service fa4841
	const RECTANGLE_16* rects;
Packit Service fa4841
	gdi = xfc->context.gdi;
Packit Service fa4841
	surfaceX = surface->gdi.outputOriginX;
Packit Service fa4841
	surfaceY = surface->gdi.outputOriginY;
Packit Service fa4841
	surfaceRect.left = 0;
Packit Service fa4841
	surfaceRect.top = 0;
Packit Service b1ea74
	surfaceRect.right = surface->gdi.mappedWidth;
Packit Service b1ea74
	surfaceRect.bottom = surface->gdi.mappedHeight;
Packit Service fa4841
	XSetClipMask(xfc->display, xfc->gc, None);
Packit Service fa4841
	XSetFunction(xfc->display, xfc->gc, GXcopy);
Packit Service fa4841
	XSetFillStyle(xfc->display, xfc->gc, FillSolid);
Packit Service b1ea74
	region16_intersect_rect(&(surface->gdi.invalidRegion), &(surface->gdi.invalidRegion),
Packit Service b1ea74
	                        &surfaceRect);
Packit Service b1ea74
	sx = surface->gdi.outputTargetWidth / (double)surface->gdi.mappedWidth;
Packit Service b1ea74
	sy = surface->gdi.outputTargetHeight / (double)surface->gdi.mappedHeight;
Packit Service fa4841
Packit Service fa4841
	if (!(rects = region16_rects(&surface->gdi.invalidRegion, &nbRects)))
Packit Service fa4841
		return CHANNEL_RC_OK;
Packit Service fa4841
Packit Service fa4841
	for (x = 0; x < nbRects; x++)
Packit Service fa4841
	{
Packit Service fa4841
		const UINT32 nXSrc = rects[x].left;
Packit Service fa4841
		const UINT32 nYSrc = rects[x].top;
Packit Service b1ea74
		const UINT32 swidth = rects[x].right - nXSrc;
Packit Service b1ea74
		const UINT32 sheight = rects[x].bottom - nYSrc;
Packit Service b1ea74
		const UINT32 nXDst = surfaceX + nXSrc * sx;
Packit Service b1ea74
		const UINT32 nYDst = surfaceY + nYSrc * sy;
Packit Service b1ea74
		const UINT32 dwidth = swidth * sx;
Packit Service b1ea74
		const UINT32 dheight = sheight * sy;
Packit Service fa4841
Packit Service fa4841
		if (surface->stage)
Packit Service fa4841
		{
Packit Service b1ea74
			if (!freerdp_image_scale(surface->stage, gdi->dstFormat, surface->stageScanline, nXSrc,
Packit Service b1ea74
			                         nYSrc, dwidth, dheight, surface->gdi.data, surface->gdi.format,
Packit Service b1ea74
			                         surface->gdi.scanline, nXSrc, nYSrc, swidth, sheight))
Packit Service fa4841
				goto fail;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (xfc->remote_app)
Packit Service fa4841
		{
Packit Service b1ea74
			XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst,
Packit Service b1ea74
			          nYDst, dwidth, dheight);
Packit Service b1ea74
			xf_lock_x11(xfc);
Packit Service b1ea74
			xf_rail_paint(xfc, nXDst, nYDst, nXDst + dwidth, nYDst + dheight);
Packit Service b1ea74
			xf_unlock_x11(xfc);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
#ifdef WITH_XRENDER
Packit Service b1ea74
		    if (xfc->context.settings->SmartSizing || xfc->context.settings->MultiTouchGestures)
Packit Service b1ea74
		{
Packit Service b1ea74
			XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image, nXSrc, nYSrc, nXDst,
Packit Service b1ea74
			          nYDst, dwidth, dheight);
Packit Service b1ea74
			xf_draw_screen(xfc, nXDst, nYDst, dwidth, dheight);
Packit Service b1ea74
		}
Packit Service b1ea74
		else
Packit Service fa4841
#endif
Packit Service b1ea74
		{
Packit Service b1ea74
			XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, nXSrc, nYSrc, nXDst,
Packit Service b1ea74
			          nYDst, dwidth, dheight);
Packit Service b1ea74
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	rc = CHANNEL_RC_OK;
Packit Service fa4841
fail:
Packit Service fa4841
	region16_clear(&surface->gdi.invalidRegion);
Packit Service fa4841
	XSetClipMask(xfc->display, xfc->gc, None);
Packit Service fa4841
	XSync(xfc->display, False);
Packit Service fa4841
	return rc;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static UINT xf_UpdateSurfaces(RdpgfxClientContext* context)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 count;
Packit Service fa4841
	UINT32 index;
Packit Service fa4841
	UINT status = CHANNEL_RC_OK;
Packit Service fa4841
	UINT16* pSurfaceIds = NULL;
Packit Service fa4841
	rdpGdi* gdi = (rdpGdi*)context->custom;
Packit Service b1ea74
	xfContext* xfc;
Packit Service fa4841
Packit Service fa4841
	if (!gdi)
Packit Service fa4841
		return status;
Packit Service fa4841
Packit Service fa4841
	if (gdi->suppressOutput)
Packit Service fa4841
		return CHANNEL_RC_OK;
Packit Service fa4841
Packit Service b1ea74
	xfc = (xfContext*)gdi->context;
Packit Service b1ea74
	EnterCriticalSection(&context->mux);
Packit Service fa4841
	context->GetSurfaceIds(context, &pSurfaceIds, &count);
Packit Service fa4841
Packit Service fa4841
	for (index = 0; index < count; index++)
Packit Service fa4841
	{
Packit Service b1ea74
		xfGfxSurface* surface = (xfGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]);
Packit Service fa4841
Packit Service b1ea74
		if (!surface)
Packit Service fa4841
			continue;
Packit Service fa4841
Packit Service b1ea74
		/* If UpdateSurfaceArea callback is available, the output has already been updated. */
Packit Service b1ea74
		if (context->UpdateSurfaceArea)
Packit Service b1ea74
		{
Packit Service b1ea74
			if (surface->gdi.windowId != 0)
Packit Service b1ea74
				continue;
Packit Service b1ea74
		}
Packit Service b1ea74
Packit Service b1ea74
		status = ERROR_INTERNAL_ERROR;
Packit Service b1ea74
Packit Service b1ea74
		if (surface->gdi.outputMapped)
Packit Service b1ea74
			status = xf_OutputUpdate(xfc, surface);
Packit Service fa4841
Packit Service fa4841
		if (status != 0)
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	free(pSurfaceIds);
Packit Service b1ea74
	LeaveCriticalSection(&context->mux);
Packit Service fa4841
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service b1ea74
UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y, UINT32 width, UINT32 height)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 count;
Packit Service fa4841
	UINT32 index;
Packit Service b1ea74
	UINT status = ERROR_INTERNAL_ERROR;
Packit Service fa4841
	xfGfxSurface* surface;
Packit Service fa4841
	RECTANGLE_16 invalidRect;
Packit Service fa4841
	RECTANGLE_16 surfaceRect;
Packit Service fa4841
	RECTANGLE_16 intersection;
Packit Service fa4841
	UINT16* pSurfaceIds = NULL;
Packit Service fa4841
	RdpgfxClientContext* context = xfc->context.gdi->gfx;
Packit Service fa4841
	invalidRect.left = x;
Packit Service fa4841
	invalidRect.top = y;
Packit Service fa4841
	invalidRect.right = x + width;
Packit Service fa4841
	invalidRect.bottom = y + height;
Packit Service b1ea74
	status = context->GetSurfaceIds(context, &pSurfaceIds, &count);
Packit Service fa4841
Packit Service b1ea74
	if (status != CHANNEL_RC_OK)
Packit Service b1ea74
		goto fail;
Packit Service b1ea74
Packit Service b1ea74
	if (!TryEnterCriticalSection(&context->mux))
Packit Service b1ea74
	{
Packit Service b1ea74
		free(pSurfaceIds);
Packit Service b1ea74
		return CHANNEL_RC_OK;
Packit Service b1ea74
	}
Packit Service fa4841
	for (index = 0; index < count; index++)
Packit Service fa4841
	{
Packit Service b1ea74
		surface = (xfGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]);
Packit Service fa4841
Packit Service fa4841
		if (!surface || !surface->gdi.outputMapped)
Packit Service fa4841
			continue;
Packit Service fa4841
Packit Service fa4841
		surfaceRect.left = surface->gdi.outputOriginX;
Packit Service fa4841
		surfaceRect.top = surface->gdi.outputOriginY;
Packit Service b1ea74
		surfaceRect.right = surface->gdi.outputOriginX + surface->gdi.outputTargetWidth;
Packit Service b1ea74
		surfaceRect.bottom = surface->gdi.outputOriginY + surface->gdi.outputTargetHeight;
Packit Service fa4841
Packit Service fa4841
		if (rectangles_intersection(&invalidRect, &surfaceRect, &intersection))
Packit Service fa4841
		{
Packit Service fa4841
			/* Invalid rects are specified relative to surface origin */
Packit Service fa4841
			intersection.left -= surfaceRect.left;
Packit Service fa4841
			intersection.top -= surfaceRect.top;
Packit Service fa4841
			intersection.right -= surfaceRect.left;
Packit Service fa4841
			intersection.bottom -= surfaceRect.top;
Packit Service b1ea74
			region16_union_rect(&surface->gdi.invalidRegion, &surface->gdi.invalidRegion,
Packit Service fa4841
			                    &intersection);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	free(pSurfaceIds);
Packit Service b1ea74
	LeaveCriticalSection(&context->mux);
Packit Service fa4841
	IFCALLRET(context->UpdateSurfaces, status, context);
Packit Service b1ea74
Packit Service b1ea74
	if (status != CHANNEL_RC_OK)
Packit Service b1ea74
		goto fail;
Packit Service b1ea74
Packit Service b1ea74
fail:
Packit Service fa4841
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
UINT32 x11_pad_scanline(UINT32 scanline, UINT32 inPad)
Packit Service fa4841
{
Packit Service fa4841
	/* Ensure X11 alignment is met */
Packit Service fa4841
	if (inPad > 0)
Packit Service fa4841
	{
Packit Service fa4841
		const UINT32 align = inPad / 8;
Packit Service fa4841
		const UINT32 pad = align - scanline % align;
Packit Service fa4841
Packit Service fa4841
		if (align != pad)
Packit Service fa4841
			scanline += pad;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* 16 byte alingment is required for ASM optimized code */
Packit Service fa4841
	if (scanline % 16)
Packit Service fa4841
		scanline += 16 - scanline % 16;
Packit Service fa4841
Packit Service fa4841
	return scanline;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service fa4841
static UINT xf_CreateSurface(RdpgfxClientContext* context,
Packit Service fa4841
                             const RDPGFX_CREATE_SURFACE_PDU* createSurface)
Packit Service fa4841
{
Packit Service fa4841
	UINT ret = CHANNEL_RC_NO_MEMORY;
Packit Service fa4841
	size_t size;
Packit Service fa4841
	xfGfxSurface* surface;
Packit Service fa4841
	rdpGdi* gdi = (rdpGdi*)context->custom;
Packit Service b1ea74
	xfContext* xfc = (xfContext*)gdi->context;
Packit Service b1ea74
	surface = (xfGfxSurface*)calloc(1, sizeof(xfGfxSurface));
Packit Service fa4841
Packit Service fa4841
	if (!surface)
Packit Service fa4841
		return CHANNEL_RC_NO_MEMORY;
Packit Service fa4841
Packit Service fa4841
	surface->gdi.codecs = gdi->context->codecs;
Packit Service fa4841
Packit Service fa4841
	if (!surface->gdi.codecs)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "%s: global GDI codecs aren't set", __FUNCTION__);
Packit Service fa4841
		goto out_free;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	surface->gdi.surfaceId = createSurface->surfaceId;
Packit Service b1ea74
	surface->gdi.width = x11_pad_scanline(createSurface->width, 0);
Packit Service b1ea74
	surface->gdi.height = x11_pad_scanline(createSurface->height, 0);
Packit Service b1ea74
	surface->gdi.mappedWidth = createSurface->width;
Packit Service b1ea74
	surface->gdi.mappedHeight = createSurface->height;
Packit Service b1ea74
	surface->gdi.outputTargetWidth = createSurface->width;
Packit Service b1ea74
	surface->gdi.outputTargetHeight = createSurface->height;
Packit Service fa4841
Packit Service fa4841
	switch (createSurface->pixelFormat)
Packit Service fa4841
	{
Packit Service fa4841
		case GFX_PIXEL_FORMAT_ARGB_8888:
Packit Service fa4841
			surface->gdi.format = PIXEL_FORMAT_BGRA32;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case GFX_PIXEL_FORMAT_XRGB_8888:
Packit Service fa4841
			surface->gdi.format = PIXEL_FORMAT_BGRX32;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service b1ea74
			WLog_ERR(TAG, "%s: unknown pixelFormat 0x%" PRIx32 "", __FUNCTION__,
Packit Service b1ea74
			         createSurface->pixelFormat);
Packit Service fa4841
			ret = ERROR_INTERNAL_ERROR;
Packit Service fa4841
			goto out_free;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format);
Packit Service fa4841
	surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad);
Packit Service fa4841
	size = surface->gdi.scanline * surface->gdi.height;
Packit Service fa4841
	surface->gdi.data = (BYTE*)_aligned_malloc(size, 16);
Packit Service fa4841
Packit Service fa4841
	if (!surface->gdi.data)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "%s: unable to allocate GDI data", __FUNCTION__);
Packit Service fa4841
		goto out_free;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ZeroMemory(surface->gdi.data, size);
Packit Service fa4841
Packit Service fa4841
	if (AreColorFormatsEqualNoAlpha(gdi->dstFormat, surface->gdi.format))
Packit Service fa4841
	{
Packit Service b1ea74
		surface->image =
Packit Service b1ea74
		    XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
Packit Service b1ea74
		                 (char*)surface->gdi.data, surface->gdi.mappedWidth,
Packit Service b1ea74
		                 surface->gdi.mappedHeight, xfc->scanline_pad, surface->gdi.scanline);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		UINT32 width = surface->gdi.width;
Packit Service fa4841
		UINT32 bytes = GetBytesPerPixel(gdi->dstFormat);
Packit Service fa4841
		surface->stageScanline = width * bytes;
Packit Service fa4841
		surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad);
Packit Service fa4841
		size = surface->stageScanline * surface->gdi.height;
Packit Service b1ea74
		surface->stage = (BYTE*)_aligned_malloc(size, 16);
Packit Service fa4841
Packit Service fa4841
		if (!surface->stage)
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "%s: unable to allocate stage buffer", __FUNCTION__);
Packit Service fa4841
			goto out_free_gdidata;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		ZeroMemory(surface->stage, size);
Packit Service b1ea74
		surface->image =
Packit Service b1ea74
		    XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char*)surface->stage,
Packit Service b1ea74
		                 surface->gdi.mappedWidth, surface->gdi.mappedHeight, xfc->scanline_pad,
Packit Service b1ea74
		                 surface->stageScanline);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!surface->image)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "%s: an error occurred when creating the XImage", __FUNCTION__);
Packit Service fa4841
		goto error_surface_image;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	surface->image->byte_order = LSBFirst;
Packit Service fa4841
	surface->image->bitmap_bit_order = LSBFirst;
Packit Service fa4841
	surface->gdi.outputMapped = FALSE;
Packit Service fa4841
	region16_init(&surface->gdi.invalidRegion);
Packit Service fa4841
Packit Service b1ea74
	if (context->SetSurfaceData(context, surface->gdi.surfaceId, (void*)surface) != CHANNEL_RC_OK)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "%s: an error occurred during SetSurfaceData", __FUNCTION__);
Packit Service fa4841
		goto error_set_surface_data;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return CHANNEL_RC_OK;
Packit Service fa4841
error_set_surface_data:
Packit Service fa4841
	surface->image->data = NULL;
Packit Service fa4841
	XDestroyImage(surface->image);
Packit Service fa4841
error_surface_image:
Packit Service fa4841
	_aligned_free(surface->stage);
Packit Service fa4841
out_free_gdidata:
Packit Service fa4841
	_aligned_free(surface->gdi.data);
Packit Service fa4841
out_free:
Packit Service fa4841
	free(surface);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service fa4841
static UINT xf_DeleteSurface(RdpgfxClientContext* context,
Packit Service fa4841
                             const RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
Packit Service fa4841
{
Packit Service fa4841
	rdpCodecs* codecs = NULL;
Packit Service fa4841
	xfGfxSurface* surface = NULL;
Packit Service b1ea74
	UINT status;
Packit Service b1ea74
	EnterCriticalSection(&context->mux);
Packit Service b1ea74
	surface = (xfGfxSurface*)context->GetSurfaceData(context, deleteSurface->surfaceId);
Packit Service fa4841
Packit Service fa4841
	if (surface)
Packit Service fa4841
	{
Packit Service b1ea74
		if (surface->gdi.windowId > 0)
Packit Service b1ea74
			IFCALL(context->UnmapWindowForSurface, context, surface->gdi.windowId);
Packit Service b1ea74
Packit Service fa4841
#ifdef WITH_GFX_H264
Packit Service fa4841
		h264_context_free(surface->gdi.h264);
Packit Service fa4841
#endif
Packit Service fa4841
		surface->image->data = NULL;
Packit Service fa4841
		XDestroyImage(surface->image);
Packit Service fa4841
		_aligned_free(surface->gdi.data);
Packit Service fa4841
		_aligned_free(surface->stage);
Packit Service fa4841
		region16_uninit(&surface->gdi.invalidRegion);
Packit Service fa4841
		codecs = surface->gdi.codecs;
Packit Service fa4841
		free(surface);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service b1ea74
	status = context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
Packit Service fa4841
Packit Service fa4841
	if (codecs && codecs->progressive)
Packit Service b1ea74
		progressive_delete_surface_context(codecs->progressive, deleteSurface->surfaceId);
Packit Service fa4841
Packit Service b1ea74
	LeaveCriticalSection(&context->mux);
Packit Service b1ea74
	return status;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
Packit Service fa4841
{
Packit Service fa4841
	rdpGdi* gdi = xfc->context.gdi;
Packit Service fa4841
	gdi_graphics_pipeline_init(gdi, gfx);
Packit Service b1ea74
Packit Service b1ea74
	if (!xfc->context.settings->SoftwareGdi)
Packit Service b1ea74
	{
Packit Service b1ea74
		gfx->UpdateSurfaces = xf_UpdateSurfaces;
Packit Service b1ea74
		gfx->CreateSurface = xf_CreateSurface;
Packit Service b1ea74
		gfx->DeleteSurface = xf_DeleteSurface;
Packit Service b1ea74
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
Packit Service fa4841
{
Packit Service fa4841
	rdpGdi* gdi = xfc->context.gdi;
Packit Service fa4841
	gdi_graphics_pipeline_uninit(gdi, gfx);
Packit Service fa4841
}