From 823411c2f3ee06dc76cad1f617d7cecab0a220db Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 24 Jan 2019 15:10:08 +0100 Subject: [PATCH] Fixed wayland buffer updates The wayland buffer size always matches the current window size. That might be different from the actual remote framebuffer size, to when copying always use the correct strides to avoid distorted screen content. --- client/Wayland/wlfreerdp.c | 26 +++++++++++++++++++------- uwac/include/uwac/uwac.h | 10 ++++++++++ uwac/libuwac/uwac-window.c | 16 ++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 7d5b8c965..3856be4b6 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -60,8 +60,12 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw { rdpGdi* gdi; char* data; - size_t baseOffset; + size_t baseSrcOffset; + size_t baseDstOffset; UINT32 i, x, y, w, h; + UwacSize geometry; + size_t stride; + UwacReturnCode rc; if (!context_w) return FALSE; @@ -73,9 +77,10 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw y = (UINT32)iy; w = (UINT32)iw; h = (UINT32)ih; + rc = UwacWindowGetDrawingBufferGeometry(context_w->window, &geometry, &stride); data = UwacWindowGetDrawingBuffer(context_w->window); - if (!data) + if (!data || (rc != UWAC_SUCCESS)) return FALSE; gdi = context_w->context.gdi; @@ -83,12 +88,19 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw if (!gdi) return FALSE; - baseOffset = y * gdi->stride + x * GetBytesPerPixel(gdi->dstFormat); - for (i = 0; i < h; i++) + /* Ignore output if the surface size does not match. */ + if ((x > geometry.width) || (y > geometry.height)) + return TRUE; + + baseSrcOffset = y * gdi->stride + x * GetBytesPerPixel(gdi->dstFormat); + baseDstOffset = y * stride + x * 4; + for (i = 0; i < MIN(h, geometry.height - y); i++) { - size_t offset = i * gdi->stride + baseOffset; - memcpy(data + offset, gdi->primary_buffer + offset, - w * GetBytesPerPixel(gdi->dstFormat)); + const size_t srcOffset = i * gdi->stride + baseSrcOffset; + const size_t dstOffset = i * stride + baseDstOffset; + + memcpy(data + dstOffset, gdi->primary_buffer + srcOffset, + MIN(w, geometry.width - x) * GetBytesPerPixel(gdi->dstFormat)); } if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS) diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index 6b54dbb57..8466b1125 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -453,6 +453,16 @@ UWAC_API void* UwacWindowGetDrawingBuffer(UwacWindow* window); UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); +/** + * returns the geometry of the given UwacWindow buffer + * + * @param window the UwacWindow + * @param geometry the geometry to fill + * @param stride the length of a buffer line in bytes + * @return UWAC_SUCCESS on success, an Uwac error otherwise + */ +UWAC_API UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry, size_t* stride); + /** * Sends a frame to the compositor with the content of the drawing buffer * diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index d1ce97208..ca97c0d99 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -670,6 +670,22 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u return UWAC_SUCCESS; } +UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry, size_t* stride) +{ + if (!window || !window->drawingBuffer) + return UWAC_ERROR_INTERNAL; + + if (geometry) + { + geometry->width = window->width; + geometry->height = window->height; + } + + if (stride) + *stride = window->stride; + + return UWAC_SUCCESS; +} UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) {