blob: 36f2583427f8c5f6962ce50ffa0d5a8f36fa1486 [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{
fei.dengf1f5fc32023-12-06 06:22:20 +0000151 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
152 DEBUG(self->mLogCategory,"wl_output: %p",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000153 UNUSED_PARAM(data);
154 UNUSED_PARAM(output);
155}
156
157void WaylandDisplay::outputHandleScale( void *data,
158 struct wl_output *output,
159 int32_t scale )
160{
fei.dengf1f5fc32023-12-06 06:22:20 +0000161 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
162 DEBUG(self->mLogCategory,"wl_output: %p scale %d",output, scale);
fei.dengf7a0cd32023-08-29 09:36:37 +0000163 UNUSED_PARAM(data);
164 UNUSED_PARAM(output);
165 UNUSED_PARAM(scale);
166}
167
fei.dengf1f5fc32023-12-06 06:22:20 +0000168void WaylandDisplay::outputHandleCrtcIndex( void *data,
169 struct wl_output *output,
170 int32_t index )
171{
172 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
173 DEBUG(self->mLogCategory,"wl_output: %p crtc index %d",output, index);
174 Tls::Mutex::Autolock _l(self->mMutex);
175 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
176 if (output == self->mOutput[i].wlOutput) {
177 self->mOutput[i].crtcIndex = index;
178 }
179 }
180}
181
fei.dengf7a0cd32023-08-29 09:36:37 +0000182static const struct wl_output_listener outputListener = {
183 WaylandDisplay::outputHandleGeometry,
184 WaylandDisplay::outputHandleMode,
185 WaylandDisplay::outputHandleDone,
fei.dengf1f5fc32023-12-06 06:22:20 +0000186 WaylandDisplay::outputHandleScale,
187 WaylandDisplay::outputHandleCrtcIndex,
fei.dengf7a0cd32023-08-29 09:36:37 +0000188};
189
190void WaylandDisplay::pointerHandleEnter(void *data, struct wl_pointer *pointer,
191 uint32_t serial, struct wl_surface *surface,
192 wl_fixed_t sx, wl_fixed_t sy)
193{
194 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
195
196 if (self->mFullScreen) {
197 wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
198 }
199}
200
201void WaylandDisplay::pointerHandleLeave(void *data, struct wl_pointer *pointer,
202 uint32_t serial, struct wl_surface *surface)
203{
204 UNUSED_PARAM(data);
205 UNUSED_PARAM(pointer);
206 UNUSED_PARAM(serial);
207 UNUSED_PARAM(surface);
208}
209
210void WaylandDisplay::pointerHandleMotion(void *data, struct wl_pointer *pointer,
211 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
212{
213 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
214 int x = wl_fixed_to_int(sx);
215 int y = wl_fixed_to_int(sy);
fei.dengb9a1a572023-09-13 01:33:57 +0000216 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 +0000217}
218
219void WaylandDisplay::pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
220 uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
221{
222 UNUSED_PARAM(data);
223 UNUSED_PARAM(wl_pointer);
224 UNUSED_PARAM(time);
225 UNUSED_PARAM(serial);
226 UNUSED_PARAM(button);
227 UNUSED_PARAM(state);
228}
229
230void WaylandDisplay::pointerHandleAxis(void *data, struct wl_pointer *wl_pointer,
231 uint32_t time, uint32_t axis, wl_fixed_t value)
232{
233 UNUSED_PARAM(data);
234 UNUSED_PARAM(wl_pointer);
235 UNUSED_PARAM(time);
236 UNUSED_PARAM(axis);
237 UNUSED_PARAM(value);
238}
239
240static const struct wl_pointer_listener pointer_listener = {
241 WaylandDisplay::pointerHandleEnter,
242 WaylandDisplay::pointerHandleLeave,
243 WaylandDisplay::pointerHandleMotion,
244 WaylandDisplay::pointerHandleButton,
245 WaylandDisplay::pointerHandleAxis,
246};
247
248void WaylandDisplay::touchHandleDown(void *data, struct wl_touch *wl_touch,
249 uint32_t serial, uint32_t time, struct wl_surface *surface,
250 int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
251{
252 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
253}
254
255void WaylandDisplay::touchHandleUp(void *data, struct wl_touch *wl_touch,
256 uint32_t serial, uint32_t time, int32_t id)
257{
258 UNUSED_PARAM(data);
259 UNUSED_PARAM(wl_touch);
260 UNUSED_PARAM(serial);
261 UNUSED_PARAM(time);
262 UNUSED_PARAM(id);
263}
264
265void WaylandDisplay::touchHandleMotion(void *data, struct wl_touch *wl_touch,
266 uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
267{
268 UNUSED_PARAM(data);
269 UNUSED_PARAM(wl_touch);
270 UNUSED_PARAM(time);
271 UNUSED_PARAM(id);
272 UNUSED_PARAM(x_w);
273 UNUSED_PARAM(y_w);
274}
275
276void WaylandDisplay::touchHandleFrame(void *data, struct wl_touch *wl_touch)
277{
278 UNUSED_PARAM(data);
279 UNUSED_PARAM(wl_touch);
280}
281
282void WaylandDisplay::touchHandleCancel(void *data, struct wl_touch *wl_touch)
283{
284 UNUSED_PARAM(data);
285 UNUSED_PARAM(wl_touch);
286}
287
288static const struct wl_touch_listener touch_listener = {
289 WaylandDisplay::touchHandleDown,
290 WaylandDisplay::touchHandleUp,
291 WaylandDisplay::touchHandleMotion,
292 WaylandDisplay::touchHandleFrame,
293 WaylandDisplay::touchHandleCancel,
294};
295
296void WaylandDisplay::keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard,
297 uint32_t format, int fd, uint32_t size)
298{
299 UNUSED_PARAM(data);
300 UNUSED_PARAM(keyboard);
301 UNUSED_PARAM(format);
302 UNUSED_PARAM(fd);
303 UNUSED_PARAM(size);
304}
305
306void WaylandDisplay::keyboardHandleEnter(void *data, struct wl_keyboard *keyboard,
307 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
308{
309 UNUSED_PARAM(data);
310 UNUSED_PARAM(keyboard);
311 UNUSED_PARAM(serial);
312 UNUSED_PARAM(surface);
313 UNUSED_PARAM(keys);
314}
315
316void WaylandDisplay::keyboardHandleLeave(void *data, struct wl_keyboard *keyboard,
317 uint32_t serial, struct wl_surface *surface)
318{
319 UNUSED_PARAM(data);
320 UNUSED_PARAM(keyboard);
321 UNUSED_PARAM(serial);
322 UNUSED_PARAM(surface);
323}
324
325void WaylandDisplay::keyboardHandleKey(void *data, struct wl_keyboard *keyboard,
326 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
327{
328 UNUSED_PARAM(data);
329 UNUSED_PARAM(keyboard);
330 UNUSED_PARAM(serial);
331 UNUSED_PARAM(time);
332 UNUSED_PARAM(key);
333 UNUSED_PARAM(state);
334}
335
336void WaylandDisplay::keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard,
337 uint32_t serial, uint32_t mods_depressed,
338 uint32_t mods_latched, uint32_t mods_locked,
339 uint32_t group)
340{
341 UNUSED_PARAM(data);
342 UNUSED_PARAM(keyboard);
343 UNUSED_PARAM(serial);
344 UNUSED_PARAM(mods_depressed);
345 UNUSED_PARAM(mods_latched);
346 UNUSED_PARAM(mods_locked);
347 UNUSED_PARAM(group);
348}
349
350static const struct wl_keyboard_listener keyboard_listener = {
351 WaylandDisplay::keyboardHandleKeymap,
352 WaylandDisplay::keyboardHandleEnter,
353 WaylandDisplay::keyboardHandleLeave,
354 WaylandDisplay::keyboardHandleKey,
355 WaylandDisplay::keyboardHandleModifiers,
356};
357
358void WaylandDisplay::seatHandleCapabilities(void *data, struct wl_seat *seat,
359 uint32_t caps)
360{
361 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
362 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !self->mPointer) {
363 self->mPointer = wl_seat_get_pointer(seat);
364 wl_pointer_add_listener(self->mPointer, &pointer_listener, data);
365 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && self->mPointer) {
366 wl_pointer_destroy(self->mPointer);
367 self->mPointer = NULL;
368 }
369
370 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !self->mKeyboard) {
371 self->mKeyboard = wl_seat_get_keyboard(seat);
372 wl_keyboard_add_listener(self->mKeyboard, &keyboard_listener, data);
373 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && self->mKeyboard) {
374 wl_keyboard_destroy(self->mKeyboard);
375 self->mKeyboard = NULL;
376 }
377
378 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !self->mTouch) {
379 self->mTouch = wl_seat_get_touch(seat);
380 wl_touch_set_user_data(self->mTouch, data);
381 wl_touch_add_listener(self->mTouch, &touch_listener, data);
382 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && self->mTouch) {
383 wl_touch_destroy(self->mTouch);
384 self->mTouch = NULL;
385 }
386}
387
388static const struct wl_seat_listener seat_listener = {
389 WaylandDisplay::seatHandleCapabilities,
390};
391
392
393void WaylandDisplay::handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel)
394{
395 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
396
fei.dengb9a1a572023-09-13 01:33:57 +0000397 INFO(self->mLogCategory,"XDG toplevel got a close event.");
fei.dengf7a0cd32023-08-29 09:36:37 +0000398}
399
400void WaylandDisplay::handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
401 int32_t width, int32_t height, struct wl_array *states)
402{
403 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
404 uint32_t *state;
405
fei.dengb9a1a572023-09-13 01:33:57 +0000406 INFO(self->mLogCategory, "XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000407 /*
408 wl_array_for_each (state, states) {
409 switch (*state) {
410 case XDG_TOPLEVEL_STATE_FULLSCREEN:
411 case XDG_TOPLEVEL_STATE_MAXIMIZED:
412 case XDG_TOPLEVEL_STATE_RESIZING:
413 case XDG_TOPLEVEL_STATE_ACTIVATED:
414 break;
415 }
416 }
417 */
418
419 if (width <= 0 || height <= 0)
420 return;
421
fei.deng26950832023-11-09 03:00:23 +0000422 if (width == self->mCurrentDisplayOutput->width && height == self->mCurrentDisplayOutput->height && self->mUpdateRenderRectangle) {
423 self->mUpdateRenderRectangle = false;
424 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
425 self->mCurrentDisplayOutput->offsetY,
426 self->mCurrentDisplayOutput->width,
427 self->mCurrentDisplayOutput->height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000428 } else{
429 self->setRenderRectangle(self->mRenderRect.x, self->mRenderRect.y, width, height);
430 }
431}
432
433static const struct xdg_toplevel_listener xdg_toplevel_listener = {
434 WaylandDisplay::handleXdgToplevelConfigure,
435 WaylandDisplay::handleXdgToplevelClose,
436};
437
438void WaylandDisplay::handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface,
439 uint32_t serial)
440{
441 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
442 xdg_surface_ack_configure (xdg_surface, serial);
443
fei.dengb9a1a572023-09-13 01:33:57 +0000444 TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
445 Tls::Mutex::Autolock _l(self->mConfigureMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000446 self->mXdgSurfaceConfigured = true;
fei.deng26950832023-11-09 03:00:23 +0000447 self->updateDisplayOutput();
fei.dengf7a0cd32023-08-29 09:36:37 +0000448}
449
450static const struct xdg_surface_listener xdg_surface_listener = {
451 WaylandDisplay::handleXdgSurfaceConfigure,
452};
453
454void
455WaylandDisplay::registryHandleGlobal (void *data, struct wl_registry *registry,
fei.dengaf9b07d2023-10-10 07:38:40 +0000456 uint32_t name, const char *interface, uint32_t version)
fei.dengf7a0cd32023-08-29 09:36:37 +0000457{
458 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000459 TRACE(self->mLogCategory,"registryHandleGlobal,name:%u,interface:%s,version:%d",name,interface,version);
fei.dengf7a0cd32023-08-29 09:36:37 +0000460
461 if (strcmp (interface, "wl_compositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000462 self->mCompositor = (struct wl_compositor *)wl_registry_bind (registry, name, &wl_compositor_interface, 1/*MIN (version, 3)*/);
fei.dengf7a0cd32023-08-29 09:36:37 +0000463 } else if (strcmp (interface, "wl_subcompositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000464 self->mSubCompositor = (struct wl_subcompositor *)wl_registry_bind (registry, name, &wl_subcompositor_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000465 } else if (strcmp (interface, "xdg_wm_base") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000466 self->mXdgWmBase = (struct xdg_wm_base *)wl_registry_bind (registry, name, &xdg_wm_base_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000467 xdg_wm_base_add_listener (self->mXdgWmBase, &xdg_wm_base_listener, (void *)self);
468 } else if (strcmp (interface, "wl_shm") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000469 self->mShm = (struct wl_shm *)wl_registry_bind (registry, name, &wl_shm_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000470 wl_shm_add_listener (self->mShm, &shm_listener, self);
471 } else if (strcmp (interface, "zwp_fullscreen_shell_v1") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000472 //self->mFullscreenShell = (struct zwp_fullscreen_shell_v1 *)wl_registry_bind (registry, name,
fei.dengf7a0cd32023-08-29 09:36:37 +0000473 // &zwp_fullscreen_shell_v1_interface, 1);
474 } else if (strcmp (interface, "wp_viewporter") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000475 self->mViewporter = (struct wp_viewporter *)wl_registry_bind (registry, name, &wp_viewporter_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000476 } else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0) {
477 if (version < 3)
478 return;
fei.dengaf9b07d2023-10-10 07:38:40 +0000479 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 +0000480 zwp_linux_dmabuf_v1_add_listener (self->mDmabuf, &dmabuf_listener, (void *)self);
481 } else if (strcmp (interface, "wl_output") == 0) {
fei.deng26950832023-11-09 03:00:23 +0000482 int i = 0;
483 uint32_t oriName = self->mCurrentDisplayOutput->name;
fei.dengaf9b07d2023-10-10 07:38:40 +0000484 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
485 if (self->mOutput[i].wlOutput == NULL) {
486 self->mOutput[i].name = name;
487 self->mOutput[i].wlOutput = (struct wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version);
fei.deng26950832023-11-09 03:00:23 +0000488 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 +0000489 wl_output_add_listener(self->mOutput[i].wlOutput, &outputListener, (void *)self);
490 if (i == 0) { //primary wl_output
491 self->mOutput[i].isPrimary = true;
492 }
fei.deng26950832023-11-09 03:00:23 +0000493 break;
fei.dengaf9b07d2023-10-10 07:38:40 +0000494 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000495 }
fei.deng26950832023-11-09 03:00:23 +0000496 if (i == DEFAULT_DISPLAY_OUTPUT_NUM) {
497 WARNING(self->mLogCategory,"Not enough free output");
498 }
499 //select current wl_output
500 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX && !self->isRunning()) {
501 TRACE(self->mLogCategory,"select %d output",self->mSelectOutputIndex);
502 self->mCurrentDisplayOutput = &self->mOutput[self->mSelectOutputIndex];
503 }
504 //if user select a wrong output index, we using a suiteble wl_output
505 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
506 WARNING(self->mLogCategory,"wl_output is null,we should find a suiteble output");
507 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
508 if (self->mOutput[i].wlOutput) {
509 self->mCurrentDisplayOutput = &self->mOutput[i];
510 break;
511 }
512 }
513 }
514 //if current wl_output update, we should update render rectangle
515 if (self->mCurrentDisplayOutput->name != oriName) {
516 self->mUpdateRenderRectangle = true;
517 }
518 //if wl_output plugin,active sending frame
519 self->setRedrawingPending(false);
fei.dengf7a0cd32023-08-29 09:36:37 +0000520 } else if (strcmp(interface, "wl_seat") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000521 //self->mSeat = (struct wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000522 //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
fei.deng31f93f12024-02-27 07:52:10 +0000523 } else if (strcmp(interface, "weston_direct_display_v1") == 0) {
524 self->mDirect_display = (struct weston_direct_display_v1 *)wl_registry_bind(registry,name, &weston_direct_display_v1_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000525 }
526}
527
528void
529WaylandDisplay::registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name)
530{
fei.deng26950832023-11-09 03:00:23 +0000531 int i;
fei.dengf7a0cd32023-08-29 09:36:37 +0000532 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000533 /* check wl_output changed */
534 DEBUG(self->mLogCategory,"wayland display remove registry handle global,name:%u",name);
fei.deng26950832023-11-09 03:00:23 +0000535 //if user selected wl_output removed, reset selected output index
536 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX &&
537 self->mOutput[self->mSelectOutputIndex].wlOutput &&
538 self->mOutput[self->mSelectOutputIndex].name == name) {
539 self->mSelectOutputIndex = INVALID_OUTPUT_INDEX;
540 }
541 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000542 if (self->mOutput[i].name == name) {
fei.deng26950832023-11-09 03:00:23 +0000543 DEBUG(self->mLogCategory,"remove wl_output name:%u,wl_output:%p",name,self->mOutput[i].wlOutput);
fei.dengaf9b07d2023-10-10 07:38:40 +0000544 self->mOutput[i].name = 0;
545 self->mOutput[i].wlOutput = NULL;
fei.deng26950832023-11-09 03:00:23 +0000546 }
547 }
548 //if current output removed, select a suiteble output
549 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
550 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
551 if (self->mOutput[i].wlOutput) {
552 self->mCurrentDisplayOutput = &self->mOutput[i];
553 self->mUpdateRenderRectangle = true;
554 }
555 }
556 //set new output rectangle
557 if (self->mUpdateRenderRectangle) {
558 self->mUpdateRenderRectangle = false;
559 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
560 self->mCurrentDisplayOutput->offsetY,
561 self->mCurrentDisplayOutput->width,
562 self->mCurrentDisplayOutput->height);
fei.dengaf9b07d2023-10-10 07:38:40 +0000563 }
564 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000565}
566
567static const struct wl_registry_listener registry_listener = {
568 WaylandDisplay::registryHandleGlobal,
569 WaylandDisplay::registryHandleGlobalRemove
570};
571
fei.dengb9a1a572023-09-13 01:33:57 +0000572WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin, int logCategory)
573 :mBufferMutex("bufferMutex"),
574 mWaylandPlugin(plugin),
575 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +0000576{
fei.dengb9a1a572023-09-13 01:33:57 +0000577 TRACE(mLogCategory,"construct WaylandDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000578 mWlDisplay = NULL;
579 mWlDisplayWrapper = NULL;
580 mWlQueue = NULL;
581 mRegistry = NULL;
582 mCompositor = NULL;
583 mXdgWmBase = NULL;
584 mViewporter = NULL;
585 mDmabuf = NULL;
586 mShm = NULL;
587 mSeat = NULL;
588 mPointer = NULL;
589 mTouch = NULL;
590 mKeyboard = NULL;
fei.deng31f93f12024-02-27 07:52:10 +0000591 mDirect_display = NULL;
fei.deng26950832023-11-09 03:00:23 +0000592 mSelectOutputIndex = INVALID_OUTPUT_INDEX;
fei.dengb9a1a572023-09-13 01:33:57 +0000593 mPoll = new Tls::Poll(true);
fei.dengf7a0cd32023-08-29 09:36:37 +0000594 //window
595 mVideoWidth = 0;
596 mVideoHeight = 0;
597 mVideoSurface = NULL;
598 mXdgSurface = NULL;
599 mXdgToplevel = NULL;
600 mAreaViewport = NULL;
601 mVideoViewport = NULL;
602 mNoBorderUpdate = false;
603 mAreaShmBuffer = NULL;
604 mCommitCnt = 0;
605 mIsSendPtsToWeston = false;
606 mReCommitAreaSurface = false;
607 mAreaSurface = NULL;
608 mAreaSurfaceWrapper = NULL;
609 mVideoSurfaceWrapper = NULL;
610 mVideoSubSurface = NULL;
611 mXdgSurfaceConfigured = false;
612 mPip = 0;
613 mIsSendVideoPlaneId = true;
fei.deng26950832023-11-09 03:00:23 +0000614 mCurrentDisplayOutput = &mOutput[0];
615 mUpdateRenderRectangle = false;
fei.dengf7a0cd32023-08-29 09:36:37 +0000616 memset(&mRenderRect, 0, sizeof(struct Rectangle));
617 memset(&mVideoRect, 0, sizeof(struct Rectangle));
618 memset(&mWindowRect, 0, sizeof(struct Rectangle));
619 mFullScreen = true; //default is full screen
620 char *env = getenv("VIDEO_RENDER_SEND_PTS_TO_WESTON");
621 if (env) {
622 int isSet = atoi(env);
623 if (isSet > 0) {
624 mIsSendPtsToWeston = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000625 INFO(mLogCategory,"set send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000626 } else {
627 mIsSendPtsToWeston = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000628 INFO(mLogCategory,"do not send pts to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000629 }
630 }
631 env = getenv("VIDEO_RENDER_SEND_VIDEO_PLANE_ID_TO_WESTON");
632 if (env) {
633 int isSet = atoi(env);
634 if (isSet == 0) {
635 mIsSendVideoPlaneId = false;
fei.dengb9a1a572023-09-13 01:33:57 +0000636 INFO(mLogCategory,"do not send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000637 } else {
638 mIsSendVideoPlaneId = true;
fei.dengb9a1a572023-09-13 01:33:57 +0000639 INFO(mLogCategory,"send video plane id to weston");
fei.dengf7a0cd32023-08-29 09:36:37 +0000640 }
641 }
642 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
643 mOutput[i].wlOutput = NULL;
644 mOutput[i].offsetX = 0;
645 mOutput[i].offsetY = 0;
646 mOutput[i].width = 0;
647 mOutput[i].height = 0;
648 mOutput[i].refreshRate = 0;
649 mOutput[i].isPrimary = false;
fei.dengaf9b07d2023-10-10 07:38:40 +0000650 mOutput[i].name = 0;
fei.deng75e8d392024-01-04 05:36:14 +0000651 mOutput[i].crtcIndex = 0;
fei.dengf7a0cd32023-08-29 09:36:37 +0000652 }
653}
654
655WaylandDisplay::~WaylandDisplay()
656{
fei.dengb9a1a572023-09-13 01:33:57 +0000657 TRACE(mLogCategory,"desconstruct WaylandDisplay");
658 if (mPoll) {
659 delete mPoll;
660 mPoll = NULL;
661 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000662}
663
664char *WaylandDisplay::require_xdg_runtime_dir()
665{
666 char *val = getenv("XDG_RUNTIME_DIR");
fei.dengb9a1a572023-09-13 01:33:57 +0000667 INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",val);
fei.dengf7a0cd32023-08-29 09:36:37 +0000668
669 return val;
670}
671
672int WaylandDisplay::openDisplay()
673{
674 char *name = require_xdg_runtime_dir();
675 //DEBUG(mLogCategory,"name:%s",name);
fei.dengb9a1a572023-09-13 01:33:57 +0000676 DEBUG(mLogCategory,"openDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000677 mWlDisplay = wl_display_connect(NULL);
678 if (!mWlDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000679 ERROR(mLogCategory,"Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
fei.dengf7a0cd32023-08-29 09:36:37 +0000680 name ? name : "NULL");
fei.dengb9a1a572023-09-13 01:33:57 +0000681 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000682 }
683
684 mWlDisplayWrapper = (struct wl_display *)wl_proxy_create_wrapper ((void *)mWlDisplay);
685 mWlQueue = wl_display_create_queue (mWlDisplay);
686 wl_proxy_set_queue ((struct wl_proxy *)mWlDisplayWrapper, mWlQueue);
687
688 mRegistry = wl_display_get_registry (mWlDisplayWrapper);
689 wl_registry_add_listener (mRegistry, &registry_listener, (void *)this);
690
691 /* we need exactly 2 roundtrips to discover global objects and their state */
692 for (int i = 0; i < 2; i++) {
693 if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000694 ERROR(mLogCategory,"Error communicating with the wayland display");
695 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000696 }
697 }
698
699 if (!mCompositor) {
fei.dengb9a1a572023-09-13 01:33:57 +0000700 ERROR(mLogCategory,"Could not bind to wl_compositor. Either it is not implemented in " \
fei.dengf7a0cd32023-08-29 09:36:37 +0000701 "the compositor, or the implemented version doesn't match");
fei.dengb9a1a572023-09-13 01:33:57 +0000702 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000703 }
704
705 if (!mDmabuf) {
fei.dengb9a1a572023-09-13 01:33:57 +0000706 ERROR(mLogCategory,"Could not bind to zwp_linux_dmabuf_v1");
707 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000708 }
709
710 if (!mXdgWmBase) {
711 /* If wl_surface and wl_display are passed via GstContext
712 * wl_shell, xdg_shell and zwp_fullscreen_shell are not used.
713 * In this case is correct to continue.
714 */
fei.dengb9a1a572023-09-13 01:33:57 +0000715 ERROR(mLogCategory,"Could not bind to either wl_shell, xdg_wm_base or "
fei.dengf7a0cd32023-08-29 09:36:37 +0000716 "zwp_fullscreen_shell, video display may not work properly.");
fei.dengb9a1a572023-09-13 01:33:57 +0000717 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000718 }
719
720 //create window surface
721 createCommonWindowSurface();
722 createXdgShellWindowSurface();
723
724 //config weston video plane
725 if (mIsSendVideoPlaneId) {
fei.dengb9a1a572023-09-13 01:33:57 +0000726 INFO(mLogCategory,"set weston video plane:%d",mPip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000727 wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
728 }
729
730 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000731 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengf7a0cd32023-08-29 09:36:37 +0000732 run("display queue");
733 mRedrawingPending = false;
734
fei.dengb9a1a572023-09-13 01:33:57 +0000735 DEBUG(mLogCategory,"openDisplay out");
736 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000737}
738
739void WaylandDisplay::closeDisplay()
740{
fei.dengb9a1a572023-09-13 01:33:57 +0000741 DEBUG(mLogCategory,"closeDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000742
743 if (isRunning()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000744 TRACE(mLogCategory,"try stop dispatch thread");
745 if (mPoll) {
746 mPoll->setFlushing(true);
747 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000748 requestExitAndWait();
749 }
750
751 //first destroy window surface
752 destroyWindowSurfaces();
753
754 if (mViewporter) {
755 wp_viewporter_destroy (mViewporter);
756 mViewporter = NULL;
757 }
758
759 if (mDmabuf) {
760 zwp_linux_dmabuf_v1_destroy (mDmabuf);
761 mDmabuf = NULL;
762 }
763
764 if (mXdgWmBase) {
765 xdg_wm_base_destroy (mXdgWmBase);
766 mXdgWmBase = NULL;
767 }
768
769 if (mCompositor) {
770 wl_compositor_destroy (mCompositor);
771 mCompositor = NULL;
772 }
773
774 if (mSubCompositor) {
775 wl_subcompositor_destroy (mSubCompositor);
776 mSubCompositor = NULL;
777 }
778
779 if (mRegistry) {
780 wl_registry_destroy (mRegistry);
781 mRegistry= NULL;
782 }
783
784 if (mWlDisplayWrapper) {
785 wl_proxy_wrapper_destroy (mWlDisplayWrapper);
786 mWlDisplayWrapper = NULL;
787 }
788
789 if (mWlQueue) {
790 wl_event_queue_destroy (mWlQueue);
791 mWlQueue = NULL;
792 }
793
794 if (mWlDisplay) {
795 wl_display_flush (mWlDisplay);
796 wl_display_disconnect (mWlDisplay);
797 mWlDisplay = NULL;
798 }
799
fei.dengb9a1a572023-09-13 01:33:57 +0000800 DEBUG(mLogCategory,"closeDisplay out");
fei.dengf7a0cd32023-08-29 09:36:37 +0000801}
802
803int WaylandDisplay::toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/)
804{
805 if (!outDmaformat || !outDmaformatModifiers) {
fei.dengb9a1a572023-09-13 01:33:57 +0000806 WARNING(mLogCategory,"NULL params");
807 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000808 }
809
810 *outDmaformat = 0;
811 *outDmaformatModifiers = 0;
812
813 uint32_t dmaformat = video_format_to_wl_dmabuf_format (format);
814 if (dmaformat == -1) {
fei.dengb9a1a572023-09-13 01:33:57 +0000815 ERROR(mLogCategory,"Error not found render video format:%d to wl dmabuf format",format);
816 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000817 }
818
fei.dengb9a1a572023-09-13 01:33:57 +0000819 TRACE(mLogCategory,"render video format:%d -> dmabuf format:%d",format,dmaformat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000820 *outDmaformat = (uint32_t)dmaformat;
821
822 /*get dmaformat and modifiers*/
823 auto item = mDmaBufferFormats.find(dmaformat);
824 if (item == mDmaBufferFormats.end()) { //not found
fei.dengb9a1a572023-09-13 01:33:57 +0000825 WARNING(mLogCategory,"Not found dmabuf for render video format :%d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000826 *outDmaformatModifiers = 0;
fei.dengb9a1a572023-09-13 01:33:57 +0000827 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000828 }
829
830 *outDmaformatModifiers = (uint64_t)item->second;
831
fei.dengb9a1a572023-09-13 01:33:57 +0000832 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000833}
834
835int WaylandDisplay::toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat)
836{
837 if (!outformat) {
fei.dengb9a1a572023-09-13 01:33:57 +0000838 WARNING(mLogCategory,"NULL params");
839 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000840 }
841
842 *outformat = 0;
843
844 int shmformat = (int)video_format_to_wl_shm_format(format);
845 if (shmformat < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000846 ERROR(mLogCategory,"Error not found render video format:%d to wl shmbuf format",format);
847 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000848 }
849
850 for (auto item = mShmFormats.begin(); item != mShmFormats.end(); ++item) {
851 uint32_t registFormat = (uint32_t)*item;
852 if (registFormat == (uint32_t)shmformat) {
853 *outformat = registFormat;
fei.dengb9a1a572023-09-13 01:33:57 +0000854 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000855 }
856 }
857
fei.dengb9a1a572023-09-13 01:33:57 +0000858 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000859}
860
861void WaylandDisplay::setVideoBufferFormat(RenderVideoFormat format)
862{
fei.dengb9a1a572023-09-13 01:33:57 +0000863 TRACE(mLogCategory,"set video buffer format: %d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000864 mBufferFormat = format;
865};
866
867void WaylandDisplay::setDisplayOutput(int output)
868{
fei.dengb9a1a572023-09-13 01:33:57 +0000869 TRACE(mLogCategory,"select display output: %d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000870 if (output < 0 || output >= DEFAULT_DISPLAY_OUTPUT_NUM) {
fei.dengb9a1a572023-09-13 01:33:57 +0000871 ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000872 return;
873 }
fei.deng26950832023-11-09 03:00:23 +0000874 //only do select output before video playing
875 if (mSelectOutputIndex != output) {
876 mSelectOutputIndex = output;
877 // if (mOutput[output].wlOutput) {
878 // mCurrentDisplayOutput = &mOutput[output];
879 // setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
880 // mOutput[output].width, mOutput[output].height);
881 // }
fei.dengf7a0cd32023-08-29 09:36:37 +0000882 }
883}
884
885int WaylandDisplay::getDisplayOutput()
886{
fei.deng26950832023-11-09 03:00:23 +0000887 return mSelectOutputIndex == INVALID_OUTPUT_INDEX? 0: mSelectOutputIndex;
fei.dengf7a0cd32023-08-29 09:36:37 +0000888}
889
890void WaylandDisplay::setPip(int pip)
891{
fei.dengb9a1a572023-09-13 01:33:57 +0000892 INFO(mLogCategory,"set pip:%d",pip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000893 mPip = pip;
894}
895
fei.deng26950832023-11-09 03:00:23 +0000896void WaylandDisplay::updateDisplayOutput()
897{
898 if (!mCurrentDisplayOutput->wlOutput || !mXdgToplevel || !mXdgSurface)
899 {
900 return;
901 }
902 if (mUpdateRenderRectangle) {
903 if (mFullScreen) {
904 DEBUG(mLogCategory,"unset full screen");
905 xdg_toplevel_unset_fullscreen (mXdgToplevel);
906 }
907
908 if (mXdgSurface) {
909 DEBUG(mLogCategory,"set geometry");
910 xdg_surface_set_window_geometry(mXdgSurface,
911 mCurrentDisplayOutput->offsetX,
912 mCurrentDisplayOutput->offsetY,
913 mCurrentDisplayOutput->width,
914 mCurrentDisplayOutput->height);
915 }
916
917 if (mFullScreen && mXdgToplevel) {
918 DEBUG(mLogCategory,"set full screen");
919 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
920 }
921 setRenderRectangle(mCurrentDisplayOutput->offsetX, mCurrentDisplayOutput->offsetY,
922 mCurrentDisplayOutput->width, mCurrentDisplayOutput->height);
923 mUpdateRenderRectangle = false;
924 }
925}
926
fei.dengf7a0cd32023-08-29 09:36:37 +0000927void WaylandDisplay::createCommonWindowSurface()
928{
929 struct wl_region *region;
930
931 mAreaSurface = wl_compositor_create_surface (mCompositor);
932 mVideoSurface = wl_compositor_create_surface (mCompositor);
933 mAreaSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mAreaSurface);
934 mVideoSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mVideoSurface);
935
936 wl_proxy_set_queue ((struct wl_proxy *) mAreaSurfaceWrapper, mWlQueue);
937 wl_proxy_set_queue ((struct wl_proxy *) mVideoSurfaceWrapper, mWlQueue);
938
939 /* embed video_surface in area_surface */
940 mVideoSubSurface = wl_subcompositor_get_subsurface (mSubCompositor, mVideoSurface, mAreaSurface);
941 wl_subsurface_set_desync (mVideoSubSurface);
942
943 if (mViewporter) {
944 mAreaViewport = wp_viewporter_get_viewport (mViewporter, mAreaSurface);
945 mVideoViewport = wp_viewporter_get_viewport (mViewporter, mVideoSurface);
946 }
947
948 /* do not accept input */
949 region = wl_compositor_create_region (mCompositor);
950 wl_surface_set_input_region (mAreaSurface, region);
951 wl_region_destroy (region);
952
953 region = wl_compositor_create_region (mCompositor);
954 wl_surface_set_input_region (mVideoSurface, region);
955 wl_region_destroy (region);
956}
957
958void WaylandDisplay::createXdgShellWindowSurface()
959{
960 /* Check which protocol we will use (in order of preference) */
961 if (mXdgWmBase) {
962 /* First create the XDG surface */
963 mXdgSurface= xdg_wm_base_get_xdg_surface (mXdgWmBase, mAreaSurface);
964 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000965 ERROR(mLogCategory,"Unable to get xdg_surface");
fei.dengf7a0cd32023-08-29 09:36:37 +0000966 return;
967 }
968 xdg_surface_add_listener (mXdgSurface, &xdg_surface_listener,(void *)this);
969
970 /* Then the toplevel */
971 mXdgToplevel= xdg_surface_get_toplevel (mXdgSurface);
972 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +0000973 ERROR(mLogCategory,"Unable to get xdg_toplevel");
fei.dengf7a0cd32023-08-29 09:36:37 +0000974 return;
975 }
976 xdg_toplevel_add_listener (mXdgToplevel, &xdg_toplevel_listener, this);
977
978 /* Finally, commit the xdg_surface state as toplevel */
979 mXdgSurfaceConfigured = false;
980 wl_surface_commit (mAreaSurface);
981 wl_display_flush (mWlDisplay);
982 /* we need exactly 3 roundtrips to discover global objects and their state */
983 for (int i = 0; i < 3; i++) {
984 if (wl_display_roundtrip_queue(mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000985 ERROR(mLogCategory,"Error communicating with the wayland display");
fei.dengf7a0cd32023-08-29 09:36:37 +0000986 }
987 }
988
989 if (mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +0000990 INFO(mLogCategory,"xdg surface had configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000991 } else {
fei.dengb9a1a572023-09-13 01:33:57 +0000992 WARNING(mLogCategory,"xdg surface not configured");
fei.dengf7a0cd32023-08-29 09:36:37 +0000993 }
994
995 //full screen show
fei.deng26950832023-11-09 03:00:23 +0000996 // if (mFullScreen && mCurrentDisplayOutput->wlOutput) {
997 // //ensureFullscreen(mFullScreen);
fei.dengf7a0cd32023-08-29 09:36:37 +0000998 // }
999 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001000 ERROR(mLogCategory,"Unable to use xdg_wm_base ");
fei.dengf7a0cd32023-08-29 09:36:37 +00001001 return;
1002 }
1003}
1004
1005void WaylandDisplay::destroyWindowSurfaces()
1006{
1007 if (mAreaShmBuffer) {
1008 delete mAreaShmBuffer;
1009 mAreaShmBuffer = NULL;
1010 }
1011
1012 //clean all wayland buffers
1013 cleanAllWaylandBuffer();
1014
1015 if (mXdgToplevel) {
1016 xdg_toplevel_destroy (mXdgToplevel);
1017 mXdgToplevel = NULL;
1018 }
1019
1020 if (mXdgSurface) {
1021 xdg_surface_destroy (mXdgSurface);
1022 mXdgSurface = NULL;
1023 }
1024
1025 if (mVideoSurfaceWrapper) {
1026 wl_proxy_wrapper_destroy (mVideoSurfaceWrapper);
1027 mVideoSurfaceWrapper = NULL;
1028 }
1029
1030 if (mVideoSubSurface) {
1031 wl_subsurface_destroy (mVideoSubSurface);
1032 mVideoSubSurface = NULL;
1033 }
1034
1035 if (mVideoSurface) {
1036 wl_surface_destroy (mVideoSurface);
1037 mVideoSurface = NULL;
1038 }
1039
1040 if (mAreaSurfaceWrapper) {
1041 wl_proxy_wrapper_destroy (mAreaSurfaceWrapper);
1042 mAreaSurfaceWrapper = NULL;
1043 }
1044
1045 if (mAreaSurface) {
1046 wl_surface_destroy (mAreaSurface);
1047 mAreaSurface = NULL;
1048 mReCommitAreaSurface = false;
1049 }
1050}
1051
1052void WaylandDisplay::ensureFullscreen(bool fullscreen)
1053{
1054 if (mXdgWmBase) {
fei.dengb9a1a572023-09-13 01:33:57 +00001055 DEBUG(mLogCategory,"full screen : %d",fullscreen);
fei.dengf7a0cd32023-08-29 09:36:37 +00001056 if (fullscreen) {
fei.deng26950832023-11-09 03:00:23 +00001057 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +00001058 } else {
1059 xdg_toplevel_unset_fullscreen (mXdgToplevel);
1060 }
1061 }
1062}
1063
1064void WaylandDisplay::setRenderRectangle(int x, int y, int w, int h)
1065{
fei.dengb9a1a572023-09-13 01:33:57 +00001066 DEBUG(mLogCategory,"set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001067
1068 if (w <= 0 || h <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +00001069 WARNING(mLogCategory, "wrong render width or height %dx%d",w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001070 return;
1071 }
1072
1073 mRenderRect.x = x;
1074 mRenderRect.y = y;
1075 mRenderRect.w = w;
1076 mRenderRect.h = h;
1077
1078 if (!mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +00001079 WARNING(mLogCategory,"Not configured xdg");
fei.dengf7a0cd32023-08-29 09:36:37 +00001080 return;
1081 }
1082
1083 if (mAreaViewport) {
1084 wp_viewport_set_destination (mAreaViewport, w, h);
1085 }
1086
1087 updateBorders();
1088
1089 if (mVideoWidth != 0 && mVideoSurface) {
1090 wl_subsurface_set_sync (mVideoSubSurface);
1091 resizeVideoSurface(true);
1092 }
1093
1094 wl_surface_damage (mAreaSurfaceWrapper, 0, 0, w, h);
1095 wl_surface_commit (mAreaSurfaceWrapper);
1096
1097 if (mVideoWidth != 0) {
1098 wl_subsurface_set_desync (mVideoSubSurface);
1099 }
1100}
1101
1102
1103void WaylandDisplay::setFrameSize(int w, int h)
1104{
1105 mVideoWidth = w;
1106 mVideoHeight = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001107 TRACE(mLogCategory,"frame w:%d,h:%d",mVideoWidth,mVideoHeight);
fei.dengf7a0cd32023-08-29 09:36:37 +00001108 if (mRenderRect.w > 0 && mVideoSurface) {
1109 resizeVideoSurface(true);
1110 }
1111}
1112
1113void WaylandDisplay::setWindowSize(int x, int y, int w, int h)
1114{
1115 mWindowRect.x = x;
1116 mWindowRect.y = y;
1117 mWindowRect.w = w;
1118 mWindowRect.h = h;
fei.dengb9a1a572023-09-13 01:33:57 +00001119 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 +00001120 if (mWindowRect.w > 0 && mVideoWidth > 0 && mVideoSurface) {
1121 //if had full screen, unset it and set window size
1122 if (mFullScreen) {
1123 mFullScreen = false;
1124 ensureFullscreen(mFullScreen);
1125 }
1126 resizeVideoSurface(true);
1127 }
1128}
1129
1130
1131void WaylandDisplay::resizeVideoSurface(bool commit)
1132{
1133 Rectangle src = {0,};
1134 Rectangle dst = {0,};
1135 Rectangle res;
1136
1137 /* center the video_subsurface inside area_subsurface */
1138 src.w = mVideoWidth;
1139 src.h = mVideoHeight;
1140 /*if had set the window size, we will scall
1141 video surface to this window size*/
1142 if (mWindowRect.w > 0 && mWindowRect.h > 0) {
1143 dst.x = mWindowRect.x;
1144 dst.y = mWindowRect.y;
1145 dst.w = mWindowRect.w;
1146 dst.h = mWindowRect.h;
1147 if (mWindowRect.w > mRenderRect.w && mWindowRect.h > mRenderRect.h) {
fei.dengb9a1a572023-09-13 01:33:57 +00001148 WARNING(mLogCategory,"Error window size:%dx%d, but render size:%dx%d,reset to render size",
fei.dengf7a0cd32023-08-29 09:36:37 +00001149 mWindowRect.w,mWindowRect.h,mRenderRect.w,mRenderRect.h);
1150 dst.x = mRenderRect.x;
1151 dst.y = mRenderRect.y;
1152 dst.w = mRenderRect.w;
1153 dst.h = mRenderRect.h;
1154 }
1155 //to do,we need set geometry?
1156 //if (mXdgSurface) {
1157 // xdg_surface_set_window_geometry(mXdgSurface, mWindowRect.x, mWindowRect.y, mWindowRect.w, mWindowRect.h);
1158 //}
1159 } else { //scal video to full screen
1160 dst.w = mRenderRect.w;
1161 dst.h = mRenderRect.h;
1162 }
1163
1164 if (mViewporter) {
1165 videoCenterRect(src, dst, &res, true);
1166 } else {
1167 videoCenterRect(src, dst, &res, false);
1168 }
1169
1170 wl_subsurface_set_position (mVideoSubSurface, res.x, res.y);
1171
1172 if (commit) {
1173 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, res.w, res.h);
1174 wl_surface_commit (mVideoSurfaceWrapper);
1175 }
1176
1177 //top level setting
1178 if (mXdgToplevel) {
1179 struct wl_region *region;
1180
1181 region = wl_compositor_create_region (mCompositor);
1182 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1183 wl_surface_set_input_region (mAreaSurface, region);
1184 wl_region_destroy (region);
1185 }
1186
1187 /* this is saved for use in wl_surface_damage */
1188 mVideoRect.x = res.x;
1189 mVideoRect.y = res.y;
1190 mVideoRect.w = res.w;
1191 mVideoRect.h = res.h;
1192
1193 //to scale video surface to full screen
1194 wp_viewport_set_destination(mVideoViewport, res.w, res.h);
fei.dengb9a1a572023-09-13 01:33:57 +00001195 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 +00001196}
1197
1198void WaylandDisplay::setOpaque()
1199{
1200 struct wl_region *region;
1201
1202 /* Set area opaque */
1203 region = wl_compositor_create_region (mCompositor);
1204 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1205 wl_surface_set_opaque_region (mAreaSurface, region);
1206 wl_region_destroy (region);
1207}
1208
1209int WaylandDisplay::prepareFrameBuffer(RenderBuffer * buf)
1210{
1211 WaylandBuffer *waylandBuf = NULL;
1212 int ret;
1213
1214 waylandBuf = findWaylandBuffer(buf);
1215 if (waylandBuf == NULL) {
fei.dengb9a1a572023-09-13 01:33:57 +00001216 waylandBuf = new WaylandBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001217 waylandBuf->setBufferFormat(mBufferFormat);
1218 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001219 if (ret != NO_ERROR) {
1220 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001221 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1222 goto waylandbuf_fail;
1223 } else {
1224 addWaylandBuffer(buf, waylandBuf);
1225 }
1226 }
fei.dengb9a1a572023-09-13 01:33:57 +00001227 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +00001228waylandbuf_fail:
1229 //delete waylandbuf
1230 delete waylandBuf;
1231 waylandBuf = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +00001232 return ERROR_UNKNOWN;
fei.dengf7a0cd32023-08-29 09:36:37 +00001233}
1234
1235void WaylandDisplay::displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime)
1236{
1237 WaylandBuffer *waylandBuf = NULL;
1238 struct wl_buffer * wlbuffer = NULL;
1239 int ret;
1240
1241 if (!buf) {
fei.dengb9a1a572023-09-13 01:33:57 +00001242 ERROR(mLogCategory,"Error input params, waylandbuffer is null");
fei.dengf7a0cd32023-08-29 09:36:37 +00001243 return;
1244 }
1245
1246 //must commit areasurface first, because weston xdg surface maybe timeout
1247 //this cause video is not display,commit can resume xdg surface
1248 if (!mReCommitAreaSurface) {
1249 mReCommitAreaSurface = true;
1250 wl_surface_commit (mAreaSurface);
1251 }
1252
fei.dengb9a1a572023-09-13 01:33:57 +00001253 TRACE(mLogCategory,"display renderBuffer:%p,PTS:%lld,realtime:%lld",buf, buf->pts, realDisplayTime);
fei.dengf7a0cd32023-08-29 09:36:37 +00001254
1255 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1256 if (buf->dma.width <=0 || buf->dma.height <=0) {
1257 buf->dma.width = mVideoWidth;
1258 buf->dma.height = mVideoHeight;
1259 }
1260 waylandBuf = findWaylandBuffer(buf);
1261 if (waylandBuf) {
1262 waylandBuf->setRenderRealTime(realDisplayTime);
1263 ret = waylandBuf->constructWlBuffer(buf);
fei.dengb9a1a572023-09-13 01:33:57 +00001264 if (ret != NO_ERROR) {
1265 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
fei.dengf7a0cd32023-08-29 09:36:37 +00001266 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1267 goto waylandbuf_fail;
1268 }
1269 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001270 ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
fei.dengf7a0cd32023-08-29 09:36:37 +00001271 goto waylandbuf_fail;
1272 }
1273 }
1274
1275 if (waylandBuf) {
1276 wlbuffer = waylandBuf->getWlBuffer();
1277 }
fei.deng1cfb2752023-10-26 08:01:25 +00001278 //if no wl_output, drop this buffer
fei.deng26950832023-11-09 03:00:23 +00001279 if (mCurrentDisplayOutput->wlOutput == NULL) {
fei.deng1cfb2752023-10-26 08:01:25 +00001280 TRACE(mLogCategory,"No wl_output");
1281 mWaylandPlugin->handleFrameDropped(buf);
1282 mWaylandPlugin->handleBufferRelease(buf);
1283 return;
1284 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001285 if (wlbuffer) {
fei.dengb9a1a572023-09-13 01:33:57 +00001286 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001287 ++mCommitCnt;
1288 uint32_t hiPts = realDisplayTime >> 32;
1289 uint32_t lowPts = realDisplayTime & 0xFFFFFFFF;
1290 //attach this wl_buffer to weston
fei.dengb9a1a572023-09-13 01:33:57 +00001291 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 +00001292 waylandBuf->attach(mVideoSurfaceWrapper);
1293
1294 if (mIsSendPtsToWeston) {
fei.dengb9a1a572023-09-13 01:33:57 +00001295 TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
fei.dengf7a0cd32023-08-29 09:36:37 +00001296 wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
1297 }
1298
1299 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, mVideoRect.w, mVideoRect.h);
1300 wl_surface_commit (mVideoSurfaceWrapper);
1301 //insert this buffer to committed weston buffer manager
1302 std::pair<int64_t, WaylandBuffer *> item(buf->pts, waylandBuf);
1303 mCommittedBufferMap.insert(item);
1304 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001305 WARNING(mLogCategory,"wlbuffer is NULL");
fei.dengf7a0cd32023-08-29 09:36:37 +00001306 /* clear both video and parent surfaces */
1307 cleanSurface();
1308 }
1309
1310 wl_display_flush (mWlDisplay);
1311
1312 return;
1313waylandbuf_fail:
1314 //notify dropped
1315 mWaylandPlugin->handleFrameDropped(buf);
1316 //notify app release this buf
1317 mWaylandPlugin->handleBufferRelease(buf);
1318 //delete waylandbuf
1319 delete waylandBuf;
1320 waylandBuf = NULL;
1321 return;
1322}
1323
1324void WaylandDisplay::handleBufferReleaseCallback(WaylandBuffer *buf)
1325{
1326 {
fei.dengb9a1a572023-09-13 01:33:57 +00001327 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001328 --mCommitCnt;
1329 //remove buffer if this buffer is ready to release
1330 RenderBuffer *renderBuffer = buf->getRenderBuffer();
1331 auto item = mCommittedBufferMap.find(renderBuffer->pts);
1332 if (item != mCommittedBufferMap.end()) {
1333 mCommittedBufferMap.erase(item);
1334 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001335 WARNING(mLogCategory,"Can't find WaylandBuffer in buffer map");
fei.dengf7a0cd32023-08-29 09:36:37 +00001336 return;
1337 }
1338 }
1339 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001340 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 +00001341 mWaylandPlugin->handleBufferRelease(renderBuffer);
1342}
1343
1344void WaylandDisplay::handleFrameDisplayedCallback(WaylandBuffer *buf)
1345{
1346 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001347 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 +00001348 mWaylandPlugin->handleFrameDisplayed(renderBuffer);
1349}
1350
1351void WaylandDisplay::handleFrameDropedCallback(WaylandBuffer *buf)
1352{
1353 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengb9a1a572023-09-13 01:33:57 +00001354 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 +00001355 mWaylandPlugin->handleFrameDropped(renderBuffer);
1356}
1357
1358
1359void WaylandDisplay::readyToRun()
1360{
1361 mFd = wl_display_get_fd (mWlDisplay);
fei.dengb9a1a572023-09-13 01:33:57 +00001362 if (mPoll) {
1363 mPoll->addFd(mFd);
1364 mPoll->setFdReadable(mFd, true);
1365 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001366}
1367
1368bool WaylandDisplay::threadLoop()
1369{
1370 int ret;
fei.dengf7a0cd32023-08-29 09:36:37 +00001371
1372 while (wl_display_prepare_read_queue (mWlDisplay, mWlQueue) != 0) {
1373 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1374 }
1375
1376 wl_display_flush (mWlDisplay);
1377
1378 /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
1379 so do use -1 to wait for ever*/
fei.dengb9a1a572023-09-13 01:33:57 +00001380 ret = mPoll->wait(-1); //wait for ever
fei.dengf7a0cd32023-08-29 09:36:37 +00001381 if (ret < 0) { //poll error
fei.dengb9a1a572023-09-13 01:33:57 +00001382 WARNING(mLogCategory,"poll error");
fei.dengf7a0cd32023-08-29 09:36:37 +00001383 wl_display_cancel_read(mWlDisplay);
1384 return false;
1385 } else if (ret == 0) { //poll time out
1386 return true; //run loop
1387 }
1388
1389 if (wl_display_read_events (mWlDisplay) == -1) {
1390 goto tag_error;
1391 }
1392
1393 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1394 return true;
1395tag_error:
fei.dengb9a1a572023-09-13 01:33:57 +00001396 ERROR(mLogCategory,"Error communicating with the wayland server");
fei.dengf7a0cd32023-08-29 09:36:37 +00001397 return false;
1398}
1399
1400void WaylandDisplay::videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling)
1401{
1402 //if dst is a small window, we scale video to map window size,don't doing center
1403 if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
1404 result->x = dst.x;
1405 result->y = dst.y;
1406 result->w = dst.w;
1407 result->h = dst.h;
fei.dengb9a1a572023-09-13 01:33:57 +00001408 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 +00001409 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1410 return;
1411 }
1412 if (!scaling) {
1413 result->w = MIN (src.w, dst.w);
1414 result->h = MIN (src.h, dst.h);
1415 result->x = dst.x + (dst.w - result->w) / 2;
1416 result->y = dst.y + (dst.h - result->h) / 2;
1417 } else {
1418 double src_ratio, dst_ratio;
1419
1420 src_ratio = (double) src.w / src.h;
1421 dst_ratio = (double) dst.w / dst.h;
1422
1423 if (src_ratio > dst_ratio) {
1424 result->w = dst.w;
1425 result->h = dst.w / src_ratio;
1426 result->x = dst.x;
1427 result->y = dst.y + (dst.h - result->h) / 2;
1428 } else if (src_ratio < dst_ratio) {
1429 result->w = dst.h * src_ratio;
1430 result->h = dst.h;
1431 result->x = dst.x + (dst.w - result->w) / 2;
1432 result->y = dst.y;
1433 } else {
1434 result->x = dst.x;
1435 result->y = dst.y;
1436 result->w = dst.w;
1437 result->h = dst.h;
1438 }
1439 }
1440
fei.dengb9a1a572023-09-13 01:33:57 +00001441 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 +00001442 src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y);
1443}
1444
1445void WaylandDisplay::updateBorders()
1446{
1447 int width,height;
1448
1449 if (mNoBorderUpdate)
1450 return;
1451
1452 if (mViewporter) {
1453 width = height = 1;
1454 mNoBorderUpdate = true;
1455 } else {
1456 width = mRenderRect.w;
1457 height = mRenderRect.h;
1458 }
1459
1460 RenderVideoFormat format = VIDEO_FORMAT_BGRA;
fei.dengb9a1a572023-09-13 01:33:57 +00001461 mAreaShmBuffer = new WaylandShmBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001462 struct wl_buffer *wlbuf = mAreaShmBuffer->constructWlBuffer(width, height, format);
1463 if (wlbuf == NULL) {
1464 delete mAreaShmBuffer;
1465 mAreaShmBuffer = NULL;
1466 }
1467
1468 wl_surface_attach(mAreaSurfaceWrapper, wlbuf, 0, 0);
1469}
1470
1471std::size_t WaylandDisplay::calculateDmaBufferHash(RenderDmaBuffer &dmabuf)
1472{
1473 std::string hashString("");
1474 for (int i = 0; i < dmabuf.planeCnt; i++) {
1475 char hashtmp[1024];
1476 snprintf (hashtmp, 1024, "%d%d%d%d%d%d", dmabuf.width,dmabuf.height,dmabuf.planeCnt,
1477 dmabuf.stride[i],dmabuf.offset[i],dmabuf.fd[i]);
1478 std::string tmp(hashtmp);
1479 hashString += tmp;
1480 }
1481
1482 std::size_t hashval = std::hash<std::string>()(hashString);
fei.dengb9a1a572023-09-13 01:33:57 +00001483 //TRACE(mLogCategory,"hashstr:%s,val:%zu",hashString.c_str(),hashval);
fei.dengf7a0cd32023-08-29 09:36:37 +00001484 return hashval;
1485}
1486
1487void WaylandDisplay::addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf)
1488{
1489 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1490 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1491 std::pair<std::size_t, WaylandBuffer *> item(hashval, waylandbuf);
fei.dengb9a1a572023-09-13 01:33:57 +00001492 //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 +00001493 mWaylandBuffersMap.insert(item);
1494 }
1495
1496 //clean invalid wayland buffer,if video resolution changed
1497 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1498 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1499 if ((waylandbuf->getFrameWidth() != buf->dma.width ||
1500 waylandbuf->getFrameHeight() != buf->dma.height) &&
1501 waylandbuf->isFree()) {
fei.dengb9a1a572023-09-13 01:33:57 +00001502 TRACE(mLogCategory,"delete wayland buffer,width:%d(%d),height:%d(%d)",
fei.dengf7a0cd32023-08-29 09:36:37 +00001503 waylandbuf->getFrameWidth(),buf->dma.width,
1504 waylandbuf->getFrameHeight(),buf->dma.height);
1505 mWaylandBuffersMap.erase(item++);
1506 delete waylandbuf;
1507 } else {
1508 item++;
1509 }
1510 }
fei.dengb9a1a572023-09-13 01:33:57 +00001511 TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
fei.dengf7a0cd32023-08-29 09:36:37 +00001512}
1513
1514WaylandBuffer* WaylandDisplay::findWaylandBuffer(RenderBuffer * buf)
1515{
1516 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1517 auto item = mWaylandBuffersMap.find(hashval);
1518 if (item == mWaylandBuffersMap.end()) {
1519 return NULL;
1520 }
1521
1522 return (WaylandBuffer*) item->second;
1523}
1524
1525void WaylandDisplay::cleanAllWaylandBuffer()
1526{
1527 //free all obtain buff
1528 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1529 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1530 mWaylandBuffersMap.erase(item++);
1531 delete waylandbuf;
1532 }
1533}
1534
1535void WaylandDisplay::flushBuffers()
1536{
fei.dengb9a1a572023-09-13 01:33:57 +00001537 INFO(mLogCategory,"flushBuffers");
1538 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001539 for (auto item = mCommittedBufferMap.begin(); item != mCommittedBufferMap.end(); item++) {
1540 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1541 waylandbuf->forceRedrawing();
1542 handleFrameDisplayedCallback(waylandbuf);
1543 }
1544}
1545
1546void WaylandDisplay::cleanSurface()
1547{
1548 /* clear both video and parent surfaces */
1549 wl_surface_attach (mVideoSurfaceWrapper, NULL, 0, 0);
1550 wl_surface_commit (mVideoSurfaceWrapper);
1551 wl_surface_attach (mAreaSurfaceWrapper, NULL, 0, 0);
1552 wl_surface_commit (mAreaSurfaceWrapper);
1553}