dmscript: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / winewayland.drv / window_surface.c
blobca613c667c67502a420fd6ab3a4956cae35b4f2b
1 /*
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
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <limits.h>
28 #include <stdlib.h>
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;
38 HWND hwnd;
39 struct wayland_surface *wayland_surface;
40 RECT bounds;
41 void *bits;
42 pthread_mutex_t mutex;
43 BITMAPINFO info;
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,
89 BITMAPINFO *info)
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));
95 return surface->bits;
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);
104 return &wws->bounds;
107 /***********************************************************************
108 * wayland_window_surface_set_region
110 static void wayland_window_surface_set_region(struct window_surface *window_surface,
111 HRGN region)
113 /* TODO */
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");
132 goto done;
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);
141 if (!shm_buffer)
143 ERR("failed to create Wayland SHM buffer, returning\n");
144 goto done;
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);
156 flushed = TRUE;
158 else
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);
166 done:
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);
181 free(wws->bits);
182 free(wws);
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;
226 wws->header.ref = 1;
227 wws->hwnd = hwnd;
228 reset_bounds(&wws->bounds);
230 if (!(wws->bits = malloc(wws->info.bmiHeader.biSizeImage)))
231 goto failed;
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);
236 return &wws->header;
238 failed:
239 wayland_window_surface_destroy(&wws->header);
240 return NULL;
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);