2014-06-05 02:03:25 +04:00
|
|
|
/**
|
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
|
|
* X11 Graphics Pipeline
|
|
|
|
*
|
|
|
|
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
2016-04-05 18:07:45 +03:00
|
|
|
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
|
|
|
* Copyright 2016 Thincast Technologies GmbH
|
2014-06-05 02:03:25 +04:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2014-09-12 19:13:01 +04:00
|
|
|
#include <freerdp/log.h>
|
2014-06-05 02:03:25 +04:00
|
|
|
#include "xf_gfx.h"
|
2017-12-20 18:13:42 +03:00
|
|
|
#include "xf_rail.h"
|
2014-06-05 02:03:25 +04:00
|
|
|
|
2018-02-12 13:14:54 +03:00
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
2014-09-12 19:13:01 +04:00
|
|
|
#define TAG CLIENT_TAG("x11")
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
static UINT xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
|
2014-06-05 02:03:25 +04:00
|
|
|
{
|
2017-03-28 12:49:13 +03:00
|
|
|
UINT rc = ERROR_INTERNAL_ERROR;
|
2015-02-07 01:46:15 +03:00
|
|
|
UINT32 surfaceX, surfaceY;
|
2014-06-05 20:36:01 +04:00
|
|
|
RECTANGLE_16 surfaceRect;
|
2016-08-03 15:16:20 +03:00
|
|
|
rdpGdi* gdi;
|
2017-03-30 18:23:04 +03:00
|
|
|
UINT32 nbRects, x;
|
|
|
|
const RECTANGLE_16* rects;
|
2016-08-03 15:16:20 +03:00
|
|
|
gdi = xfc->context.gdi;
|
2016-04-05 18:07:45 +03:00
|
|
|
surfaceX = surface->gdi.outputOriginX;
|
|
|
|
surfaceY = surface->gdi.outputOriginY;
|
2017-04-11 13:30:37 +03:00
|
|
|
surfaceRect.left = 0;
|
|
|
|
surfaceRect.top = 0;
|
|
|
|
surfaceRect.right = surface->gdi.width;
|
|
|
|
surfaceRect.bottom = surface->gdi.height;
|
2014-06-13 00:13:12 +04:00
|
|
|
XSetClipMask(xfc->display, xfc->gc, None);
|
|
|
|
XSetFunction(xfc->display, xfc->gc, GXcopy);
|
|
|
|
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
|
2017-03-30 18:23:04 +03:00
|
|
|
region16_intersect_rect(&(surface->gdi.invalidRegion),
|
|
|
|
&(surface->gdi.invalidRegion), &surfaceRect);
|
2014-06-05 06:49:03 +04:00
|
|
|
|
2017-03-30 18:23:04 +03:00
|
|
|
if (!(rects = region16_rects(&surface->gdi.invalidRegion, &nbRects)))
|
|
|
|
return CHANNEL_RC_OK;
|
2014-06-05 20:36:01 +04:00
|
|
|
|
2017-03-30 18:23:04 +03:00
|
|
|
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;
|
2014-06-05 20:36:01 +04:00
|
|
|
|
2014-09-17 22:29:56 +04:00
|
|
|
if (surface->stage)
|
|
|
|
{
|
2017-03-28 12:49:13 +03:00
|
|
|
if (!freerdp_image_copy(surface->stage, gdi->dstFormat,
|
2017-03-30 18:23:04 +03:00
|
|
|
surface->stageScanline, nXSrc, nYSrc,
|
2017-03-28 12:49:13 +03:00
|
|
|
width, height,
|
|
|
|
surface->gdi.data, surface->gdi.format,
|
2017-03-30 18:23:04 +03:00
|
|
|
surface->gdi.scanline, nXSrc, nYSrc,
|
2017-03-28 12:49:13 +03:00
|
|
|
NULL, FREERDP_FLIP_NONE))
|
|
|
|
goto fail;
|
2014-09-17 22:29:56 +04:00
|
|
|
}
|
|
|
|
|
2017-12-20 18:13:42 +03:00
|
|
|
if (xfc->remote_app)
|
2014-12-01 13:56:44 +03:00
|
|
|
{
|
2017-12-20 18:13:42 +03:00
|
|
|
XPutImage(xfc->display, xfc->primary, xfc->gc,
|
2017-03-30 18:23:04 +03:00
|
|
|
surface->image, nXSrc, nYSrc,
|
|
|
|
nXDst, nYDst, width, height);
|
2017-12-20 18:13:42 +03:00
|
|
|
xf_lock_x11(xfc, FALSE);
|
|
|
|
xf_rail_paint(xfc, nXDst, nYDst, nXDst + width, nYDst + height);
|
|
|
|
xf_unlock_x11(xfc, FALSE);
|
2014-12-01 13:56:44 +03:00
|
|
|
}
|
2017-12-20 18:13:42 +03:00
|
|
|
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);
|
|
|
|
}
|
2014-06-05 06:49:03 +04:00
|
|
|
}
|
2014-06-05 20:36:01 +04:00
|
|
|
|
2017-03-28 12:49:13 +03:00
|
|
|
rc = CHANNEL_RC_OK;
|
|
|
|
fail:
|
2016-04-05 18:07:45 +03:00
|
|
|
region16_clear(&surface->gdi.invalidRegion);
|
2014-06-13 00:13:12 +04:00
|
|
|
XSetClipMask(xfc->display, xfc->gc, None);
|
2015-06-30 12:41:23 +03:00
|
|
|
XSync(xfc->display, False);
|
2017-03-28 12:49:13 +03:00
|
|
|
return rc;
|
2014-06-05 20:36:01 +04:00
|
|
|
}
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
static UINT xf_UpdateSurfaces(RdpgfxClientContext* context)
|
2015-02-07 01:46:15 +03:00
|
|
|
{
|
2015-06-09 16:22:26 +03:00
|
|
|
UINT16 count;
|
2016-04-05 18:07:45 +03:00
|
|
|
UINT32 index;
|
|
|
|
UINT status = CHANNEL_RC_OK;
|
2015-02-11 00:32:07 +03:00
|
|
|
xfGfxSurface* surface;
|
|
|
|
UINT16* pSurfaceIds = NULL;
|
2016-07-13 15:58:11 +03:00
|
|
|
rdpGdi* gdi = (rdpGdi*)context->custom;
|
|
|
|
xfContext* xfc = (xfContext*) gdi->context;
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!gdi)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
if (!gdi->graphicsReset)
|
|
|
|
return status;
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2018-02-08 12:34:49 +03:00
|
|
|
if (gdi->suppressOutput)
|
|
|
|
return CHANNEL_RC_OK;
|
|
|
|
|
2015-06-09 16:22:26 +03:00
|
|
|
context->GetSurfaceIds(context, &pSurfaceIds, &count);
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2015-02-11 00:32:07 +03:00
|
|
|
for (index = 0; index < count; index++)
|
2015-02-07 01:46:15 +03:00
|
|
|
{
|
2015-02-11 00:32:07 +03:00
|
|
|
surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!surface || !surface->gdi.outputMapped)
|
2015-02-11 00:32:07 +03:00
|
|
|
continue;
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2015-02-11 00:32:07 +03:00
|
|
|
status = xf_OutputUpdate(xfc, surface);
|
2015-02-07 01:46:15 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (status != 0)
|
2015-02-11 00:32:07 +03:00
|
|
|
break;
|
2015-02-07 01:46:15 +03:00
|
|
|
}
|
|
|
|
|
2015-02-11 00:32:07 +03:00
|
|
|
free(pSurfaceIds);
|
|
|
|
return status;
|
2015-02-07 01:46:15 +03:00
|
|
|
}
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y,
|
2016-07-14 17:08:06 +03:00
|
|
|
UINT32 width, UINT32 height)
|
2014-06-13 00:13:12 +04:00
|
|
|
{
|
2015-06-09 16:22:26 +03:00
|
|
|
UINT16 count;
|
2016-04-05 18:07:45 +03:00
|
|
|
UINT32 index;
|
|
|
|
UINT status = CHANNEL_RC_OK;
|
2015-02-11 00:32:07 +03:00
|
|
|
xfGfxSurface* surface;
|
2014-06-13 00:13:12 +04:00
|
|
|
RECTANGLE_16 invalidRect;
|
2015-02-11 00:32:07 +03:00
|
|
|
RECTANGLE_16 surfaceRect;
|
|
|
|
RECTANGLE_16 intersection;
|
|
|
|
UINT16* pSurfaceIds = NULL;
|
2018-02-08 15:55:36 +03:00
|
|
|
RdpgfxClientContext* context = xfc->context.gdi->gfx;
|
2014-06-13 00:13:12 +04:00
|
|
|
invalidRect.left = x;
|
|
|
|
invalidRect.top = y;
|
2014-06-20 01:08:50 +04:00
|
|
|
invalidRect.right = x + width;
|
|
|
|
invalidRect.bottom = y + height;
|
2015-06-09 16:22:26 +03:00
|
|
|
context->GetSurfaceIds(context, &pSurfaceIds, &count);
|
2015-02-11 00:32:07 +03:00
|
|
|
|
|
|
|
for (index = 0; index < count; index++)
|
|
|
|
{
|
|
|
|
surface = (xfGfxSurface*) context->GetSurfaceData(context, pSurfaceIds[index]);
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!surface || !surface->gdi.outputMapped)
|
2015-02-11 00:32:07 +03:00
|
|
|
continue;
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
surfaceRect.left = surface->gdi.outputOriginX;
|
|
|
|
surfaceRect.top = surface->gdi.outputOriginY;
|
|
|
|
surfaceRect.right = surface->gdi.outputOriginX + surface->gdi.width;
|
|
|
|
surfaceRect.bottom = surface->gdi.outputOriginY + surface->gdi.height;
|
2015-02-11 00:32:07 +03:00
|
|
|
|
|
|
|
if (rectangles_intersection(&invalidRect, &surfaceRect, &intersection))
|
|
|
|
{
|
|
|
|
/* Invalid rects are specified relative to surface origin */
|
|
|
|
intersection.left -= surfaceRect.left;
|
|
|
|
intersection.top -= surfaceRect.top;
|
|
|
|
intersection.right -= surfaceRect.left;
|
|
|
|
intersection.bottom -= surfaceRect.top;
|
2016-04-05 18:07:45 +03:00
|
|
|
region16_union_rect(&surface->gdi.invalidRegion,
|
2016-07-14 17:08:06 +03:00
|
|
|
&surface->gdi.invalidRegion,
|
|
|
|
&intersection);
|
2015-02-11 00:32:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(pSurfaceIds);
|
2016-04-05 18:07:45 +03:00
|
|
|
IFCALLRET(context->UpdateSurfaces, status, context);
|
2015-02-07 01:46:15 +03:00
|
|
|
return status;
|
2014-06-13 00:13:12 +04:00
|
|
|
}
|
|
|
|
|
2017-02-15 13:56:50 +03:00
|
|
|
UINT32 x11_pad_scanline(UINT32 scanline, UINT32 inPad)
|
2016-11-24 11:02:06 +03:00
|
|
|
{
|
2017-02-15 13:56:50 +03:00
|
|
|
/* Ensure X11 alignment is met */
|
2016-11-24 11:02:06 +03:00
|
|
|
if (inPad > 0)
|
|
|
|
{
|
|
|
|
const UINT32 align = inPad / 8;
|
|
|
|
const UINT32 pad = align - scanline % align;
|
|
|
|
|
|
|
|
if (align != pad)
|
|
|
|
scanline += pad;
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:56:50 +03:00
|
|
|
/* 16 byte alingment is required for ASM optimized code */
|
|
|
|
if (scanline % 16)
|
|
|
|
scanline += 16 - scanline % 16;
|
|
|
|
|
2016-11-24 11:02:06 +03:00
|
|
|
return scanline;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-27 15:25:09 +03:00
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-04-05 18:07:45 +03:00
|
|
|
static UINT xf_CreateSurface(RdpgfxClientContext* context,
|
2016-07-14 17:08:06 +03:00
|
|
|
const RDPGFX_CREATE_SURFACE_PDU* createSurface)
|
2014-06-05 02:03:25 +04:00
|
|
|
{
|
2017-05-01 23:39:52 +03:00
|
|
|
UINT ret = CHANNEL_RC_NO_MEMORY;
|
2016-04-05 18:07:45 +03:00
|
|
|
size_t size;
|
2014-06-13 00:13:12 +04:00
|
|
|
xfGfxSurface* surface;
|
2016-07-13 15:58:11 +03:00
|
|
|
rdpGdi* gdi = (rdpGdi*)context->custom;
|
|
|
|
xfContext* xfc = (xfContext*) gdi->context;
|
2018-02-08 13:55:57 +03:00
|
|
|
surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface));
|
2014-06-13 00:13:12 +04:00
|
|
|
|
|
|
|
if (!surface)
|
2016-04-05 18:07:45 +03:00
|
|
|
return CHANNEL_RC_NO_MEMORY;
|
2014-06-05 02:03:25 +04:00
|
|
|
|
2016-12-06 18:44:00 +03:00
|
|
|
surface->gdi.codecs = gdi->context->codecs;
|
2018-02-08 13:55:57 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!surface->gdi.codecs)
|
2014-06-05 02:03:25 +04:00
|
|
|
{
|
2017-05-01 23:39:52 +03:00
|
|
|
WLog_ERR(TAG, "%s: global GDI codecs aren't set", __FUNCTION__);
|
|
|
|
goto out_free;
|
2014-06-05 02:03:25 +04:00
|
|
|
}
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
surface->gdi.surfaceId = createSurface->surfaceId;
|
|
|
|
surface->gdi.width = (UINT32) createSurface->width;
|
|
|
|
surface->gdi.height = (UINT32) createSurface->height;
|
2016-07-14 17:08:06 +03:00
|
|
|
|
|
|
|
switch (createSurface->pixelFormat)
|
2014-07-02 00:32:36 +04:00
|
|
|
{
|
2016-07-14 17:08:06 +03:00
|
|
|
case GFX_PIXEL_FORMAT_ARGB_8888:
|
|
|
|
surface->gdi.format = PIXEL_FORMAT_BGRA32;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GFX_PIXEL_FORMAT_XRGB_8888:
|
|
|
|
surface->gdi.format = PIXEL_FORMAT_BGRX32;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2017-05-01 23:39:52 +03:00
|
|
|
WLog_ERR(TAG, "%s: unknown pixelFormat 0x%"PRIx32"", __FUNCTION__, createSurface->pixelFormat);
|
|
|
|
ret = ERROR_INTERNAL_ERROR;
|
|
|
|
goto out_free;
|
2014-07-02 00:32:36 +04:00
|
|
|
}
|
|
|
|
|
2017-05-01 23:39:52 +03:00
|
|
|
surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format);
|
2016-11-24 11:02:06 +03:00
|
|
|
surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad);
|
2016-04-05 18:07:45 +03:00
|
|
|
size = surface->gdi.scanline * surface->gdi.height;
|
2017-05-01 23:39:52 +03:00
|
|
|
surface->gdi.data = (BYTE*)_aligned_malloc(size, 16);
|
2018-02-08 13:55:57 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!surface->gdi.data)
|
2014-08-13 22:56:40 +04:00
|
|
|
{
|
2017-05-01 23:39:52 +03:00
|
|
|
WLog_ERR(TAG, "%s: unable to allocate GDI data", __FUNCTION__);
|
|
|
|
goto out_free;
|
2014-08-13 22:56:40 +04:00
|
|
|
}
|
2018-02-08 13:55:57 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
ZeroMemory(surface->gdi.data, size);
|
2016-07-14 17:08:06 +03:00
|
|
|
|
2017-03-28 12:49:13 +03:00
|
|
|
if (AreColorFormatsEqualNoAlpha(gdi->dstFormat, surface->gdi.format))
|
2014-07-09 02:04:24 +04:00
|
|
|
{
|
2016-04-05 18:07:45 +03:00
|
|
|
surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0,
|
2016-07-14 17:08:06 +03:00
|
|
|
(char*) surface->gdi.data, surface->gdi.width, surface->gdi.height,
|
|
|
|
xfc->scanline_pad, surface->gdi.scanline);
|
2014-07-09 02:04:24 +04:00
|
|
|
}
|
2016-04-05 18:07:45 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT32 width = surface->gdi.width;
|
2016-08-03 15:16:20 +03:00
|
|
|
UINT32 bytes = GetBytesPerPixel(gdi->dstFormat);
|
2016-04-05 18:07:45 +03:00
|
|
|
surface->stageScanline = width * bytes;
|
2016-11-24 11:02:06 +03:00
|
|
|
surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad);
|
2016-04-05 18:07:45 +03:00
|
|
|
size = surface->stageScanline * surface->gdi.height;
|
2017-05-01 23:39:52 +03:00
|
|
|
surface->stage = (BYTE*) _aligned_malloc(size, 16);
|
2018-02-08 13:55:57 +03:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (!surface->stage)
|
|
|
|
{
|
2017-05-01 23:39:52 +03:00
|
|
|
WLog_ERR(TAG, "%s: unable to allocate stage buffer", __FUNCTION__);
|
|
|
|
goto out_free_gdidata;
|
2016-04-05 18:07:45 +03:00
|
|
|
}
|
2017-05-01 23:39:52 +03:00
|
|
|
|
2018-02-08 13:55:57 +03:00
|
|
|
ZeroMemory(surface->stage, size);
|
2016-07-13 15:58:11 +03:00
|
|
|
surface->image = XCreateImage(xfc->display, xfc->visual, xfc->depth,
|
2016-07-14 17:08:06 +03:00
|
|
|
ZPixmap, 0, (char*) surface->stage,
|
|
|
|
surface->gdi.width, surface->gdi.height,
|
2017-01-19 19:16:25 +03:00
|
|
|
xfc->scanline_pad, surface->stageScanline);
|
2016-03-02 17:16:49 +03:00
|
|
|
}
|
|
|
|
|
2017-05-01 23:39:52 +03:00
|
|
|
if (!surface->image)
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "%s: an error occurred when creating the XImage", __FUNCTION__);
|
|
|
|
goto error_surface_image;
|
|
|
|
}
|
|
|
|
|
2017-09-18 11:47:56 +03:00
|
|
|
surface->image->byte_order = LSBFirst;
|
|
|
|
surface->image->bitmap_bit_order = LSBFirst;
|
2016-04-05 18:07:45 +03:00
|
|
|
surface->gdi.outputMapped = FALSE;
|
|
|
|
region16_init(&surface->gdi.invalidRegion);
|
2018-02-08 13:55:57 +03:00
|
|
|
|
2017-07-10 16:29:09 +03:00
|
|
|
if (context->SetSurfaceData(context, surface->gdi.surfaceId, (void*) surface) != CHANNEL_RC_OK)
|
2017-05-01 23:39:52 +03:00
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "%s: an error occurred during SetSurfaceData", __FUNCTION__);
|
|
|
|
goto error_set_surface_data;
|
|
|
|
}
|
|
|
|
|
2018-02-08 13:55:57 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2017-05-01 23:39:52 +03:00
|
|
|
error_set_surface_data:
|
2018-02-12 13:14:54 +03:00
|
|
|
surface->image->data = NULL;
|
2018-02-12 12:02:35 +03:00
|
|
|
XDestroyImage(surface->image);
|
2017-05-01 23:39:52 +03:00
|
|
|
error_surface_image:
|
|
|
|
_aligned_free(surface->stage);
|
|
|
|
out_free_gdidata:
|
|
|
|
_aligned_free(surface->gdi.data);
|
|
|
|
out_free:
|
|
|
|
free(surface);
|
|
|
|
return ret;
|
2016-03-02 17:16:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function description
|
|
|
|
*
|
|
|
|
* @return 0 on success, otherwise a Win32 error code
|
|
|
|
*/
|
2016-04-05 18:07:45 +03:00
|
|
|
static UINT xf_DeleteSurface(RdpgfxClientContext* context,
|
2016-07-14 17:08:06 +03:00
|
|
|
const RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
|
2014-07-02 07:28:09 +04:00
|
|
|
{
|
2016-04-05 18:07:45 +03:00
|
|
|
rdpCodecs* codecs = NULL;
|
|
|
|
xfGfxSurface* surface = NULL;
|
2016-07-14 17:08:06 +03:00
|
|
|
surface = (xfGfxSurface*) context->GetSurfaceData(context,
|
|
|
|
deleteSurface->surfaceId);
|
2014-07-02 07:28:09 +04:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (surface)
|
|
|
|
{
|
2017-08-14 11:16:14 +03:00
|
|
|
#ifdef WITH_GFX_H264
|
|
|
|
h264_context_free(surface->gdi.h264);
|
|
|
|
#endif
|
2018-02-12 13:14:54 +03:00
|
|
|
surface->image->data = NULL;
|
2018-02-12 12:02:35 +03:00
|
|
|
XDestroyImage(surface->image);
|
2016-04-05 18:07:45 +03:00
|
|
|
_aligned_free(surface->gdi.data);
|
|
|
|
_aligned_free(surface->stage);
|
|
|
|
region16_uninit(&surface->gdi.invalidRegion);
|
|
|
|
codecs = surface->gdi.codecs;
|
|
|
|
free(surface);
|
|
|
|
}
|
2014-07-02 07:28:09 +04:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
|
2014-07-02 07:28:09 +04:00
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
if (codecs && codecs->progressive)
|
2016-07-14 17:08:06 +03:00
|
|
|
progressive_delete_surface_context(codecs->progressive,
|
|
|
|
deleteSurface->surfaceId);
|
2014-07-02 07:28:09 +04:00
|
|
|
|
2015-06-09 16:22:26 +03:00
|
|
|
return CHANNEL_RC_OK;
|
2014-07-02 07:28:09 +04:00
|
|
|
}
|
|
|
|
|
2016-04-05 18:07:45 +03:00
|
|
|
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
|
2014-07-02 07:28:09 +04:00
|
|
|
{
|
2016-04-05 18:07:45 +03:00
|
|
|
rdpGdi* gdi = xfc->context.gdi;
|
|
|
|
gdi_graphics_pipeline_init(gdi, gfx);
|
|
|
|
gfx->UpdateSurfaces = xf_UpdateSurfaces;
|
|
|
|
gfx->CreateSurface = xf_CreateSurface;
|
|
|
|
gfx->DeleteSurface = xf_DeleteSurface;
|
|
|
|
}
|
2014-06-20 21:52:13 +04:00
|
|
|
|
|
|
|
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
|
|
|
|
{
|
2016-04-05 18:07:45 +03:00
|
|
|
rdpGdi* gdi = xfc->context.gdi;
|
|
|
|
gdi_graphics_pipeline_uninit(gdi, gfx);
|
2014-06-20 21:52:13 +04:00
|
|
|
}
|