blob: fd5fbbf2c7e6cacef344189f1fbc04bb21d15129 [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"
fei.deng649b0e22024-09-03 18:57:13 +080035#define FRAME_FREEZE_THRESHOLD(x) (x*1.67)
36#define DETECT_FRAMERATE_CNT (5)
fei.dengf7a0cd32023-08-29 09:36:37 +000037
38void WaylandDisplay::dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
39 uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
40{
41 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +000042 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +000043 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
fei.dengb9a1a572023-09-13 01:33:57 +000044 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 +000045 uint64_t modifier = ((uint64_t)modifier_hi << 32) | modifier_lo;
46 auto item = self->mDmaBufferFormats.find(format);
47 if (item == self->mDmaBufferFormats.end()) {
48 std::pair<uint32_t ,uint64_t> item(format, modifier);
49 self->mDmaBufferFormats.insert(item);
50 } else { //found format
51 item->second = modifier;
52 }
53 }
54}
55
56void
57WaylandDisplay::dmaBufferFormat (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
58 uint32_t format)
59{
60#if 0
61 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
62
63 if (wl_dmabuf_format_to_video_format (format) != VIDEO_FORMAT_UNKNOWN) {
64 TRACE(mLogCategory,"regist dmabuffer format:%d : %s",format);
65 //self->mDmaBufferFormats.push_back(format);
66 }
67#endif
68 /* XXX: deprecated */
69}
70
71static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
72 WaylandDisplay::dmaBufferFormat,
73 WaylandDisplay::dmabuf_modifiers
74};
75
76static void
77handle_xdg_wm_base_ping (void *user_data, struct xdg_wm_base *xdg_wm_base,
78 uint32_t serial)
79{
80 xdg_wm_base_pong (xdg_wm_base, serial);
81}
82
83static const struct xdg_wm_base_listener xdg_wm_base_listener = {
84 handle_xdg_wm_base_ping
85};
86
87void WaylandDisplay::shmFormat(void *data, struct wl_shm *wl_shm, uint32_t format)
88{
89 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
90 self->mShmFormats.push_back(format);
91}
92
93static const struct wl_shm_listener shm_listener = {
94 WaylandDisplay::shmFormat
95};
96
97void WaylandDisplay::outputHandleGeometry( void *data,
98 struct wl_output *output,
99 int x,
100 int y,
101 int physicalWidth,
102 int physicalHeight,
103 int subPixel,
104 const char *make,
105 const char *model,
106 int transform )
107{
108 UNUSED_PARAM(make);
109 UNUSED_PARAM(model);
110
111 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengb9a1a572023-09-13 01:33:57 +0000112 DEBUG(self->mLogCategory,"wl_output %p x:%d,y:%d,physicalWidth:%d,physicalHeight:%d,subPixel:%d,trans:%d",
113 output,x, y,physicalWidth, physicalHeight,subPixel,transform);
114 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000115 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
116 if (output == self->mOutput[i].wlOutput) {
117 self->mOutput[i].offsetX = x;
118 self->mOutput[i].offsetY = y;
119 }
120 }
121}
122
123void WaylandDisplay::outputHandleMode( void *data,
124 struct wl_output *output,
125 uint32_t flags,
126 int width,
127 int height,
128 int refreshRate )
129{
130 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
131
132 if ( flags & WL_OUTPUT_MODE_CURRENT ) {
fei.dengb9a1a572023-09-13 01:33:57 +0000133 Tls::Mutex::Autolock _l(self->mMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000134 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
135 if (output == self->mOutput[i].wlOutput) {
136 self->mOutput[i].width = width;
137 self->mOutput[i].height = height;
138 self->mOutput[i].refreshRate = refreshRate;
139 }
140 }
fei.deng26950832023-11-09 03:00:23 +0000141
142 DEBUG(self->mLogCategory,"wl_output: %p (%dx%d) refreshrate:%d,select output index %d",output, width, height,refreshRate,self->mSelectOutputIndex);
143 if (self->mCurrentDisplayOutput->width > 0 &&
144 self->mCurrentDisplayOutput->height > 0) {
145 self->updateDisplayOutput();
fei.dengf7a0cd32023-08-29 09:36:37 +0000146 }
147 }
148}
149
150void WaylandDisplay::outputHandleDone( void *data,
151 struct wl_output *output )
152{
fei.dengf1f5fc32023-12-06 06:22:20 +0000153 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
154 DEBUG(self->mLogCategory,"wl_output: %p",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000155 UNUSED_PARAM(data);
156 UNUSED_PARAM(output);
157}
158
159void WaylandDisplay::outputHandleScale( void *data,
160 struct wl_output *output,
161 int32_t scale )
162{
fei.dengf1f5fc32023-12-06 06:22:20 +0000163 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
164 DEBUG(self->mLogCategory,"wl_output: %p scale %d",output, scale);
fei.dengf7a0cd32023-08-29 09:36:37 +0000165 UNUSED_PARAM(data);
166 UNUSED_PARAM(output);
167 UNUSED_PARAM(scale);
168}
169
fei.dengf1f5fc32023-12-06 06:22:20 +0000170void WaylandDisplay::outputHandleCrtcIndex( void *data,
171 struct wl_output *output,
172 int32_t index )
173{
174 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
175 DEBUG(self->mLogCategory,"wl_output: %p crtc index %d",output, index);
176 Tls::Mutex::Autolock _l(self->mMutex);
177 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
178 if (output == self->mOutput[i].wlOutput) {
179 self->mOutput[i].crtcIndex = index;
180 }
181 }
182}
183
fei.deng640c3c92024-04-12 08:31:19 +0000184//aml weston always add crtcIndex in callbacks.
fei.dengf7a0cd32023-08-29 09:36:37 +0000185static const struct wl_output_listener outputListener = {
186 WaylandDisplay::outputHandleGeometry,
187 WaylandDisplay::outputHandleMode,
188 WaylandDisplay::outputHandleDone,
fei.dengf1f5fc32023-12-06 06:22:20 +0000189 WaylandDisplay::outputHandleScale,
190 WaylandDisplay::outputHandleCrtcIndex,
fei.dengf7a0cd32023-08-29 09:36:37 +0000191};
192
193void WaylandDisplay::pointerHandleEnter(void *data, struct wl_pointer *pointer,
194 uint32_t serial, struct wl_surface *surface,
195 wl_fixed_t sx, wl_fixed_t sy)
196{
197 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
198
199 if (self->mFullScreen) {
200 wl_pointer_set_cursor(pointer, serial, NULL, 0, 0);
201 }
202}
203
204void WaylandDisplay::pointerHandleLeave(void *data, struct wl_pointer *pointer,
205 uint32_t serial, struct wl_surface *surface)
206{
207 UNUSED_PARAM(data);
208 UNUSED_PARAM(pointer);
209 UNUSED_PARAM(serial);
210 UNUSED_PARAM(surface);
211}
212
213void WaylandDisplay::pointerHandleMotion(void *data, struct wl_pointer *pointer,
214 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
215{
216 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
217 int x = wl_fixed_to_int(sx);
218 int y = wl_fixed_to_int(sy);
fei.dengb9a1a572023-09-13 01:33:57 +0000219 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 +0000220}
221
222void WaylandDisplay::pointerHandleButton(void *data, struct wl_pointer *wl_pointer,
223 uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
224{
225 UNUSED_PARAM(data);
226 UNUSED_PARAM(wl_pointer);
227 UNUSED_PARAM(time);
228 UNUSED_PARAM(serial);
229 UNUSED_PARAM(button);
230 UNUSED_PARAM(state);
231}
232
233void WaylandDisplay::pointerHandleAxis(void *data, struct wl_pointer *wl_pointer,
234 uint32_t time, uint32_t axis, wl_fixed_t value)
235{
236 UNUSED_PARAM(data);
237 UNUSED_PARAM(wl_pointer);
238 UNUSED_PARAM(time);
239 UNUSED_PARAM(axis);
240 UNUSED_PARAM(value);
241}
242
243static const struct wl_pointer_listener pointer_listener = {
244 WaylandDisplay::pointerHandleEnter,
245 WaylandDisplay::pointerHandleLeave,
246 WaylandDisplay::pointerHandleMotion,
247 WaylandDisplay::pointerHandleButton,
248 WaylandDisplay::pointerHandleAxis,
249};
250
251void WaylandDisplay::touchHandleDown(void *data, struct wl_touch *wl_touch,
252 uint32_t serial, uint32_t time, struct wl_surface *surface,
253 int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
254{
255 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
256}
257
258void WaylandDisplay::touchHandleUp(void *data, struct wl_touch *wl_touch,
259 uint32_t serial, uint32_t time, int32_t id)
260{
261 UNUSED_PARAM(data);
262 UNUSED_PARAM(wl_touch);
263 UNUSED_PARAM(serial);
264 UNUSED_PARAM(time);
265 UNUSED_PARAM(id);
266}
267
268void WaylandDisplay::touchHandleMotion(void *data, struct wl_touch *wl_touch,
269 uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
270{
271 UNUSED_PARAM(data);
272 UNUSED_PARAM(wl_touch);
273 UNUSED_PARAM(time);
274 UNUSED_PARAM(id);
275 UNUSED_PARAM(x_w);
276 UNUSED_PARAM(y_w);
277}
278
279void WaylandDisplay::touchHandleFrame(void *data, struct wl_touch *wl_touch)
280{
281 UNUSED_PARAM(data);
282 UNUSED_PARAM(wl_touch);
283}
284
285void WaylandDisplay::touchHandleCancel(void *data, struct wl_touch *wl_touch)
286{
287 UNUSED_PARAM(data);
288 UNUSED_PARAM(wl_touch);
289}
290
291static const struct wl_touch_listener touch_listener = {
292 WaylandDisplay::touchHandleDown,
293 WaylandDisplay::touchHandleUp,
294 WaylandDisplay::touchHandleMotion,
295 WaylandDisplay::touchHandleFrame,
296 WaylandDisplay::touchHandleCancel,
297};
298
299void WaylandDisplay::keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard,
300 uint32_t format, int fd, uint32_t size)
301{
302 UNUSED_PARAM(data);
303 UNUSED_PARAM(keyboard);
304 UNUSED_PARAM(format);
305 UNUSED_PARAM(fd);
306 UNUSED_PARAM(size);
307}
308
309void WaylandDisplay::keyboardHandleEnter(void *data, struct wl_keyboard *keyboard,
310 uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
311{
312 UNUSED_PARAM(data);
313 UNUSED_PARAM(keyboard);
314 UNUSED_PARAM(serial);
315 UNUSED_PARAM(surface);
316 UNUSED_PARAM(keys);
317}
318
319void WaylandDisplay::keyboardHandleLeave(void *data, struct wl_keyboard *keyboard,
320 uint32_t serial, struct wl_surface *surface)
321{
322 UNUSED_PARAM(data);
323 UNUSED_PARAM(keyboard);
324 UNUSED_PARAM(serial);
325 UNUSED_PARAM(surface);
326}
327
328void WaylandDisplay::keyboardHandleKey(void *data, struct wl_keyboard *keyboard,
329 uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
330{
331 UNUSED_PARAM(data);
332 UNUSED_PARAM(keyboard);
333 UNUSED_PARAM(serial);
334 UNUSED_PARAM(time);
335 UNUSED_PARAM(key);
336 UNUSED_PARAM(state);
337}
338
339void WaylandDisplay::keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard,
340 uint32_t serial, uint32_t mods_depressed,
341 uint32_t mods_latched, uint32_t mods_locked,
342 uint32_t group)
343{
344 UNUSED_PARAM(data);
345 UNUSED_PARAM(keyboard);
346 UNUSED_PARAM(serial);
347 UNUSED_PARAM(mods_depressed);
348 UNUSED_PARAM(mods_latched);
349 UNUSED_PARAM(mods_locked);
350 UNUSED_PARAM(group);
351}
352
353static const struct wl_keyboard_listener keyboard_listener = {
354 WaylandDisplay::keyboardHandleKeymap,
355 WaylandDisplay::keyboardHandleEnter,
356 WaylandDisplay::keyboardHandleLeave,
357 WaylandDisplay::keyboardHandleKey,
358 WaylandDisplay::keyboardHandleModifiers,
359};
360
361void WaylandDisplay::seatHandleCapabilities(void *data, struct wl_seat *seat,
362 uint32_t caps)
363{
364 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
365 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !self->mPointer) {
366 self->mPointer = wl_seat_get_pointer(seat);
367 wl_pointer_add_listener(self->mPointer, &pointer_listener, data);
368 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && self->mPointer) {
369 wl_pointer_destroy(self->mPointer);
370 self->mPointer = NULL;
371 }
372
373 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !self->mKeyboard) {
374 self->mKeyboard = wl_seat_get_keyboard(seat);
375 wl_keyboard_add_listener(self->mKeyboard, &keyboard_listener, data);
376 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && self->mKeyboard) {
377 wl_keyboard_destroy(self->mKeyboard);
378 self->mKeyboard = NULL;
379 }
380
381 if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !self->mTouch) {
382 self->mTouch = wl_seat_get_touch(seat);
383 wl_touch_set_user_data(self->mTouch, data);
384 wl_touch_add_listener(self->mTouch, &touch_listener, data);
385 } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && self->mTouch) {
386 wl_touch_destroy(self->mTouch);
387 self->mTouch = NULL;
388 }
389}
390
391static const struct wl_seat_listener seat_listener = {
392 WaylandDisplay::seatHandleCapabilities,
393};
394
395
396void WaylandDisplay::handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel)
397{
398 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
399
fei.dengb9a1a572023-09-13 01:33:57 +0000400 INFO(self->mLogCategory,"XDG toplevel got a close event.");
fei.dengf7a0cd32023-08-29 09:36:37 +0000401}
402
403void WaylandDisplay::handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel,
404 int32_t width, int32_t height, struct wl_array *states)
405{
406 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
407 uint32_t *state;
408
fei.dengb9a1a572023-09-13 01:33:57 +0000409 INFO(self->mLogCategory, "XDG toplevel got a configure event, width:height [ %d, %d ].", width, height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000410 /*
411 wl_array_for_each (state, states) {
412 switch (*state) {
413 case XDG_TOPLEVEL_STATE_FULLSCREEN:
414 case XDG_TOPLEVEL_STATE_MAXIMIZED:
415 case XDG_TOPLEVEL_STATE_RESIZING:
416 case XDG_TOPLEVEL_STATE_ACTIVATED:
417 break;
418 }
419 }
420 */
421
422 if (width <= 0 || height <= 0)
423 return;
424
fei.deng26950832023-11-09 03:00:23 +0000425 if (width == self->mCurrentDisplayOutput->width && height == self->mCurrentDisplayOutput->height && self->mUpdateRenderRectangle) {
426 self->mUpdateRenderRectangle = false;
427 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
428 self->mCurrentDisplayOutput->offsetY,
429 self->mCurrentDisplayOutput->width,
430 self->mCurrentDisplayOutput->height);
fei.dengf7a0cd32023-08-29 09:36:37 +0000431 } else{
432 self->setRenderRectangle(self->mRenderRect.x, self->mRenderRect.y, width, height);
433 }
434}
435
436static const struct xdg_toplevel_listener xdg_toplevel_listener = {
437 WaylandDisplay::handleXdgToplevelConfigure,
438 WaylandDisplay::handleXdgToplevelClose,
439};
440
441void WaylandDisplay::handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface,
442 uint32_t serial)
443{
444 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
445 xdg_surface_ack_configure (xdg_surface, serial);
446
fei.dengb9a1a572023-09-13 01:33:57 +0000447 TRACE(self->mLogCategory,"handleXdgSurfaceConfigure");
448 Tls::Mutex::Autolock _l(self->mConfigureMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +0000449 self->mXdgSurfaceConfigured = true;
fei.deng26950832023-11-09 03:00:23 +0000450 self->updateDisplayOutput();
fei.dengf7a0cd32023-08-29 09:36:37 +0000451}
452
453static const struct xdg_surface_listener xdg_surface_listener = {
454 WaylandDisplay::handleXdgSurfaceConfigure,
455};
456
fei.dengd0da4e22024-07-04 11:29:13 +0800457void WaylandDisplay::handleSurfaceDestroy(void *data, struct wl_callback *callback, uint32_t time)
458{
459 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
460 INFO(self->mLogCategory,"handle video surface destroy");
461 Tls::Mutex::Autolock _l(self->mMutex);
462 self->mCondition.signal();
463 wl_callback_destroy (callback);
464}
465
466static const struct wl_callback_listener surface_destroy_listener = {
467 WaylandDisplay::handleSurfaceDestroy,
468};
469
fei.deng640c3c92024-04-12 08:31:19 +0000470void WaylandDisplay::amlConfigure(void *data, struct aml_config *config, const char *list) {
471 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
472 TRACE(self->mLogCategory,"aml_config:%s",list);
473 if (list && strlen(list) > 0) {
474 if (strstr(list, "set_video_plane")) {
475 TRACE(self->mLogCategory,"weston enable set_video_plane");
476 self->mAmlConfigAPIList.enableSetVideoPlane = true;
477 }
478 if (strstr(list, "set_pts")) {
479 TRACE(self->mLogCategory,"weston enable set_pts");
480 self->mAmlConfigAPIList.enableSetPts = true;
481 }
482 if (strstr(list, "drop")) {
483 TRACE(self->mLogCategory,"weston enable drop");
484 self->mAmlConfigAPIList.enableDropFrame = true;
485 }
486 if (strstr(list, "keep_last_frame")) {
487 TRACE(self->mLogCategory,"weston enable keep_last_frame");
488 self->mAmlConfigAPIList.enableKeepLastFrame = true;
489 }
fei.dengd0da4e22024-07-04 11:29:13 +0800490 if (strstr(list, "surface_destroy_cb")) {
491 TRACE(self->mLogCategory,"weston enable surface_destroy_cb");
492 self->mAmlConfigAPIList.enableSurfaceDestroyCallback = true;
493 }
fei.deng6c425232024-07-19 16:15:31 +0800494 if (strstr(list, "set_display_rate")) {
495 TRACE(self->mLogCategory,"weston enable set_display_rate");
496 self->mAmlConfigAPIList.enableSetDisplayRate = true;
497 }
fei.deng9bf724e2024-08-01 11:34:52 +0800498 if (strstr(list, "set_surface_invisible")) {
499 TRACE(self->mLogCategory,"weston enable set_surface_invisible");
500 self->mAmlConfigAPIList.enableSetSurfaceInvisible = true;
501 }
fei.deng649b0e22024-09-03 18:57:13 +0800502 if (strstr(list, "display_time")) {
503 TRACE(self->mLogCategory,"weston enable display_time");
504 self->mAmlConfigAPIList.enableDisplayTime = true;
505 }
fei.deng640c3c92024-04-12 08:31:19 +0000506 }
507}
508
509static const struct aml_config_listener aml_config_listener = {
510 WaylandDisplay::amlConfigure,
511};
512
fei.dengf7a0cd32023-08-29 09:36:37 +0000513void
514WaylandDisplay::registryHandleGlobal (void *data, struct wl_registry *registry,
fei.dengaf9b07d2023-10-10 07:38:40 +0000515 uint32_t name, const char *interface, uint32_t version)
fei.dengf7a0cd32023-08-29 09:36:37 +0000516{
517 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000518 TRACE(self->mLogCategory,"registryHandleGlobal,name:%u,interface:%s,version:%d",name,interface,version);
fei.dengf7a0cd32023-08-29 09:36:37 +0000519
520 if (strcmp (interface, "wl_compositor") == 0) {
fei.deng96aa7f72024-09-29 15:46:52 +0800521 self->mCompositor = (struct wl_compositor *)wl_registry_bind (registry, name, &wl_compositor_interface, version);
fei.dengf7a0cd32023-08-29 09:36:37 +0000522 } else if (strcmp (interface, "wl_subcompositor") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000523 self->mSubCompositor = (struct wl_subcompositor *)wl_registry_bind (registry, name, &wl_subcompositor_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000524 } else if (strcmp (interface, "xdg_wm_base") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000525 self->mXdgWmBase = (struct xdg_wm_base *)wl_registry_bind (registry, name, &xdg_wm_base_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000526 xdg_wm_base_add_listener (self->mXdgWmBase, &xdg_wm_base_listener, (void *)self);
527 } else if (strcmp (interface, "wl_shm") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000528 self->mShm = (struct wl_shm *)wl_registry_bind (registry, name, &wl_shm_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000529 wl_shm_add_listener (self->mShm, &shm_listener, self);
530 } else if (strcmp (interface, "zwp_fullscreen_shell_v1") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000531 //self->mFullscreenShell = (struct zwp_fullscreen_shell_v1 *)wl_registry_bind (registry, name,
fei.dengf7a0cd32023-08-29 09:36:37 +0000532 // &zwp_fullscreen_shell_v1_interface, 1);
533 } else if (strcmp (interface, "wp_viewporter") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000534 self->mViewporter = (struct wp_viewporter *)wl_registry_bind (registry, name, &wp_viewporter_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000535 } else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0) {
536 if (version < 3)
537 return;
fei.dengaf9b07d2023-10-10 07:38:40 +0000538 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 +0000539 zwp_linux_dmabuf_v1_add_listener (self->mDmabuf, &dmabuf_listener, (void *)self);
540 } else if (strcmp (interface, "wl_output") == 0) {
fei.deng26950832023-11-09 03:00:23 +0000541 int i = 0;
542 uint32_t oriName = self->mCurrentDisplayOutput->name;
fei.dengaf9b07d2023-10-10 07:38:40 +0000543 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
544 if (self->mOutput[i].wlOutput == NULL) {
545 self->mOutput[i].name = name;
546 self->mOutput[i].wlOutput = (struct wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version);
fei.deng26950832023-11-09 03:00:23 +0000547 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 +0000548 wl_output_add_listener(self->mOutput[i].wlOutput, &outputListener, (void *)self);
549 if (i == 0) { //primary wl_output
550 self->mOutput[i].isPrimary = true;
551 }
fei.deng26950832023-11-09 03:00:23 +0000552 break;
fei.dengaf9b07d2023-10-10 07:38:40 +0000553 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000554 }
fei.deng26950832023-11-09 03:00:23 +0000555 if (i == DEFAULT_DISPLAY_OUTPUT_NUM) {
556 WARNING(self->mLogCategory,"Not enough free output");
557 }
558 //select current wl_output
559 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX && !self->isRunning()) {
560 TRACE(self->mLogCategory,"select %d output",self->mSelectOutputIndex);
561 self->mCurrentDisplayOutput = &self->mOutput[self->mSelectOutputIndex];
562 }
563 //if user select a wrong output index, we using a suiteble wl_output
564 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
565 WARNING(self->mLogCategory,"wl_output is null,we should find a suiteble output");
566 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
567 if (self->mOutput[i].wlOutput) {
568 self->mCurrentDisplayOutput = &self->mOutput[i];
569 break;
570 }
571 }
572 }
573 //if current wl_output update, we should update render rectangle
574 if (self->mCurrentDisplayOutput->name != oriName) {
575 self->mUpdateRenderRectangle = true;
576 }
577 //if wl_output plugin,active sending frame
578 self->setRedrawingPending(false);
fei.dengf7a0cd32023-08-29 09:36:37 +0000579 } else if (strcmp(interface, "wl_seat") == 0) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000580 //self->mSeat = (struct wl_seat *)wl_registry_bind(registry, name, &wl_seat_interface, 1);
fei.dengf7a0cd32023-08-29 09:36:37 +0000581 //wl_seat_add_listener(self->mSeat, &seat_listener, (void *)self);
fei.deng31f93f12024-02-27 07:52:10 +0000582 } else if (strcmp(interface, "weston_direct_display_v1") == 0) {
583 self->mDirect_display = (struct weston_direct_display_v1 *)wl_registry_bind(registry,name, &weston_direct_display_v1_interface, 1);
fei.deng640c3c92024-04-12 08:31:19 +0000584 } else if (strcmp(interface, "aml_config") == 0) {
585 self->mAmlConfig = (struct aml_config*)wl_registry_bind(registry, name, &aml_config_interface, 1);
586 aml_config_add_listener(self->mAmlConfig, &aml_config_listener, (void *)self);
fei.dengf7a0cd32023-08-29 09:36:37 +0000587 }
588}
589
590void
591WaylandDisplay::registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name)
592{
fei.deng26950832023-11-09 03:00:23 +0000593 int i;
fei.dengf7a0cd32023-08-29 09:36:37 +0000594 WaylandDisplay *self = static_cast<WaylandDisplay *>(data);
fei.dengaf9b07d2023-10-10 07:38:40 +0000595 /* check wl_output changed */
596 DEBUG(self->mLogCategory,"wayland display remove registry handle global,name:%u",name);
fei.deng26950832023-11-09 03:00:23 +0000597 //if user selected wl_output removed, reset selected output index
598 if (self->mSelectOutputIndex != INVALID_OUTPUT_INDEX &&
599 self->mOutput[self->mSelectOutputIndex].wlOutput &&
600 self->mOutput[self->mSelectOutputIndex].name == name) {
601 self->mSelectOutputIndex = INVALID_OUTPUT_INDEX;
602 }
603 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
fei.dengaf9b07d2023-10-10 07:38:40 +0000604 if (self->mOutput[i].name == name) {
fei.deng26950832023-11-09 03:00:23 +0000605 DEBUG(self->mLogCategory,"remove wl_output name:%u,wl_output:%p",name,self->mOutput[i].wlOutput);
fei.dengaf9b07d2023-10-10 07:38:40 +0000606 self->mOutput[i].name = 0;
607 self->mOutput[i].wlOutput = NULL;
fei.deng26950832023-11-09 03:00:23 +0000608 }
609 }
610 //if current output removed, select a suiteble output
611 if (self->mCurrentDisplayOutput->wlOutput == NULL) {
612 for (i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
613 if (self->mOutput[i].wlOutput) {
614 self->mCurrentDisplayOutput = &self->mOutput[i];
615 self->mUpdateRenderRectangle = true;
616 }
617 }
618 //set new output rectangle
619 if (self->mUpdateRenderRectangle) {
620 self->mUpdateRenderRectangle = false;
621 self->setRenderRectangle(self->mCurrentDisplayOutput->offsetX,
622 self->mCurrentDisplayOutput->offsetY,
623 self->mCurrentDisplayOutput->width,
624 self->mCurrentDisplayOutput->height);
fei.dengaf9b07d2023-10-10 07:38:40 +0000625 }
626 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000627}
628
629static const struct wl_registry_listener registry_listener = {
630 WaylandDisplay::registryHandleGlobal,
631 WaylandDisplay::registryHandleGlobalRemove
632};
633
fei.dengb9a1a572023-09-13 01:33:57 +0000634WaylandDisplay::WaylandDisplay(WaylandPlugin *plugin, int logCategory)
635 :mBufferMutex("bufferMutex"),
636 mWaylandPlugin(plugin),
637 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +0000638{
fei.dengb9a1a572023-09-13 01:33:57 +0000639 TRACE(mLogCategory,"construct WaylandDisplay");
fei.dengf7a0cd32023-08-29 09:36:37 +0000640 mWlDisplay = NULL;
641 mWlDisplayWrapper = NULL;
642 mWlQueue = NULL;
643 mRegistry = NULL;
644 mCompositor = NULL;
645 mXdgWmBase = NULL;
646 mViewporter = NULL;
647 mDmabuf = NULL;
648 mShm = NULL;
649 mSeat = NULL;
650 mPointer = NULL;
651 mTouch = NULL;
652 mKeyboard = NULL;
fei.deng31f93f12024-02-27 07:52:10 +0000653 mDirect_display = NULL;
fei.deng26950832023-11-09 03:00:23 +0000654 mSelectOutputIndex = INVALID_OUTPUT_INDEX;
fei.dengb9a1a572023-09-13 01:33:57 +0000655 mPoll = new Tls::Poll(true);
fei.dengf7a0cd32023-08-29 09:36:37 +0000656 //window
657 mVideoWidth = 0;
658 mVideoHeight = 0;
659 mVideoSurface = NULL;
660 mXdgSurface = NULL;
661 mXdgToplevel = NULL;
662 mAreaViewport = NULL;
663 mVideoViewport = NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000664 mAreaShmBuffer = NULL;
665 mCommitCnt = 0;
fei.dengf7a0cd32023-08-29 09:36:37 +0000666 mAreaSurface = NULL;
667 mAreaSurfaceWrapper = NULL;
668 mVideoSurfaceWrapper = NULL;
669 mVideoSubSurface = NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000670 mPip = 0;
fei.deng640c3c92024-04-12 08:31:19 +0000671 mKeepLastFrame = 0; //default is off keep last frame
le.hane8c8fdd2024-09-19 09:28:50 +0000672 mKeepFrameOnFlush = 1;
673 mFirstPtsAfterFlush = -1;
fei.deng3287c082024-04-23 09:29:22 +0000674 mSignalFirstFramePts = false;
fei.deng4029e682024-06-26 17:06:31 +0800675 mToSendKeepLastFrame = false;
fei.deng1c94a342024-08-05 19:33:28 +0800676 mVideoPlaneZorder = -1;
677 mVideoPlaneZorderChanged = false;
fei.deng96aa7f72024-09-29 15:46:52 +0800678 mVideoRotateDegree = -1;
fei.dengf7a0cd32023-08-29 09:36:37 +0000679}
680
681WaylandDisplay::~WaylandDisplay()
682{
fei.dengb9a1a572023-09-13 01:33:57 +0000683 TRACE(mLogCategory,"desconstruct WaylandDisplay");
684 if (mPoll) {
685 delete mPoll;
686 mPoll = NULL;
687 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000688}
689
690char *WaylandDisplay::require_xdg_runtime_dir()
691{
692 char *val = getenv("XDG_RUNTIME_DIR");
fei.dengb9a1a572023-09-13 01:33:57 +0000693 INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",val);
fei.dengdd910ef2024-06-07 10:25:30 +0800694 //if not set XDG_RUNTIME_DIR,set default value
695 // if (!val) {
696 // val = const_cast<char *>("/run/user/0");
697 // setenv("XDG_RUNTIME_DIR",val,0);
698 // WARNING(mLogCategory,"XDG_RUNTIME_DIR is not set,set default %s",val);
699 // }
fei.dengf7a0cd32023-08-29 09:36:37 +0000700
701 return val;
702}
703
704int WaylandDisplay::openDisplay()
705{
fei.dengf862f9c2024-10-24 16:46:55 +0800706 frameCallbackTimeUs = 0;
fei.deng649b0e22024-09-03 18:57:13 +0800707 mLastDisplayFramePts = -1;
708 mLastDisplayFrameTimeUs = -1;
709 mFrameDurationUs = 0;
710 mPreFramePts = -1;
711 mFrameRateDetectCnt = 0;
712 mFrameRateDetectPeriod = 0;
fei.denga4abbd52024-07-11 19:17:50 +0800713 mPixelAspectRatio = 1.0;
714 mUpdateVideoSurface = false;
fei.dengdd910ef2024-06-07 10:25:30 +0800715 mNoBorderUpdate = false;
716 mReCommitAreaSurface = false;
717 mXdgSurfaceConfigured = false;
718 mUpdateRenderRectangle = false;
fei.deng6c425232024-07-19 16:15:31 +0800719 mFrameRateFractionNum = 0;
720 mFrameRateFractionDenom = 1;
721 mFrameRateChanged = false;
fei.deng1c94a342024-08-05 19:33:28 +0800722 mVideoPlaneZorder = -1;
723 mVideoPlaneZorderChanged = false;
fei.dengdd910ef2024-06-07 10:25:30 +0800724 memset(&mRenderRect, 0, sizeof(struct Rectangle));
725 memset(&mVideoRect, 0, sizeof(struct Rectangle));
726 memset(&mWindowRect, 0, sizeof(struct Rectangle));
727 mFullScreen = true; //default is full screen
728 mAmlConfig = NULL;
729 //weston config private api
730 mAmlConfigAPIList.enableDropFrame = false;
731 mAmlConfigAPIList.enableKeepLastFrame = false;
732 mAmlConfigAPIList.enableSetPts = false;
733 mAmlConfigAPIList.enableSetVideoPlane = false;
fei.dengd0da4e22024-07-04 11:29:13 +0800734 mAmlConfigAPIList.enableSurfaceDestroyCallback = false;
fei.deng6c425232024-07-19 16:15:31 +0800735 mAmlConfigAPIList.enableSetDisplayRate = false;
fei.deng9bf724e2024-08-01 11:34:52 +0800736 mAmlConfigAPIList.enableSetSurfaceInvisible = false;
fei.deng649b0e22024-09-03 18:57:13 +0800737 mAmlConfigAPIList.enableDisplayTime = false;
fei.dengdd910ef2024-06-07 10:25:30 +0800738 mCurrentDisplayOutput = &mOutput[0];
739 for (int i = 0; i < DEFAULT_DISPLAY_OUTPUT_NUM; i++) {
740 mOutput[i].wlOutput = NULL;
741 mOutput[i].offsetX = 0;
742 mOutput[i].offsetY = 0;
743 mOutput[i].width = 0;
744 mOutput[i].height = 0;
745 mOutput[i].refreshRate = 0;
746 mOutput[i].isPrimary = false;
747 mOutput[i].name = 0;
748 mOutput[i].crtcIndex = 0;
749 }
fei.deng4029e682024-06-26 17:06:31 +0800750 /*if mKeepLastFrame had set but mToSendKeepLastFrame is false,maybe
751 playback is doing FF/FW action,so we keep set it on new connection*/
752 if (!mToSendKeepLastFrame && mKeepLastFrame) {
753 mToSendKeepLastFrame = true;
754 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000755 char *name = require_xdg_runtime_dir();
756 //DEBUG(mLogCategory,"name:%s",name);
fei.dengb9a1a572023-09-13 01:33:57 +0000757 DEBUG(mLogCategory,"openDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000758 mWlDisplay = wl_display_connect(NULL);
759 if (!mWlDisplay) {
fei.dengb9a1a572023-09-13 01:33:57 +0000760 ERROR(mLogCategory,"Failed to connect to the wayland display, XDG_RUNTIME_DIR='%s'",
fei.dengf7a0cd32023-08-29 09:36:37 +0000761 name ? name : "NULL");
fei.dengb9a1a572023-09-13 01:33:57 +0000762 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000763 }
764
765 mWlDisplayWrapper = (struct wl_display *)wl_proxy_create_wrapper ((void *)mWlDisplay);
766 mWlQueue = wl_display_create_queue (mWlDisplay);
767 wl_proxy_set_queue ((struct wl_proxy *)mWlDisplayWrapper, mWlQueue);
768
769 mRegistry = wl_display_get_registry (mWlDisplayWrapper);
770 wl_registry_add_listener (mRegistry, &registry_listener, (void *)this);
771
772 /* we need exactly 2 roundtrips to discover global objects and their state */
773 for (int i = 0; i < 2; i++) {
774 if (wl_display_roundtrip_queue (mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000775 ERROR(mLogCategory,"Error communicating with the wayland display");
776 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000777 }
778 }
779
780 if (!mCompositor) {
fei.dengb9a1a572023-09-13 01:33:57 +0000781 ERROR(mLogCategory,"Could not bind to wl_compositor. Either it is not implemented in " \
fei.dengf7a0cd32023-08-29 09:36:37 +0000782 "the compositor, or the implemented version doesn't match");
fei.dengb9a1a572023-09-13 01:33:57 +0000783 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000784 }
785
786 if (!mDmabuf) {
fei.dengb9a1a572023-09-13 01:33:57 +0000787 ERROR(mLogCategory,"Could not bind to zwp_linux_dmabuf_v1");
788 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000789 }
790
791 if (!mXdgWmBase) {
792 /* If wl_surface and wl_display are passed via GstContext
793 * wl_shell, xdg_shell and zwp_fullscreen_shell are not used.
794 * In this case is correct to continue.
795 */
fei.dengb9a1a572023-09-13 01:33:57 +0000796 ERROR(mLogCategory,"Could not bind to either wl_shell, xdg_wm_base or "
fei.dengf7a0cd32023-08-29 09:36:37 +0000797 "zwp_fullscreen_shell, video display may not work properly.");
fei.dengb9a1a572023-09-13 01:33:57 +0000798 return ERROR_OPEN_FAIL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000799 }
800
801 //create window surface
802 createCommonWindowSurface();
803 createXdgShellWindowSurface();
804
805 //config weston video plane
fei.deng640c3c92024-04-12 08:31:19 +0000806 if (mAmlConfigAPIList.enableSetVideoPlane) {
fei.dengb9a1a572023-09-13 01:33:57 +0000807 INFO(mLogCategory,"set weston video plane:%d",mPip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000808 wl_surface_set_video_plane(mVideoSurfaceWrapper, mPip);
809 }
810
811 //run wl display queue dispatch
fei.dengb9a1a572023-09-13 01:33:57 +0000812 DEBUG(mLogCategory,"To run wl display dispatch queue");
fei.dengdd910ef2024-06-07 10:25:30 +0800813 if (mPoll) {
814 mPoll->setFlushing(false);
815 }
fei.dengf862f9c2024-10-24 16:46:55 +0800816 setThreadPriority(60);
817 run("waylandProtocolThread");
fei.dengf7a0cd32023-08-29 09:36:37 +0000818 mRedrawingPending = false;
le.hane8c8fdd2024-09-19 09:28:50 +0000819 wl_surface_set_video_plane_mute(mVideoSurfaceWrapper, 0);
fei.dengf7a0cd32023-08-29 09:36:37 +0000820
fei.dengb9a1a572023-09-13 01:33:57 +0000821 DEBUG(mLogCategory,"openDisplay out");
822 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000823}
824
825void WaylandDisplay::closeDisplay()
826{
fei.dengb9a1a572023-09-13 01:33:57 +0000827 DEBUG(mLogCategory,"closeDisplay in");
fei.dengf7a0cd32023-08-29 09:36:37 +0000828
fei.dengd0da4e22024-07-04 11:29:13 +0800829 //first destroy window surface
830 destroyWindowSurfaces();
fei.dengf7a0cd32023-08-29 09:36:37 +0000831
fei.deng4029e682024-06-26 17:06:31 +0800832 //flush pending event to weston
fei.dengdd910ef2024-06-07 10:25:30 +0800833 if (mWlDisplay) {
834 wl_display_flush (mWlDisplay);
835 }
836
fei.dengd0da4e22024-07-04 11:29:13 +0800837 //wait video surface destroyed or 50ms timeout
838 if (mAmlConfigAPIList.enableSurfaceDestroyCallback) {
839 INFO(mLogCategory,"waiting surface_destroy_cb from weston");
840 Tls::Mutex::Autolock _l(mMutex);
841 if (ERROR_TIMED_OUT == mCondition.waitRelative(mMutex, 50/*microsecond*/)) {
842 WARNING(mLogCategory,"waited surface_destroy_cb timeout");
843 }
844 }
845
846 //we should receive all event from weston before stopped dispatch queue
847 if (isRunning()) {
848 TRACE(mLogCategory,"try stop dispatch thread");
849 if (mPoll) {
850 mPoll->setFlushing(true);
851 }
852 requestExitAndWait();
853 }
854 //after destroyed surface,then destroy buffers,otherwise maybe crash
855 if (mAreaShmBuffer) {
856 delete mAreaShmBuffer;
857 mAreaShmBuffer = NULL;
858 }
859
860 //clean all wayland buffers
861 cleanAllWaylandBuffer();
fei.dengf7a0cd32023-08-29 09:36:37 +0000862
863 if (mViewporter) {
864 wp_viewporter_destroy (mViewporter);
865 mViewporter = NULL;
866 }
867
868 if (mDmabuf) {
869 zwp_linux_dmabuf_v1_destroy (mDmabuf);
870 mDmabuf = NULL;
871 }
872
873 if (mXdgWmBase) {
874 xdg_wm_base_destroy (mXdgWmBase);
875 mXdgWmBase = NULL;
876 }
877
878 if (mCompositor) {
879 wl_compositor_destroy (mCompositor);
880 mCompositor = NULL;
881 }
882
883 if (mSubCompositor) {
884 wl_subcompositor_destroy (mSubCompositor);
885 mSubCompositor = NULL;
886 }
887
888 if (mRegistry) {
889 wl_registry_destroy (mRegistry);
890 mRegistry= NULL;
891 }
892
893 if (mWlDisplayWrapper) {
894 wl_proxy_wrapper_destroy (mWlDisplayWrapper);
895 mWlDisplayWrapper = NULL;
896 }
897
fei.deng640c3c92024-04-12 08:31:19 +0000898 if (mAmlConfig) {
899 aml_config_destroy(mAmlConfig);
900 mAmlConfig = NULL;
901 }
902
fei.dengf7a0cd32023-08-29 09:36:37 +0000903 if (mWlQueue) {
904 wl_event_queue_destroy (mWlQueue);
905 mWlQueue = NULL;
906 }
907
908 if (mWlDisplay) {
909 wl_display_flush (mWlDisplay);
910 wl_display_disconnect (mWlDisplay);
911 mWlDisplay = NULL;
912 }
913
fei.dengb9a1a572023-09-13 01:33:57 +0000914 DEBUG(mLogCategory,"closeDisplay out");
fei.dengf7a0cd32023-08-29 09:36:37 +0000915}
916
917int WaylandDisplay::toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/)
918{
919 if (!outDmaformat || !outDmaformatModifiers) {
fei.dengb9a1a572023-09-13 01:33:57 +0000920 WARNING(mLogCategory,"NULL params");
921 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000922 }
923
924 *outDmaformat = 0;
925 *outDmaformatModifiers = 0;
926
927 uint32_t dmaformat = video_format_to_wl_dmabuf_format (format);
928 if (dmaformat == -1) {
fei.dengb9a1a572023-09-13 01:33:57 +0000929 ERROR(mLogCategory,"Error not found render video format:%d to wl dmabuf format",format);
930 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000931 }
932
fei.dengb9a1a572023-09-13 01:33:57 +0000933 TRACE(mLogCategory,"render video format:%d -> dmabuf format:%d",format,dmaformat);
fei.dengf7a0cd32023-08-29 09:36:37 +0000934 *outDmaformat = (uint32_t)dmaformat;
935
936 /*get dmaformat and modifiers*/
937 auto item = mDmaBufferFormats.find(dmaformat);
938 if (item == mDmaBufferFormats.end()) { //not found
fei.dengb9a1a572023-09-13 01:33:57 +0000939 WARNING(mLogCategory,"Not found dmabuf for render video format :%d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000940 *outDmaformatModifiers = 0;
fei.dengb9a1a572023-09-13 01:33:57 +0000941 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000942 }
943
944 *outDmaformatModifiers = (uint64_t)item->second;
945
fei.dengb9a1a572023-09-13 01:33:57 +0000946 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000947}
948
949int WaylandDisplay::toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat)
950{
951 if (!outformat) {
fei.dengb9a1a572023-09-13 01:33:57 +0000952 WARNING(mLogCategory,"NULL params");
953 return ERROR_PARAM_NULL;
fei.dengf7a0cd32023-08-29 09:36:37 +0000954 }
955
956 *outformat = 0;
957
958 int shmformat = (int)video_format_to_wl_shm_format(format);
959 if (shmformat < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000960 ERROR(mLogCategory,"Error not found render video format:%d to wl shmbuf format",format);
961 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000962 }
963
964 for (auto item = mShmFormats.begin(); item != mShmFormats.end(); ++item) {
965 uint32_t registFormat = (uint32_t)*item;
966 if (registFormat == (uint32_t)shmformat) {
967 *outformat = registFormat;
fei.dengb9a1a572023-09-13 01:33:57 +0000968 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000969 }
970 }
971
fei.dengb9a1a572023-09-13 01:33:57 +0000972 return ERROR_NOT_FOUND;
fei.dengf7a0cd32023-08-29 09:36:37 +0000973}
974
975void WaylandDisplay::setVideoBufferFormat(RenderVideoFormat format)
976{
fei.dengb9a1a572023-09-13 01:33:57 +0000977 TRACE(mLogCategory,"set video buffer format: %d",format);
fei.dengf7a0cd32023-08-29 09:36:37 +0000978 mBufferFormat = format;
979};
980
981void WaylandDisplay::setDisplayOutput(int output)
982{
fei.dengb9a1a572023-09-13 01:33:57 +0000983 TRACE(mLogCategory,"select display output: %d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000984 if (output < 0 || output >= DEFAULT_DISPLAY_OUTPUT_NUM) {
fei.dengb9a1a572023-09-13 01:33:57 +0000985 ERROR(mLogCategory, "display output index error,please set 0:primary or 1:extend,now:%d",output);
fei.dengf7a0cd32023-08-29 09:36:37 +0000986 return;
987 }
fei.deng26950832023-11-09 03:00:23 +0000988 //only do select output before video playing
989 if (mSelectOutputIndex != output) {
990 mSelectOutputIndex = output;
991 // if (mOutput[output].wlOutput) {
992 // mCurrentDisplayOutput = &mOutput[output];
993 // setRenderRectangle(mOutput[output].offsetX, mOutput[output].offsetY,
994 // mOutput[output].width, mOutput[output].height);
995 // }
fei.dengf7a0cd32023-08-29 09:36:37 +0000996 }
997}
998
999int WaylandDisplay::getDisplayOutput()
1000{
fei.deng26950832023-11-09 03:00:23 +00001001 return mSelectOutputIndex == INVALID_OUTPUT_INDEX? 0: mSelectOutputIndex;
fei.dengf7a0cd32023-08-29 09:36:37 +00001002}
1003
1004void WaylandDisplay::setPip(int pip)
1005{
fei.dengb9a1a572023-09-13 01:33:57 +00001006 INFO(mLogCategory,"set pip:%d",pip);
fei.dengf7a0cd32023-08-29 09:36:37 +00001007 mPip = pip;
1008}
1009
fei.deng26950832023-11-09 03:00:23 +00001010void WaylandDisplay::updateDisplayOutput()
1011{
1012 if (!mCurrentDisplayOutput->wlOutput || !mXdgToplevel || !mXdgSurface)
1013 {
1014 return;
1015 }
1016 if (mUpdateRenderRectangle) {
1017 if (mFullScreen) {
1018 DEBUG(mLogCategory,"unset full screen");
1019 xdg_toplevel_unset_fullscreen (mXdgToplevel);
1020 }
1021
1022 if (mXdgSurface) {
1023 DEBUG(mLogCategory,"set geometry");
1024 xdg_surface_set_window_geometry(mXdgSurface,
1025 mCurrentDisplayOutput->offsetX,
1026 mCurrentDisplayOutput->offsetY,
1027 mCurrentDisplayOutput->width,
1028 mCurrentDisplayOutput->height);
1029 }
1030
1031 if (mFullScreen && mXdgToplevel) {
1032 DEBUG(mLogCategory,"set full screen");
1033 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
1034 }
1035 setRenderRectangle(mCurrentDisplayOutput->offsetX, mCurrentDisplayOutput->offsetY,
1036 mCurrentDisplayOutput->width, mCurrentDisplayOutput->height);
1037 mUpdateRenderRectangle = false;
1038 }
1039}
1040
fei.dengf7a0cd32023-08-29 09:36:37 +00001041void WaylandDisplay::createCommonWindowSurface()
1042{
1043 struct wl_region *region;
1044
1045 mAreaSurface = wl_compositor_create_surface (mCompositor);
1046 mVideoSurface = wl_compositor_create_surface (mCompositor);
1047 mAreaSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mAreaSurface);
1048 mVideoSurfaceWrapper = (struct wl_surface *)wl_proxy_create_wrapper (mVideoSurface);
1049
1050 wl_proxy_set_queue ((struct wl_proxy *) mAreaSurfaceWrapper, mWlQueue);
1051 wl_proxy_set_queue ((struct wl_proxy *) mVideoSurfaceWrapper, mWlQueue);
1052
1053 /* embed video_surface in area_surface */
1054 mVideoSubSurface = wl_subcompositor_get_subsurface (mSubCompositor, mVideoSurface, mAreaSurface);
1055 wl_subsurface_set_desync (mVideoSubSurface);
1056
fei.dengd0da4e22024-07-04 11:29:13 +08001057 //add video surface callback to weston if weston enable this feature
1058 if (mVideoSurface && mAmlConfigAPIList.enableSurfaceDestroyCallback) {
1059 struct wl_callback *surfaceDestroyCb = wl_surface_destroy_callback(mVideoSurface);
1060 wl_callback_add_listener(surfaceDestroyCb, &surface_destroy_listener, this);
1061 }
1062
fei.dengf7a0cd32023-08-29 09:36:37 +00001063 if (mViewporter) {
1064 mAreaViewport = wp_viewporter_get_viewport (mViewporter, mAreaSurface);
1065 mVideoViewport = wp_viewporter_get_viewport (mViewporter, mVideoSurface);
1066 }
1067
fei.deng9bf724e2024-08-01 11:34:52 +08001068 /*set area surface to invisible. prevent frame droped at start playback,
1069 wl_surface_set_invisible must called before mAreaSurface commit called*/
1070 if (mAmlConfigAPIList.enableSetSurfaceInvisible) {
1071 int invisible = 1;
1072 INFO(mLogCategory,"set surface invisible:%d",invisible);
1073 wl_surface_set_invisible(mAreaSurfaceWrapper, invisible);
1074 }
1075
fei.deng649b0e22024-09-03 18:57:13 +08001076 if (mAmlConfigAPIList.enableDisplayTime) {
1077 INFO(mLogCategory,"set enable display time");
1078 wl_surface_enable_display_time(mVideoSurface, 1);
1079 }
1080
fei.dengf7a0cd32023-08-29 09:36:37 +00001081 /* do not accept input */
1082 region = wl_compositor_create_region (mCompositor);
1083 wl_surface_set_input_region (mAreaSurface, region);
1084 wl_region_destroy (region);
1085
1086 region = wl_compositor_create_region (mCompositor);
1087 wl_surface_set_input_region (mVideoSurface, region);
1088 wl_region_destroy (region);
1089}
1090
1091void WaylandDisplay::createXdgShellWindowSurface()
1092{
1093 /* Check which protocol we will use (in order of preference) */
1094 if (mXdgWmBase) {
1095 /* First create the XDG surface */
1096 mXdgSurface= xdg_wm_base_get_xdg_surface (mXdgWmBase, mAreaSurface);
1097 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +00001098 ERROR(mLogCategory,"Unable to get xdg_surface");
fei.dengf7a0cd32023-08-29 09:36:37 +00001099 return;
1100 }
1101 xdg_surface_add_listener (mXdgSurface, &xdg_surface_listener,(void *)this);
1102
1103 /* Then the toplevel */
1104 mXdgToplevel= xdg_surface_get_toplevel (mXdgSurface);
1105 if (!mXdgSurface) {
fei.dengb9a1a572023-09-13 01:33:57 +00001106 ERROR(mLogCategory,"Unable to get xdg_toplevel");
fei.dengf7a0cd32023-08-29 09:36:37 +00001107 return;
1108 }
1109 xdg_toplevel_add_listener (mXdgToplevel, &xdg_toplevel_listener, this);
1110
1111 /* Finally, commit the xdg_surface state as toplevel */
1112 mXdgSurfaceConfigured = false;
1113 wl_surface_commit (mAreaSurface);
1114 wl_display_flush (mWlDisplay);
1115 /* we need exactly 3 roundtrips to discover global objects and their state */
1116 for (int i = 0; i < 3; i++) {
1117 if (wl_display_roundtrip_queue(mWlDisplay, mWlQueue) < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +00001118 ERROR(mLogCategory,"Error communicating with the wayland display");
fei.dengf7a0cd32023-08-29 09:36:37 +00001119 }
1120 }
1121
1122 if (mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +00001123 INFO(mLogCategory,"xdg surface had configured");
fei.dengf7a0cd32023-08-29 09:36:37 +00001124 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001125 WARNING(mLogCategory,"xdg surface not configured");
fei.dengf7a0cd32023-08-29 09:36:37 +00001126 }
1127
1128 //full screen show
fei.deng26950832023-11-09 03:00:23 +00001129 // if (mFullScreen && mCurrentDisplayOutput->wlOutput) {
1130 // //ensureFullscreen(mFullScreen);
fei.dengf7a0cd32023-08-29 09:36:37 +00001131 // }
1132 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001133 ERROR(mLogCategory,"Unable to use xdg_wm_base ");
fei.dengf7a0cd32023-08-29 09:36:37 +00001134 return;
1135 }
1136}
1137
1138void WaylandDisplay::destroyWindowSurfaces()
1139{
fei.dengf7a0cd32023-08-29 09:36:37 +00001140 if (mXdgToplevel) {
1141 xdg_toplevel_destroy (mXdgToplevel);
1142 mXdgToplevel = NULL;
1143 }
1144
1145 if (mXdgSurface) {
1146 xdg_surface_destroy (mXdgSurface);
1147 mXdgSurface = NULL;
1148 }
1149
1150 if (mVideoSurfaceWrapper) {
1151 wl_proxy_wrapper_destroy (mVideoSurfaceWrapper);
1152 mVideoSurfaceWrapper = NULL;
1153 }
1154
1155 if (mVideoSubSurface) {
1156 wl_subsurface_destroy (mVideoSubSurface);
1157 mVideoSubSurface = NULL;
1158 }
1159
1160 if (mVideoSurface) {
1161 wl_surface_destroy (mVideoSurface);
1162 mVideoSurface = NULL;
1163 }
1164
1165 if (mAreaSurfaceWrapper) {
1166 wl_proxy_wrapper_destroy (mAreaSurfaceWrapper);
1167 mAreaSurfaceWrapper = NULL;
1168 }
1169
1170 if (mAreaSurface) {
1171 wl_surface_destroy (mAreaSurface);
1172 mAreaSurface = NULL;
1173 mReCommitAreaSurface = false;
1174 }
1175}
1176
1177void WaylandDisplay::ensureFullscreen(bool fullscreen)
1178{
1179 if (mXdgWmBase) {
fei.dengb9a1a572023-09-13 01:33:57 +00001180 DEBUG(mLogCategory,"full screen : %d",fullscreen);
fei.dengf7a0cd32023-08-29 09:36:37 +00001181 if (fullscreen) {
fei.deng26950832023-11-09 03:00:23 +00001182 xdg_toplevel_set_fullscreen (mXdgToplevel, mCurrentDisplayOutput->wlOutput);
fei.dengf7a0cd32023-08-29 09:36:37 +00001183 } else {
1184 xdg_toplevel_unset_fullscreen (mXdgToplevel);
1185 }
1186 }
1187}
1188
1189void WaylandDisplay::setRenderRectangle(int x, int y, int w, int h)
1190{
fei.dengb9a1a572023-09-13 01:33:57 +00001191 DEBUG(mLogCategory,"set render rect:x:%d,y:%d,w:%d,h:%d",x,y,w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001192
1193 if (w <= 0 || h <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +00001194 WARNING(mLogCategory, "wrong render width or height %dx%d",w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001195 return;
1196 }
1197
1198 mRenderRect.x = x;
1199 mRenderRect.y = y;
1200 mRenderRect.w = w;
1201 mRenderRect.h = h;
1202
1203 if (!mXdgSurfaceConfigured) {
fei.dengb9a1a572023-09-13 01:33:57 +00001204 WARNING(mLogCategory,"Not configured xdg");
fei.dengf7a0cd32023-08-29 09:36:37 +00001205 return;
1206 }
1207
1208 if (mAreaViewport) {
1209 wp_viewport_set_destination (mAreaViewport, w, h);
1210 }
1211
1212 updateBorders();
1213
1214 if (mVideoWidth != 0 && mVideoSurface) {
1215 wl_subsurface_set_sync (mVideoSubSurface);
1216 resizeVideoSurface(true);
1217 }
1218
1219 wl_surface_damage (mAreaSurfaceWrapper, 0, 0, w, h);
1220 wl_surface_commit (mAreaSurfaceWrapper);
1221
1222 if (mVideoWidth != 0) {
1223 wl_subsurface_set_desync (mVideoSubSurface);
1224 }
1225}
1226
fei.dengf7a0cd32023-08-29 09:36:37 +00001227void WaylandDisplay::setFrameSize(int w, int h)
1228{
1229 mVideoWidth = w;
1230 mVideoHeight = h;
fei.denga4abbd52024-07-11 19:17:50 +08001231 mUpdateVideoSurface = true;
fei.dengb9a1a572023-09-13 01:33:57 +00001232 TRACE(mLogCategory,"frame w:%d,h:%d",mVideoWidth,mVideoHeight);
fei.dengf7a0cd32023-08-29 09:36:37 +00001233}
1234
1235void WaylandDisplay::setWindowSize(int x, int y, int w, int h)
1236{
1237 mWindowRect.x = x;
1238 mWindowRect.y = y;
1239 mWindowRect.w = w;
1240 mWindowRect.h = h;
fei.denga4abbd52024-07-11 19:17:50 +08001241 mUpdateVideoSurface = true;
fei.dengb9a1a572023-09-13 01:33:57 +00001242 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 +00001243}
1244
fei.denga4abbd52024-07-11 19:17:50 +08001245void WaylandDisplay::setPixelAspectRatio(double ratio)
1246{
1247 mPixelAspectRatio = ratio;
1248 mUpdateVideoSurface = true;
1249}
fei.dengf7a0cd32023-08-29 09:36:37 +00001250
1251void WaylandDisplay::resizeVideoSurface(bool commit)
1252{
1253 Rectangle src = {0,};
1254 Rectangle dst = {0,};
1255 Rectangle res;
1256
1257 /* center the video_subsurface inside area_subsurface */
1258 src.w = mVideoWidth;
1259 src.h = mVideoHeight;
1260 /*if had set the window size, we will scall
1261 video surface to this window size*/
1262 if (mWindowRect.w > 0 && mWindowRect.h > 0) {
1263 dst.x = mWindowRect.x;
1264 dst.y = mWindowRect.y;
1265 dst.w = mWindowRect.w;
1266 dst.h = mWindowRect.h;
1267 if (mWindowRect.w > mRenderRect.w && mWindowRect.h > mRenderRect.h) {
fei.dengb9a1a572023-09-13 01:33:57 +00001268 WARNING(mLogCategory,"Error window size:%dx%d, but render size:%dx%d,reset to render size",
fei.dengf7a0cd32023-08-29 09:36:37 +00001269 mWindowRect.w,mWindowRect.h,mRenderRect.w,mRenderRect.h);
1270 dst.x = mRenderRect.x;
1271 dst.y = mRenderRect.y;
1272 dst.w = mRenderRect.w;
1273 dst.h = mRenderRect.h;
1274 }
1275 //to do,we need set geometry?
1276 //if (mXdgSurface) {
1277 // xdg_surface_set_window_geometry(mXdgSurface, mWindowRect.x, mWindowRect.y, mWindowRect.w, mWindowRect.h);
1278 //}
1279 } else { //scal video to full screen
1280 dst.w = mRenderRect.w;
1281 dst.h = mRenderRect.h;
1282 }
1283
1284 if (mViewporter) {
1285 videoCenterRect(src, dst, &res, true);
1286 } else {
1287 videoCenterRect(src, dst, &res, false);
1288 }
1289
1290 wl_subsurface_set_position (mVideoSubSurface, res.x, res.y);
1291
1292 if (commit) {
1293 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, res.w, res.h);
1294 wl_surface_commit (mVideoSurfaceWrapper);
1295 }
1296
1297 //top level setting
1298 if (mXdgToplevel) {
1299 struct wl_region *region;
1300
1301 region = wl_compositor_create_region (mCompositor);
1302 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1303 wl_surface_set_input_region (mAreaSurface, region);
1304 wl_region_destroy (region);
1305 }
1306
1307 /* this is saved for use in wl_surface_damage */
1308 mVideoRect.x = res.x;
1309 mVideoRect.y = res.y;
1310 mVideoRect.w = res.w;
1311 mVideoRect.h = res.h;
1312
fei.denga4abbd52024-07-11 19:17:50 +08001313 //to scale video surface
fei.dengf7a0cd32023-08-29 09:36:37 +00001314 wp_viewport_set_destination(mVideoViewport, res.w, res.h);
fei.denga4abbd52024-07-11 19:17:50 +08001315 wl_display_flush (mWlDisplay);
fei.dengb9a1a572023-09-13 01:33:57 +00001316 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 +00001317}
1318
1319void WaylandDisplay::setOpaque()
1320{
1321 struct wl_region *region;
1322
1323 /* Set area opaque */
1324 region = wl_compositor_create_region (mCompositor);
1325 wl_region_add (region, 0, 0, mRenderRect.w, mRenderRect.h);
1326 wl_surface_set_opaque_region (mAreaSurface, region);
1327 wl_region_destroy (region);
1328}
1329
1330int WaylandDisplay::prepareFrameBuffer(RenderBuffer * buf)
1331{
1332 WaylandBuffer *waylandBuf = NULL;
1333 int ret;
fei.dengda0cd9f2024-07-24 09:25:11 +08001334 bool isNew = false;
fei.dengf7a0cd32023-08-29 09:36:37 +00001335
fei.deng649b0e22024-09-03 18:57:13 +08001336 //detect frame rate and frame duration
1337 if (mFrameRateFractionNum == 0) {
1338 if (mPreFramePts == -1) {
1339 mPreFramePts = buf->pts; //ns
1340 } else {
1341 if (mFrameRateDetectCnt < DETECT_FRAMERATE_CNT) {
1342 mFrameRateDetectPeriod += (buf->pts - mPreFramePts);
1343 ++mFrameRateDetectCnt;
1344 }
1345 if (mFrameRateDetectCnt == DETECT_FRAMERATE_CNT) {
1346 int64_t mFrameDurationUs = (mFrameRateDetectPeriod/mFrameRateDetectCnt)/1000;
1347 double rate = 1000000.0/mFrameDurationUs;
1348 mFrameRateFractionNum = rate * 100;
1349 mFrameRateFractionDenom = 100;
1350 mFrameRateChanged = true;
1351 INFO(mLogCategory,"detect frame num:%d,denom:%d,dur:%lld us",
1352 mFrameRateFractionNum,mFrameRateFractionDenom,mFrameDurationUs);
1353 }
1354 }
1355 }
1356 mPreFramePts = buf->pts;
1357
fei.dengdd910ef2024-06-07 10:25:30 +08001358 if (!mDmabuf)
1359 {
1360 ERROR(mLogCategory,"Error zwp_linux_dmabuf_v1");
1361 return ERROR_UNKNOWN;
1362 }
1363
fei.dengf7a0cd32023-08-29 09:36:37 +00001364 waylandBuf = findWaylandBuffer(buf);
1365 if (waylandBuf == NULL) {
fei.dengb9a1a572023-09-13 01:33:57 +00001366 waylandBuf = new WaylandBuffer(this, mLogCategory);
fei.dengda0cd9f2024-07-24 09:25:11 +08001367 isNew = true;
1368 }
1369 waylandBuf->setBufferFormat(mBufferFormat);
1370 ret = waylandBuf->constructWlBuffer(buf);
1371 if (ret != NO_ERROR) {
1372 WARNING(mLogCategory,"dmabufConstructWlBuffer fail,release waylandbuf");
1373 //delete waylanBuf,WaylandBuffer object destruct will call release callback
1374 goto waylandbuf_fail;
1375 }
1376 if (isNew) {
1377 addWaylandBuffer(buf, waylandBuf);
fei.dengf7a0cd32023-08-29 09:36:37 +00001378 }
fei.dengb9a1a572023-09-13 01:33:57 +00001379 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +00001380waylandbuf_fail:
fei.denga7618662024-10-30 14:24:48 +08001381 if (!isNew) {
1382 removeWaylandBuffer(buf);
1383 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001384 //delete waylandbuf
1385 delete waylandBuf;
1386 waylandBuf = NULL;
fei.dengb9a1a572023-09-13 01:33:57 +00001387 return ERROR_UNKNOWN;
fei.dengf7a0cd32023-08-29 09:36:37 +00001388}
1389
1390void WaylandDisplay::displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime)
1391{
fei.deng19b48692024-08-13 14:17:55 +08001392 WaylandBuffer *waylandBuf = NULL;
1393 struct wl_buffer * wlbuffer = NULL;
1394 int ret;
1395
1396 if (!buf) {
1397 ERROR(mLogCategory,"Error input params, RenderBuffer is null");
1398 return;
1399 }
1400
1401 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1402 if (buf->dma.width <=0 || buf->dma.height <=0) {
1403 buf->dma.width = mVideoWidth;
1404 buf->dma.height = mVideoHeight;
1405 }
1406
1407 waylandBuf = findWaylandBuffer(buf);
1408 if (waylandBuf) {
1409 waylandBuf->setRenderRealTime(realDisplayTime);
1410 } else {
1411 ERROR(mLogCategory,"NOT found wayland buffer,please prepare buffer first");
1412 goto waylandbuf_fail;
1413 }
1414 }
1415
1416 //if no wl_output, drop this buffer
1417 if (mCurrentDisplayOutput->wlOutput == NULL) {
1418 TRACE(mLogCategory,"No wl_output");
1419 //insert this buffer to committed weston buffer manager
1420 std::pair<int64_t, WaylandBuffer *> item(realDisplayTime, waylandBuf);
1421 mCommittedBufferMap.insert(item);
1422 mWaylandPlugin->handleFrameDropped(buf);
1423 WaylandBuffer::bufferRelease(waylandBuf,NULL);
1424 return;
1425 }
1426
1427 //must commit areasurface first, because weston xdg surface maybe timeout
1428 //this cause video is not display,commit can resume xdg surface
1429 if (!mReCommitAreaSurface) {
1430 mReCommitAreaSurface = true;
1431 wl_surface_commit (mAreaSurface);
1432 }
1433
fei.deng6c425232024-07-19 16:15:31 +08001434 //set frame rate to weston,it lets weston to select suitable mode
1435 if (mFrameRateChanged && mAmlConfigAPIList.enableSetDisplayRate) {
1436 mFrameRateChanged = false;
1437 TRACE(mLogCategory,"set frame rate %d/%d to weston", mFrameRateFractionNum, mFrameRateFractionDenom);
1438 wl_surface_set_display_rate(mVideoSurfaceWrapper, mFrameRateFractionNum, mFrameRateFractionDenom);
1439 }
fei.denga4abbd52024-07-11 19:17:50 +08001440 //update video surface size
le.han692592c2024-10-12 06:24:44 +00001441 if (mUpdateVideoSurface && mVideoSurface) {
fei.denga4abbd52024-07-11 19:17:50 +08001442 mUpdateVideoSurface = false;
1443 //if had full screen, unset it and set window size
1444 if (mFullScreen) {
1445 mFullScreen = false;
1446 ensureFullscreen(mFullScreen);
1447 }
1448 resizeVideoSurface(true);
fei.dengda0cd9f2024-07-24 09:25:11 +08001449 /*clean wayland buffers those allocated
1450 before resolution changed and had release by weston */
1451 cleanWaylandBufferBeforeResChanged();
fei.denga4abbd52024-07-11 19:17:50 +08001452 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001453
fei.deng1c94a342024-08-05 19:33:28 +08001454 if (mVideoPlaneZorderChanged && mVideoSurfaceWrapper) {
1455 mVideoPlaneZorderChanged = false;
1456 wl_surface_set_zorder(mVideoSurfaceWrapper, mVideoPlaneZorder);
1457 }
1458
fei.dengdd910ef2024-06-07 10:25:30 +08001459 //TRACE(mLogCategory,"display renderBuffer:%p,PTS:%lld us,realtime:%lld",buf, buf->pts/1000, realDisplayTime);
fei.dengf7a0cd32023-08-29 09:36:37 +00001460
fei.dengf7a0cd32023-08-29 09:36:37 +00001461 if (waylandBuf) {
1462 wlbuffer = waylandBuf->getWlBuffer();
1463 }
fei.deng19b48692024-08-13 14:17:55 +08001464
fei.dengf7a0cd32023-08-29 09:36:37 +00001465 if (wlbuffer) {
fei.dengf3ee6912024-08-30 18:22:55 +08001466 auto cItem = mCommittedBufferMap.find(realDisplayTime);
1467 if (cItem != mCommittedBufferMap.end()) {
1468 TRACE(mLogCategory,"Error.release same display time buffer,pts:%lld us",buf->pts/1000);
1469 goto waylandbuf_fail;
1470 }
fei.dengb9a1a572023-09-13 01:33:57 +00001471 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001472 ++mCommitCnt;
1473 uint32_t hiPts = realDisplayTime >> 32;
1474 uint32_t lowPts = realDisplayTime & 0xFFFFFFFF;
1475 //attach this wl_buffer to weston
fei.denga4abbd52024-07-11 19:17:50 +08001476 TRACE(mLogCategory,"++attach,renderbuf:%p,wl_buffer:%p(%d,%d,%d,%d),pts:%lld us,commitCnt:%d",
1477 buf,wlbuffer,mVideoRect.x,mVideoRect.y,mVideoRect.w,mVideoRect.h,buf->pts/1000,mCommitCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +00001478 waylandBuf->attach(mVideoSurfaceWrapper);
1479
fei.deng640c3c92024-04-12 08:31:19 +00001480 if (mAmlConfigAPIList.enableSetPts) {
fei.dengb9a1a572023-09-13 01:33:57 +00001481 TRACE(mLogCategory,"display time:%lld,hiPts:%u,lowPts:%u",realDisplayTime, hiPts, lowPts);
fei.dengf7a0cd32023-08-29 09:36:37 +00001482 wl_surface_set_pts(mVideoSurfaceWrapper, hiPts, lowPts);
1483 }
1484
le.hane8c8fdd2024-09-19 09:28:50 +00001485 if (!mKeepFrameOnFlush && mFirstPtsAfterFlush == -1) {
1486 mFirstPtsAfterFlush = buf->pts;
1487 }
1488
fei.deng96aa7f72024-09-29 15:46:52 +08001489 //doing video rotate if needed
1490 if (mVideoRotateDegree >= 0) {
1491 /*weston accept degree map: transfer value->degree, 0->0, 1->90,2->180,3->270
1492 detail see: enum wl_output_transform or search WL_OUTPUT_TRANSFORM_xxx*/
1493 int transform = 0;
1494 switch (mVideoRotateDegree) {
1495 case 90: {
1496 transform = 1;
1497 } break;
1498 case 180: {
1499 transform = 2;
1500 } break;
1501 case 270: {
1502 transform = 3;
1503 } break;
1504 default:
1505 transform = 0;
1506 }
1507 wl_surface_set_buffer_transform(mVideoSurfaceWrapper, transform);
1508 }
1509
fei.dengf7a0cd32023-08-29 09:36:37 +00001510 wl_surface_damage (mVideoSurfaceWrapper, 0, 0, mVideoRect.w, mVideoRect.h);
1511 wl_surface_commit (mVideoSurfaceWrapper);
1512 //insert this buffer to committed weston buffer manager
fei.dengae8c90a2024-06-27 13:39:53 +08001513 std::pair<int64_t, WaylandBuffer *> item(realDisplayTime, waylandBuf);
fei.dengf7a0cd32023-08-29 09:36:37 +00001514 mCommittedBufferMap.insert(item);
1515 } else {
fei.dengb9a1a572023-09-13 01:33:57 +00001516 WARNING(mLogCategory,"wlbuffer is NULL");
fei.dengf7a0cd32023-08-29 09:36:37 +00001517 /* clear both video and parent surfaces */
fei.deng19b48692024-08-13 14:17:55 +08001518 //cleanSurface();
1519 goto waylandbuf_fail;
fei.dengf7a0cd32023-08-29 09:36:37 +00001520 }
1521
1522 wl_display_flush (mWlDisplay);
fei.deng4029e682024-06-26 17:06:31 +08001523 //set keep last frame or not when after send first buffer to weston,1 keep last frame, 0 not
1524 if (mToSendKeepLastFrame) {
1525 setKeepLastFrame(mKeepLastFrame);
1526 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001527
1528 return;
1529waylandbuf_fail:
1530 //notify dropped
1531 mWaylandPlugin->handleFrameDropped(buf);
1532 //notify app release this buf
1533 mWaylandPlugin->handleBufferRelease(buf);
fei.dengf3ee6912024-08-30 18:22:55 +08001534
fei.dengf7a0cd32023-08-29 09:36:37 +00001535 return;
1536}
1537
1538void WaylandDisplay::handleBufferReleaseCallback(WaylandBuffer *buf)
1539{
fei.denga4abbd52024-07-11 19:17:50 +08001540 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.dengf7a0cd32023-08-29 09:36:37 +00001541 {
fei.dengb9a1a572023-09-13 01:33:57 +00001542 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001543 //remove buffer if this buffer is ready to release
fei.dengae8c90a2024-06-27 13:39:53 +08001544 auto item = mCommittedBufferMap.find(buf->getRenderRealTime());
fei.dengf7a0cd32023-08-29 09:36:37 +00001545 if (item != mCommittedBufferMap.end()) {
fei.dengdd910ef2024-06-07 10:25:30 +08001546 --mCommitCnt;
fei.dengf7a0cd32023-08-29 09:36:37 +00001547 mCommittedBufferMap.erase(item);
1548 } else {
fei.denga4abbd52024-07-11 19:17:50 +08001549 TRACE(mLogCategory,"Error,Can't find WaylandBuffer pts:%lld us (%lld) in buffer map",
1550 renderBuffer->pts/1000,buf->getRenderRealTime());
fei.dengf7a0cd32023-08-29 09:36:37 +00001551 return;
1552 }
1553 }
fei.denga4abbd52024-07-11 19:17:50 +08001554
1555 TRACE(mLogCategory,"renderBuffer :%p,priv:%p,PTS:%lld us,realtime:%lld us,commitCnt:%d",renderBuffer,renderBuffer->priv,renderBuffer->pts/1000,buf->getRenderRealTime(),mCommitCnt);
fei.dengf7a0cd32023-08-29 09:36:37 +00001556 mWaylandPlugin->handleBufferRelease(renderBuffer);
1557}
1558
1559void WaylandDisplay::handleFrameDisplayedCallback(WaylandBuffer *buf)
1560{
1561 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.denga4abbd52024-07-11 19:17:50 +08001562 TRACE(mLogCategory,"renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
fei.deng3287c082024-04-23 09:29:22 +00001563 if (!mSignalFirstFramePts) {
1564 mSignalFirstFramePts = true;
1565 mWaylandPlugin->handleMsgNotify(MSG_FIRST_FRAME, (void*)&renderBuffer->pts);
1566 }
fei.dengf862f9c2024-10-24 16:46:55 +08001567 mWaylandPlugin->signalWaitTimeout();
fei.dengf7a0cd32023-08-29 09:36:37 +00001568 mWaylandPlugin->handleFrameDisplayed(renderBuffer);
le.hane8c8fdd2024-09-19 09:28:50 +00001569 if (!mKeepFrameOnFlush && mFirstPtsAfterFlush == renderBuffer->pts) {
1570 mKeepFrameOnFlush = 1;
1571 mFirstPtsAfterFlush = -1;
1572 wl_surface_set_video_plane_mute(mVideoSurfaceWrapper, 0);
1573 INFO(mLogCategory,"unmute video plane");
1574 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001575}
1576
1577void WaylandDisplay::handleFrameDropedCallback(WaylandBuffer *buf)
1578{
1579 RenderBuffer *renderBuffer = buf->getRenderBuffer();
fei.denga4abbd52024-07-11 19:17:50 +08001580 TRACE(mLogCategory,"renderBuffer :%p,PTS:%lld us,realtime:%lld us",renderBuffer,renderBuffer->pts/1000,buf->getRenderRealTime());
fei.dengf7a0cd32023-08-29 09:36:37 +00001581 mWaylandPlugin->handleFrameDropped(renderBuffer);
1582}
1583
fei.deng649b0e22024-09-03 18:57:13 +08001584void WaylandDisplay::handleFrameTime(WaylandBuffer *buf,uint32_t sec, uint32_t usec)
1585{
1586 RenderBuffer *renderBuffer = buf->getRenderBuffer();
1587 int64_t frameDisplayTimeUs = int64_t(sec)*1000000LL + usec;
1588 if (mLastDisplayFramePts == -1) {
1589 mLastDisplayFramePts = renderBuffer->pts;
1590 mLastDisplayFrameTimeUs = frameDisplayTimeUs;
1591 } else { //calculate last frame displayed duration
1592 int64_t duration = frameDisplayTimeUs - mLastDisplayFrameTimeUs;
1593 TRACE(mLogCategory,"now pts:%lld us,time:%u us,pre pts:%lld us,dur:%lld us",
1594 renderBuffer->pts/1000,frameDisplayTimeUs,mLastDisplayFramePts/1000,duration);
1595 if (mFrameDurationUs > 0 && duration > FRAME_FREEZE_THRESHOLD(mFrameDurationUs)) {
1596 FrameDisplayInfo frameDisplayInfo = {-1, -1};
1597 frameDisplayInfo.pts = mLastDisplayFramePts;
1598 frameDisplayInfo.duration = duration;
1599 TRACE(mLogCategory,"report freeze frame,pts:%lld us,duration:%lld us",frameDisplayInfo.pts/1000,frameDisplayInfo.duration);
1600 mWaylandPlugin->handleMsgNotify(MSG_FRAME_FREEZE, &frameDisplayInfo);
1601 }
1602 mLastDisplayFramePts = renderBuffer->pts;
1603 mLastDisplayFrameTimeUs = frameDisplayTimeUs;
1604 }
1605}
1606
fei.dengf7a0cd32023-08-29 09:36:37 +00001607
1608void WaylandDisplay::readyToRun()
1609{
1610 mFd = wl_display_get_fd (mWlDisplay);
fei.dengb9a1a572023-09-13 01:33:57 +00001611 if (mPoll) {
1612 mPoll->addFd(mFd);
1613 mPoll->setFdReadable(mFd, true);
1614 }
fei.dengf7a0cd32023-08-29 09:36:37 +00001615}
1616
fei.dengdd910ef2024-06-07 10:25:30 +08001617void WaylandDisplay::readyToExit()
1618{
1619 if (mPoll && mFd >= 0) {
1620 mPoll->removeFd(mFd);
1621 }
1622}
1623
fei.dengf7a0cd32023-08-29 09:36:37 +00001624bool WaylandDisplay::threadLoop()
1625{
1626 int ret;
fei.dengf7a0cd32023-08-29 09:36:37 +00001627
1628 while (wl_display_prepare_read_queue (mWlDisplay, mWlQueue) != 0) {
1629 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1630 }
1631
1632 wl_display_flush (mWlDisplay);
1633
1634 /*poll timeout value must > 300 ms,otherwise zwp_linux_dmabuf will create failed,
1635 so do use -1 to wait for ever*/
fei.dengb9a1a572023-09-13 01:33:57 +00001636 ret = mPoll->wait(-1); //wait for ever
fei.dengf7a0cd32023-08-29 09:36:37 +00001637 if (ret < 0) { //poll error
fei.dengb9a1a572023-09-13 01:33:57 +00001638 WARNING(mLogCategory,"poll error");
fei.dengf7a0cd32023-08-29 09:36:37 +00001639 wl_display_cancel_read(mWlDisplay);
1640 return false;
1641 } else if (ret == 0) { //poll time out
1642 return true; //run loop
1643 }
1644
1645 if (wl_display_read_events (mWlDisplay) == -1) {
1646 goto tag_error;
1647 }
1648
1649 wl_display_dispatch_queue_pending (mWlDisplay, mWlQueue);
1650 return true;
1651tag_error:
fei.dengb9a1a572023-09-13 01:33:57 +00001652 ERROR(mLogCategory,"Error communicating with the wayland server");
fei.dengf7a0cd32023-08-29 09:36:37 +00001653 return false;
1654}
1655
1656void WaylandDisplay::videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling)
1657{
1658 //if dst is a small window, we scale video to map window size,don't doing center
fei.dengda0cd9f2024-07-24 09:25:11 +08001659 // if (mRenderRect.w != dst.w && mRenderRect.h != dst.h) {
1660 // result->x = dst.x;
1661 // result->y = dst.y;
1662 // result->w = dst.w;
1663 // result->h = dst.h;
1664 // TRACE(mLogCategory,"small window source is %dx%d dest is %dx%d, result is %d,%d,%d,%d",
1665 // src.w, src.h, dst.w, dst.h, result->x, result->y, result->w, result->h);
1666 // return;
1667 // }
fei.dengf7a0cd32023-08-29 09:36:37 +00001668 if (!scaling) {
1669 result->w = MIN (src.w, dst.w);
1670 result->h = MIN (src.h, dst.h);
1671 result->x = dst.x + (dst.w - result->w) / 2;
1672 result->y = dst.y + (dst.h - result->h) / 2;
1673 } else {
1674 double src_ratio, dst_ratio;
1675
fei.denga4abbd52024-07-11 19:17:50 +08001676 src_ratio = (double) (src.w * mPixelAspectRatio) / src.h;
fei.dengf7a0cd32023-08-29 09:36:37 +00001677 dst_ratio = (double) dst.w / dst.h;
1678
1679 if (src_ratio > dst_ratio) {
1680 result->w = dst.w;
1681 result->h = dst.w / src_ratio;
1682 result->x = dst.x;
1683 result->y = dst.y + (dst.h - result->h) / 2;
1684 } else if (src_ratio < dst_ratio) {
1685 result->w = dst.h * src_ratio;
1686 result->h = dst.h;
1687 result->x = dst.x + (dst.w - result->w) / 2;
1688 result->y = dst.y;
1689 } else {
1690 result->x = dst.x;
1691 result->y = dst.y;
1692 result->w = dst.w;
1693 result->h = dst.h;
1694 }
1695 }
1696
fei.denga4abbd52024-07-11 19:17:50 +08001697 TRACE(mLogCategory,"source is %dx%d dest is %dx%d, result is %d,%d,%d,%d",
1698 src.w, src.h, dst.w, dst.h, result->x, result->y,result->w, result->h);
fei.dengf7a0cd32023-08-29 09:36:37 +00001699}
1700
1701void WaylandDisplay::updateBorders()
1702{
1703 int width,height;
1704
1705 if (mNoBorderUpdate)
1706 return;
1707
1708 if (mViewporter) {
1709 width = height = 1;
1710 mNoBorderUpdate = true;
1711 } else {
1712 width = mRenderRect.w;
1713 height = mRenderRect.h;
1714 }
1715
1716 RenderVideoFormat format = VIDEO_FORMAT_BGRA;
fei.dengb9a1a572023-09-13 01:33:57 +00001717 mAreaShmBuffer = new WaylandShmBuffer(this, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +00001718 struct wl_buffer *wlbuf = mAreaShmBuffer->constructWlBuffer(width, height, format);
1719 if (wlbuf == NULL) {
1720 delete mAreaShmBuffer;
1721 mAreaShmBuffer = NULL;
1722 }
1723
1724 wl_surface_attach(mAreaSurfaceWrapper, wlbuf, 0, 0);
1725}
1726
1727std::size_t WaylandDisplay::calculateDmaBufferHash(RenderDmaBuffer &dmabuf)
1728{
1729 std::string hashString("");
1730 for (int i = 0; i < dmabuf.planeCnt; i++) {
1731 char hashtmp[1024];
fei.dengda0cd9f2024-07-24 09:25:11 +08001732 snprintf (hashtmp, 1024, "%d%d%d%d%d%d%d",i,dmabuf.width,dmabuf.height,dmabuf.planeCnt,
fei.dengf7a0cd32023-08-29 09:36:37 +00001733 dmabuf.stride[i],dmabuf.offset[i],dmabuf.fd[i]);
1734 std::string tmp(hashtmp);
1735 hashString += tmp;
1736 }
1737
1738 std::size_t hashval = std::hash<std::string>()(hashString);
fei.dengb9a1a572023-09-13 01:33:57 +00001739 //TRACE(mLogCategory,"hashstr:%s,val:%zu",hashString.c_str(),hashval);
fei.dengf7a0cd32023-08-29 09:36:37 +00001740 return hashval;
1741}
1742
1743void WaylandDisplay::addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf)
1744{
fei.deng19b48692024-08-13 14:17:55 +08001745 Tls::Mutex::Autolock _l(mBufferMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001746 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
1747 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1748 std::pair<std::size_t, WaylandBuffer *> item(hashval, waylandbuf);
fei.dengb9a1a572023-09-13 01:33:57 +00001749 //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 +00001750 mWaylandBuffersMap.insert(item);
1751 }
fei.dengb9a1a572023-09-13 01:33:57 +00001752 TRACE(mLogCategory,"mWaylandBuffersMap size:%d",mWaylandBuffersMap.size());
fei.dengf7a0cd32023-08-29 09:36:37 +00001753}
1754
1755WaylandBuffer* WaylandDisplay::findWaylandBuffer(RenderBuffer * buf)
1756{
fei.deng19b48692024-08-13 14:17:55 +08001757 Tls::Mutex::Autolock _l(mBufferMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001758 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1759 auto item = mWaylandBuffersMap.find(hashval);
1760 if (item == mWaylandBuffersMap.end()) {
1761 return NULL;
1762 }
1763
1764 return (WaylandBuffer*) item->second;
1765}
1766
fei.denga7618662024-10-30 14:24:48 +08001767void WaylandDisplay::removeWaylandBuffer(RenderBuffer * buf)
1768{
1769 Tls::Mutex::Autolock _l(mBufferMutex);
1770 std::size_t hashval = calculateDmaBufferHash(buf->dma);
1771 auto item = mWaylandBuffersMap.find(hashval);
1772 if (item == mWaylandBuffersMap.end()) {
1773 return ;
1774 }
1775
1776 mWaylandBuffersMap.erase(item);
1777}
1778
fei.dengf7a0cd32023-08-29 09:36:37 +00001779void WaylandDisplay::cleanAllWaylandBuffer()
1780{
fei.deng19b48692024-08-13 14:17:55 +08001781 Tls::Mutex::Autolock _l(mBufferMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001782 //free all obtain buff
1783 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1784 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1785 mWaylandBuffersMap.erase(item++);
1786 delete waylandbuf;
1787 }
1788}
1789
fei.dengda0cd9f2024-07-24 09:25:11 +08001790
1791/**
1792 * @brief clean wayland buffers those malloc before resolution changed
1793 *
1794 */
1795void WaylandDisplay::cleanWaylandBufferBeforeResChanged()
1796{
fei.deng19b48692024-08-13 14:17:55 +08001797 Tls::Mutex::Autolock _l(mBufferMutex);
fei.dengda0cd9f2024-07-24 09:25:11 +08001798 for (auto item = mWaylandBuffersMap.begin(); item != mWaylandBuffersMap.end(); ) {
1799 WaylandBuffer *wlbuf = (WaylandBuffer*)item->second;
1800 if (wlbuf->isFree()) {
1801 mWaylandBuffersMap.erase(item++);
1802 delete wlbuf;
1803 } else {
1804 item++;
1805 }
1806 }
1807}
1808
fei.dengf7a0cd32023-08-29 09:36:37 +00001809void WaylandDisplay::flushBuffers()
1810{
fei.dengb9a1a572023-09-13 01:33:57 +00001811 INFO(mLogCategory,"flushBuffers");
1812 Tls::Mutex::Autolock _l(mRenderMutex);
fei.dengf7a0cd32023-08-29 09:36:37 +00001813 for (auto item = mCommittedBufferMap.begin(); item != mCommittedBufferMap.end(); item++) {
1814 WaylandBuffer *waylandbuf = (WaylandBuffer*)item->second;
1815 waylandbuf->forceRedrawing();
1816 handleFrameDisplayedCallback(waylandbuf);
1817 }
1818}
1819
1820void WaylandDisplay::cleanSurface()
1821{
1822 /* clear both video and parent surfaces */
1823 wl_surface_attach (mVideoSurfaceWrapper, NULL, 0, 0);
1824 wl_surface_commit (mVideoSurfaceWrapper);
1825 wl_surface_attach (mAreaSurfaceWrapper, NULL, 0, 0);
1826 wl_surface_commit (mAreaSurfaceWrapper);
fei.deng640c3c92024-04-12 08:31:19 +00001827}
1828
1829void WaylandDisplay::setKeepLastFrame(int keep)
1830{
1831 mKeepLastFrame = keep;
1832 if (mVideoSurfaceWrapper && mAmlConfigAPIList.enableKeepLastFrame) {
1833 INFO(mLogCategory,"keep last frame:%d",keep);
1834 wl_surface_keep_last_frame(mVideoSurfaceWrapper, keep);
fei.deng4029e682024-06-26 17:06:31 +08001835 mToSendKeepLastFrame = false;
1836 return;
fei.deng640c3c92024-04-12 08:31:19 +00001837 }
fei.deng4029e682024-06-26 17:06:31 +08001838 mToSendKeepLastFrame = true;
fei.deng6c425232024-07-19 16:15:31 +08001839}
1840
le.hane8c8fdd2024-09-19 09:28:50 +00001841void WaylandDisplay::setKeepLastFrameOnFlush(int keepOnFlush)
1842{
1843 mKeepFrameOnFlush = keepOnFlush;
1844 INFO(mLogCategory,"keep last frame:%d",mKeepFrameOnFlush);
1845 if (mVideoSurfaceWrapper && !mKeepFrameOnFlush) {
1846 INFO(mLogCategory,"mute video plane");
1847 wl_surface_set_video_plane_mute(mVideoSurfaceWrapper, 1);
1848 }
1849}
1850
le.han15dacdd2024-09-18 05:46:09 +00001851void WaylandDisplay::setImmediatelyOutput(int enable)
1852{
1853 if (mVideoSurfaceWrapper) {
1854 wl_surface_enable_ll_mode(mVideoSurfaceWrapper, enable);
1855 }
1856 INFO(mLogCategory,"set immediately output:%d", enable);
1857}
1858
fei.deng6c425232024-07-19 16:15:31 +08001859void WaylandDisplay::setFrameRate(int frameRateNum, int frameRateDenom)
1860{
1861 mFrameRateFractionNum = frameRateNum;
1862 mFrameRateFractionDenom = frameRateDenom;
1863 if (mFrameRateFractionDenom == 0) {
1864 mFrameRateFractionDenom = 1;
1865 }
fei.deng649b0e22024-09-03 18:57:13 +08001866
1867 if (mFrameRateFractionNum > 0) {
1868 mFrameDurationUs = 1000000 * mFrameRateFractionDenom/mFrameRateFractionNum;
1869 mFrameRateChanged = true;
fei.deng6c425232024-07-19 16:15:31 +08001870 }
fei.deng649b0e22024-09-03 18:57:13 +08001871
1872 INFO(mLogCategory,"num:%d,denom:%d,frame dur:%lld us",
1873 mFrameRateFractionNum, mFrameRateFractionDenom,mFrameDurationUs);
fei.deng1c94a342024-08-05 19:33:28 +08001874}
1875
1876void WaylandDisplay::setVideoPlaneZorder(int zorder)
1877{
1878 mVideoPlaneZorder = zorder;
1879 mVideoPlaneZorderChanged = true;
1880 if (mVideoSurfaceWrapper) {
1881 mVideoPlaneZorderChanged = false;
1882 wl_surface_set_zorder(mVideoSurfaceWrapper, mVideoPlaneZorder);
1883 }
fei.deng649b0e22024-09-03 18:57:13 +08001884}
1885
1886void WaylandDisplay::pause()
1887{
1888 mLastDisplayFramePts = -1;
1889 mLastDisplayFrameTimeUs = -1;
1890}
1891void WaylandDisplay::resume()
1892{
1893
fei.dengf7a0cd32023-08-29 09:36:37 +00001894}