Merge pull request #6284 from akallabeth/wayland

Lock wayland buffer updates
This commit is contained in:
Martin Fleisz 2020-06-19 11:44:28 +02:00 committed by GitHub
commit 152bf0cda4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 39 deletions

View File

@ -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) static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih)
{ {
BOOL res = FALSE;
rdpGdi* gdi; rdpGdi* gdi;
char* data; char* data;
UINT32 x, y, w, h; 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)) if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0))
return FALSE; return FALSE;
EnterCriticalSection(&context_w->critical);
x = (UINT32)ix; x = (UINT32)ix;
y = (UINT32)iy; y = (UINT32)iy;
w = (UINT32)iw; 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); data = UwacWindowGetDrawingBuffer(context_w->window);
if (!data || (rc != UWAC_SUCCESS)) if (!data || (rc != UWAC_SUCCESS))
return FALSE; goto fail;
gdi = context_w->context.gdi; gdi = context_w->context.gdi;
if (!gdi) if (!gdi)
return FALSE; goto fail;
/* Ignore output if the surface size does not match. */ /* Ignore output if the surface size does not match. */
if (((INT64)x > geometry.width) || ((INT64)y > geometry.height)) if (((INT64)x > geometry.width) || ((INT64)y > geometry.height))
return TRUE; {
res = TRUE;
goto fail;
}
area.left = x; area.left = x;
area.top = y; 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, if (!wlf_copy_image(gdi->primary_buffer, gdi->stride, gdi->width, gdi->height, data, stride,
geometry.width, geometry.height, &area, geometry.width, geometry.height, &area,
context_w->context.settings->SmartSizing)) context_w->context.settings->SmartSizing))
return FALSE; goto fail;
if (!wlf_scale_coordinates(&context_w->context, &x, &y, FALSE)) if (!wlf_scale_coordinates(&context_w->context, &x, &y, FALSE))
return FALSE; goto fail;
if (!wlf_scale_coordinates(&context_w->context, &w, &h, FALSE)) 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) if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
return FALSE; goto fail;
if (UwacWindowSubmitBuffer(context_w->window, false) != UWAC_SUCCESS) 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) 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) static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
{ {
BOOL rc;
UwacEvent event; UwacEvent event;
wlfContext* context; wlfContext* context;
@ -321,9 +330,11 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break; break;
case UWAC_EVENT_FRAME_DONE: 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; return FALSE;
break; break;
case UWAC_EVENT_POINTER_ENTER: case UWAC_EVENT_POINTER_ENTER:
@ -552,6 +563,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
if (!wfl->displayHandle) if (!wfl->displayHandle)
return FALSE; return FALSE;
InitializeCriticalSection(&wfl->critical);
return TRUE; return TRUE;
} }
@ -567,6 +580,7 @@ static void wlf_client_free(freerdp* instance, rdpContext* context)
if (wlf->displayHandle) if (wlf->displayHandle)
CloseHandle(wlf->displayHandle); CloseHandle(wlf->displayHandle);
DeleteCriticalSection(&wlf->critical);
} }
static int wfl_client_start(rdpContext* context) static int wfl_client_start(rdpContext* context)

View File

@ -50,6 +50,7 @@ struct wlf_context
wfClipboard* clipboard; wfClipboard* clipboard;
wlfDispContext* disp; wlfDispContext* disp;
wLog* log; wLog* log;
CRITICAL_SECTION critical;
}; };
BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP);

View File

@ -235,7 +235,8 @@ struct uwac_window
struct wl_region* opaque_region; struct wl_region* opaque_region;
struct wl_region* input_region; struct wl_region* input_region;
UwacBuffer *drawingBuffer, *pendingBuffer; SSIZE_T drawingBufferIdx;
SSIZE_T pendingBufferIdx;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_shell_surface* shell_surface; struct wl_shell_surface* shell_surface;
struct xdg_surface* xdg_surface; struct xdg_surface* xdg_surface;

View File

