diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 5086220d2..11b747e60 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -62,6 +62,7 @@ static BOOL wl_begin_paint(rdpContext* context) static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih) { + BOOL res = FALSE; rdpGdi* gdi; char* data; UINT32 x, y, w, h; @@ -76,6 +77,7 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0)) return FALSE; + EnterCriticalSection(&context_w->critical); x = (UINT32)ix; y = (UINT32)iy; w = (UINT32)iw; @@ -84,16 +86,19 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw data = UwacWindowGetDrawingBuffer(context_w->window); if (!data || (rc != UWAC_SUCCESS)) - return FALSE; + goto fail; gdi = context_w->context.gdi; if (!gdi) - return FALSE; + goto fail; /* Ignore output if the surface size does not match. */ if (((INT64)x > geometry.width) || ((INT64)y > geometry.height)) - return TRUE; + { + res = TRUE; + goto fail; + } area.left = x; area.top = y; @@ -103,21 +108,24 @@ static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw if (!wlf_copy_image(gdi->primary_buffer, gdi->stride, gdi->width, gdi->height, data, stride, geometry.width, geometry.height, &area, context_w->context.settings->SmartSizing)) - return FALSE; + goto fail; if (!wlf_scale_coordinates(&context_w->context, &x, &y, FALSE)) - return FALSE; + goto fail; if (!wlf_scale_coordinates(&context_w->context, &w, &h, FALSE)) - return FALSE; + goto fail; if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS) - return FALSE; + goto fail; if (UwacWindowSubmitBuffer(context_w->window, false) != UWAC_SUCCESS) - return FALSE; + goto fail; - return TRUE; + res = TRUE; +fail: + LeaveCriticalSection(&context_w->critical); + return res; } static BOOL wl_end_paint(rdpContext* context) @@ -296,6 +304,7 @@ static void wl_post_disconnect(freerdp* instance) static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) { + BOOL rc; UwacEvent event; wlfContext* context; @@ -321,9 +330,11 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) break; case UWAC_EVENT_FRAME_DONE: - if (UwacWindowSubmitBuffer(context->window, false) != UWAC_SUCCESS) + EnterCriticalSection(&context->critical); + rc = UwacWindowSubmitBuffer(context->window, false); + LeaveCriticalSection(&context->critical); + if (rc != UWAC_SUCCESS) return FALSE; - break; case UWAC_EVENT_POINTER_ENTER: @@ -552,6 +563,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context) if (!wfl->displayHandle) return FALSE; + InitializeCriticalSection(&wfl->critical); + return TRUE; } @@ -567,6 +580,7 @@ static void wlf_client_free(freerdp* instance, rdpContext* context) if (wlf->displayHandle) CloseHandle(wlf->displayHandle); + DeleteCriticalSection(&wlf->critical); } static int wfl_client_start(rdpContext* context) diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index 09d056ae4..d64706690 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -50,6 +50,7 @@ struct wlf_context wfClipboard* clipboard; wlfDispContext* disp; wLog* log; + CRITICAL_SECTION critical; }; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h index 75ad6e0fe..2ef073de1 100644 --- a/uwac/libuwac/uwac-priv.h +++ b/uwac/libuwac/uwac-priv.h @@ -235,7 +235,8 @@ struct uwac_window struct wl_region* opaque_region; struct wl_region* input_region; - UwacBuffer *drawingBuffer, *pendingBuffer; + SSIZE_T drawingBufferIdx; + SSIZE_T pendingBufferIdx; struct wl_surface* surface; struct wl_shell_surface* shell_surface; struct xdg_surface* xdg_surface; diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index f76d43bcc..1dc5574ff 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -136,13 +136,13 @@ static void xdg_handle_toplevel_configure(void* data, struct xdg_toplevel* xdg_t { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -219,13 +219,13 @@ static void ivi_handle_configure(void* data, struct ivi_surface* surface, int32_ { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -277,13 +277,13 @@ static void shell_configure(void* data, struct wl_shell_surface* surface, uint32 { assert( uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); - window->drawingBuffer = window->pendingBuffer = NULL; + window->drawingBufferIdx = window->pendingBufferIdx = -1; return; } - window->drawingBuffer = &window->buffers[0]; - if (window->pendingBuffer != NULL) - window->pendingBuffer = window->drawingBuffer; + window->drawingBufferIdx = 0; + if (window->pendingBufferIdx != -1) + window->pendingBufferIdx = window->drawingBufferIdx; } else { @@ -364,15 +364,21 @@ error_mmap: return ret; } -static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w) +static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w, SSIZE_T* index) { - int i, ret; + SSIZE_T i; + int ret; + + if (index) + *index = -1; for (i = 0; i < w->nbuffers; i++) { if (!w->buffers[i].used) { w->buffers[i].used = true; + if (index) + *index = i; return &w->buffers[i]; } } @@ -386,6 +392,8 @@ static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w) } w->buffers[i].used = true; + if (index) + *index = i; return &w->buffers[i]; } @@ -457,7 +465,8 @@ UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t h } w->buffers[0].used = true; - w->drawingBuffer = &w->buffers[0]; + w->drawingBufferIdx = 0; + w->pendingBufferIdx = -1; w->surface = wl_compositor_create_surface(display->compositor); if (!w->surface) @@ -603,7 +612,16 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t void* UwacWindowGetDrawingBuffer(UwacWindow* window) { - return window->drawingBuffer->data; + UwacBuffer* buffer; + + if (window->drawingBufferIdx < 0) + return NULL; + + buffer = &window->buffers[window->drawingBufferIdx]; + if (!buffer) + return NULL; + + return buffer->data; } static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t time); @@ -654,7 +672,7 @@ static void frame_done_cb(void* data, struct wl_callback* callback, uint32_t tim UwacFrameDoneEvent* event; wl_callback_destroy(callback); - window->pendingBuffer = NULL; + window->pendingBufferIdx = -1; event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE); if (event) @@ -677,13 +695,20 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u uint32_t height) { RECTANGLE_16 box; + UwacBuffer* buf; box.left = x; box.top = y; box.right = x + width; box.bottom = y + height; - UwacBuffer* buf = window->drawingBuffer; + if (window->drawingBufferIdx < 0) + return UWAC_ERROR_INTERNAL; + + buf = &window->buffers[window->drawingBufferIdx]; + if (!buf) + return UWAC_ERROR_INTERNAL; + if (!region16_union_rect(&buf->damage, &buf->damage, &box)) return UWAC_ERROR_INTERNAL; @@ -695,7 +720,7 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry, size_t* stride) { - if (!window || !window->drawingBuffer) + if (!window || (window->drawingBufferIdx < 0)) return UWAC_ERROR_INTERNAL; if (geometry) @@ -712,22 +737,29 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) { - UwacBuffer* drawingBuffer = window->drawingBuffer; + UwacBuffer* currentDrawingBuffer; + UwacBuffer* nextDrawingBuffer; + UwacBuffer* pendingBuffer; - if (window->pendingBuffer || !drawingBuffer->dirty) + if (window->drawingBufferIdx < 0) + return UWAC_ERROR_INTERNAL; + + currentDrawingBuffer = &window->buffers[window->drawingBufferIdx]; + + if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty) return UWAC_SUCCESS; - window->pendingBuffer = drawingBuffer; - window->drawingBuffer = UwacWindowFindFreeBuffer(window); + window->pendingBufferIdx = window->drawingBufferIdx; + nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx); + pendingBuffer = &window->buffers[window->pendingBufferIdx]; - if (!window->drawingBuffer) + if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0)) return UWAC_ERROR_NOMEMORY; if (copyContentForNextFrame) - memcpy(window->drawingBuffer->data, window->pendingBuffer->data, - window->stride * window->height); + memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height); - UwacSubmitBufferPtr(window, drawingBuffer); + UwacSubmitBufferPtr(window, pendingBuffer); return UWAC_SUCCESS; }