blob: 2e1004147b32a3134b04c032d10ef51b31915c8a [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"
36
37#define TAG "rlib:wayland_buffer"
38
39WaylandBuffer::WaylandBuffer(WaylandDisplay *display)
40 : mDisplay(display)
41{
42 mRenderBuffer = NULL;
43 mWaylandWlWrap = NULL;
44 mUsedByCompositor = false;
45 mRedrawingPending = false;
46 mRealTime = -1;
47 mBufferFormat = VIDEO_FORMAT_UNKNOWN;
48 mFrameWidth = 0;
49 mFrameHeight = 0;
50}
51
52WaylandBuffer::~WaylandBuffer()
53{
54 /*if weston obtains the wl_buffer,we need
55 * notify user to release renderBuffer*/
56 if (mRenderBuffer) {
57 mDisplay->handleBufferReleaseCallback(this);
58 mRenderBuffer = NULL;
59 }
60 if (mWaylandWlWrap) {
61 delete mWaylandWlWrap;
62 mWaylandWlWrap = NULL;
63 }
64}
65
66void WaylandBuffer::bufferRelease (void *data, struct wl_buffer *wl_buffer)
67{
68 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
69 TRACE("--wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
70 waylandBuffer->mUsedByCompositor = false;
71 //sometimes this callback be called twice
72 //this cause double free,so check mRenderBuffer
73 if (waylandBuffer->mRenderBuffer) {
74 waylandBuffer->mDisplay->handleBufferReleaseCallback(waylandBuffer);
75 waylandBuffer->mRenderBuffer = NULL;
76 }
77}
78
79void WaylandBuffer::bufferdroped (void *data, struct wl_buffer *wl_buffer)
80{
81 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
82 WARNING("--droped wl_buffer:%p,renderBuffer:%p",wl_buffer,waylandBuffer->mRenderBuffer);
83 waylandBuffer->mUsedByCompositor = false;
84
85 if (waylandBuffer->mRenderBuffer) {
86 waylandBuffer->mDisplay->handleFrameDropedCallback(waylandBuffer);
87 waylandBuffer->mDisplay->handleBufferReleaseCallback(waylandBuffer);
88 waylandBuffer->mRenderBuffer = NULL;
89 }
90}
91
92static const struct wl_buffer_listener buffer_listener = {
93 WaylandBuffer::bufferRelease,
94 WaylandBuffer::bufferdroped
95};
96// static const struct wl_buffer_listener buffer_listener = {
97// WaylandBuffer::bufferRelease
98// };
99
100/*if we commit buffers to weston too fast,it causes weston can't invoke this callback*/
101void WaylandBuffer::frameDisplayedCallback(void *data, struct wl_callback *callback, uint32_t time)
102{
103 WaylandBuffer* waylandBuffer = static_cast<WaylandBuffer*>(data);
104 waylandBuffer->mDisplay->setRedrawingPending(false);
105 waylandBuffer->mLock.lock();
106 bool redrawing = waylandBuffer->mRedrawingPending;
107 waylandBuffer->mRedrawingPending = false;
108 waylandBuffer->mLock.unlock();
109 if (waylandBuffer->mRenderBuffer && redrawing) {
110 waylandBuffer->mDisplay->handleFrameDisplayedCallback(waylandBuffer);
111 }
112 wl_callback_destroy (callback);
113}
114
115static const struct wl_callback_listener frame_callback_listener = {
116 WaylandBuffer::frameDisplayedCallback
117};
118
119int WaylandBuffer::constructWlBuffer(RenderBuffer *buf)
120{
121 struct wl_buffer * wlbuffer = NULL;
122
123 mRenderBuffer = buf;
124 if (mWaylandWlWrap) {
125 return 0;
126 }
127
128 if (buf->flag & BUFFER_FLAG_DMA_BUFFER) {
129 WaylandDmaBuffer *waylanddma = new WaylandDmaBuffer(mDisplay);
130 wlbuffer = waylanddma->constructWlBuffer(&buf->dma, mBufferFormat);
131 if (!wlbuffer) {
132 delete waylanddma;
133 ERROR("create wl_buffer fail");
134 return -1;
135 }
136 mWaylandWlWrap = waylanddma;
137 mFrameWidth = buf->dma.width;
138 mFrameHeight = buf->dma.height;
139 }
140
141 /*register buffer release listen*/
142 wl_buffer_add_listener (wlbuffer, &buffer_listener, this);
143
144 return 0;
145}
146
147struct wl_buffer *WaylandBuffer::getWlBuffer()
148{
149 if (mWaylandWlWrap) {
150 return mWaylandWlWrap->getWlBuffer();
151 } else {
152 return NULL;
153 }
154}
155
156void WaylandBuffer::attach(struct wl_surface *surface)
157{
158 struct wl_callback *callback;
159 struct wl_buffer *wlbuffer = NULL;
160 if (mUsedByCompositor) {
161 DEBUG("buffer used by compositor");
162 return;
163 }
164
165 //callback when this frame displayed
166 callback = wl_surface_frame (surface);
167 wl_callback_add_listener (callback, &frame_callback_listener, this);
168 mDisplay->setRedrawingPending(true);
169
170 wlbuffer = getWlBuffer();
171 if (wlbuffer) {
172 wl_surface_attach (surface, wlbuffer, 0, 0);
173 }
174
175 mUsedByCompositor = true;
176 mRedrawingPending = true;
177}