@ -136,13 +136,13 @@ static void xdg_handle_toplevel_configure(void* data, struct xdg_toplevel* xdg_t
{ {
assert( assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL; window->drawingBufferIdx = window->pendingBufferIdx = -1;
return; return;
} }
window->drawingBuffer = &window->buffers[0]; window->drawingBufferIdx = 0;
if (window->pendingBuffer != NULL) if (window->pendingBufferIdx != -1)
window->pendingBuffer = window->drawingBuffer; window->pendingBufferIdx = window->drawingBufferIdx;
} }
else else
{ {
@ -219,13 +219,13 @@ static void ivi_handle_configure(void* data, struct ivi_surface* surface, int32_
{ {
assert( assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL; window->drawingBufferIdx = window->pendingBufferIdx = -1;
return; return;
} }
window->drawingBuffer = &window->buffers[0]; window->drawingBufferIdx = 0;
if (window->pendingBuffer != NULL) if (window->pendingBufferIdx != -1)
window->pendingBuffer = window->drawingBuffer; window->pendingBufferIdx = window->drawingBufferIdx;
} }
else else
{ {
@ -277,13 +277,13 @@ static void shell_configure(void* data, struct wl_shell_surface* surface, uint32
{ {
assert( assert(
uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
window->drawingBuffer = window->pendingBuffer = NULL; window->drawingBufferIdx = window->pendingBufferIdx = -1;
return; return;
} }
window->drawingBuffer = &window->buffers[0]; window->drawingBufferIdx = 0;
if (window->pendingBuffer != NULL) if (window->pendingBufferIdx != -1)
window->pendingBuffer = window->drawingBuffer; window->pendingBufferIdx = window->drawingBufferIdx;
} }
else else
{ {
@ -364,15 +364,21 @@ error_mmap:
return ret; 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++) for (i = 0; i < w->nbuffers; i++)
{ {
if (!w->buffers[i].used) if (!w->buffers[i].used)
{ {
w->buffers[i].used = true; w->buffers[i].used = true;
if (index)
*index = i;
return &w->buffers[i]; return &w->buffers[i];
} }
} }
@ -386,6 +392,8 @@ static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w)
} }
w->buffers[i].used = true; w->buffers[i].used = true;
if (index)
*index = i;
return &w->buffers[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->buffers[0].used = true;
w->drawingBuffer = &w->buffers[0]; w->drawingBufferIdx = 0;
w->pendingBufferIdx = -1;
w->surface = wl_compositor_create_surface(display->compositor); w->surface = wl_compositor_create_surface(display->compositor);
if (!w->surface) if (!w->surface)
@ -603,7 +612,16 @@ UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t
void* UwacWindowGetDrawingBuffer(UwacWindow* window) 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); 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; UwacFrameDoneEvent* event;
wl_callback_destroy(callback); wl_callback_destroy(callback);
window->pendingBuffer = NULL; window->pendingBufferIdx = -1;
event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE); event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
if (event) if (event)
@ -677,13 +695,20 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, u
uint32_t height) uint32_t height)
{ {
RECTANGLE_16 box; RECTANGLE_16 box;
UwacBuffer* buf;
box.left = x; box.left = x;
box.top = y; box.top = y;
box.right = x + width; box.right = x + width;
box.bottom = y + height; 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)) if (!region16_union_rect(&buf->damage, &buf->damage, &box))
return UWAC_ERROR_INTERNAL; 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, UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry,
size_t* stride) size_t* stride)
{ {
if (!window || !window->drawingBuffer) if (!window || (window->drawingBufferIdx < 0))
return UWAC_ERROR_INTERNAL; return UWAC_ERROR_INTERNAL;
if (geometry) if (geometry)
@ -712,22 +737,29 @@ UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize*
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNextFrame) 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; return UWAC_SUCCESS;
window->pendingBuffer = drawingBuffer; window->pendingBufferIdx = window->drawingBufferIdx;
window->drawingBuffer = UwacWindowFindFreeBuffer(window); nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx);
pendingBuffer = &window->buffers[window->pendingBufferIdx];
if (!window->drawingBuffer) if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0))
return UWAC_ERROR_NOMEMORY; return UWAC_ERROR_NOMEMORY;
if (copyContentForNextFrame) if (copyContentForNextFrame)
memcpy(window->drawingBuffer->data, window->pendingBuffer->data, memcpy(nextDrawingBuffer->data, pendingBuffer->data, window->stride * window->height);
window->stride * window->height);
UwacSubmitBufferPtr(window, drawingBuffer); UwacSubmitBufferPtr(window, pendingBuffer);
return UWAC_SUCCESS; return UWAC_SUCCESS;
} }