2 * Wayland window surface implementation
4 * Copyright 2020 Alexandros Frantzis for Collabora Ltd
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "waylanddrv.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv
);
35 struct wayland_window_surface
37 struct window_surface header
;
39 struct wayland_surface
*wayland_surface
;
42 pthread_mutex_t mutex
;
46 static struct wayland_window_surface
*wayland_window_surface_cast(
47 struct window_surface
*window_surface
)
49 return (struct wayland_window_surface
*)window_surface
;
52 static inline void reset_bounds(RECT
*bounds
)
54 bounds
->left
= bounds
->top
= INT_MAX
;
55 bounds
->right
= bounds
->bottom
= INT_MIN
;
58 static void buffer_release(void *data
, struct wl_buffer
*buffer
)
60 struct wayland_shm_buffer
*shm_buffer
= data
;
61 TRACE("shm_buffer=%p\n", shm_buffer
);
62 wayland_shm_buffer_destroy(shm_buffer
);
65 static const struct wl_buffer_listener buffer_listener
= { buffer_release
};
67 /***********************************************************************
68 * wayland_window_surface_lock
70 static void wayland_window_surface_lock(struct window_surface
*window_surface
)
72 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
73 pthread_mutex_lock(&wws
->mutex
);
76 /***********************************************************************
77 * wayland_window_surface_unlock
79 static void wayland_window_surface_unlock(struct window_surface
*window_surface
)
81 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
82 pthread_mutex_unlock(&wws
->mutex
);
85 /***********************************************************************
86 * wayland_window_surface_get_bitmap_info
88 static void *wayland_window_surface_get_bitmap_info(struct window_surface
*window_surface
,
91 struct wayland_window_surface
*surface
= wayland_window_surface_cast(window_surface
);
92 /* We don't store any additional information at the end of our BITMAPINFO, so
93 * just copy the structure itself. */
94 memcpy(info
, &surface
->info
, sizeof(*info
));
98 /***********************************************************************
99 * wayland_window_surface_get_bounds
101 static RECT
*wayland_window_surface_get_bounds(struct window_surface
*window_surface
)
103 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
107 /***********************************************************************
108 * wayland_window_surface_set_region
110 static void wayland_window_surface_set_region(struct window_surface
*window_surface
,
116 /***********************************************************************
117 * wayland_window_surface_flush
119 static void wayland_window_surface_flush(struct window_surface
*window_surface
)
121 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
122 struct wayland_shm_buffer
*shm_buffer
;
123 BOOL flushed
= FALSE
;
125 wayland_window_surface_lock(window_surface
);
127 if (IsRectEmpty(&wws
->bounds
)) goto done
;
129 if (!wws
->wayland_surface
)
131 ERR("missing wayland surface, returning\n");
135 TRACE("surface=%p hwnd=%p surface_rect=%s bounds=%s\n", wws
, wws
->hwnd
,
136 wine_dbgstr_rect(&wws
->header
.rect
), wine_dbgstr_rect(&wws
->bounds
));
138 shm_buffer
= wayland_shm_buffer_create(wws
->info
.bmiHeader
.biWidth
,
139 abs(wws
->info
.bmiHeader
.biHeight
),
140 WL_SHM_FORMAT_XRGB8888
);
143 ERR("failed to create Wayland SHM buffer, returning\n");
147 wl_buffer_add_listener(shm_buffer
->wl_buffer
, &buffer_listener
, shm_buffer
);
149 memcpy(shm_buffer
->map_data
, wws
->bits
, shm_buffer
->map_size
);
151 pthread_mutex_lock(&wws
->wayland_surface
->mutex
);
152 if (wws
->wayland_surface
->current_serial
)
154 wayland_surface_attach_shm(wws
->wayland_surface
, shm_buffer
);
155 wl_surface_commit(wws
->wayland_surface
->wl_surface
);
160 TRACE("Wayland surface not configured yet, not flushing\n");
161 wayland_shm_buffer_destroy(shm_buffer
);
163 pthread_mutex_unlock(&wws
->wayland_surface
->mutex
);
164 wl_display_flush(process_wayland
.wl_display
);
167 if (flushed
) reset_bounds(&wws
->bounds
);
168 wayland_window_surface_unlock(window_surface
);
171 /***********************************************************************
172 * wayland_window_surface_destroy
174 static void wayland_window_surface_destroy(struct window_surface
*window_surface
)
176 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
178 TRACE("surface=%p\n", wws
);
180 pthread_mutex_destroy(&wws
->mutex
);
185 static const struct window_surface_funcs wayland_window_surface_funcs
=
187 wayland_window_surface_lock
,
188 wayland_window_surface_unlock
,
189 wayland_window_surface_get_bitmap_info
,
190 wayland_window_surface_get_bounds
,
191 wayland_window_surface_set_region
,
192 wayland_window_surface_flush
,
193 wayland_window_surface_destroy
196 /***********************************************************************
197 * wayland_window_surface_create
199 struct window_surface
*wayland_window_surface_create(HWND hwnd
, const RECT
*rect
)
201 struct wayland_window_surface
*wws
;
202 int width
= rect
->right
- rect
->left
;
203 int height
= rect
->bottom
- rect
->top
;
204 pthread_mutexattr_t mutexattr
;
206 TRACE("hwnd %p rect %s\n", hwnd
, wine_dbgstr_rect(rect
));
208 wws
= calloc(1, sizeof(*wws
));
209 if (!wws
) return NULL
;
210 wws
->info
.bmiHeader
.biSize
= sizeof(wws
->info
.bmiHeader
);
211 wws
->info
.bmiHeader
.biClrUsed
= 0;
212 wws
->info
.bmiHeader
.biBitCount
= 32;
213 wws
->info
.bmiHeader
.biCompression
= BI_RGB
;
214 wws
->info
.bmiHeader
.biWidth
= width
;
215 wws
->info
.bmiHeader
.biHeight
= -height
; /* top-down */
216 wws
->info
.bmiHeader
.biPlanes
= 1;
217 wws
->info
.bmiHeader
.biSizeImage
= width
* height
* 4;
219 pthread_mutexattr_init(&mutexattr
);
220 pthread_mutexattr_settype(&mutexattr
, PTHREAD_MUTEX_RECURSIVE
);
221 pthread_mutex_init(&wws
->mutex
, &mutexattr
);
222 pthread_mutexattr_destroy(&mutexattr
);
224 wws
->header
.funcs
= &wayland_window_surface_funcs
;
225 wws
->header
.rect
= *rect
;
228 reset_bounds(&wws
->bounds
);
230 if (!(wws
->bits
= malloc(wws
->info
.bmiHeader
.biSizeImage
)))
233 TRACE("created %p hwnd %p %s bits [%p,%p)\n", wws
, hwnd
, wine_dbgstr_rect(rect
),
234 wws
->bits
, (char *)wws
->bits
+ wws
->info
.bmiHeader
.biSizeImage
);
239 wayland_window_surface_destroy(&wws
->header
);
243 /***********************************************************************
244 * wayland_window_surface_update_wayland_surface
246 void wayland_window_surface_update_wayland_surface(struct window_surface
*window_surface
,
247 struct wayland_surface
*wayland_surface
)
249 struct wayland_window_surface
*wws
= wayland_window_surface_cast(window_surface
);
251 wayland_window_surface_lock(window_surface
);
253 TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws
, wws
->hwnd
, wayland_surface
);
255 wws
->wayland_surface
= wayland_surface
;
257 wayland_window_surface_unlock(window_surface
);