Skip to content
Snippets Groups Projects
Commit 6b0a84c8 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard
Browse files

winewayland.drv: Implement a simple window_surface flush.

Flush a window_surface to a Wayland surface by creating a wl_shm buffer
matching the window size, copying the whole window contents to that
buffer and attaching it to the corresponding Wayland surface.
parent d53cb720
No related branches found
No related tags found
No related merge requests found
......@@ -94,6 +94,10 @@ static void registry_handle_global(void *data, struct wl_registry *registry,
version < 2 ? version : 2);
xdg_wm_base_add_listener(process_wayland.xdg_wm_base, &xdg_wm_base_listener, NULL);
}
else if (strcmp(interface, "wl_shm") == 0)
{
process_wayland.wl_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
}
}
static void registry_handle_global_remove(void *data, struct wl_registry *registry,
......@@ -176,6 +180,11 @@ BOOL wayland_process_init(void)
ERR("Wayland compositor doesn't support xdg_wm_base\n");
return FALSE;
}
if (!process_wayland.wl_shm)
{
ERR("Wayland compositor doesn't support wl_shm\n");
return FALSE;
}
wayland_init_display_devices(FALSE);
......
......@@ -25,12 +25,17 @@
#include "config.h"
#include <stdlib.h>
#include <unistd.h>
#include "waylanddrv.h"
#include "wine/debug.h"
#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
/* We only use 4 byte formats. */
#define WINEWAYLAND_BYTES_PER_PIXEL 4
/* Protects access to the user data of xdg_surface */
static pthread_mutex_t xdg_data_mutex = PTHREAD_MUTEX_INITIALIZER;
......@@ -197,3 +202,130 @@ void wayland_surface_clear_role(struct wayland_surface *surface)
wl_display_flush(process_wayland.wl_display);
}
/**********************************************************************
* wayland_surface_attach_shm
*
* Attaches a SHM buffer to a wayland surface.
*/
void wayland_surface_attach_shm(struct wayland_surface *surface,
struct wayland_shm_buffer *shm_buffer)
{
TRACE("surface=%p shm_buffer=%p (%dx%d)\n",
surface, shm_buffer, shm_buffer->width, shm_buffer->height);
wl_surface_attach(surface->wl_surface, shm_buffer->wl_buffer, 0, 0);
wl_surface_damage_buffer(surface->wl_surface, 0, 0,
shm_buffer->width, shm_buffer->height);
}
/**********************************************************************
* wayland_shm_buffer_destroy
*
* Destroys a SHM buffer.
*/
void wayland_shm_buffer_destroy(struct wayland_shm_buffer *shm_buffer)
{
TRACE("%p map=%p\n", shm_buffer, shm_buffer->map_data);
if (shm_buffer->wl_buffer)
wl_buffer_destroy(shm_buffer->wl_buffer);
if (shm_buffer->map_data)
NtUnmapViewOfSection(GetCurrentProcess(), shm_buffer->map_data);
free(shm_buffer);
}
/**********************************************************************
* wayland_shm_buffer_create
*
* Creates a SHM buffer with the specified width, height and format.
*/
struct wayland_shm_buffer *wayland_shm_buffer_create(int width, int height,
enum wl_shm_format format)
{
struct wayland_shm_buffer *shm_buffer = NULL;
HANDLE handle = 0;
int fd = -1;
SIZE_T view_size = 0;
LARGE_INTEGER section_size;
NTSTATUS status;
struct wl_shm_pool *pool;
int stride, size;
stride = width * WINEWAYLAND_BYTES_PER_PIXEL;
size = stride * height;
if (size == 0)
{
ERR("Invalid shm_buffer size %dx%d\n", width, height);
goto err;
}
shm_buffer = calloc(1, sizeof(*shm_buffer));
if (!shm_buffer)
{
ERR("Failed to allocate space for SHM buffer\n");
goto err;
}
TRACE("%p %dx%d format=%d size=%d\n", shm_buffer, width, height, format, size);
shm_buffer->width = width;
shm_buffer->height = height;
shm_buffer->map_size = size;
section_size.QuadPart = size;
status = NtCreateSection(&handle,
GENERIC_READ | SECTION_MAP_READ | SECTION_MAP_WRITE,
NULL, &section_size, PAGE_READWRITE, SEC_COMMIT, 0);
if (status)
{
ERR("Failed to create SHM section status=0x%lx\n", (long)status);
goto err;
}
status = NtMapViewOfSection(handle, GetCurrentProcess(),
(PVOID)&shm_buffer->map_data, 0, 0, NULL,
&view_size, ViewUnmap, 0, PAGE_READWRITE);
if (status)
{
shm_buffer->map_data = NULL;
ERR("Failed to create map SHM handle status=0x%lx\n", (long)status);
goto err;
}
status = wine_server_handle_to_fd(handle, FILE_READ_DATA, &fd, NULL);
if (status)
{
ERR("Failed to get fd from SHM handle status=0x%lx\n", (long)status);
goto err;
}
pool = wl_shm_create_pool(process_wayland.wl_shm, fd, size);
if (!pool)
{
ERR("Failed to create SHM pool fd=%d size=%d\n", fd, size);
goto err;
}
shm_buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0, width, height,
stride, format);
wl_shm_pool_destroy(pool);
if (!shm_buffer->wl_buffer)
{
ERR("Failed to create SHM buffer %dx%d\n", width, height);
goto err;
}
close(fd);
NtClose(handle);
TRACE("=> map=%p\n", shm_buffer->map_data);
return shm_buffer;
err:
if (fd >= 0) close(fd);
if (handle) NtClose(handle);
if (shm_buffer) wayland_shm_buffer_destroy(shm_buffer);
return NULL;
}
......@@ -61,6 +61,7 @@ struct wayland
struct zxdg_output_manager_v1 *zxdg_output_manager_v1;
struct wl_compositor *wl_compositor;
struct xdg_wm_base *xdg_wm_base;
struct wl_shm *wl_shm;
struct wl_list output_list;
/* Protects the output_list and the wayland_output.current states. */
pthread_mutex_t output_mutex;
......@@ -102,6 +103,14 @@ struct wayland_surface
pthread_mutex_t mutex;
};
struct wayland_shm_buffer
{
struct wl_buffer *wl_buffer;
int width, height;
void *map_data;
size_t map_size;
};
/**********************************************************************
* Wayland initialization
*/
......@@ -125,12 +134,24 @@ struct wayland_surface *wayland_surface_create(void) DECLSPEC_HIDDEN;
void wayland_surface_destroy(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_make_toplevel(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_clear_role(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_attach_shm(struct wayland_surface *surface,
struct wayland_shm_buffer *shm_buffer) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland SHM buffer
*/
struct wayland_shm_buffer *wayland_shm_buffer_create(int width, int height,
enum wl_shm_format format) DECLSPEC_HIDDEN;
void wayland_shm_buffer_destroy(struct wayland_shm_buffer *shm_buffer) DECLSPEC_HIDDEN;
/**********************************************************************
* Wayland window surface
*/
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect) DECLSPEC_HIDDEN;
void wayland_window_surface_update_wayland_surface(struct window_surface *surface,
struct wayland_surface *wayland_surface) DECLSPEC_HIDDEN;
/**********************************************************************
* USER driver functions
......
......@@ -107,7 +107,11 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
pthread_mutex_unlock(&win_data_mutex);
if (data->window_surface) window_surface_release(data->window_surface);
if (data->window_surface)
{
wayland_window_surface_update_wayland_surface(data->window_surface, NULL);
window_surface_release(data->window_surface);
}
if (data->wayland_surface) wayland_surface_destroy(data->wayland_surface);
free(data);
}
......@@ -153,6 +157,8 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
/* We don't want wayland surfaces for child windows. */
if (parent != NtUserGetDesktopWindow() && parent != 0)
{
if (data->window_surface)
wayland_window_surface_update_wayland_surface(data->window_surface, NULL);
if (surface) wayland_surface_destroy(surface);
surface = NULL;
goto out;
......@@ -178,6 +184,9 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
pthread_mutex_unlock(&surface->mutex);
}
if (data->window_surface)
wayland_window_surface_update_wayland_surface(data->window_surface, surface);
out:
TRACE("hwnd=%p surface=%p=>%p\n", data->hwnd, data->wayland_surface, surface);
data->wayland_surface = surface;
......
......@@ -36,6 +36,7 @@ struct wayland_window_surface
{
struct window_surface header;
HWND hwnd;
struct wayland_surface *wayland_surface;
RECT bounds;
void *bits;
pthread_mutex_t mutex;
......@@ -54,6 +55,15 @@ static inline void reset_bounds(RECT *bounds)
bounds->right = bounds->bottom = INT_MIN;
}
static void buffer_release(void *data, struct wl_buffer *buffer)
{
struct wayland_shm_buffer *shm_buffer = data;
TRACE("shm_buffer=%p\n", shm_buffer);
wayland_shm_buffer_destroy(shm_buffer);
}
static const struct wl_buffer_listener buffer_listener = { buffer_release };
/***********************************************************************
* wayland_window_surface_lock
*/
......@@ -108,7 +118,46 @@ static void wayland_window_surface_set_region(struct window_surface *window_surf
*/
static void wayland_window_surface_flush(struct window_surface *window_surface)
{
/* TODO */
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
struct wayland_shm_buffer *shm_buffer;
BOOL flushed = FALSE;
wayland_window_surface_lock(window_surface);
if (IsRectEmpty(&wws->bounds)) goto done;
if (!wws->wayland_surface)
{
ERR("missing wayland surface, returning\n");
goto done;
}
TRACE("surface=%p hwnd=%p surface_rect=%s bounds=%s\n", wws, wws->hwnd,
wine_dbgstr_rect(&wws->header.rect), wine_dbgstr_rect(&wws->bounds));
shm_buffer = wayland_shm_buffer_create(wws->info.bmiHeader.biWidth,
abs(wws->info.bmiHeader.biHeight),
WL_SHM_FORMAT_XRGB8888);
if (!shm_buffer)
{
ERR("failed to create Wayland SHM buffer, returning\n");
goto done;
}
wl_buffer_add_listener(shm_buffer->wl_buffer, &buffer_listener, shm_buffer);
memcpy(shm_buffer->map_data, wws->bits, shm_buffer->map_size);
pthread_mutex_lock(&wws->wayland_surface->mutex);
wayland_surface_attach_shm(wws->wayland_surface, shm_buffer);
wl_surface_commit(wws->wayland_surface->wl_surface);
pthread_mutex_unlock(&wws->wayland_surface->mutex);
wl_display_flush(process_wayland.wl_display);
flushed = TRUE;
done:
if (flushed) reset_bounds(&wws->bounds);
wayland_window_surface_unlock(window_surface);
}
/***********************************************************************
......@@ -182,3 +231,20 @@ failed:
wayland_window_surface_destroy(&wws->header);
return NULL;
}
/***********************************************************************
* wayland_window_surface_update_wayland_surface
*/
void wayland_window_surface_update_wayland_surface(struct window_surface *window_surface,
struct wayland_surface *wayland_surface)
{
struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface);
wayland_window_surface_lock(window_surface);
TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, wws->hwnd, wayland_surface);
wws->wayland_surface = wayland_surface;
wayland_window_surface_unlock(window_surface);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment