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