blob: eb06a2236348e23baf40b507ca06e2c0da8e467f [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))
fei.deng26950832023-11-09 03:00:23 +000032#define INVALID_OUTPUT_INDEX (-1)
fei.dengf7a0cd32023-08-29 09:36:37 +000033
34#define TAG "rlib:wayland_display"
35
36void WaylandDisplay::dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
37 uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
38{
39 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +000040 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +000041 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
fei.dengb9a1a572023-09-13 01:33:57 +000042 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 +000043 uint64_t modifier = ((uint64_t)modifier_hi << 32) | modifier_lo;
44 auto item = self->mDmaBufferFormats.find(format);
45 if (item == self->mDmaBufferFormats.end()) {
46 std::pair<uint32_t ,uint64_t> item(format, modifier);
47 self->mDmaBufferFormats.insert(item);
48 } else { //found format
49 item->second = modifier;
50 }
51 }
52}
53
54void
55WaylandDisplay::dmaBufferFormat (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
56 uint32_t format)
57{
58#if 0
59 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
60
61 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
62 TRACE(mLogCategory,"regist dmabuffer format:%d : %s",format);
63 //self->mDmaBufferFormats.push_back(format);
64 }
65#endif
66 /* XXX: deprecated */
67}
68
69static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
70 WaylandDisplay::dmaBufferFormat,
71 WaylandDisplay::dmabuf_modifiers
72};
73
74static void
75handle_xdg_wm_base_ping (void *user_data, struct xdg_wm_base *xdg_wm_base,
76 uint32_t serial)
77{
78 xdg_wm_base_pong (xdg_wm_base, serial);
79}
80
81static const struct xdg_wm_base_listener xdg_wm_base_listener = {
82 handle_xdg_wm_base_ping
83};
84
85void WaylandDisplay::shmFormat(void *data, struct wl_shm *wl_shm, uint32_t format)
86{
87 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
88 self->mShmFormats.push_back(format);
89}
90
91static const struct wl_shm_listener shm_listener = {
92 WaylandDisplay::shmFormat
93};
94
95void WaylandDisplay::outputHandleGeometry( void *data,
96 struct wl_output *output,
97 int x,
98 int y,
99 int physicalWidth,
100 int physicalHeight,
101 int subPixel,
102 const char *make,
103 const char *model,
104 int transform )
105{
106 UNUSED_PARAM(make);
107 UNUSED_PARAM(model);
108
109 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +0000110 DEBUG(self->mLogCategory,"wl_output %p x:%d,y:%d,physicalWidth:%d,physicalHeight:%d,subPixel:%d,trans:%d",
111 output,x, y,physicalWidth, physicalHeight,subPixel,transform);
112 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000113 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
114 if (output == self->mOutput[i].wlOutput) {
115 self->mOutput[i].offsetX = x;
116 self->mOutput[i].offsetY = y;
117 }
118 }
119}
120
121void WaylandDisplay::outputHandleMode( void *data,
122 struct wl_output *output,
123 uint32_t flags,
124 int width,
125 int height,
126 int refreshRate )
127{
128 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
129
130 if ( flags & WL_OUTPUT_MODE_CURRENT ) {
fei.dengb9a1a572023-09-13 01:33:57 +0000131 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000132 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
133 if (output == self->mOutput[i].wlOutput) {
134 self->mOutput[i].width = width;
135 self->mOutput[i].height = height;
136 self->mOutput[i].refreshRate = refreshRate;
137 }
138 }
fei.deng26950832023-11-09 03:00:23 +0000139
140 DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,select output index %d",output, width, height,refreshRate,self->mSelectOutputIndex);
141 if (self->mCurrentDisplayOutput->width > 0 &&
142 self->mCurrentDisplayOutput->height > 0) {
143 self->updateDisplayOutput();
fei.dengf7a0cd32023-08-29 09:36:37 +0000144 }
145 }
146}
147
148void WaylandDisplay::outputHandleDone( void *data,
149 struct wl_output *output )
150{
151 UNUSED_PARAM(data);
152 UNUSED_PARAM(output);
153}
154
155void WaylandDisplay::outputHandleScale( void *data,
156 struct wl_output *output,
157 int32_t scale )
158{
159 UNUSED_PARAM(data);
160 UNUSED_PARAM(output);
161 UNUSED_PARAM(scale);
162}
163
164static const struct wl_output_listener outputListener = {
165 WaylandDisplay::outputHandleGeometry,
166 WaylandDisplay::outputHandleMode,
167 WaylandDisplay::outputHandleDone,
168 WaylandDisplay::outputHandleScale
169};
170
171void WaylandDisplay::pointerHandleEnter(void *data, struct wl_pointer *pointer,
172 uint32_t serial, struct wl_surface *surface,
173 wl_fixed_t sx, wl_fixed_t sy)
174{
175 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
176
177 if (self->mFullScreen) {
178 wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
179 }
180}
181
182void WaylandDisplay::pointerHandleLeave(void *data, struct wl_pointer *pointer,
183 uint32_t serial, struct wl_surface *surface)
184{
185 UNUSED_PARAM(data);
186 UNUSED_PARAM(pointer);
187 UNUSED_PARAM(serial);
188 UNUSED_PARAM(surface);
189}
190
191void WaylandDisplay::pointerHandleMotion(void *data, struct wl_pointer *pointer,
192 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
193{
194 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
195 int x = wl_fixed_to_int(sx);
196 int y = wl_fixed_to_int(sy);
fei.dengb9a1a572023-09-13 01:33:57 +0000197 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 +0000198}
199
200void WaylandDisplay::pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
201 uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
202{
203 UNUSED_PARAM(data);
204 UNUSED_PARAM(wl_pointer);
205 UNUSED_PARAM(time);
206 UNUSED_PARAM(serial);
207 UNUSED_PARAM(button);
208 UNUSED_PARAM(state);
209}
210
211void WaylandDisplay::pointerHandleAxis(void *data, struct wl_pointer *wl_pointer,
212 uint32_t time, uint32_t axis, wl_fixed_t value)
213{
214 UNUSED_PARAM(data);
215 UNUSED_PARAM(wl_pointer);
216 UNUSED_PARAM(time);
217 UNUSED_PARAM(axis);
218 UNUSED_PARAM(value);
219}
220
221static const struct wl_pointer_listener pointer_listener = {
222 WaylandDisplay::pointerHandleEnter,
223 WaylandDisplay::pointerHandleLeave,
224 WaylandDisplay::pointerHandleMotion,
225 WaylandDisplay::pointerHandleButton,
226 WaylandDisplay::pointerHandleAxis,
227};
228
229void WaylandDisplay::touchHandleDown(void *data, struct wl_touch *wl_touch,
230 uint32_t serial, uint32_t time, struct wl_surface *surface,
231 int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
232{
233 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
234}
235
236void WaylandDisplay::touchHandleUp(void *data, struct wl_touch *wl_touch,
237 uint32_t serial, uint32_t time, int32_t id)
238{
239 UNUSED_PARAM(data);
240 UNUSED_PARAM(wl_touch);
241 UNUSED_PARAM(serial);
242 UNUSED_PARAM(time);
243 UNUSED_PARAM(id);
244}
245
246void WaylandDisplay::touchHandleMotion(void *data, struct wl_touch *wl_touch,
247 uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
248{
249 UNUSED_PARAM(data);
250 UNUSED_PARAM(wl_touch);
251 UNUSED_PARAM(time);
252 UNUSED_PARAM(id);
253 UNUSED_PARAM(x_w);
254 UNUSED_PARAM(y_w);
255}
256
257void WaylandDisplay::touchHandleFrame(void *data, struct wl_touch *wl_touch)
258{
259 UNUSED_PARAM(data);
260 UNUSED_PARAM(wl_touch);
261}
262
263void WaylandDisplay::touchHandleCancel(void *data, struct wl_touch *wl_touch)
264{
265 UNUSED_PARAM(data);
266 UNUSED_PARAM(wl_touch);
267}
268
269static const struct wl_touch_listener touch_listener = {
270 WaylandDisplay::touchHandleDown,
271 WaylandDisplay::touchHandleUp,
272 WaylandDisplay::touchHandleMotion,
273 WaylandDisplay::touchHandleFrame,
274 WaylandDisplay::touchHandleCancel,
275};
276
277void WaylandDisplay::keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard,
278 uint32_t format, int fd, uint32_t size)
279{
280 UNUSED_PARAM(data);
281 UNUSED_PARAM(keyboard);
282 UNUSED_PARAM(format);
283 UNUSED_PARAM(fd);
284 UNUSED_PARAM(size);
285}
286
287void WaylandDisplay::keyboardHandleEnter(void *data, struct wl_keyboard *keyboard,
288 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
289{
290 UNUSED_PARAM(data);
291 UNUSED_PARAM(keyboard);
292 UNUSED_PARAM(serial);
293 UNUSED_PARAM(surface);
294 UNUSED_PARAM(keys);
295}
296
297void WaylandDisplay::keyboardHandleLeave(void *data, struct wl_keyboard *keyboard,
298 uint32_t serial, struct wl_surface *surface)
299{
300 UNUSED_PARAM(data);
301 UNUSED_PARAM(keyboard);
302 UNUSED_PARAM(serial);
303 UNUSED_PARAM(surface);
304}
305
306void WaylandDisplay::keyboardHandleKey(void *data, struct wl_keyboard *keyboard,
307 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
308{
309 UNUSED_PARAM(data);
310 UNUSED_PARAM(keyboard);
311 UNUSED_PARAM(serial);
312 UNUSED_PARAM(time);
313 UNUSED_PARAM(key);
314 UNUSED_PARAM(state);
315}
316
317void WaylandDisplay::keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard,
318 uint32_t serial, uint32_t mods_depressed,
319 uint32_t mods_latched, uint32_t mods_locked,
320 uint32_t group)
321{
322 UNUSED_PARAM(data);
323 UNUSED_PARAM(keyboard);
324 UNUSED_PARAM(serial);
325 UNUSED_PARAM(mods_depressed);
326 UNUSED_PARAM(mods_latched);
327 UNUSED_PARAM(mods_locked);
328 UNUSED_PARAM(group);
329}
330
331static const struct wl_keyboard_listener keyboard_listener = {
332 WaylandDisplay::keyboardHandleKeymap,
333 WaylandDisplay::keyboardHandleEnter,
334 WaylandDisplay::keyboardHandleLeave,
335 WaylandDisplay::keyboardHandleKey,
336 WaylandDisplay::keyboardHandleModifiers,
337};
338
339void WaylandDisplay::seatHandleCapabilities(void *data, struct wl_seat *seat,
340 uint32_t caps)
341{
342 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
343 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !self->mPointer) {
344 self->mPointer = wl_seat_get_pointer(seat);
345 wl_pointer_add_listener(self->mPointer, &pointer_listener, data);
346 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && self->mPointer) {
347 wl_pointer_destroy(self->mPointer);
348 self->mPointer = NULL;
349 }
350
351 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !self->mKeyboard) {
352 self->mKeyboard = wl_seat_get_keyboard(seat);
353 wl_keyboard_add_listener(self->mKeyboard, &keyboard_listener, data);
354 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && self->mKeyboard) {
355 wl_keyboard_destroy(self->mKeyboard);
356 self->mKeyboard = NULL;
357 }
358
359 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !self->mTouch) {
360 self->mTouch = wl_seat_get_touch(seat);
361 wl_touch_set_user_data(self->mTouch, data);
362 wl_touch_add_listener(self->mTouch, &touch_listener, data);
363 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && self->mTouch) {
364 wl_touch_destroy(self->mTouch);
365 self->mTouch = NULL;
366 }
367}
368
369static const struct wl_seat_listener seat_listener = {
370 WaylandDisplay::seatHandleCapabilities,
371};
372
373
374void WaylandDisplay::handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel)
375{
376 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
377
fei.dengb9a1a572023-09-13 01:33:57 +0000378 INFO(self->mLogCategory,"XDG toplevel got a close event.");
fei.dengf7a0cd32023-08-29 09:36:37 +0000379}
380
381void WaylandDisplay::handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
382 int32_t width, int32_t height, struct wl_array *states)
383{
384 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
385 uint32_t *state;
386
fei.dengb9a1a572023-09-13 01:33:57 +0000387 INFO(self->mLogCategory, "XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000388 /*
389 wl_array_for_each (state, states) {
390 switch (*state) {
391 case XDG_TOPLEVEL_STATE_FULLSCREEN:
392 case XDG_TOPLEVEL_STATE_MAXIMIZED:
393 case XDG_TOPLEVEL_STATE_RESIZING:
394 case XDG_TOPLEVEL_STATE_ACTIVATED:
395 break;
396 }
397 }
398 */
399
400 if (width <= 0 || height <= 0)
401 return;
402
fei.deng26950832023-11-09 03:00:23 +0000403 if (width == self->mCurrentDisplayOutput->width && height == self->mCurrentDisplayOutput->height && self->mUpdateRenderRectangle) {
404 self->mUpdateRenderRectangle = false;
405 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
406 self->mCurrentDisplayOutput->offsetY,
407 self->mCurrentDisplayOutput->width,
408 self->mCurrentDisplayOutput->height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000409 } else{
410 self->setRenderRectangle(self->mRenderRect.x, self->mRenderRect.y, width, height);
411 }
412}
413
414static const struct xdg_toplevel_listener xdg_toplevel_listener = {
415 WaylandDisplay::handleXdgToplevelConfigure,
416 WaylandDisplay::handleXdgToplevelClose,
417};
418
419void WaylandDisplay::handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface,
420 uint32_t serial)
421{
422 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
423 xdg_surface_ack_configure (xdg_surface, serial);
424
fei.dengb9a1a572023-09-13 01:33:57 +0000425 TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
426 Tls::Mutex::Autolock _l(self->mConfigureMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000427 self->mXdgSurfaceConfigured = true;
fei.deng26950832023-11-09 03:00:23 +0000428 self->updateDisplayOutput();
fei.dengf7a0cd32023-08-29 09:36:37 +0000429}
430
431static const struct xdg_surface_listener xdg_surface_listener = {
432 WaylandDisplay::handleXdgSurfaceConfigure,
433};
434
435void
436WaylandDisplay::registryHandleGlobal (void *data, struct wl_registry *registry,
fei.dengaf9b07d2023-10-10 07:38:40 +0000437 uint32_t name, const char *interface, uint32_t version)
fei.dengf7a0cd32023-08-29 09:36:37 +0000438{
439 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000440 TRACE(self->mLogCategory,"registryHandleGlobal,name:%u,interface:%s,version:%d",name,interface,version);
fei.dengf7a0cd32023-08-29 09:36:37 +0000441
442 if (strcmp (interface, "wl_compositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000443 self->mCompositor = (struct wl_compositor *)wl_registry_bind (registry, name, &wl_compositor_interface, 1/*MIN (version, 3)*/);
fei.dengf7a0cd32023-08-29 09:36:37 +0000444 } else if (strcmp (interface, "wl_subcompositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000445 self->mSubCompositor = (struct wl_subcompositor *)wl_registry_bind (registry, name, &wl_subcompositor_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000446 } else if (strcmp (interface, "xdg_wm_base") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000447 self->mXdgWmBase = (struct xdg_wm_base *)wl_registry_bind (registry, name, &xdg_wm_base_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000448 xdg_wm_base_add_listener (self->mXdgWmBase, &xdg_wm_base_listener, (void *)self);
449 } else if (strcmp (interface, "wl_shm") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000450 self->mShm = (struct wl_shm *)wl_registry_bind (registry, name, &wl_shm_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000451 wl_shm_add_listener (self->mShm, &shm_listener, self);
452 } else if (strcmp (interface, "zwp_fullscreen_shell_v1") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000453 //self->mFullscreenShell = (struct zwp_fullscreen_shell_v1 *)wl_registry_bind (registry, name,
fei.dengf7a0cd32023-08-29 09:36:37 +0000454 // &zwp_fullscreen_shell_v1_interface, 1);
455 } else if (strcmp (interface, "wp_viewporter") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000456 self->mViewporter = (struct wp_viewporter *)wl_registry_bind (registry, name, &wp_viewporter_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000457 } else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0) {
458 if (version < 3)
459 return;
fei.dengaf9b07d2023-10-10 07:38:40 +0000460 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 +0000461 zwp_linux_dmabuf_v1_add_listener (self->mDmabuf, &dmabuf_listener, (void *)self);
462 } else if (strcmp (interface, "wl_output") == 0) {
fei.deng26950832023-11-09 03:00:23 +0000463 int i = 0;
464 uint32_t oriName = self->mCurrentDisplayOutput->name;
fei.dengaf9b07d2023-10-10 07:38:40 +0000465 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
466 if (self->mOutput[i].wlOutput == NULL) {
467 self->mOutput[i].name = name;
468 self->mOutput[i].wlOutput = (struct wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version);
fei.deng26950832023-11-09 03:00:23 +0000469 TRACE(self->mLogCategory,"name:%u, wl_output:%p, select:%d",self->mOutput[i].name,self->mOutput[i].wlOutput,self->mSelectOutputIndex);
fei.dengaf9b07d2023-10-10 07:38:40 +0000470 wl_output_add_listener(self->mOutput[i].wlOutput, &outputListener, (void *)self);
471 if (i == 0) { //primary wl_output
472 self->mOutput[i].isPrimary = true;
473 }
fei.deng26950832023-11-09 03:00:23 +0000474 break;
fei.dengaf9b07d2023-10-10 07:38:40 +0000475 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000476 }
fei.deng26950832023-11-09 03:00:23 +0000477 if (i == DEFAULT_DISPLAY_OUTPUT_NUM) {
478 WARNING(self->mLogCategory,"Not enough free output");
479 }
480 //select current wl_output
481 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX && !self->isRunning()) {
482 TRACE(self->mLogCategory,"select %d output",self->mSelectOutputIndex);
483 self->mCurrentDisplayOutput = &self->mOutput[self->mSelectOutputIndex];
484 }
485 //if user select a wrong output index, we using a suiteble wl_output
486 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
487 WARNING(self->mLogCategory,"wl_output is null,we should find a suiteble output");
488 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
489 if (self->mOutput[i].wlOutput) {
490 self->mCurrentDisplayOutput = &self->mOutput[i];
491 break;
492 }
493 }
494 }
495 //if current wl_output update, we should update render rectangle
496 if (self->mCurrentDisplayOutput->name != oriName) {
497 self->mUpdateRenderRectangle = true;
498 }
499 //if wl_output plugin,active sending frame
500 self->setRedrawingPending(false);
fei.dengf7a0cd32023-08-29 09:36:37 +0000501 } else if (strcmp(interface, "wl_seat") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000502 //self->mSeat = (struct wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000503 //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
504 }
505}
506
507void
508WaylandDisplay::registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name)
509{
fei.deng26950832023-11-09 03:00:23 +0000510 int i;
fei.dengf7a0cd32023-08-29 09:36:37 +0000511 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000512 /* check wl_output changed */
513 DEBUG(self->mLogCategory,"wayland display remove registry handle global,name:%u",name);
fei.deng26950832023-11-09 03:00:23 +0000514 //if user selected wl_output removed, reset selected output index
515 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX &&
516 self->mOutput[self->mSelectOutputIndex].wlOutput &&
517 self->mOutput[self->mSelectOutputIndex].name == name) {
518 self->mSelectOutputIndex = INVALID_OUTPUT_INDEX;
519 }
520 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000521 if (self->mOutput[i].name == name) {
fei.deng26950832023-11-09 03:00:23 +0000522 DEBUG(self->mLogCategory,"remove wl_output name:%u,wl_output:%p",name,self->mOutput[i].wlOutput);
fei.dengaf9b07d2023-10-10 07:38:40 +0000523 self->mOutput[i].name = 0;
524 self->mOutput[i].wlOutput = NULL;
fei.deng26950832023-11-09 03:00:23 +0000525 }
526 }
527 //if current output removed, select a suiteble output
528 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
529 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
530 if (self->mOutput[i].wlOutput) {
531 self->mCurrentDisplayOutput = &self->mOutput[i];
532 self->mUpdateRenderRectangle = true;
533 }
534 }
535 //set new output rectangle
536 if (self->mUpdateRenderRectangle) {
537 self->mUpdateRenderRectangle = false;
538 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
539 self->mCurrentDisplayOutput->offsetY,
540 self->mCurrentDisplayOutput->width,
541 self->mCurrentDisplayOutput->height);
fei.dengaf9b07d2023-10-10 07:38:40 +0000542 }
543 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000544}
545
546static const struct wl_registry_listener registry_listener = {
547 WaylandDisplay::registryHandleGlobal,
548 WaylandDisplay::registryHandleGlobalRemove
549};
550
fei.dengb9a1a572023-09-13 01:33:57 +0000551WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin, int logCategory)
552 :mBufferMutex("bufferMutex"),
553 mWaylandPlugin(plugin),
554 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +0000555{
fei.dengb9a1a572023-09-13 01:33:57 +0000556 TRACE(mLogCategory,"construct WaylandDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000557 mWlDisplay = NULL;
558 mWlDisplayWrapper = NULL;
559 mWlQueue = NULL;
560 mRegistry = NULL;
561 mCompositor = NULL;
562 mXdgWmBase = NULL;
563 mViewporter = NULL;
564 mDmabuf = NULL;
565 mShm = NULL;
566 mSeat = NULL;
567 mPointer = NULL;
568 mTouch = NULL;
569 mKeyboard = NULL;
fei.deng26950832023-11-09 03:00:23 +0000570 mSelectOutputIndex = INVALID_OUTPUT_INDEX;
fei.dengb9a1a572023-09-13 01:33:57 +0000571 mPoll = new Tls::Poll(true);
fei.dengf7a0cd32023-08-29 09:36:37 +0000572 //window
573 mVideoWidth = 0;
574 mVideoHeight = 0;
575 mVideoSurface = NULL;
576 mXdgSurface = NULL;
577 mXdgToplevel = NULL;
578 mAreaViewport = NULL;
579 mVideoViewport = NULL;
580 mNoBorderUpdate = false;
581 mAreaShmBuffer = NULL;
582 mCommitCnt = 0;
583 mIsSendPtsToWeston = false;
584 mReCommitAreaSurface = false;
585 mAreaSurface = NULL;
586 mAreaSurfaceWrapper = NULL;
587 mVideoSurfaceWrapper = NULL;
588 mVideoSubSurface = NULL;
589 mXdgSurfaceConfigured = false;
590 mPip = 0;
591 mIsSendVideoPlaneId = true;
fei.deng26950832023-11-09 03:00:23 +0000592 mCurrentDisplayOutput = &mOutput[0];
593 mUpdateRenderRectangle = false;
fei.dengf7a0cd32023-08-29 09:36:37 +0000594 memset(&mRenderRect, 0, sizeof(struct Rectangle));
595 memset(&mVideoRect, 0, sizeof(struct Rectangle));
596 memset(&mWindowRect, 0, sizeof(struct Rectangle));
597 mFullScreen = true; //default is full screen
598 char *env = getenv("VIDEO_RENDER_SEND_PTS_TO_WESTON");
599 if (env) {
600 int isSet = atoi(env);
601 if (isSet > 0) {
602 mIsSendPtsToWeston = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000603 INFO(mLogCategory,"set send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000604 } else {
605 mIsSendPtsToWeston = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000606 INFO(mLogCategory,"do not send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000607 }
608 }
609 env = getenv("VIDEO_RENDER_SEND_VIDEO_PLANE_ID_TO_WESTON");
610 if (env) {
611 int isSet = atoi(env);
612 if (isSet == 0) {
613 mIsSendVideoPlaneId = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000614 INFO(mLogCategory,"do not send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000615 } else {
616 mIsSendVideoPlaneId = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000617 INFO(mLogCategory,"send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000618 }
619 }
620 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
621 mOutput[i].wlOutput = NULL;
622 mOutput[i].offsetX = 0;
623 mOutput[i].offsetY = 0;
624 mOutput[i].width = 0;
625 mOutput[i].height = 0;
626 mOutput[i].refreshRate = 0;
627 mOutput[i].isPrimary = false;
fei.dengaf9b07d2023-10-10 07:38:40 +0000628 mOutput[i].name = 0;
fei.dengf7a0cd32023-08-29 09:36:37 +0000629 }
630}
631
632WaylandDisplay::~WaylandDisplay()
633{
fei.dengb9a1a572023-09-13 01:33:57 +0000634 TRACE(mLogCategory,"desconstruct WaylandDisplay");
635 if (mPoll) {
636 delete mPoll;
637 mPoll = NULL;
638 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000639}
640
641char *WaylandDisplay::require_xdg_runtime_dir()
642{
643 char *val = getenv("XDG_RUNTIME_DIR");
fei.dengb9a1a572023-09-13 01:33:57 +0000644 INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",val);
fei.dengf7a0cd32023-08-29 09:36:37 +0000645
646 return val;
647}
648
649int WaylandDisplay::openDisplay()
650{
651 char *name = require_xdg_runtime_dir();
652 //DEBUG(mLogCategory,"name:%s",name);
fei.dengb9a1a572023-09-13 01:33:57 +0000653 DEBUG(mLogCategory,"openDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000654 mWlDisplay = wl_display_connect(NULL);
655 if (!mWlDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000656 ERROR(mLogCategory,"Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
fei.dengf7a0cd32023-08-29 09:36:37 +0000657 name ? name : "NULL");
fei.dengb9a1a572023-09-13 01:33:57 +0000658 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000659 }
660
661 mWlDisplayWrapper = (struct wl_display *)wl_proxy_create_wrapper ((void *)mWlDisplay);
662 mWlQueue = wl_display_create_queue (mWlDisplay);
663 wl_proxy_set_queue ((struct wl_proxy *)mWlDisplayWrapper, mWlQueue);
664
665 mRegistry = wl_display_get_registry (mWlDisplayWrapper);
666 wl_registry_add_listener (mRegistry, &registry_listener, (void *)this);
667
668 /* we need exactly 2 roundtrips to discover global objects and their state */
669 for (int i = 0; i < 2; i++) {
670 if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000671 ERROR(mLogCategory,"Error communicating with the wayland display");
672 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000673 }
674 }
675
676 if (!mCompositor) {
fei.dengb9a1a572023-09-13 01:33:57 +0000677 ERROR(mLogCategory,"Could not bind to wl_compositor. Either it is not implemented in " \
fei.dengf7a0cd32023-08-29 09:36:37 +0000678 "the compositor, or the implemented version doesn't match");
fei.dengb9a1a572023-09-13 01:33:57 +0000679 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000680 }
681
682 if (!mDmabuf) {
fei.dengb9a1a572023-09-13 01:33:57 +0000683 ERROR(mLogCategory,"Could not bind to zwp_linux_dmabuf_v1");
684 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000685 }
686
687 if (!mXdgWmBase) {
688 /* If wl_surface and wl_display are passed via GstContext
689 * wl_shell, xdg_shell and zwp_fullscreen_shell are not used.
690 * In this case is correct to continue.
691 */
fei.dengb9a1a572023-09-13 01:33:57 +0000692 ERROR(mLogCategory,"Could not bind to either wl_shell, xdg_wm_base or "
fei.dengf7a0cd32023-08-29 09:36:37 +0000693 "zwp_fullscreen_shell, video display may not work properly.");
fei.dengb9a1a572023-09-13 01:33:57 +0000694 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000695 }
696
697 //create window surface
698 createCommonWindowSurface();
699 createXdgShellWindowSurface();
700
701 //config weston video plane
702 if (mIsSendVideoPlaneId) {
fei.dengb9a1a572023-09-13 01:33:57 +0000703 INFO(mLogCategory,"set weston video plane:%d",mPip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000704 wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
705 }
706
707 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000708 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengf7a0cd32023-08-29 09:36:37 +0000709 run("display queue");
710 mRedrawingPending = false;
711
fei.dengb9a1a572023-09-13 01:33:57 +0000712 DEBUG(mLogCategory,"openDisplay out");
713 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000714}
715
716void WaylandDisplay::closeDisplay()
717{
fei.dengb9a1a572023-09-13 01:33:57 +0000718 DEBUG(mLogCategory,"closeDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000719
720 if (isRunning()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000721 TRACE(mLogCategory,"try stop dispatch thread");
722 if (mPoll) {
723 mPoll->setFlushing(true);
724 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000725 requestExitAndWait();
726 }
727
728 //first destroy window surface
729 destroyWindowSurfaces();
730
731 if (mViewporter) {
732 wp_viewporter_destroy (mViewporter);
733 mViewporter = NULL;
734 }
735
736 if (mDmabuf) {
737 zwp_linux_dmabuf_v1_destroy (mDmabuf);
738 mDmabuf = NULL;
739 }
740
741 if (mXdgWmBase) {
742 xdg_wm_base_destroy (mXdgWmBase);
743 mXdgWmBase = NULL;
744 }
745
746 if (mCompositor) {
747 wl_compositor_destroy (mCompositor);
748 mCompositor = NULL;
749 }
750
751 if (mSubCompositor) {
752 wl_subcompositor_destroy (mSubCompositor);
753 mSubCompositor = NULL;
754 }
755
756 if (mRegistry) {
757 wl_registry_destroy (mRegistry);
758 mRegistry= NULL;
759 }
760
761 if (mWlDisplayWrapper) {
762 wl_proxy_wrapper_destroy (mWlDisplayWrapper);
763 mWlDisplayWrapper = NULL;
764 }
765
766 if (mWlQueue) {
767 wl_event_queue_destroy (mWlQueue);
768 mWlQueue = NULL;
769 }
770
771 if (mWlDisplay) {
772 wl_display_flush (mWlDisplay);
773 wl_display_disconnect (mWlDisplay);
774 mWlDisplay = NULL;
775 }
776
fei.dengb9a1a572023-09-13 01:33:57 +0000777 DEBUG(mLogCategory,"closeDisplay out");
fei.dengf7a0cd32023-08-29 09:36:37 +0000778}
779
780int WaylandDisplay::toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/)
781{
782 if (!outDmaformat || !outDmaformatModifiers) {
fei.dengb9a1a572023-09-13 01:33:57 +0000783 WARNING(mLogCategory,"NULL params");
784 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000785 }
786
787 *outDmaformat = 0;
788 *outDmaformatModifiers = 0;
789
790 uint32_t dmaformat = video_format_to_wl_dmabuf_format (format);
791 if (dmaformat == -1) {
fei.dengb9a1a572023-09-13 01:33:57 +0000792 ERROR(mLogCategory,"Error not found render video format:%d to wl dmabuf format",format);
793 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000794 }
795
fei.dengb9a1a572023-09-13 01:33:57 +0000796 TRACE(mLogCategory,"render video format:%d -> dmabuf format:%d",format,dmaformat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000797 *outDmaformat = (uint32_t)dmaformat;
798
799 /*get dmaformat and modifiers*/
800 auto item = mDmaBufferFormats.find(dmaformat);
801 if (item == mDmaBufferFormats.end()) { //not found
fei.dengb9a1a572023-09-13 01:33:57 +0000802 WARNING(mLogCategory,"Not found dmabuf for render video format :%d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000803 *outDmaformatModifiers = 0;
fei.dengb9a1a572023-09-13 01:33:57 +0000804 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000805 }
806
807 *outDmaformatModifiers = (uint64_t)item->second;
808
fei.dengb9a1a572023-09-13 01:33:57 +0000809 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000810}
811
812int WaylandDisplay::toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat)
813{
814 if (!outformat) {
fei.dengb9a1a572023-09-13 01:33:57 +0000815 WARNING(mLogCategory,"NULL params");
816 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000817 }
818
819 *outformat = 0;
820
821 int shmformat = (int)video_format_to_wl_shm_format(format);
822 if (shmformat < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000823 ERROR(mLogCategory,"Error not found render video format:%d to wl shmbuf format",format);
824 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000825 }
826
827 for (auto item = mShmFormats.begin(); item != mShmFormats.end(); ++item) {
828 uint32_t registFormat = (uint32_t)*item;
829 if (registFormat == (uint32_t)shmformat) {
830 *outformat = registFormat;
fei.dengb9a1a572023-09-13 01:33:57 +0000831 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000832 }
833 }
834
fei.dengb9a1a572023-09-13 01:33:57 +0000835 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000836}
837
838void WaylandDisplay::setVideoBufferFormat(RenderVideoFormat format)
839{
fei.dengb9a1a572023-09-13 01:33:57 +0000840 TRACE(mLogCategory,"set video buffer format: %d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000841 mBufferFormat = format;
842};
843
844void WaylandDisplay::setDisplayOutput(int output)
845{
fei.dengb9a1a572023-09-13 01:33:57 +0000846 TRACE(mLogCategory,"select display output: %d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000847 if (output < 0 || output >= DEFAULT_DISPLAY_OUTPUT_NUM) {
fei.dengb9a1a572023-09-13 01:33:57 +0000848 ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000849 return;
850 }
fei.deng26950832023-11-09 03:00:23 +0000851 //only do select output before video playing
852 if (mSelectOutputIndex != output) {
853 mSelectOutputIndex = output;
854 // if (mOutput[output].wlOutput) {
855 // mCurrentDisplayOutput = &mOutput[output];
856 // setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
857 // mOutput[output].width, mOutput[output].height);
858 // }
fei.dengf7a0cd32023-08-29 09:36:37 +0000859 }
860}
861
862int WaylandDisplay::getDisplayOutput()
863{
fei.deng26950832023-11-09 03:00:23 +0000864 return mSelectOutputIndex == INVALID_OUTPUT_INDEX? 0: mSelectOutputIndex;
fei.dengf7a0cd32023-08-29 09:36:37 +0000865}
866
867void WaylandDisplay::setPip(int pip)
868{
fei.dengb9a1a572023-09-13 01:33:57 +0000869 INFO(mLogCategory,"set pip:%d",pip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000870 mPip = pip;
871}
872
fei.deng26950832023-11-09 03:00:23 +0000873void WaylandDisplay::updateDisplayOutput()
874{
875 if (!mCurrentDisplayOutput->wlOutput || !mXdgToplevel || !mXdgSurface)
876 {
877 return;
878 }
879 if (mUpdateRenderRectangle) {
880 if (mFullScreen) {
881 DEBUG(mLogCategory,"unset full screen");
882 xdg_toplevel_unset_fullscreen (mXdgToplevel);
883 }
884
885 if (mXdgSurface) {
886 DEBUG(mLogCategory,"set geometry");
887 xdg_surface_set_window_geometry(mXdgSurface,
888 mCurrentDisplayOutput->offsetX,
889 mCurrentDisplayOutput->offsetY,
890 mCurrentDisplayOutput->width,
891 mCurrentDisplayOutput->height);
892 }
893
894 if (mFullScreen && mXdgToplevel) {
895 DEBUG(mLogCategory,"set full screen");
896 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
897 }
898 setRenderRectangle(mCurrentDisplayOutput->offsetX, mCurrentDisplayOutput->offsetY,
899 mCurrentDisplayOutput->width, mCurrentDisplayOutput->height);
900 mUpdateRenderRectangle = false;
901 }
902}
903
fei.dengf7a0cd32023-08-29 09:36:37 +0000904void WaylandDisplay::createCommonWindowSurface()
905{
906 struct wl_region *region;
907
908 mAreaSurface = wl_compositor_create_surface (mCompositor);
909 mVideoSurface = wl_compositor_create_surface (mCompositor);
910 mAreaSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mAreaSurface);
911 mVideoSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mVideoSurface);
912
913 wl_proxy_set_queue ((struct wl_proxy *) mAreaSurfaceWrapper, mWlQueue);
914 wl_proxy_set_queue ((struct wl_proxy *) mVideoSurfaceWrapper, mWlQueue);
915
916 /* embed video_surface in area_surface */
917 mVideoSubSurface = wl_subcompositor_get_subsurface (mSubCompositor, mVideoSurface, mAreaSurface);
918 wl_subsurface_set_desync (mVideoSubSurface);
919
920 if (mViewporter) {
921 mAreaViewport = wp_viewporter_get_viewport (mViewporter, mAreaSurface);
922 mVideoViewport = wp_viewporter_get_viewport (mViewporter, mVideoSurface);
923 }
924
925 /* do not accept input */
926 region = wl_compositor_create_region (mCompositor);
927 wl_surface_set_input_region (mAreaSurface, region);
928 wl_region_destroy (region);
929
930 region = wl_compositor_create_region (mCompositor);
931 wl_surface_set_input_region (mVideoSurface, region);
932 wl_region_destroy (region);
933}
934
935void WaylandDisplay::createXdgShellWindowSurface()
936{
937 /* Check which protocol we will use (in order of preference) */
938 if (mXdgWmBase) {
939 /* First create the XDG surface */
940 mXdgSurface= xdg_wm_base_get_xdg_surface (mXdgWmBase, mAreaSurface);
941 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000942 ERROR(mLogCategory,"Unable to get xdg_surface");
fei.dengf7a0cd32023-08-29 09:36:37 +0000943 return;
944 }
945 xdg_surface_add_listener (mXdgSurface, &xdg_surface_listener,(void *)this);
946
947 /* Then the toplevel */
948 mXdgToplevel= xdg_surface_get_toplevel (mXdgSurface);
949 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000950 ERROR(mLogCategory,"Unable to get xdg_toplevel");
fei.dengf7a0cd32023-08-29 09:36:37 +0000951 return;
952 }
953 xdg_toplevel_add_listener (mXdgToplevel, &xdg_toplevel_listener, this);
954
955 /* Finally, commit the xdg_surface state as toplevel */
956 mXdgSurfaceConfigured = false;
957 wl_surface_commit (mAreaSurface);
958 wl_display_flush (mWlDisplay);
959 /* we need exactly 3 roundtrips to discover global objects and their state */
960 for (int i = 0; i < 3; i++) {
961 if (wl_display_roundtrip_queue(mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000962 ERROR(mLogCategory,"Error communicating with the wayland display");
fei.dengf7a0cd32023-08-29 09:36:37 +0000963 }
964 }
965
966 if (mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +0000967 INFO(mLogCategory,"xdg surface had configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000968 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000969 WARNING(mLogCategory,"xdg surface not configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000970 }
971
972 //full screen show
fei.deng26950832023-11-09 03:00:23 +0000973 // if (mFullScreen && mCurrentDisplayOutput->wlOutput) {
974 // //ensureFullscreen(mFullScreen);
fei.dengf7a0cd32023-08-29 09:36:37 +0000975 // }
976 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000977 ERROR(mLogCategory,"Unable to use xdg_wm_base ");
fei.dengf7a0cd32023-08-29 09:36:37 +0000978 return;
979 }
980}
981
982void WaylandDisplay::destroyWindowSurfaces()
983{
984 if (mAreaShmBuffer) {
985 delete mAreaShmBuffer;
986 mAreaShmBuffer = NULL;
987 }
988
989 //clean all wayland buffers
990 cleanAllWaylandBuffer();
991
992 if (mXdgToplevel) {
993 xdg_toplevel_destroy (mXdgToplevel);
994 mXdgToplevel = NULL;
995 }
996
997 if (mXdgSurface) {
998 xdg_surface_destroy (mXdgSurface);
999 mXdgSurface = NULL;
1000 }
1001
1002 if (mVideoSurfaceWrapper) {
1003 wl_proxy_wrapper_destroy (mVideoSurfaceWrapper);
1004 mVideoSurfaceWrapper = NULL;
1005 }
1006
1007 if (mVideoSubSurface) {
1008 wl_subsurface_destroy (mVideoSubSurface);
1009 mVideoSubSurface = NULL;
1010 }
1011
1012 if (mVideoSurface) {
1013 wl_surface_destroy (mVideoSurface);
1014 mVideoSurface = NULL;
1015 }
1016
1017 if (mAreaSurfaceWrapper) {
1018 wl_proxy_wrapper_destroy (mAreaSurfaceWrapper);
1019 mAreaSurfaceWrapper = NULL;
1020 }
1021
1022 if (mAreaSurface) {
1023 wl_surface_destroy (mAreaSurface);
1024 mAreaSurface = NULL;
1025 mReCommitAreaSurface = false;
1026 }
1027}
1028
1029void WaylandDisplay::ensureFullscreen(bool fullscreen)
1030{
1031 if (mXdgWmBase) {
fei.dengb9a1a572023-09-13 01:33:57 +00001032 DEBUG(mLogCategory,"full screen : %d",fullscreen);
fei.dengf7a0cd32023-08-29 09:36:37 +00001033 if (fullscreen) {
fei.deng26950832023-11-09 03:00:23 +00001034 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +00001035 } else {
1036 xdg_toplevel_unset_fullscreen (mXdgToplevel);
1037 }
1038 }
1039}
1040
1041void WaylandDisplay::setRenderRectangle(int x, int y, int w, int h)
1042{
fei.dengb9a1a572023-09-13 01:33:57 +00001043 DEBUG(mLogCategory,"set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001044
1045 if (w <= 0 || h <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +00001046 WARNING(mLogCategory, "wrong render width or height %dx%d",w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001047 return;
1048 }
1049
1050 mRenderRect.x = x;
1051 mRenderRect.y = y;
1052 mRenderRect.w = w;
1053 mRenderRect.h = h;
1054
1055 if (!mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +00001056 WARNING(mLogCategory,"Not configured xdg");
fei.dengf7a0cd32023-08-29 09:36:37 +00001057 return;
1058 }
1059
1060 if (mAreaViewport) {
1061 wp_viewport_set_destination (mAreaViewport, w, h);
1062 }
1063
1064 updateBorders();
1065
1066 if (mVideoWidth != 0 && mVideoSurface) {
1067 wl_subsurface_set_sync (mVideoSubSurface);
1068 resizeVideoSurface(true);
1069 }
1070
1071 wl_surface_damage (mAreaSurfaceWrapper, 0, 0, w, h);
1072 wl_surface_commit (mAreaSurfaceWrapper);
1073
1074 if (mVideoWidth != 0) {
1075 wl_subsurface_set_desync (mVideoSubSurface);
1076 }
1077}
1078
1079
1080void WaylandDisplay::setFrameSize(int w, int h)
1081{
1082 mVideoWidth = w;
1083 mVideoHeight = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001084 TRACE(mLogCategory,"frame w:%d,h:%d",mVideoWidth,mVideoHeight);
fei.dengf7a0cd32023-08-29 09:36:37 +00001085 if (mRenderRect.w > 0 && mVideoSurface) {
1086 resizeVideoSurface(true);
1087 }
1088}
1089
1090void WaylandDisplay::setWindowSize(int x, int y, int w, int h)
1091{
1092 mWindowRect.x = x;
1093 mWindowRect.y = y;
1094 mWindowRect.w = w;
1095 mWindowRect.h = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001096 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 +00001097 if (mWindowRect.w > 0 && mVideoWidth > 0 && mVideoSurface) {
1098 //if had full screen, unset it and set window size
1099 if (mFullScreen) {
1100 mFullScreen = false;
1101 ensureFullscreen(mFullScreen);
1102 }
1103 resizeVideoSurface(true);
1104 }
1105}
1106
1107
1108void WaylandDisplay::resizeVideoSurface(bool commit)
1109{
1110 Rectangle src = {0,};
1111 Rectangle dst = {0,};
1112 Rectangle res;
1113
1114 /* center the video_subsurface inside area_subsurface */
1115 src.w = mVideoWidth;
1116 src.h = mVideoHeight;
1117 /*if had set the window size, we will scall
1118 video surface to this window size*/
1119 if (mWindowRect.w > 0 && mWindowRect.h > 0) {
1120 dst.x = mWindowRect.x;
1121 dst.y = mWindowRect.y;
1122 dst.w = mWindowRect.w;
1123 dst.h = mWindowRect.h;
1124 if (mWindowRect.w > mRenderRect.w && mWindowRect.h > mRenderRect.h) {
fei.dengb9a1a572023-09-13 01:33:57 +00001125 WARNING(mLogCategory,"Error window size:%dx%d, but render size:%dx%d,reset to render size",
fei.dengf7a0cd32023-08-29 09:36:37 +00001126 mWindowRect.w,mWindowRect.h,mRenderRect.w,mRenderRect.h);
1127 dst.x = mRenderRect.x;
1128 dst.y = mRenderRect.y;
1129 dst.w = mRenderRect.w;
1130 dst.h = mRenderRect.h;
1131 }
1132 //to do,we need set geometry?
1133 //if (mXdgSurface) {
1134 // xdg_surface_set_window_geometry(mXdgSurface, mWindowRect.x, mWindowRect.y, mWindowRect.w, mWindowRect.h);
1135 //}
1136 } else { //scal video to full screen
1137 dst.w = mRenderRect.w;
1138 dst.h = mRenderRect.h;
1139 }
1140
1141 if (mViewporter) {
1142 videoCenterRect(src, dst, &res, true);
1143 } else {
1144 videoCenterRect(src, dst, &res, false);
1145 }
1146
1147 wl_subsurface_set_position (mVideoSubSurface, res.x, res.y);
1148
1149 if (commit) {
1150 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, res.w, res.h);
1151 wl_surface_commit (mVideoSurfaceWrapper);
1152 }
1153
1154 //top level setting
1155 if (mXdgToplevel) {
1156 struct wl_region *region;
1157
1158 region = wl_compositor_create_region (mCompositor);
1159 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1160 wl_surface_set_input_region (mAreaSurface, region);
1161 wl_region_destroy (region);
1162 }
1163
1164 /* this is saved for use in wl_surface_damage */
1165 mVideoRect.x = res.x;
1166 mVideoRect.y = res.y;
1167 mVideoRect.w = res.w;
1168 mVideoRect.h = res.h;
1169
1170 //to scale video surface to full screen
1171 wp_viewport_set_destination(mVideoViewport, res.w, res.h);
fei.dengb9a1a572023-09-13 01:33:57 +00001172 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 +00001173}
1174
1175void WaylandDisplay::setOpaque()
1176{
1177 struct wl_region *region;
1178
1179 /* Set area opaque */
1180 region = wl_compositor_create_region (mCompositor);
1181 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1182 wl_surface_set_opaque_region (mAreaSurface, region);
1183 wl_region_destroy (region);
1184}
1185
1186int WaylandDisplay::prepareFrameBuffer(RenderBuffer * buf)
1187{
1188 WaylandBuffer *waylandBuf = NULL;
1189 int ret;
1190
1191 waylandBuf = findWaylandBuffer(buf);
1192 if (waylandBuf == NULL) {
fei.dengb9a1a572023-09-13 01:33:57 +00001193 waylandBuf = new WaylandBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001194 waylandBuf->setBufferFormat(mBufferFormat);
1195 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001196 if (ret != NO_ERROR) {
1197 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001198 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1199 goto waylandbuf_fail;
1200 } else {
1201 addWaylandBuffer(buf, waylandBuf);
1202 }
1203 }
fei.dengb9a1a572023-09-13 01:33:57 +00001204 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +00001205waylandbuf_fail:
1206 //delete waylandbuf
1207 delete waylandBuf;
1208 waylandBuf = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +00001209 return ERROR_UNKNOWN;
fei.dengf7a0cd32023-08-29 09:36:37 +00001210}
1211
1212void WaylandDisplay::displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime)
1213{
1214 WaylandBuffer *waylandBuf = NULL;
1215 struct wl_buffer * wlbuffer = NULL;
1216 int ret;
1217
1218 if (!buf) {
fei.dengb9a1a572023-09-13 01:33:57 +00001219 ERROR(mLogCategory,"Error input params, waylandbuffer is null");
fei.dengf7a0cd32023-08-29 09:36:37 +00001220 return;
1221 }
1222
1223 //must commit areasurface first, because weston xdg surface maybe timeout
1224 //this cause video is not display,commit can resume xdg surface
1225 if (!mReCommitAreaSurface) {
1226 mReCommitAreaSurface = true;
1227 wl_surface_commit (mAreaSurface);
1228 }
1229
fei.dengb9a1a572023-09-13 01:33:57 +00001230 TRACE(mLogCategory,"display renderBuffer:%p,PTS:%lld,realtime:%lld",buf, buf->pts, realDisplayTime);
fei.dengf7a0cd32023-08-29 09:36:37 +00001231
1232 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1233 if (buf->dma.width <=0 || buf->dma.height <=0) {
1234 buf->dma.width = mVideoWidth;
1235 buf->dma.height = mVideoHeight;
1236 }
1237 waylandBuf = findWaylandBuffer(buf);
1238 if (waylandBuf) {
1239 waylandBuf->setRenderRealTime(realDisplayTime);
1240 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001241 if (ret != NO_ERROR) {
1242 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001243 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1244 goto waylandbuf_fail;
1245 }
1246 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001247 ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
fei.dengf7a0cd32023-08-29 09:36:37 +00001248 goto waylandbuf_fail;
1249 }
1250 }
1251
1252 if (waylandBuf) {
1253 wlbuffer = waylandBuf->getWlBuffer();
1254 }
fei.deng1cfb2752023-10-26 08:01:25 +00001255 //if no wl_output, drop this buffer
fei.deng26950832023-11-09 03:00:23 +00001256 if (mCurrentDisplayOutput->wlOutput == NULL) {
fei.deng1cfb2752023-10-26 08:01:25 +00001257 TRACE(mLogCategory,"No wl_output");
1258 mWaylandPlugin->handleFrameDropped(buf);
1259 mWaylandPlugin->handleBufferRelease(buf);
1260 return;
1261 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001262 if (wlbuffer) {
fei.dengb9a1a572023-09-13 01:33:57 +00001263 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001264 ++mCommitCnt;
1265 uint32_t hiPts = realDisplayTime >> 32;
1266 uint32_t lowPts = realDisplayTime & 0xFFFFFFFF;
1267 //attach this wl_buffer to weston
fei.dengb9a1a572023-09-13 01:33:57 +00001268 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 +00001269 waylandBuf->attach(mVideoSurfaceWrapper);
1270
1271 if (mIsSendPtsToWeston) {
fei.dengb9a1a572023-09-13 01:33:57 +00001272 TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
fei.dengf7a0cd32023-08-29 09:36:37 +00001273 wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
1274 }
1275
1276 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, mVideoRect.w, mVideoRect.h);
1277 wl_surface_commit (mVideoSurfaceWrapper);
1278 //insert this buffer to committed weston buffer manager
1279 std::pair<int64_t, WaylandBuffer *> item(buf->pts, waylandBuf);
1280 mCommittedBufferMap.insert(item);
1281 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001282 WARNING(mLogCategory,"wlbuffer is NULL");
fei.dengf7a0cd32023-08-29 09:36:37 +00001283 /* clear both video and parent surfaces */
1284 cleanSurface();
1285 }
1286
1287 wl_display_flush (mWlDisplay);
1288
1289 return;
1290waylandbuf_fail:
1291 //notify dropped
1292 mWaylandPlugin->handleFrameDropped(buf);
1293 //notify app release this buf
1294 mWaylandPlugin->handleBufferRelease(buf);
1295 //delete waylandbuf
1296 delete waylandBuf;
1297 waylandBuf = NULL;
1298 return;
1299}
1300
1301void WaylandDisplay::handleBufferReleaseCallback(WaylandBuffer *buf)
1302{
1303 {
fei.dengb9a1a572023-09-13 01:33:57 +00001304 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001305 --mCommitCnt;
1306 //remove buffer if this buffer is ready to release
1307 RenderBuffer *renderBuffer = buf->getRenderBuffer();
1308 auto item = mCommittedBufferMap.find(renderBuffer->pts);
1309 if (item != mCommittedBufferMap.end()) {
1310 mCommittedBufferMap.erase(item);
1311 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001312 WARNING(mLogCategory,"Can't find WaylandBuffer in buffer map");
fei.dengf7a0cd32023-08-29 09:36:37 +00001313 return;
1314 }
1315 }
1316 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001317 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 +00001318 mWaylandPlugin->handleBufferRelease(renderBuffer);
1319}
1320
1321void WaylandDisplay::handleFrameDisplayedCallback(WaylandBuffer *buf)
1322{
1323 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001324 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 +00001325 mWaylandPlugin->handleFrameDisplayed(renderBuffer);
1326}
1327
1328void WaylandDisplay::handleFrameDropedCallback(WaylandBuffer *buf)
1329{
1330 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001331 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 +00001332 mWaylandPlugin->handleFrameDropped(renderBuffer);
1333}
1334
1335
1336void WaylandDisplay::readyToRun()
1337{
1338 mFd = wl_display_get_fd (mWlDisplay);
fei.dengb9a1a572023-09-13 01:33:57 +00001339 if (mPoll) {
1340 mPoll->addFd(mFd);
1341 mPoll->setFdReadable(mFd, true);
1342 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001343}
1344
1345bool WaylandDisplay::threadLoop()
1346{
1347 int ret;
fei.dengf7a0cd32023-08-29 09:36:37 +00001348
1349 while (wl_display_prepare_read_queue (mWlDisplay, mWlQueue) != 0) {
1350 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1351 }
1352
1353 wl_display_flush (mWlDisplay);
1354
1355 /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
1356 so do use -1 to wait for ever*/
fei.dengb9a1a572023-09-13 01:33:57 +00001357 ret = mPoll->wait(-1); //wait for ever
fei.dengf7a0cd32023-08-29 09:36:37 +00001358 if (ret < 0) { //poll error
fei.dengb9a1a572023-09-13 01:33:57 +00001359 WARNING(mLogCategory,"poll error");
fei.dengf7a0cd32023-08-29 09:36:37 +00001360 wl_display_cancel_read(mWlDisplay);
1361 return false;
1362 } else if (ret == 0) { //poll time out
1363 return true; //run loop
1364 }
1365
1366 if (wl_display_read_events (mWlDisplay) == -1) {
1367 goto tag_error;
1368 }
1369
1370 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1371 return true;
1372tag_error:
fei.dengb9a1a572023-09-13 01:33:57 +00001373 ERROR(mLogCategory,"Error communicating with the wayland server");
fei.dengf7a0cd32023-08-29 09:36:37 +00001374 return false;
1375}
1376
1377void WaylandDisplay::videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling)
1378{
1379 //if dst is a small window, we scale video to map window size,don't doing center
1380 if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
1381 result->x = dst.x;
1382 result->y = dst.y;
1383 result->w = dst.w;
1384 result->h = dst.h;
fei.dengb9a1a572023-09-13 01:33:57 +00001385 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 +00001386 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1387 return;
1388 }
1389 if (!scaling) {
1390 result->w = MIN (src.w, dst.w);
1391 result->h = MIN (src.h, dst.h);
1392 result->x = dst.x + (dst.w - result->w) / 2;
1393 result->y = dst.y + (dst.h - result->h) / 2;
1394 } else {
1395 double src_ratio, dst_ratio;
1396
1397 src_ratio = (double) src.w / src.h;
1398 dst_ratio = (double) dst.w / dst.h;
1399
1400 if (src_ratio > dst_ratio) {
1401 result->w = dst.w;
1402 result->h = dst.w / src_ratio;
1403 result->x = dst.x;
1404 result->y = dst.y + (dst.h - result->h) / 2;
1405 } else if (src_ratio < dst_ratio) {
1406 result->w = dst.h * src_ratio;
1407 result->h = dst.h;
1408 result->x = dst.x + (dst.w - result->w) / 2;
1409 result->y = dst.y;
1410 } else {
1411 result->x = dst.x;
1412 result->y = dst.y;
1413 result->w = dst.w;
1414 result->h = dst.h;
1415 }
1416 }
1417
fei.dengb9a1a572023-09-13 01:33:57 +00001418 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 +00001419 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1420}
1421
1422void WaylandDisplay::updateBorders()
1423{
1424 int width,height;
1425
1426 if (mNoBorderUpdate)
1427 return;
1428
1429 if (mViewporter) {
1430 width = height = 1;
1431 mNoBorderUpdate = true;
1432 } else {
1433 width = mRenderRect.w;
1434 height = mRenderRect.h;
1435 }
1436
1437 RenderVideoFormat format = VIDEO_FORMAT_BGRA;
fei.dengb9a1a572023-09-13 01:33:57 +00001438 mAreaShmBuffer = new WaylandShmBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001439 struct wl_buffer *wlbuf = mAreaShmBuffer->constructWlBuffer(width, height, format);
1440 if (wlbuf == NULL) {
1441 delete mAreaShmBuffer;
1442 mAreaShmBuffer = NULL;
1443 }
1444
1445 wl_surface_attach(mAreaSurfaceWrapper, wlbuf, 0, 0);
1446}
1447
1448std::size_t WaylandDisplay::calculateDmaBufferHash(RenderDmaBuffer &dmabuf)
1449{
1450 std::string hashString("");
1451 for (int i = 0; i < dmabuf.planeCnt; i++) {
1452 char hashtmp[1024];
1453 snprintf (hashtmp, 1024, "%d%d%d%d%d%d", dmabuf.width,dmabuf.height,dmabuf.planeCnt,
1454 dmabuf.stride[i],dmabuf.offset[i],dmabuf.fd[i]);
1455 std::string tmp(hashtmp);
1456 hashString += tmp;
1457 }
1458
1459 std::size_t hashval = std::hash<std::string>()(hashString);
fei.dengb9a1a572023-09-13 01:33:57 +00001460 //TRACE(mLogCategory,"hashstr:%s,val:%zu",hashString.c_str(),hashval);
fei.dengf7a0cd32023-08-29 09:36:37 +00001461 return hashval;
1462}
1463
1464void WaylandDisplay::addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf)
1465{
1466 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1467 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1468 std::pair<std::size_t, WaylandBuffer *> item(hashval, waylandbuf);
fei.dengb9a1a572023-09-13 01:33:57 +00001469 //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 +00001470 mWaylandBuffersMap.insert(item);
1471 }
1472
1473 //clean invalid wayland buffer,if video resolution changed
1474 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1475 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1476 if ((waylandbuf->getFrameWidth() != buf->dma.width ||
1477 waylandbuf->getFrameHeight() != buf->dma.height) &&
1478 waylandbuf->isFree()) {
fei.dengb9a1a572023-09-13 01:33:57 +00001479 TRACE(mLogCategory,"delete wayland buffer,width:%d(%d),height:%d(%d)",
fei.dengf7a0cd32023-08-29 09:36:37 +00001480 waylandbuf->getFrameWidth(),buf->dma.width,
1481 waylandbuf->getFrameHeight(),buf->dma.height);
1482 mWaylandBuffersMap.erase(item++);
1483 delete waylandbuf;
1484 } else {
1485 item++;
1486 }
1487 }
fei.dengb9a1a572023-09-13 01:33:57 +00001488 TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
fei.dengf7a0cd32023-08-29 09:36:37 +00001489}
1490
1491WaylandBuffer* WaylandDisplay::findWaylandBuffer(RenderBuffer * buf)
1492{
1493 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1494 auto item = mWaylandBuffersMap.find(hashval);
1495 if (item == mWaylandBuffersMap.end()) {
1496 return NULL;
1497 }
1498
1499 return (WaylandBuffer*) item->second;
1500}
1501
1502void WaylandDisplay::cleanAllWaylandBuffer()
1503{
1504 //free all obtain buff
1505 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1506 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1507 mWaylandBuffersMap.erase(item++);
1508 delete waylandbuf;
1509 }
1510}
1511
1512void WaylandDisplay::flushBuffers()
1513{
fei.dengb9a1a572023-09-13 01:33:57 +00001514 INFO(mLogCategory,"flushBuffers");
1515 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001516 for (auto item = mCommittedBufferMap.begin(); item != mCommittedBufferMap.end(); item++) {
1517 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1518 waylandbuf->forceRedrawing();
1519 handleFrameDisplayedCallback(waylandbuf);
1520 }
1521}
1522
1523void WaylandDisplay::cleanSurface()
1524{
1525 /* clear both video and parent surfaces */
1526 wl_surface_attach (mVideoSurfaceWrapper, NULL, 0, 0);
1527 wl_surface_commit (mVideoSurfaceWrapper);
1528 wl_surface_attach (mAreaSurfaceWrapper, NULL, 0, 0);
1529 wl_surface_commit (mAreaSurfaceWrapper);
1530}