242 lines
5.9 KiB
C++
242 lines
5.9 KiB
C++
/*
|
|
* 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/mman.h>
|
|
#include <sys/epoll.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "wayland_shm.h"
|
|
#include "Logger.h"
|
|
#include "wayland_display.h"
|
|
#include "ErrorCode.h"
|
|
#include "Utils.h"
|
|
#include "wayland_videoformat.h"
|
|
|
|
#define TAG "rlib:wayland_shm"
|
|
|
|
WaylandShmBuffer::WaylandShmBuffer(WaylandDisplay *display, int logCategory)
|
|
{
|
|
mDisplay = display;
|
|
mWlBuffer = NULL;
|
|
mStride = 0;
|
|
mData = NULL;
|
|
mSize = 0;
|
|
mWidth = 0;
|
|
mHeight = 0;
|
|
mFormat = VIDEO_FORMAT_UNKNOWN;
|
|
mLogCategory = logCategory;
|
|
}
|
|
|
|
WaylandShmBuffer::~WaylandShmBuffer()
|
|
{
|
|
if (mWlBuffer) {
|
|
wl_buffer_destroy(mWlBuffer);
|
|
mWlBuffer = NULL;
|
|
}
|
|
if (mData) {
|
|
munmap(mData, mSize);
|
|
mData = NULL;
|
|
}
|
|
}
|
|
|
|
struct wl_buffer *WaylandShmBuffer::constructAreaShmWlBuffer(int width, int height, RenderVideoFormat format)
|
|
{
|
|
struct wl_shm_pool *pool = NULL;
|
|
int fd = -1;
|
|
int ret = 0;
|
|
|
|
mWidth = width;
|
|
mHeight = height;
|
|
mFormat = format;
|
|
|
|
switch (format)
|
|
{
|
|
case VIDEO_FORMAT_YUY2:
|
|
case VIDEO_FORMAT_YVYU:
|
|
case VIDEO_FORMAT_UYVY:
|
|
case VIDEO_FORMAT_VYUY: {
|
|
mStride = ROUND_UP_4 (width * 2);
|
|
mSize = mStride * height;
|
|
} break;
|
|
case VIDEO_FORMAT_AYUV:
|
|
case VIDEO_FORMAT_RGBx:
|
|
case VIDEO_FORMAT_RGBA:
|
|
case VIDEO_FORMAT_BGRA:
|
|
case VIDEO_FORMAT_xRGB:
|
|
case VIDEO_FORMAT_ARGB:
|
|
case VIDEO_FORMAT_xBGR:
|
|
case VIDEO_FORMAT_ABGR:
|
|
case VIDEO_FORMAT_r210:
|
|
case VIDEO_FORMAT_Y410:
|
|
case VIDEO_FORMAT_VUYA:
|
|
case VIDEO_FORMAT_BGR10A2_LE:
|
|
case VIDEO_FORMAT_BGRx: {
|
|
mStride = width * 4;
|
|
mSize = mStride * height;
|
|
} break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (mStride <= 0 || mSize <= 0) {
|
|
WARNING(mLogCategory,"Unsupport format");
|
|
goto tag_err;
|
|
}
|
|
|
|
fd = createAnonymousFile(mSize);
|
|
if (fd < 0) {
|
|
ERROR(mLogCategory,"create anonymous file fail");
|
|
return NULL;
|
|
}
|
|
|
|
mData = mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
|
if (mData == MAP_FAILED) {
|
|
ERROR(mLogCategory,"mmap failed: %s",strerror(errno));
|
|
mData = NULL;
|
|
goto tag_err;
|
|
}
|
|
//init buffer data,set alpha transparent
|
|
memset(mData, 0x00, mSize);
|
|
|
|
if (mDisplay->getShm() == NULL) {
|
|
ERROR(mLogCategory,"Shm is null");
|
|
goto tag_err;
|
|
}
|
|
|
|
uint32_t shmFormat;
|
|
ret = mDisplay->toShmBufferFormat(format, &shmFormat);
|
|
if (ret != NO_ERROR) {
|
|
ERROR(mLogCategory,"video format to shm format fail");
|
|
goto tag_err;
|
|
}
|
|
|
|
pool = wl_shm_create_pool(mDisplay->getShm(), fd, mSize);
|
|
mWlBuffer = wl_shm_pool_create_buffer(pool, 0,
|
|
width, height,
|
|
mStride, shmFormat);
|
|
|
|
wl_shm_pool_destroy(pool);
|
|
close(fd);
|
|
fd = -1;
|
|
return mWlBuffer;
|
|
|
|
tag_err:
|
|
if (fd > 0) {
|
|
close(fd);
|
|
fd = -1;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief request shm memory buffer. only support 1 plane
|
|
*
|
|
* @param buffer
|
|
* @param format
|
|
* @return struct wl_buffer*
|
|
*/
|
|
struct wl_buffer *WaylandShmBuffer::constructVideoWlBuffer(RenderBuffer *buffer, RenderVideoFormat format)
|
|
{
|
|
struct wl_shm_pool *pool = NULL;
|
|
uint32_t shmFormat;
|
|
int ret;
|
|
int fd = -1;
|
|
|
|
ret = mDisplay->toShmBufferFormat(format, &shmFormat);
|
|
if (ret != NO_ERROR) {
|
|
ERROR(mLogCategory,"Error change render video format to dmabuffer format fail");
|
|
return NULL;
|
|
}
|
|
|
|
mFormat = format;
|
|
mWidth = buffer->dma.width;
|
|
mHeight = buffer->dma.height;
|
|
mStride = buffer->dma.stride[0];
|
|
mSize = buffer->dma.size[0];
|
|
mOffset = buffer->dma.offset[0];
|
|
fd = buffer->dma.fd[0];
|
|
|
|
TRACE(mLogCategory,"shm buf %s,fd:%d,stride:%d,size:%d (%dx%d)",print_shm_format_name(shmFormat), fd, mStride, mSize, mWidth, mHeight);
|
|
pool = wl_shm_create_pool(mDisplay->getShm(), fd, mSize);
|
|
if (pool) {
|
|
mWlBuffer = wl_shm_pool_create_buffer(pool, mOffset,
|
|
mWidth, mHeight,
|
|
mStride, shmFormat);
|
|
wl_shm_pool_destroy(pool);
|
|
}
|
|
|
|
return mWlBuffer;
|
|
}
|
|
|
|
int WaylandShmBuffer::createAnonymousFile(off_t size)
|
|
{
|
|
char filename[1024];
|
|
const char *path;
|
|
static int init = 0;
|
|
int fd = -1;
|
|
int ret;
|
|
|
|
path = getenv("XDG_RUNTIME_DIR");
|
|
if (!path) {
|
|
WARNING(mLogCategory,"not set XDG_RUNTIME_DIR env");
|
|
goto tag_err;
|
|
}
|
|
|
|
/* allocate shm pool */
|
|
snprintf (filename, 1024, "%s/%s-%d-%s", path, "wayland-shm", init++, "XXXXXX");
|
|
|
|
fd = mkstemp(filename);
|
|
if (fd < 0) {
|
|
ERROR(mLogCategory,"make anonymous file fail");
|
|
goto tag_err;
|
|
}
|
|
|
|
unlink(filename);
|
|
|
|
//set cloexec
|
|
{
|
|
long flags;
|
|
|
|
flags = fcntl(fd, F_GETFD);
|
|
if (flags == -1)
|
|
goto tag_err;
|
|
|
|
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
|
goto tag_err;
|
|
}
|
|
|
|
do {
|
|
ret = ftruncate(fd, size);
|
|
} while (ret < 0 && errno == EINTR);
|
|
if (ret < 0) {
|
|
goto tag_err;
|
|
}
|
|
|
|
return fd;
|
|
|
|
tag_err:
|
|
if (fd > 0) {
|
|
close(fd);
|
|
fd = -1;
|
|
}
|
|
|
|
return -1;
|
|
} |