blob: 390dee43521c8a44ca4e4e68a916c06c5200026e [file] [log] [blame]
fei.dengf7a0cd32023-08-29 09:36:37 +00001/*
2 * Copyright (C) 2021 Amlogic Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <string>
17#include "wayland_display.h"
fei.dengb9a1a572023-09-13 01:33:57 +000018#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000019#include "Logger.h"
20#include "wayland_plugin.h"
21#include "wayland_videoformat.h"
22#include "wayland_shm.h"
23#include "wayland_dma.h"
24#include "wayland_buffer.h"
25
26#ifndef MAX
27# define MAX(a,b) ((a) > (b)? (a) : (b))
28# define MIN(a,b) ((a) < (b)? (a) : (b))
29#endif
30
31#define UNUSED_PARAM(x) ((void)(x))
32
33#define TAG "rlib:wayland_display"
34
35void WaylandDisplay::dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
36 uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
37{
38 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +000039 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +000040 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
fei.dengb9a1a572023-09-13 01:33:57 +000041 TRACE(self->mLogCategory,"regist dmabuffer format:%d (%s) hi:%x,lo:%x",format,print_dmabuf_format_name(format),modifier_hi,modifier_lo);
fei.dengf7a0cd32023-08-29 09:36:37 +000042 uint64_t modifier = ((uint64_t)modifier_hi << 32) | modifier_lo;
43 auto item = self->mDmaBufferFormats.find(format);
44 if (item == self->mDmaBufferFormats.end()) {
45 std::pair<uint32_t ,uint64_t> item(format, modifier);
46 self->mDmaBufferFormats.insert(item);
47 } else { //found format
48 item->second = modifier;
49 }
50 }
51}
52
53void
54WaylandDisplay::dmaBufferFormat (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
55 uint32_t format)
56{
57#if 0
58 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
59
60 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
61 TRACE(mLogCategory,"regist dmabuffer format:%d : %s",format);
62 //self->mDmaBufferFormats.push_back(format);
63 }
64#endif
65 /* XXX: deprecated */
66}
67
68static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
69 WaylandDisplay::dmaBufferFormat,
70 WaylandDisplay::dmabuf_modifiers
71};
72
73static void
74handle_xdg_wm_base_ping (void *user_data, struct xdg_wm_base *xdg_wm_base,
75 uint32_t serial)
76{
77 xdg_wm_base_pong (xdg_wm_base, serial);
78}
79
80static const struct xdg_wm_base_listener xdg_wm_base_listener = {
81 handle_xdg_wm_base_ping
82};
83
84void WaylandDisplay::shmFormat(void *data, struct wl_shm *wl_shm, uint32_t format)
85{
86 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
87 self->mShmFormats.push_back(format);
88}
89
90static const struct wl_shm_listener shm_listener = {
91 WaylandDisplay::shmFormat
92};
93
94void WaylandDisplay::outputHandleGeometry( void *data,
95 struct wl_output *output,
96 int x,
97 int y,
98 int physicalWidth,
99 int physicalHeight,
100 int subPixel,
101 const char *make,
102 const char *model,
103 int transform )
104{
105 UNUSED_PARAM(make);
106 UNUSED_PARAM(model);
107
108 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +0000109 DEBUG(self->mLogCategory,"wl_output %p x:%d,y:%d,physicalWidth:%d,physicalHeight:%d,subPixel:%d,trans:%d",
110 output,x, y,physicalWidth, physicalHeight,subPixel,transform);
111 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000112 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
113 if (output == self->mOutput[i].wlOutput) {
114 self->mOutput[i].offsetX = x;
115 self->mOutput[i].offsetY = y;
116 }
117 }
118}
119
120void WaylandDisplay::outputHandleMode( void *data,
121 struct wl_output *output,
122 uint32_t flags,
123 int width,
124 int height,
125 int refreshRate )
126{
127 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
128
129 if ( flags & WL_OUTPUT_MODE_CURRENT ) {
fei.dengb9a1a572023-09-13 01:33:57 +0000130 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000131 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
132 if (output == self->mOutput[i].wlOutput) {
133 self->mOutput[i].width = width;
134 self->mOutput[i].height = height;
135 self->mOutput[i].refreshRate = refreshRate;
136 }
137 }
138 //if a displayoutput had been selected,set this rectangle to wayland
139 int selectOutput = self->mActiveOutput;
fei.dengb9a1a572023-09-13 01:33:57 +0000140 DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,active output index %d\n",output, width, height,refreshRate,selectOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +0000141 if (selectOutput >= 0 && selectOutput < DEFAULT_DISPLAY_OUTPUT_NUM) {
142 if (self->mOutput[selectOutput].width > 0 && self->mOutput[selectOutput].height > 0) {
143 self->setRenderRectangle(self->mOutput[selectOutput].offsetX,
144 self->mOutput[selectOutput].offsetY,
145 self->mOutput[selectOutput].width,
146 self->mOutput[selectOutput].height);
147 }
148 }
149 }
150}
151
152void WaylandDisplay::outputHandleDone( void *data,
153 struct wl_output *output )
154{
155 UNUSED_PARAM(data);
156 UNUSED_PARAM(output);
157}
158
159void WaylandDisplay::outputHandleScale( void *data,
160 struct wl_output *output,
161 int32_t scale )
162{
163 UNUSED_PARAM(data);
164 UNUSED_PARAM(output);
165 UNUSED_PARAM(scale);
166}
167
168static const struct wl_output_listener outputListener = {
169 WaylandDisplay::outputHandleGeometry,
170 WaylandDisplay::outputHandleMode,
171 WaylandDisplay::outputHandleDone,
172 WaylandDisplay::outputHandleScale
173};
174
175void WaylandDisplay::pointerHandleEnter(void *data, struct wl_pointer *pointer,
176 uint32_t serial, struct wl_surface *surface,
177 wl_fixed_t sx, wl_fixed_t sy)
178{
179 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
180
181 if (self->mFullScreen) {
182 wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
183 }
184}
185
186void WaylandDisplay::pointerHandleLeave(void *data, struct wl_pointer *pointer,
187 uint32_t serial, struct wl_surface *surface)
188{
189 UNUSED_PARAM(data);
190 UNUSED_PARAM(pointer);
191 UNUSED_PARAM(serial);
192 UNUSED_PARAM(surface);
193}
194
195void WaylandDisplay::pointerHandleMotion(void *data, struct wl_pointer *pointer,
196 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
197{
198 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
199 int x = wl_fixed_to_int(sx);
200 int y = wl_fixed_to_int(sy);
fei.dengb9a1a572023-09-13 01:33:57 +0000201 DEBUG(self->mLogCategory,"pointer motion fixed[%d, %d] to-int: x[%d] y[%d]\n", sx, sy, x, y);
fei.dengf7a0cd32023-08-29 09:36:37 +0000202}
203
204void WaylandDisplay::pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
205 uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
206{
207 UNUSED_PARAM(data);
208 UNUSED_PARAM(wl_pointer);
209 UNUSED_PARAM(time);
210 UNUSED_PARAM(serial);
211 UNUSED_PARAM(button);
212 UNUSED_PARAM(state);
213}
214
215void WaylandDisplay::pointerHandleAxis(void *data, struct wl_pointer *wl_pointer,
216 uint32_t time, uint32_t axis, wl_fixed_t value)
217{
218 UNUSED_PARAM(data);
219 UNUSED_PARAM(wl_pointer);
220 UNUSED_PARAM(time);
221 UNUSED_PARAM(axis);
222 UNUSED_PARAM(value);
223}
224
225static const struct wl_pointer_listener pointer_listener = {
226 WaylandDisplay::pointerHandleEnter,
227 WaylandDisplay::pointerHandleLeave,
228 WaylandDisplay::pointerHandleMotion,
229 WaylandDisplay::pointerHandleButton,
230 WaylandDisplay::pointerHandleAxis,
231};
232
233void WaylandDisplay::touchHandleDown(void *data, struct wl_touch *wl_touch,
234 uint32_t serial, uint32_t time, struct wl_surface *surface,
235 int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
236{
237 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
238}
239
240void WaylandDisplay::touchHandleUp(void *data, struct wl_touch *wl_touch,
241 uint32_t serial, uint32_t time, int32_t id)
242{
243 UNUSED_PARAM(data);
244 UNUSED_PARAM(wl_touch);
245 UNUSED_PARAM(serial);
246 UNUSED_PARAM(time);
247 UNUSED_PARAM(id);
248}
249
250void WaylandDisplay::touchHandleMotion(void *data, struct wl_touch *wl_touch,
251 uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
252{
253 UNUSED_PARAM(data);
254 UNUSED_PARAM(wl_touch);
255 UNUSED_PARAM(time);
256 UNUSED_PARAM(id);
257 UNUSED_PARAM(x_w);
258 UNUSED_PARAM(y_w);
259}
260
261void WaylandDisplay::touchHandleFrame(void *data, struct wl_touch *wl_touch)
262{
263 UNUSED_PARAM(data);
264 UNUSED_PARAM(wl_touch);
265}
266
267void WaylandDisplay::touchHandleCancel(void *data, struct wl_touch *wl_touch)
268{
269 UNUSED_PARAM(data);
270 UNUSED_PARAM(wl_touch);
271}
272
273static const struct wl_touch_listener touch_listener = {
274 WaylandDisplay::touchHandleDown,
275 WaylandDisplay::touchHandleUp,
276 WaylandDisplay::touchHandleMotion,
277 WaylandDisplay::touchHandleFrame,
278 WaylandDisplay::touchHandleCancel,
279};
280
281void WaylandDisplay::keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard,
282 uint32_t format, int fd, uint32_t size)
283{
284 UNUSED_PARAM(data);
285 UNUSED_PARAM(keyboard);
286 UNUSED_PARAM(format);
287 UNUSED_PARAM(fd);
288 UNUSED_PARAM(size);
289}
290
291void WaylandDisplay::keyboardHandleEnter(void *data, struct wl_keyboard *keyboard,
292 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
293{
294 UNUSED_PARAM(data);
295 UNUSED_PARAM(keyboard);
296 UNUSED_PARAM(serial);
297 UNUSED_PARAM(surface);
298 UNUSED_PARAM(keys);
299}
300
301void WaylandDisplay::keyboardHandleLeave(void *data, struct wl_keyboard *keyboard,
302 uint32_t serial, struct wl_surface *surface)
303{
304 UNUSED_PARAM(data);
305 UNUSED_PARAM(keyboard);
306 UNUSED_PARAM(serial);
307 UNUSED_PARAM(surface);
308}
309
310void WaylandDisplay::keyboardHandleKey(void *data, struct wl_keyboard *keyboard,
311 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
312{
313 UNUSED_PARAM(data);
314 UNUSED_PARAM(keyboard);
315 UNUSED_PARAM(serial);
316 UNUSED_PARAM(time);
317 UNUSED_PARAM(key);
318 UNUSED_PARAM(state);
319}
320
321void WaylandDisplay::keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard,
322 uint32_t serial, uint32_t mods_depressed,
323 uint32_t mods_latched, uint32_t mods_locked,
324 uint32_t group)
325{
326 UNUSED_PARAM(data);
327 UNUSED_PARAM(keyboard);
328 UNUSED_PARAM(serial);
329 UNUSED_PARAM(mods_depressed);
330 UNUSED_PARAM(mods_latched);
331 UNUSED_PARAM(mods_locked);
332 UNUSED_PARAM(group);
333}
334
335static const struct wl_keyboard_listener keyboard_listener = {
336 WaylandDisplay::keyboardHandleKeymap,
337 WaylandDisplay::keyboardHandleEnter,
338 WaylandDisplay::keyboardHandleLeave,
339 WaylandDisplay::keyboardHandleKey,
340 WaylandDisplay::keyboardHandleModifiers,
341};
342
343void WaylandDisplay::seatHandleCapabilities(void *data, struct wl_seat *seat,
344 uint32_t caps)
345{
346 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
347 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !self->mPointer) {
348 self->mPointer = wl_seat_get_pointer(seat);
349 wl_pointer_add_listener(self->mPointer, &pointer_listener, data);
350 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && self->mPointer) {
351 wl_pointer_destroy(self->mPointer);
352 self->mPointer = NULL;
353 }
354
355 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !self->mKeyboard) {
356 self->mKeyboard = wl_seat_get_keyboard(seat);
357 wl_keyboard_add_listener(self->mKeyboard, &keyboard_listener, data);
358 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && self->mKeyboard) {
359 wl_keyboard_destroy(self->mKeyboard);
360 self->mKeyboard = NULL;
361 }
362
363 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !self->mTouch) {
364 self->mTouch = wl_seat_get_touch(seat);
365 wl_touch_set_user_data(self->mTouch, data);
366 wl_touch_add_listener(self->mTouch, &touch_listener, data);
367 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && self->mTouch) {
368 wl_touch_destroy(self->mTouch);
369 self->mTouch = NULL;
370 }
371}
372
373static const struct wl_seat_listener seat_listener = {
374 WaylandDisplay::seatHandleCapabilities,
375};
376
377
378void WaylandDisplay::handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel)
379{
380 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
381
fei.dengb9a1a572023-09-13 01:33:57 +0000382 INFO(self->mLogCategory,"XDG toplevel got a close event.");
fei.dengf7a0cd32023-08-29 09:36:37 +0000383}
384
385void WaylandDisplay::handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
386 int32_t width, int32_t height, struct wl_array *states)
387{
388 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
389 uint32_t *state;
390
fei.dengb9a1a572023-09-13 01:33:57 +0000391 INFO(self->mLogCategory, "XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000392 /*
393 wl_array_for_each (state, states) {
394 switch (*state) {
395 case XDG_TOPLEVEL_STATE_FULLSCREEN:
396 case XDG_TOPLEVEL_STATE_MAXIMIZED:
397 case XDG_TOPLEVEL_STATE_RESIZING:
398 case XDG_TOPLEVEL_STATE_ACTIVATED:
399 break;
400 }
401 }
402 */
403
404 if (width <= 0 || height <= 0)
405 return;
406
407 int selectOutput = self->mActiveOutput;
408 if (width == self->mOutput[selectOutput].width && height == self->mOutput[selectOutput].height) {
409 self->setRenderRectangle(self->mOutput[selectOutput].offsetX,
410 self->mOutput[selectOutput].offsetY,
411 self->mOutput[selectOutput].width,
412 self->mOutput[selectOutput].height);
413 } else{
414 self->setRenderRectangle(self->mRenderRect.x, self->mRenderRect.y, width, height);
415 }
416}
417
418static const struct xdg_toplevel_listener xdg_toplevel_listener = {
419 WaylandDisplay::handleXdgToplevelConfigure,
420 WaylandDisplay::handleXdgToplevelClose,
421};
422
423void WaylandDisplay::handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface,
424 uint32_t serial)
425{
426 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
427 xdg_surface_ack_configure (xdg_surface, serial);
428
fei.dengb9a1a572023-09-13 01:33:57 +0000429 TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
430 Tls::Mutex::Autolock _l(self->mConfigureMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000431 self->mXdgSurfaceConfigured = true;
432 if (self->mRenderRect.w > 0 && self->mRenderRect.h) {
fei.dengb9a1a572023-09-13 01:33:57 +0000433 DEBUG(self->mLogCategory,"set xdg surface geometry(%d,%d,%d,%d)",self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000434 xdg_surface_set_window_geometry(self->mXdgSurface,self->mRenderRect.x,self->mRenderRect.y,self->mRenderRect.w,self->mRenderRect.h);
435 }
436}
437
438static const struct xdg_surface_listener xdg_surface_listener = {
439 WaylandDisplay::handleXdgSurfaceConfigure,
440};
441
442void
443WaylandDisplay::registryHandleGlobal (void *data, struct wl_registry *registry,
fei.dengaf9b07d2023-10-10 07:38:40 +0000444 uint32_t name, const char *interface, uint32_t version)
fei.dengf7a0cd32023-08-29 09:36:37 +0000445{
446 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000447 TRACE(self->mLogCategory,"registryHandleGlobal,name:%u,interface:%s,version:%d",name,interface,version);
fei.dengf7a0cd32023-08-29 09:36:37 +0000448
449 if (strcmp (interface, "wl_compositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000450 self->mCompositor = (struct wl_compositor *)wl_registry_bind (registry, name, &wl_compositor_interface, 1/*MIN (version, 3)*/);
fei.dengf7a0cd32023-08-29 09:36:37 +0000451 } else if (strcmp (interface, "wl_subcompositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000452 self->mSubCompositor = (struct wl_subcompositor *)wl_registry_bind (registry, name, &wl_subcompositor_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000453 } else if (strcmp (interface, "xdg_wm_base") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000454 self->mXdgWmBase = (struct xdg_wm_base *)wl_registry_bind (registry, name, &xdg_wm_base_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000455 xdg_wm_base_add_listener (self->mXdgWmBase, &xdg_wm_base_listener, (void *)self);
456 } else if (strcmp (interface, "wl_shm") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000457 self->mShm = (struct wl_shm *)wl_registry_bind (registry, name, &wl_shm_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000458 wl_shm_add_listener (self->mShm, &shm_listener, self);
459 } else if (strcmp (interface, "zwp_fullscreen_shell_v1") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000460 //self->mFullscreenShell = (struct zwp_fullscreen_shell_v1 *)wl_registry_bind (registry, name,
fei.dengf7a0cd32023-08-29 09:36:37 +0000461 // &zwp_fullscreen_shell_v1_interface, 1);
462 } else if (strcmp (interface, "wp_viewporter") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000463 self->mViewporter = (struct wp_viewporter *)wl_registry_bind (registry, name, &wp_viewporter_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000464 } else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0) {
465 if (version < 3)
466 return;
fei.dengaf9b07d2023-10-10 07:38:40 +0000467 self->mDmabuf = (struct zwp_linux_dmabuf_v1 *)wl_registry_bind (registry, name, &zwp_linux_dmabuf_v1_interface, 3);
fei.dengf7a0cd32023-08-29 09:36:37 +0000468 zwp_linux_dmabuf_v1_add_listener (self->mDmabuf, &dmabuf_listener, (void *)self);
469 } else if (strcmp (interface, "wl_output") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000470 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
471 if (self->mOutput[i].wlOutput == NULL) {
472 self->mOutput[i].name = name;
473 self->mOutput[i].wlOutput = (struct wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version);
474 wl_output_add_listener(self->mOutput[i].wlOutput, &outputListener, (void *)self);
475 if (i == 0) { //primary wl_output
476 self->mOutput[i].isPrimary = true;
477 }
fei.deng1cfb2752023-10-26 08:01:25 +0000478 //if wl_output plugin,active sending frame
479 if (self->mOutput[self->mActiveOutput].wlOutput) {
480 self->setRedrawingPending(false);
481 }
fei.dengaf9b07d2023-10-10 07:38:40 +0000482 return;
483 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000484 }
fei.dengaf9b07d2023-10-10 07:38:40 +0000485 WARNING(self->mLogCategory,"Not enough free output");
fei.dengf7a0cd32023-08-29 09:36:37 +0000486 } else if (strcmp(interface, "wl_seat") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000487 //self->mSeat = (struct wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000488 //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
489 }
490}
491
492void
493WaylandDisplay::registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name)
494{
495 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000496 /* check wl_output changed */
497 DEBUG(self->mLogCategory,"wayland display remove registry handle global,name:%u",name);
498 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
499 if (self->mOutput[i].name == name) {
500 self->mOutput[i].name = 0;
501 self->mOutput[i].wlOutput = NULL;
502 DEBUG(self->mLogCategory,"remove wl_output name:%u",name);
503 }
504 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000505}
506
507static const struct wl_registry_listener registry_listener = {
508 WaylandDisplay::registryHandleGlobal,
509 WaylandDisplay::registryHandleGlobalRemove
510};
511
fei.dengb9a1a572023-09-13 01:33:57 +0000512WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin, int logCategory)
513 :mBufferMutex("bufferMutex"),
514 mWaylandPlugin(plugin),
515 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +0000516{
fei.dengb9a1a572023-09-13 01:33:57 +0000517 TRACE(mLogCategory,"construct WaylandDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000518 mWlDisplay = NULL;
519 mWlDisplayWrapper = NULL;
520 mWlQueue = NULL;
521 mRegistry = NULL;
522 mCompositor = NULL;
523 mXdgWmBase = NULL;
524 mViewporter = NULL;
525 mDmabuf = NULL;
526 mShm = NULL;
527 mSeat = NULL;
528 mPointer = NULL;
529 mTouch = NULL;
530 mKeyboard = NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000531 mActiveOutput = 0; //default is primary output
fei.dengb9a1a572023-09-13 01:33:57 +0000532 mPoll = new Tls::Poll(true);
fei.dengf7a0cd32023-08-29 09:36:37 +0000533 //window
534 mVideoWidth = 0;
535 mVideoHeight = 0;
536 mVideoSurface = NULL;
537 mXdgSurface = NULL;
538 mXdgToplevel = NULL;
539 mAreaViewport = NULL;
540 mVideoViewport = NULL;
541 mNoBorderUpdate = false;
542 mAreaShmBuffer = NULL;
543 mCommitCnt = 0;
544 mIsSendPtsToWeston = false;
545 mReCommitAreaSurface = false;
546 mAreaSurface = NULL;
547 mAreaSurfaceWrapper = NULL;
548 mVideoSurfaceWrapper = NULL;
549 mVideoSubSurface = NULL;
550 mXdgSurfaceConfigured = false;
551 mPip = 0;
552 mIsSendVideoPlaneId = true;
553 memset(&mRenderRect, 0, sizeof(struct Rectangle));
554 memset(&mVideoRect, 0, sizeof(struct Rectangle));
555 memset(&mWindowRect, 0, sizeof(struct Rectangle));
556 mFullScreen = true; //default is full screen
557 char *env = getenv("VIDEO_RENDER_SEND_PTS_TO_WESTON");
558 if (env) {
559 int isSet = atoi(env);
560 if (isSet > 0) {
561 mIsSendPtsToWeston = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000562 INFO(mLogCategory,"set send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000563 } else {
564 mIsSendPtsToWeston = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000565 INFO(mLogCategory,"do not send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000566 }
567 }
568 env = getenv("VIDEO_RENDER_SEND_VIDEO_PLANE_ID_TO_WESTON");
569 if (env) {
570 int isSet = atoi(env);
571 if (isSet == 0) {
572 mIsSendVideoPlaneId = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000573 INFO(mLogCategory,"do not send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000574 } else {
575 mIsSendVideoPlaneId = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000576 INFO(mLogCategory,"send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000577 }
578 }
579 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
580 mOutput[i].wlOutput = NULL;
581 mOutput[i].offsetX = 0;
582 mOutput[i].offsetY = 0;
583 mOutput[i].width = 0;
584 mOutput[i].height = 0;
585 mOutput[i].refreshRate = 0;
586 mOutput[i].isPrimary = false;
fei.dengaf9b07d2023-10-10 07:38:40 +0000587 mOutput[i].name = 0;
fei.dengf7a0cd32023-08-29 09:36:37 +0000588 }
589}
590
591WaylandDisplay::~WaylandDisplay()
592{
fei.dengb9a1a572023-09-13 01:33:57 +0000593 TRACE(mLogCategory,"desconstruct WaylandDisplay");
594 if (mPoll) {
595 delete mPoll;
596 mPoll = NULL;
597 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000598}
599
600char *WaylandDisplay::require_xdg_runtime_dir()
601{
602 char *val = getenv("XDG_RUNTIME_DIR");
fei.dengb9a1a572023-09-13 01:33:57 +0000603 INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",val);
fei.dengf7a0cd32023-08-29 09:36:37 +0000604
605 return val;
606}
607
608int WaylandDisplay::openDisplay()
609{
610 char *name = require_xdg_runtime_dir();
611 //DEBUG(mLogCategory,"name:%s",name);
fei.dengb9a1a572023-09-13 01:33:57 +0000612 DEBUG(mLogCategory,"openDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000613 mWlDisplay = wl_display_connect(NULL);
614 if (!mWlDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000615 ERROR(mLogCategory,"Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
fei.dengf7a0cd32023-08-29 09:36:37 +0000616 name ? name : "NULL");
fei.dengb9a1a572023-09-13 01:33:57 +0000617 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000618 }
619
620 mWlDisplayWrapper = (struct wl_display *)wl_proxy_create_wrapper ((void *)mWlDisplay);
621 mWlQueue = wl_display_create_queue (mWlDisplay);
622 wl_proxy_set_queue ((struct wl_proxy *)mWlDisplayWrapper, mWlQueue);
623
624 mRegistry = wl_display_get_registry (mWlDisplayWrapper);
625 wl_registry_add_listener (mRegistry, &registry_listener, (void *)this);
626
627 /* we need exactly 2 roundtrips to discover global objects and their state */
628 for (int i = 0; i < 2; i++) {
629 if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000630 ERROR(mLogCategory,"Error communicating with the wayland display");
631 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000632 }
633 }
634
635 if (!mCompositor) {
fei.dengb9a1a572023-09-13 01:33:57 +0000636 ERROR(mLogCategory,"Could not bind to wl_compositor. Either it is not implemented in " \
fei.dengf7a0cd32023-08-29 09:36:37 +0000637 "the compositor, or the implemented version doesn't match");
fei.dengb9a1a572023-09-13 01:33:57 +0000638 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000639 }
640
641 if (!mDmabuf) {
fei.dengb9a1a572023-09-13 01:33:57 +0000642 ERROR(mLogCategory,"Could not bind to zwp_linux_dmabuf_v1");
643 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000644 }
645
646 if (!mXdgWmBase) {
647 /* If wl_surface and wl_display are passed via GstContext
648 * wl_shell, xdg_shell and zwp_fullscreen_shell are not used.
649 * In this case is correct to continue.
650 */
fei.dengb9a1a572023-09-13 01:33:57 +0000651 ERROR(mLogCategory,"Could not bind to either wl_shell, xdg_wm_base or "
fei.dengf7a0cd32023-08-29 09:36:37 +0000652 "zwp_fullscreen_shell, video display may not work properly.");
fei.dengb9a1a572023-09-13 01:33:57 +0000653 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000654 }
655
656 //create window surface
657 createCommonWindowSurface();
658 createXdgShellWindowSurface();
659
660 //config weston video plane
661 if (mIsSendVideoPlaneId) {
fei.dengb9a1a572023-09-13 01:33:57 +0000662 INFO(mLogCategory,"set weston video plane:%d",mPip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000663 wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
664 }
665
666 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000667 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengf7a0cd32023-08-29 09:36:37 +0000668 run("display queue");
669 mRedrawingPending = false;
670
fei.dengb9a1a572023-09-13 01:33:57 +0000671 DEBUG(mLogCategory,"openDisplay out");
672 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000673}
674
675void WaylandDisplay::closeDisplay()
676{
fei.dengb9a1a572023-09-13 01:33:57 +0000677 DEBUG(mLogCategory,"closeDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000678
679 if (isRunning()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000680 TRACE(mLogCategory,"try stop dispatch thread");
681 if (mPoll) {
682 mPoll->setFlushing(true);
683 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000684 requestExitAndWait();
685 }
686
687 //first destroy window surface
688 destroyWindowSurfaces();
689
690 if (mViewporter) {
691 wp_viewporter_destroy (mViewporter);
692 mViewporter = NULL;
693 }
694
695 if (mDmabuf) {
696 zwp_linux_dmabuf_v1_destroy (mDmabuf);
697 mDmabuf = NULL;
698 }
699
700 if (mXdgWmBase) {
701 xdg_wm_base_destroy (mXdgWmBase);
702 mXdgWmBase = NULL;
703 }
704
705 if (mCompositor) {
706 wl_compositor_destroy (mCompositor);
707 mCompositor = NULL;
708 }
709
710 if (mSubCompositor) {
711 wl_subcompositor_destroy (mSubCompositor);
712 mSubCompositor = NULL;
713 }
714
715 if (mRegistry) {
716 wl_registry_destroy (mRegistry);
717 mRegistry= NULL;
718 }
719
720 if (mWlDisplayWrapper) {
721 wl_proxy_wrapper_destroy (mWlDisplayWrapper);
722 mWlDisplayWrapper = NULL;
723 }
724
725 if (mWlQueue) {
726 wl_event_queue_destroy (mWlQueue);
727 mWlQueue = NULL;
728 }
729
730 if (mWlDisplay) {
731 wl_display_flush (mWlDisplay);
732 wl_display_disconnect (mWlDisplay);
733 mWlDisplay = NULL;
734 }
735
fei.dengb9a1a572023-09-13 01:33:57 +0000736 DEBUG(mLogCategory,"closeDisplay out");
fei.dengf7a0cd32023-08-29 09:36:37 +0000737}
738
739int WaylandDisplay::toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/)
740{
741 if (!outDmaformat || !outDmaformatModifiers) {
fei.dengb9a1a572023-09-13 01:33:57 +0000742 WARNING(mLogCategory,"NULL params");
743 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000744 }
745
746 *outDmaformat = 0;
747 *outDmaformatModifiers = 0;
748
749 uint32_t dmaformat = video_format_to_wl_dmabuf_format (format);
750 if (dmaformat == -1) {
fei.dengb9a1a572023-09-13 01:33:57 +0000751 ERROR(mLogCategory,"Error not found render video format:%d to wl dmabuf format",format);
752 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000753 }
754
fei.dengb9a1a572023-09-13 01:33:57 +0000755 TRACE(mLogCategory,"render video format:%d -> dmabuf format:%d",format,dmaformat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000756 *outDmaformat = (uint32_t)dmaformat;
757
758 /*get dmaformat and modifiers*/
759 auto item = mDmaBufferFormats.find(dmaformat);
760 if (item == mDmaBufferFormats.end()) { //not found
fei.dengb9a1a572023-09-13 01:33:57 +0000761 WARNING(mLogCategory,"Not found dmabuf for render video format :%d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000762 *outDmaformatModifiers = 0;
fei.dengb9a1a572023-09-13 01:33:57 +0000763 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000764 }
765
766 *outDmaformatModifiers = (uint64_t)item->second;
767
fei.dengb9a1a572023-09-13 01:33:57 +0000768 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000769}
770
771int WaylandDisplay::toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat)
772{
773 if (!outformat) {
fei.dengb9a1a572023-09-13 01:33:57 +0000774 WARNING(mLogCategory,"NULL params");
775 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000776 }
777
778 *outformat = 0;
779
780 int shmformat = (int)video_format_to_wl_shm_format(format);
781 if (shmformat < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000782 ERROR(mLogCategory,"Error not found render video format:%d to wl shmbuf format",format);
783 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000784 }
785
786 for (auto item = mShmFormats.begin(); item != mShmFormats.end(); ++item) {
787 uint32_t registFormat = (uint32_t)*item;
788 if (registFormat == (uint32_t)shmformat) {
789 *outformat = registFormat;
fei.dengb9a1a572023-09-13 01:33:57 +0000790 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000791 }
792 }
793
fei.dengb9a1a572023-09-13 01:33:57 +0000794 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000795}
796
797void WaylandDisplay::setVideoBufferFormat(RenderVideoFormat format)
798{
fei.dengb9a1a572023-09-13 01:33:57 +0000799 TRACE(mLogCategory,"set video buffer format: %d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000800 mBufferFormat = format;
801};
802
803void WaylandDisplay::setDisplayOutput(int output)
804{
fei.dengb9a1a572023-09-13 01:33:57 +0000805 TRACE(mLogCategory,"select display output: %d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000806 if (output < 0 || output >= DEFAULT_DISPLAY_OUTPUT_NUM) {
fei.dengb9a1a572023-09-13 01:33:57 +0000807 ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000808 return;
809 }
fei.deng1cfb2752023-10-26 08:01:25 +0000810
fei.dengf7a0cd32023-08-29 09:36:37 +0000811 if (mActiveOutput != output) {
fei.dengf7a0cd32023-08-29 09:36:37 +0000812 mActiveOutput = output;
fei.deng1cfb2752023-10-26 08:01:25 +0000813 if (mOutput[output].wlOutput) {
814 setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
815 mOutput[output].width, mOutput[output].height);
816 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000817 }
818}
819
820int WaylandDisplay::getDisplayOutput()
821{
822 return mActiveOutput;
823}
824
825void WaylandDisplay::setPip(int pip)
826{
fei.dengb9a1a572023-09-13 01:33:57 +0000827 INFO(mLogCategory,"set pip:%d",pip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000828 mPip = pip;
829}
830
831void WaylandDisplay::createCommonWindowSurface()
832{
833 struct wl_region *region;
834
835 mAreaSurface = wl_compositor_create_surface (mCompositor);
836 mVideoSurface = wl_compositor_create_surface (mCompositor);
837 mAreaSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mAreaSurface);
838 mVideoSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mVideoSurface);
839
840 wl_proxy_set_queue ((struct wl_proxy *) mAreaSurfaceWrapper, mWlQueue);
841 wl_proxy_set_queue ((struct wl_proxy *) mVideoSurfaceWrapper, mWlQueue);
842
843 /* embed video_surface in area_surface */
844 mVideoSubSurface = wl_subcompositor_get_subsurface (mSubCompositor, mVideoSurface, mAreaSurface);
845 wl_subsurface_set_desync (mVideoSubSurface);
846
847 if (mViewporter) {
848 mAreaViewport = wp_viewporter_get_viewport (mViewporter, mAreaSurface);
849 mVideoViewport = wp_viewporter_get_viewport (mViewporter, mVideoSurface);
850 }
851
852 /* do not accept input */
853 region = wl_compositor_create_region (mCompositor);
854 wl_surface_set_input_region (mAreaSurface, region);
855 wl_region_destroy (region);
856
857 region = wl_compositor_create_region (mCompositor);
858 wl_surface_set_input_region (mVideoSurface, region);
859 wl_region_destroy (region);
860}
861
862void WaylandDisplay::createXdgShellWindowSurface()
863{
864 /* Check which protocol we will use (in order of preference) */
865 if (mXdgWmBase) {
866 /* First create the XDG surface */
867 mXdgSurface= xdg_wm_base_get_xdg_surface (mXdgWmBase, mAreaSurface);
868 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000869 ERROR(mLogCategory,"Unable to get xdg_surface");
fei.dengf7a0cd32023-08-29 09:36:37 +0000870 return;
871 }
872 xdg_surface_add_listener (mXdgSurface, &xdg_surface_listener,(void *)this);
873
874 /* Then the toplevel */
875 mXdgToplevel= xdg_surface_get_toplevel (mXdgSurface);
876 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000877 ERROR(mLogCategory,"Unable to get xdg_toplevel");
fei.dengf7a0cd32023-08-29 09:36:37 +0000878 return;
879 }
880 xdg_toplevel_add_listener (mXdgToplevel, &xdg_toplevel_listener, this);
881
882 /* Finally, commit the xdg_surface state as toplevel */
883 mXdgSurfaceConfigured = false;
884 wl_surface_commit (mAreaSurface);
885 wl_display_flush (mWlDisplay);
886 /* we need exactly 3 roundtrips to discover global objects and their state */
887 for (int i = 0; i < 3; i++) {
888 if (wl_display_roundtrip_queue(mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000889 ERROR(mLogCategory,"Error communicating with the wayland display");
fei.dengf7a0cd32023-08-29 09:36:37 +0000890 }
891 }
892
893 if (mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +0000894 INFO(mLogCategory,"xdg surface had configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000895 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000896 WARNING(mLogCategory,"xdg surface not configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000897 }
898
899 //full screen show
900 if (mFullScreen && mOutput[mActiveOutput].wlOutput) {
901 ensureFullscreen(mFullScreen);
902 }
903
904 //if wl_output had detected, the width and height of mRenderRect will be set
905 //we need invoking setRenderRectangle
906 // if (mRenderRect.w > 0 && mRenderRect.h > 0) {
907 // setRenderRectangle(mRenderRect.x, mRenderRect.y, mRenderRect.w, mRenderRect.h);
908 // }
909 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000910 ERROR(mLogCategory,"Unable to use xdg_wm_base ");
fei.dengf7a0cd32023-08-29 09:36:37 +0000911 return;
912 }
913}
914
915void WaylandDisplay::destroyWindowSurfaces()
916{
917 if (mAreaShmBuffer) {
918 delete mAreaShmBuffer;
919 mAreaShmBuffer = NULL;
920 }
921
922 //clean all wayland buffers
923 cleanAllWaylandBuffer();
924
925 if (mXdgToplevel) {
926 xdg_toplevel_destroy (mXdgToplevel);
927 mXdgToplevel = NULL;
928 }
929
930 if (mXdgSurface) {
931 xdg_surface_destroy (mXdgSurface);
932 mXdgSurface = NULL;
933 }
934
935 if (mVideoSurfaceWrapper) {
936 wl_proxy_wrapper_destroy (mVideoSurfaceWrapper);
937 mVideoSurfaceWrapper = NULL;
938 }
939
940 if (mVideoSubSurface) {
941 wl_subsurface_destroy (mVideoSubSurface);
942 mVideoSubSurface = NULL;
943 }
944
945 if (mVideoSurface) {
946 wl_surface_destroy (mVideoSurface);
947 mVideoSurface = NULL;
948 }
949
950 if (mAreaSurfaceWrapper) {
951 wl_proxy_wrapper_destroy (mAreaSurfaceWrapper);
952 mAreaSurfaceWrapper = NULL;
953 }
954
955 if (mAreaSurface) {
956 wl_surface_destroy (mAreaSurface);
957 mAreaSurface = NULL;
958 mReCommitAreaSurface = false;
959 }
960}
961
962void WaylandDisplay::ensureFullscreen(bool fullscreen)
963{
964 if (mXdgWmBase) {
fei.dengb9a1a572023-09-13 01:33:57 +0000965 DEBUG(mLogCategory,"full screen : %d",fullscreen);
fei.dengf7a0cd32023-08-29 09:36:37 +0000966 if (fullscreen) {
967 xdg_toplevel_set_fullscreen (mXdgToplevel, mOutput[mActiveOutput].wlOutput);
968 } else {
969 xdg_toplevel_unset_fullscreen (mXdgToplevel);
970 }
971 }
972}
973
974void WaylandDisplay::setRenderRectangle(int x, int y, int w, int h)
975{
fei.dengb9a1a572023-09-13 01:33:57 +0000976 DEBUG(mLogCategory,"set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000977
978 if (w <= 0 || h <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000979 WARNING(mLogCategory, "wrong render width or height %dx%d",w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000980 return;
981 }
982
983 mRenderRect.x = x;
984 mRenderRect.y = y;
985 mRenderRect.w = w;
986 mRenderRect.h = h;
987
988 if (!mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +0000989 WARNING(mLogCategory,"Not configured xdg");
fei.dengf7a0cd32023-08-29 09:36:37 +0000990 return;
991 }
992
993 if (mAreaViewport) {
994 wp_viewport_set_destination (mAreaViewport, w, h);
995 }
996
997 updateBorders();
998
999 if (mVideoWidth != 0 && mVideoSurface) {
1000 wl_subsurface_set_sync (mVideoSubSurface);
1001 resizeVideoSurface(true);
1002 }
1003
1004 wl_surface_damage (mAreaSurfaceWrapper, 0, 0, w, h);
1005 wl_surface_commit (mAreaSurfaceWrapper);
1006
1007 if (mVideoWidth != 0) {
1008 wl_subsurface_set_desync (mVideoSubSurface);
1009 }
1010}
1011
1012
1013void WaylandDisplay::setFrameSize(int w, int h)
1014{
1015 mVideoWidth = w;
1016 mVideoHeight = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001017 TRACE(mLogCategory,"frame w:%d,h:%d",mVideoWidth,mVideoHeight);
fei.dengf7a0cd32023-08-29 09:36:37 +00001018 if (mRenderRect.w > 0 && mVideoSurface) {
1019 resizeVideoSurface(true);
1020 }
1021}
1022
1023void WaylandDisplay::setWindowSize(int x, int y, int w, int h)
1024{
1025 mWindowRect.x = x;
1026 mWindowRect.y = y;
1027 mWindowRect.w = w;
1028 mWindowRect.h = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001029 TRACE(mLogCategory,"window size:x:%d,y:%d,w:%d,h:%d",mWindowRect.x,mWindowRect.y,mWindowRect.w,mWindowRect.h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001030 if (mWindowRect.w > 0 && mVideoWidth > 0 && mVideoSurface) {
1031 //if had full screen, unset it and set window size
1032 if (mFullScreen) {
1033 mFullScreen = false;
1034 ensureFullscreen(mFullScreen);
1035 }
1036 resizeVideoSurface(true);
1037 }
1038}
1039
1040
1041void WaylandDisplay::resizeVideoSurface(bool commit)
1042{
1043 Rectangle src = {0,};
1044 Rectangle dst = {0,};
1045 Rectangle res;
1046
1047 /* center the video_subsurface inside area_subsurface */
1048 src.w = mVideoWidth;
1049 src.h = mVideoHeight;
1050 /*if had set the window size, we will scall
1051 video surface to this window size*/
1052 if (mWindowRect.w > 0 && mWindowRect.h > 0) {
1053 dst.x = mWindowRect.x;
1054 dst.y = mWindowRect.y;
1055 dst.w = mWindowRect.w;
1056 dst.h = mWindowRect.h;
1057 if (mWindowRect.w > mRenderRect.w && mWindowRect.h > mRenderRect.h) {
fei.dengb9a1a572023-09-13 01:33:57 +00001058 WARNING(mLogCategory,"Error window size:%dx%d, but render size:%dx%d,reset to render size",
fei.dengf7a0cd32023-08-29 09:36:37 +00001059 mWindowRect.w,mWindowRect.h,mRenderRect.w,mRenderRect.h);
1060 dst.x = mRenderRect.x;
1061 dst.y = mRenderRect.y;
1062 dst.w = mRenderRect.w;
1063 dst.h = mRenderRect.h;
1064 }
1065 //to do,we need set geometry?
1066 //if (mXdgSurface) {
1067 // xdg_surface_set_window_geometry(mXdgSurface, mWindowRect.x, mWindowRect.y, mWindowRect.w, mWindowRect.h);
1068 //}
1069 } else { //scal video to full screen
1070 dst.w = mRenderRect.w;
1071 dst.h = mRenderRect.h;
1072 }
1073
1074 if (mViewporter) {
1075 videoCenterRect(src, dst, &res, true);
1076 } else {
1077 videoCenterRect(src, dst, &res, false);
1078 }
1079
1080 wl_subsurface_set_position (mVideoSubSurface, res.x, res.y);
1081
1082 if (commit) {
1083 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, res.w, res.h);
1084 wl_surface_commit (mVideoSurfaceWrapper);
1085 }
1086
1087 //top level setting
1088 if (mXdgToplevel) {
1089 struct wl_region *region;
1090
1091 region = wl_compositor_create_region (mCompositor);
1092 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1093 wl_surface_set_input_region (mAreaSurface, region);
1094 wl_region_destroy (region);
1095 }
1096
1097 /* this is saved for use in wl_surface_damage */
1098 mVideoRect.x = res.x;
1099 mVideoRect.y = res.y;
1100 mVideoRect.w = res.w;
1101 mVideoRect.h = res.h;
1102
1103 //to scale video surface to full screen
1104 wp_viewport_set_destination(mVideoViewport, res.w, res.h);
fei.dengb9a1a572023-09-13 01:33:57 +00001105 TRACE(mLogCategory,"video rectangle,x:%d,y:%d,w:%d,h:%d",mVideoRect.x, mVideoRect.y, mVideoRect.w, mVideoRect.h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001106}
1107
1108void WaylandDisplay::setOpaque()
1109{
1110 struct wl_region *region;
1111
1112 /* Set area opaque */
1113 region = wl_compositor_create_region (mCompositor);
1114 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1115 wl_surface_set_opaque_region (mAreaSurface, region);
1116 wl_region_destroy (region);
1117}
1118
1119int WaylandDisplay::prepareFrameBuffer(RenderBuffer * buf)
1120{
1121 WaylandBuffer *waylandBuf = NULL;
1122 int ret;
1123
1124 waylandBuf = findWaylandBuffer(buf);
1125 if (waylandBuf == NULL) {
fei.dengb9a1a572023-09-13 01:33:57 +00001126 waylandBuf = new WaylandBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001127 waylandBuf->setBufferFormat(mBufferFormat);
1128 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001129 if (ret != NO_ERROR) {
1130 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001131 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1132 goto waylandbuf_fail;
1133 } else {
1134 addWaylandBuffer(buf, waylandBuf);
1135 }
1136 }
fei.dengb9a1a572023-09-13 01:33:57 +00001137 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +00001138waylandbuf_fail:
1139 //delete waylandbuf
1140 delete waylandBuf;
1141 waylandBuf = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +00001142 return ERROR_UNKNOWN;
fei.dengf7a0cd32023-08-29 09:36:37 +00001143}
1144
1145void WaylandDisplay::displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime)
1146{
1147 WaylandBuffer *waylandBuf = NULL;
1148 struct wl_buffer * wlbuffer = NULL;
1149 int ret;
1150
1151 if (!buf) {
fei.dengb9a1a572023-09-13 01:33:57 +00001152 ERROR(mLogCategory,"Error input params, waylandbuffer is null");
fei.dengf7a0cd32023-08-29 09:36:37 +00001153 return;
1154 }
1155
1156 //must commit areasurface first, because weston xdg surface maybe timeout
1157 //this cause video is not display,commit can resume xdg surface
1158 if (!mReCommitAreaSurface) {
1159 mReCommitAreaSurface = true;
1160 wl_surface_commit (mAreaSurface);
1161 }
1162
fei.dengb9a1a572023-09-13 01:33:57 +00001163 TRACE(mLogCategory,"display renderBuffer:%p,PTS:%lld,realtime:%lld",buf, buf->pts, realDisplayTime);
fei.dengf7a0cd32023-08-29 09:36:37 +00001164
1165 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1166 if (buf->dma.width <=0 || buf->dma.height <=0) {
1167 buf->dma.width = mVideoWidth;
1168 buf->dma.height = mVideoHeight;
1169 }
1170 waylandBuf = findWaylandBuffer(buf);
1171 if (waylandBuf) {
1172 waylandBuf->setRenderRealTime(realDisplayTime);
1173 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001174 if (ret != NO_ERROR) {
1175 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001176 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1177 goto waylandbuf_fail;
1178 }
1179 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001180 ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
fei.dengf7a0cd32023-08-29 09:36:37 +00001181 goto waylandbuf_fail;
1182 }
1183 }
1184
1185 if (waylandBuf) {
1186 wlbuffer = waylandBuf->getWlBuffer();
1187 }
fei.deng1cfb2752023-10-26 08:01:25 +00001188 //if no wl_output, drop this buffer
1189 if (mOutput[mActiveOutput].wlOutput == NULL) {
1190 TRACE(mLogCategory,"No wl_output");
1191 mWaylandPlugin->handleFrameDropped(buf);
1192 mWaylandPlugin->handleBufferRelease(buf);
1193 return;
1194 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001195 if (wlbuffer) {
fei.dengb9a1a572023-09-13 01:33:57 +00001196 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001197 ++mCommitCnt;
1198 uint32_t hiPts = realDisplayTime >> 32;
1199 uint32_t lowPts = realDisplayTime & 0xFFFFFFFF;
1200 //attach this wl_buffer to weston
fei.dengb9a1a572023-09-13 01:33:57 +00001201 TRACE(mLogCategory,"++attach,renderbuf:%p,wl_buffer:%p(0,0,%d,%d),pts:%lld,commitCnt:%d",buf,wlbuffer,mVideoRect.w,mVideoRect.h,buf->pts,mCommitCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +00001202 waylandBuf->attach(mVideoSurfaceWrapper);
1203
1204 if (mIsSendPtsToWeston) {
fei.dengb9a1a572023-09-13 01:33:57 +00001205 TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
fei.dengf7a0cd32023-08-29 09:36:37 +00001206 wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
1207 }
1208
1209 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, mVideoRect.w, mVideoRect.h);
1210 wl_surface_commit (mVideoSurfaceWrapper);
1211 //insert this buffer to committed weston buffer manager
1212 std::pair<int64_t, WaylandBuffer *> item(buf->pts, waylandBuf);
1213 mCommittedBufferMap.insert(item);
1214 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001215 WARNING(mLogCategory,"wlbuffer is NULL");
fei.dengf7a0cd32023-08-29 09:36:37 +00001216 /* clear both video and parent surfaces */
1217 cleanSurface();
1218 }
1219
1220 wl_display_flush (mWlDisplay);
1221
1222 return;
1223waylandbuf_fail:
1224 //notify dropped
1225 mWaylandPlugin->handleFrameDropped(buf);
1226 //notify app release this buf
1227 mWaylandPlugin->handleBufferRelease(buf);
1228 //delete waylandbuf
1229 delete waylandBuf;
1230 waylandBuf = NULL;
1231 return;
1232}
1233
1234void WaylandDisplay::handleBufferReleaseCallback(WaylandBuffer *buf)
1235{
1236 {
fei.dengb9a1a572023-09-13 01:33:57 +00001237 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001238 --mCommitCnt;
1239 //remove buffer if this buffer is ready to release
1240 RenderBuffer *renderBuffer = buf->getRenderBuffer();
1241 auto item = mCommittedBufferMap.find(renderBuffer->pts);
1242 if (item != mCommittedBufferMap.end()) {
1243 mCommittedBufferMap.erase(item);
1244 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001245 WARNING(mLogCategory,"Can't find WaylandBuffer in buffer map");
fei.dengf7a0cd32023-08-29 09:36:37 +00001246 return;
1247 }
1248 }
1249 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001250 TRACE(mLogCategory,"handle release renderBuffer :%p,priv:%p,PTS:%lld,realtime:%lld us,commitCnt:%d",renderBuffer,renderBuffer->priv,renderBuffer->pts/1000,buf->getRenderRealTime(),mCommitCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +00001251 mWaylandPlugin->handleBufferRelease(renderBuffer);
1252}
1253
1254void WaylandDisplay::handleFrameDisplayedCallback(WaylandBuffer *buf)
1255{
1256 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001257 TRACE(mLogCategory,"handle displayed renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
fei.dengf7a0cd32023-08-29 09:36:37 +00001258 mWaylandPlugin->handleFrameDisplayed(renderBuffer);
1259}
1260
1261void WaylandDisplay::handleFrameDropedCallback(WaylandBuffer *buf)
1262{
1263 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001264 TRACE(mLogCategory,"handle droped renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
fei.dengf7a0cd32023-08-29 09:36:37 +00001265 mWaylandPlugin->handleFrameDropped(renderBuffer);
1266}
1267
1268
1269void WaylandDisplay::readyToRun()
1270{
1271 mFd = wl_display_get_fd (mWlDisplay);
fei.dengb9a1a572023-09-13 01:33:57 +00001272 if (mPoll) {
1273 mPoll->addFd(mFd);
1274 mPoll->setFdReadable(mFd, true);
1275 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001276}
1277
1278bool WaylandDisplay::threadLoop()
1279{
1280 int ret;
fei.dengf7a0cd32023-08-29 09:36:37 +00001281
1282 while (wl_display_prepare_read_queue (mWlDisplay, mWlQueue) != 0) {
1283 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1284 }
1285
1286 wl_display_flush (mWlDisplay);
1287
1288 /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
1289 so do use -1 to wait for ever*/
fei.dengb9a1a572023-09-13 01:33:57 +00001290 ret = mPoll->wait(-1); //wait for ever
fei.dengf7a0cd32023-08-29 09:36:37 +00001291 if (ret < 0) { //poll error
fei.dengb9a1a572023-09-13 01:33:57 +00001292 WARNING(mLogCategory,"poll error");
fei.dengf7a0cd32023-08-29 09:36:37 +00001293 wl_display_cancel_read(mWlDisplay);
1294 return false;
1295 } else if (ret == 0) { //poll time out
1296 return true; //run loop
1297 }
1298
1299 if (wl_display_read_events (mWlDisplay) == -1) {
1300 goto tag_error;
1301 }
1302
1303 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1304 return true;
1305tag_error:
fei.dengb9a1a572023-09-13 01:33:57 +00001306 ERROR(mLogCategory,"Error communicating with the wayland server");
fei.dengf7a0cd32023-08-29 09:36:37 +00001307 return false;
1308}
1309
1310void WaylandDisplay::videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling)
1311{
1312 //if dst is a small window, we scale video to map window size,don't doing center
1313 if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
1314 result->x = dst.x;
1315 result->y = dst.y;
1316 result->w = dst.w;
1317 result->h = dst.h;
fei.dengb9a1a572023-09-13 01:33:57 +00001318 TRACE(mLogCategory,"small window source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
fei.dengf7a0cd32023-08-29 09:36:37 +00001319 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1320 return;
1321 }
1322 if (!scaling) {
1323 result->w = MIN (src.w, dst.w);
1324 result->h = MIN (src.h, dst.h);
1325 result->x = dst.x + (dst.w - result->w) / 2;
1326 result->y = dst.y + (dst.h - result->h) / 2;
1327 } else {
1328 double src_ratio, dst_ratio;
1329
1330 src_ratio = (double) src.w / src.h;
1331 dst_ratio = (double) dst.w / dst.h;
1332
1333 if (src_ratio > dst_ratio) {
1334 result->w = dst.w;
1335 result->h = dst.w / src_ratio;
1336 result->x = dst.x;
1337 result->y = dst.y + (dst.h - result->h) / 2;
1338 } else if (src_ratio < dst_ratio) {
1339 result->w = dst.h * src_ratio;
1340 result->h = dst.h;
1341 result->x = dst.x + (dst.w - result->w) / 2;
1342 result->y = dst.y;
1343 } else {
1344 result->x = dst.x;
1345 result->y = dst.y;
1346 result->w = dst.w;
1347 result->h = dst.h;
1348 }
1349 }
1350
fei.dengb9a1a572023-09-13 01:33:57 +00001351 TRACE(mLogCategory,"source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d",
fei.dengf7a0cd32023-08-29 09:36:37 +00001352 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1353}
1354
1355void WaylandDisplay::updateBorders()
1356{
1357 int width,height;
1358
1359 if (mNoBorderUpdate)
1360 return;
1361
1362 if (mViewporter) {
1363 width = height = 1;
1364 mNoBorderUpdate = true;
1365 } else {
1366 width = mRenderRect.w;
1367 height = mRenderRect.h;
1368 }
1369
1370 RenderVideoFormat format = VIDEO_FORMAT_BGRA;
fei.dengb9a1a572023-09-13 01:33:57 +00001371 mAreaShmBuffer = new WaylandShmBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001372 struct wl_buffer *wlbuf = mAreaShmBuffer->constructWlBuffer(width, height, format);
1373 if (wlbuf == NULL) {
1374 delete mAreaShmBuffer;
1375 mAreaShmBuffer = NULL;
1376 }
1377
1378 wl_surface_attach(mAreaSurfaceWrapper, wlbuf, 0, 0);
1379}
1380
1381std::size_t WaylandDisplay::calculateDmaBufferHash(RenderDmaBuffer &dmabuf)
1382{
1383 std::string hashString("");
1384 for (int i = 0; i < dmabuf.planeCnt; i++) {
1385 char hashtmp[1024];
1386 snprintf (hashtmp, 1024, "%d%d%d%d%d%d", dmabuf.width,dmabuf.height,dmabuf.planeCnt,
1387 dmabuf.stride[i],dmabuf.offset[i],dmabuf.fd[i]);
1388 std::string tmp(hashtmp);
1389 hashString += tmp;
1390 }
1391
1392 std::size_t hashval = std::hash<std::string>()(hashString);
fei.dengb9a1a572023-09-13 01:33:57 +00001393 //TRACE(mLogCategory,"hashstr:%s,val:%zu",hashString.c_str(),hashval);
fei.dengf7a0cd32023-08-29 09:36:37 +00001394 return hashval;
1395}
1396
1397void WaylandDisplay::addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf)
1398{
1399 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1400 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1401 std::pair<std::size_t, WaylandBuffer *> item(hashval, waylandbuf);
fei.dengb9a1a572023-09-13 01:33:57 +00001402 //TRACE(mLogCategory,"fd:%d,w:%d,h:%d,%p,hash:%zu",buf->dma.fd[0],buf->dma.width,buf->dma.height,waylandbuf,hashval);
fei.dengf7a0cd32023-08-29 09:36:37 +00001403 mWaylandBuffersMap.insert(item);
1404 }
1405
1406 //clean invalid wayland buffer,if video resolution changed
1407 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1408 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1409 if ((waylandbuf->getFrameWidth() != buf->dma.width ||
1410 waylandbuf->getFrameHeight() != buf->dma.height) &&
1411 waylandbuf->isFree()) {
fei.dengb9a1a572023-09-13 01:33:57 +00001412 TRACE(mLogCategory,"delete wayland buffer,width:%d(%d),height:%d(%d)",
fei.dengf7a0cd32023-08-29 09:36:37 +00001413 waylandbuf->getFrameWidth(),buf->dma.width,
1414 waylandbuf->getFrameHeight(),buf->dma.height);
1415 mWaylandBuffersMap.erase(item++);
1416 delete waylandbuf;
1417 } else {
1418 item++;
1419 }
1420 }
fei.dengb9a1a572023-09-13 01:33:57 +00001421 TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
fei.dengf7a0cd32023-08-29 09:36:37 +00001422}
1423
1424WaylandBuffer* WaylandDisplay::findWaylandBuffer(RenderBuffer * buf)
1425{
1426 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1427 auto item = mWaylandBuffersMap.find(hashval);
1428 if (item == mWaylandBuffersMap.end()) {
1429 return NULL;
1430 }
1431
1432 return (WaylandBuffer*) item->second;
1433}
1434
1435void WaylandDisplay::cleanAllWaylandBuffer()
1436{
1437 //free all obtain buff
1438 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1439 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1440 mWaylandBuffersMap.erase(item++);
1441 delete waylandbuf;
1442 }
1443}
1444
1445void WaylandDisplay::flushBuffers()
1446{
fei.dengb9a1a572023-09-13 01:33:57 +00001447 INFO(mLogCategory,"flushBuffers");
1448 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001449 for (auto item = mCommittedBufferMap.begin(); item != mCommittedBufferMap.end(); item++) {
1450 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1451 waylandbuf->forceRedrawing();
1452 handleFrameDisplayedCallback(waylandbuf);
1453 }
1454}
1455
1456void WaylandDisplay::cleanSurface()
1457{
1458 /* clear both video and parent surfaces */
1459 wl_surface_attach (mVideoSurfaceWrapper, NULL, 0, 0);
1460 wl_surface_commit (mVideoSurfaceWrapper);
1461 wl_surface_attach (mAreaSurfaceWrapper, NULL, 0, 0);
1462 wl_surface_commit (mAreaSurfaceWrapper);
1463}