blob: 60605a3479ed2e08e587aa14bf691df15b42cc30 [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 <sys/types.h>
17#include <sys/socket.h>
18#include <unistd.h>
19#include <fcntl.h>
20#include <errno.h>
21#include <sys/epoll.h>
22#include <string.h>
23#include <stdlib.h>
24#include <wayland-client.h>
25#include "xdg-shell-client-protocol.h"
26#include "viewporter-client-protocol.h"
27#include "linux-dmabuf-unstable-v1-client-protocol.h"
28#include "fullscreen-shell-unstable-v1-client-protocol.h"
29#include "wayland_display.h"
30#include "wayland_buffer.h"
31#include "Logger.h"
32#include "wayland_videoformat.h"
33#include "wayland_dma.h"
34#include "wayland_shm.h"
35#include "Utils.h"
fei.dengb9a1a572023-09-13 01:33:57 +000036#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000037
38#define TAG "rlib:wayland_buffer"
39
fei.dengb9a1a572023-09-13 01:33:57 +000040WaylandBuffer::WaylandBuffer(WaylandDisplay *display, int logCategory)
41 : mDisplay(display),
42 mLogCategory(logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +000043{
44 mRenderBuffer = NULL;
45 mWaylandWlWrap = NULL;
46 mUsedByCompositor = false;
47 mRedrawingPending = false;
48 mRealTime = -1;
49 mBufferFormat = VIDEO_FORMAT_UNKNOWN;
50 mFrameWidth = 0;
51 mFrameHeight = 0;
fei.dengda0cd9f2024-07-24 09:25:11 +080052 //TRACE(mLogCategory,"new WaylandBuffer:%p",this);
fei.dengf7a0cd32023-08-29 09:36:37 +000053}
54
55WaylandBuffer::~WaylandBuffer()
56{
57 /*if weston obtains the wl_buffer,we need
58 * notify user to release renderBuffer*/
59 if (mRenderBuffer) {
60 mDisplay->handleBufferReleaseCallback(this);
61 mRenderBuffer = NULL;
62 }
63 if (mWaylandWlWrap) {
64 delete mWaylandWlWrap;
65 mWaylandWlWrap = NULL;
66 }
fei.dengda0cd9f2024-07-24 09:25:11 +080067 //TRACE(mLogCategory,"delete WaylandBuffer:%p",this);
fei.dengf7a0cd32023-08-29 09:36:37 +000068}
69
70void WaylandBuffer::bufferRelease (void *data, struct wl_buffer *wl_buffer)
71{
72 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
fei.dengda0cd9f2024-07-24 09:25:11 +080073 //TRACE(waylandBuffer->mLogCategory,"--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
fei.dengf7a0cd32023-08-29 09:36:37 +000074 waylandBuffer->mUsedByCompositor = false;
75 //sometimes this callback be called twice
76 //this cause double free,so check mRenderBuffer
77 if (waylandBuffer->mRenderBuffer) {
78 waylandBuffer->mDisplay->handleBufferReleaseCallback(waylandBuffer);
79 waylandBuffer->mRenderBuffer = NULL;
fei.dengae8c90a2024-06-27 13:39:53 +080080 waylandBuffer->mRealTime = -1;
fei.dengf7a0cd32023-08-29 09:36:37 +000081 }
fei.dengda0cd9f2024-07-24 09:25:11 +080082 //release dma buffer if resolution changed after buffer release callback
fei.denga4abbd52024-07-11 19:17:50 +080083 int fw = waylandBuffer->mDisplay->getFrameWidth();
84 int fh = waylandBuffer->mDisplay->getFrameHeight();
85 if ( (waylandBuffer->mFrameWidth != fw || waylandBuffer->mFrameHeight != fh) &&
86 waylandBuffer->mWaylandWlWrap) {
fei.deng6c425232024-07-19 16:15:31 +080087 TRACE(waylandBuffer->mLogCategory,"resolution changed,delete WaylandBuffer:%p,WaylandDmaBuffer:%p",waylandBuffer,waylandBuffer->mWaylandWlWrap);
fei.denga4abbd52024-07-11 19:17:50 +080088 delete waylandBuffer->mWaylandWlWrap;
fei.dengda0cd9f2024-07-24 09:25:11 +080089 waylandBuffer->mLock.lock();
fei.denga4abbd52024-07-11 19:17:50 +080090 waylandBuffer->mWaylandWlWrap = NULL;
fei.dengda0cd9f2024-07-24 09:25:11 +080091 waylandBuffer->mLock.unlock();
fei.denga4abbd52024-07-11 19:17:50 +080092 }
fei.dengf7a0cd32023-08-29 09:36:37 +000093}
94
95void WaylandBuffer::bufferdroped (void *data, struct wl_buffer *wl_buffer)
96{
97 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
fei.dengb9a1a572023-09-13 01:33:57 +000098 WARNING(waylandBuffer->mLogCategory,"--droped wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
fei.dengf7a0cd32023-08-29 09:36:37 +000099 waylandBuffer->mUsedByCompositor = false;
100
101 if (waylandBuffer->mRenderBuffer) {
102 waylandBuffer->mDisplay->handleFrameDropedCallback(waylandBuffer);
103 waylandBuffer->mDisplay->handleBufferReleaseCallback(waylandBuffer);
104 waylandBuffer->mRenderBuffer = NULL;
105 }
106}
107
fei.deng640c3c92024-04-12 08:31:19 +0000108static const struct wl_buffer_listener buffer_with_drop_listener = {
109 WaylandBuffer::bufferRelease,
110 WaylandBuffer::bufferdroped,
111};
112
113static const struct wl_buffer_listener buffer_listener = {
114 WaylandBuffer::bufferRelease
115};
fei.dengf7a0cd32023-08-29 09:36:37 +0000116
117/*if we commit buffers to weston too fast,it causes weston can't invoke this callback*/
118void WaylandBuffer::frameDisplayedCallback(void *data, struct wl_callback *callback, uint32_t time)
119{
120 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
121 waylandBuffer->mDisplay->setRedrawingPending(false);
122 waylandBuffer->mLock.lock();
123 bool redrawing = waylandBuffer->mRedrawingPending;
124 waylandBuffer->mRedrawingPending = false;
125 waylandBuffer->mLock.unlock();
126 if (waylandBuffer->mRenderBuffer && redrawing) {
fei.dengda0cd9f2024-07-24 09:25:11 +0800127 //TRACE(waylandBuffer->mLogCategory,"renderBuffer:%p, pts:%lld us",waylandBuffer->mRenderBuffer,waylandBuffer->mRenderBuffer->pts/1000);
fei.dengf7a0cd32023-08-29 09:36:37 +0000128 waylandBuffer->mDisplay->handleFrameDisplayedCallback(waylandBuffer);
129 }
130 wl_callback_destroy (callback);
131}
132
133static const struct wl_callback_listener frame_callback_listener = {
134 WaylandBuffer::frameDisplayedCallback
135};
136
137int WaylandBuffer::constructWlBuffer(RenderBuffer *buf)
138{
139 struct wl_buffer * wlbuffer = NULL;
fei.deng640c3c92024-04-12 08:31:19 +0000140 WaylandDisplay::AmlConfigAPIList *amlConfigAPI = mDisplay->getAmlConfigAPIList();
fei.dengf7a0cd32023-08-29 09:36:37 +0000141
142 mRenderBuffer = buf;
143 if (mWaylandWlWrap) {
fei.dengb9a1a572023-09-13 01:33:57 +0000144 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000145 }
146
147 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
fei.dengb9a1a572023-09-13 01:33:57 +0000148 WaylandDmaBuffer *waylanddma = new WaylandDmaBuffer(mDisplay, mLogCategory);
fei.dengf7a0cd32023-08-29 09:36:37 +0000149 wlbuffer = waylanddma->constructWlBuffer(&buf->dma, mBufferFormat);
150 if (!wlbuffer) {
151 delete waylanddma;
fei.dengb9a1a572023-09-13 01:33:57 +0000152 ERROR(mLogCategory,"create wl_buffer fail");
153 return ERROR_INVALID_OPERATION;
fei.dengf7a0cd32023-08-29 09:36:37 +0000154 }
155 mWaylandWlWrap = waylanddma;
156 mFrameWidth = buf->dma.width;
157 mFrameHeight = buf->dma.height;
fei.dengda0cd9f2024-07-24 09:25:11 +0800158 //TRACE(mLogCategory,"WaylandBuffer:%p,WaylandDmaBuffer:%p",this,mWaylandWlWrap);
fei.dengf7a0cd32023-08-29 09:36:37 +0000159 }
160
161 /*register buffer release listen*/
fei.deng640c3c92024-04-12 08:31:19 +0000162 if (amlConfigAPI->enableDropFrame) {
163 wl_buffer_add_listener (wlbuffer, &buffer_with_drop_listener, this);
164 } else {
165 wl_buffer_add_listener (wlbuffer, &buffer_listener, this);
166 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000167
fei.dengb9a1a572023-09-13 01:33:57 +0000168 return NO_ERROR;
fei.dengf7a0cd32023-08-29 09:36:37 +0000169}
170
171struct wl_buffer *WaylandBuffer::getWlBuffer()
172{
173 if (mWaylandWlWrap) {
174 return mWaylandWlWrap->getWlBuffer();
175 } else {
176 return NULL;
177 }
178}
179
180void WaylandBuffer::attach(struct wl_surface *surface)
181{
182 struct wl_callback *callback;
183 struct wl_buffer *wlbuffer = NULL;
184 if (mUsedByCompositor) {
fei.dengb9a1a572023-09-13 01:33:57 +0000185 DEBUG(mLogCategory,"buffer used by compositor");
fei.dengf7a0cd32023-08-29 09:36:37 +0000186 return;
187 }
188
189 //callback when this frame displayed
190 callback = wl_surface_frame (surface);
191 wl_callback_add_listener (callback, &frame_callback_listener, this);
192 mDisplay->setRedrawingPending(true);
193
194 wlbuffer = getWlBuffer();
195 if (wlbuffer) {
196 wl_surface_attach (surface, wlbuffer, 0, 0);
197 }
198
199 mUsedByCompositor = true;
200 mRedrawingPending = true;
fei.denga4abbd52024-07-11 19:17:50 +0800201}
202
fei.dengda0cd9f2024-07-24 09:25:11 +0800203/**
204 * @brief check wayland buffer is free. if this is free
205 * ,it will be delete by waylandbuffer manager
206 *
207 * @return true if this buffer is free
208 * @return false if this buffer will be used
209 */
fei.denga4abbd52024-07-11 19:17:50 +0800210bool WaylandBuffer::isFree()
211{
fei.dengda0cd9f2024-07-24 09:25:11 +0800212 int fw = mDisplay->getFrameWidth();
213 int fh = mDisplay->getFrameHeight();
214 Tls::Mutex::Autolock _l(mLock);
fei.denga4abbd52024-07-11 19:17:50 +0800215 if (!mWaylandWlWrap && !mRenderBuffer) {
216 return true;
217 }
fei.dengda0cd9f2024-07-24 09:25:11 +0800218 /*if resolution changed,this buffer should be deleted after weston
219 release this buffer */
220 if ((mFrameWidth > 0 && mFrameHeight > 0 && fw > 0 && fh > 0) &&
221 (mFrameWidth != fw || mFrameHeight != fh) &&
222 !mRenderBuffer && !mUsedByCompositor) {
223 return true;
224 }
fei.denga4abbd52024-07-11 19:17:50 +0800225 return false;
226};