blob: 5b23abaa9969f90c667080744ab6fea6b815a933 [file] [log] [blame]
/*
* Copyright (C) 2021 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/epoll.h>
#include <string.h>
#include <stdlib.h>
#include <wayland-client.h>
#include "xdg-shell-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "fullscreen-shell-unstable-v1-client-protocol.h"
#include "wayland_dma.h"
#include "Logger.h"
#include "wayland_display.h"
#include "ErrorCode.h"
#define TAG "rlib:wayland_dma"
WaylandDmaBuffer::WaylandDmaBuffer(WaylandDisplay *display, int logCategory)
: mDisplay(display),
mLogCategory(logCategory)
{
mRenderDmaBuffer = {0,};
mWlBuffer = NULL;
mData = NULL;
mSize = 0;
}
WaylandDmaBuffer::~WaylandDmaBuffer()
{
//release wl_buffer
if (mWlBuffer) {
TRACE(mLogCategory,"delete WaylandDmaBuffer:%p,wl_buffer:%p",this,mWlBuffer);
wl_buffer_destroy(mWlBuffer);
mWlBuffer = NULL;
}
}
void WaylandDmaBuffer::dmabufCreateSuccess(void *data,
struct zwp_linux_buffer_params_v1 *params,
struct wl_buffer *new_buffer)
{
WaylandDmaBuffer *waylandDma = static_cast<WaylandDmaBuffer*>(data);
TRACE(waylandDma->mLogCategory,"++create dma wl_buffer:%p ",new_buffer);
Tls::Mutex::Autolock _l(waylandDma->mMutex);
waylandDma->mWlBuffer = new_buffer;
waylandDma->mCondition.signal();
}
void WaylandDmaBuffer::dmabufCreateFail(void *data,
struct zwp_linux_buffer_params_v1 *params)
{
WaylandDmaBuffer *waylandDma = static_cast<WaylandDmaBuffer*>(data);
Tls::Mutex::Autolock _l(waylandDma->mMutex);
TRACE(waylandDma->mLogCategory,"!!!create dma wl_buffer fail");
waylandDma->mWlBuffer = NULL;
waylandDma->mCondition.signal();
}
static const struct zwp_linux_buffer_params_v1_listener dmabuf_params_listener = {
WaylandDmaBuffer::dmabufCreateSuccess,
WaylandDmaBuffer::dmabufCreateFail
};
struct wl_buffer *WaylandDmaBuffer::constructWlBuffer(RenderDmaBuffer *dmabuf, RenderVideoFormat format)
{
struct zwp_linux_buffer_params_v1 *params = NULL;
int ret;
int64_t timeout;
uint64_t formatModifier = 0;
uint32_t flags = 0;
uint32_t dmabufferFormat;
ret = mDisplay->toDmaBufferFormat(format, &dmabufferFormat, &formatModifier);
if (ret != NO_ERROR) {
ERROR(mLogCategory,"Error change render video format to dmabuffer format fail");
return NULL;
}
//check dma buffer
if (dmabuf->planeCnt < 0) {
ERROR(mLogCategory,"Error dmabuf plane count is 0");
return NULL;
}
for (int i = 0; i < dmabuf->planeCnt; i++) {
if (dmabuf->fd[i] <= 0) {
ERROR(mLogCategory,"Error dmabuf plane fd is 0");
return NULL;
}
}
memcpy(&mRenderDmaBuffer, dmabuf, sizeof(RenderDmaBuffer));
params = zwp_linux_dmabuf_v1_create_params (mDisplay->getDmaBuf());
if (!params) {
ERROR(mLogCategory, "zwp_linux_dmabuf_v1_create_params fail");
return NULL;
}
//told weston to direct display drm buffer
if (mDisplay->getWlDirectDisplay()) {
weston_direct_display_v1_enable(mDisplay->getWlDirectDisplay(), params);
}
for (int i = 0; i < dmabuf->planeCnt; i++) {
TRACE(mLogCategory,"dma buf index:%d,fd:%d,stride:%d,offset:%d",i, dmabuf->fd[i],dmabuf->stride[i], dmabuf->offset[i]);
zwp_linux_buffer_params_v1_add(params,
dmabuf->fd[i],
i, /*plane_idx*/
dmabuf->offset[i], /*data offset*/
dmabuf->stride[i],
formatModifier >> 32,
formatModifier & 0xffffffff);
}
/* Request buffer creation */
zwp_linux_buffer_params_v1_add_listener (params, &dmabuf_params_listener, (void *)this);
TRACE(mLogCategory,"zwp_linux_buffer_params_v1_create,dma width:%d,height:%d,dmabufferformat:%d",dmabuf->width,dmabuf->height,dmabufferFormat);
zwp_linux_buffer_params_v1_create (params, dmabuf->width, dmabuf->height, dmabufferFormat, flags);
/* Wait for the request answer */
wl_display_flush (mDisplay->getWlDisplay());
Tls::Mutex::Autolock _l(mMutex);
if (!mWlBuffer) { //if this wlbuffer had created,don't wait zwp linux buffer callback
mWlBuffer =(struct wl_buffer *)0xffffffff;
while (mWlBuffer == (struct wl_buffer *)0xffffffff) { //try wait for 1000 ms
if (ERROR_TIMED_OUT == mCondition.waitRelative(mMutex, 1000/*microsecond*/)) {
WARNING(mLogCategory,"zwp_linux_buffer_params_v1_create timeout");
mWlBuffer = NULL;
}
}
}
//destroy zwp linux buffer params
zwp_linux_buffer_params_v1_destroy (params);
return mWlBuffer;
}