blob: bf221ecbe7b9f0ed17628a7f9e08ae6ef4739329 [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/mman.h>
22#include <sys/epoll.h>
23#include <string.h>
24#include <stdlib.h>
25#include "wayland_shm.h"
26#include "Logger.h"
27#include "wayland_display.h"
fei.dengb9a1a572023-09-13 01:33:57 +000028#include "ErrorCode.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000029#include "Utils.h"
30
31#define TAG "rlib:wayland_shm"
32
fei.dengb9a1a572023-09-13 01:33:57 +000033WaylandShmBuffer::WaylandShmBuffer(WaylandDisplay *display, int logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +000034{
35 mDisplay = display;
36 mWlBuffer = NULL;
37 mStride = 0;
38 mData = NULL;
39 mSize = 0;
40 mWidth = 0;
41 mHeight = 0;
42 mFormat = VIDEO_FORMAT_UNKNOWN;
fei.dengb9a1a572023-09-13 01:33:57 +000043 mLogCategory = logCategory;
fei.dengf7a0cd32023-08-29 09:36:37 +000044}
45
46WaylandShmBuffer::~WaylandShmBuffer()
47{
48
49}
50
51struct wl_buffer *WaylandShmBuffer::constructWlBuffer(int width, int height, RenderVideoFormat format)
52{
53 struct wl_shm_pool *pool;
54 int fd;
55 int ret;
56
57 mWidth = width;
58 mHeight = height;
59 mFormat = format;
60
61 switch (format)
62 {
63 case VIDEO_FORMAT_YUY2:
64 case VIDEO_FORMAT_YVYU:
65 case VIDEO_FORMAT_UYVY:
66 case VIDEO_FORMAT_VYUY: {
67 mStride = ROUND_UP_4 (width * 2);
68 mSize = mStride * height;
69 } break;
70 case VIDEO_FORMAT_AYUV:
71 case VIDEO_FORMAT_RGBx:
72 case VIDEO_FORMAT_RGBA:
73 case VIDEO_FORMAT_BGRA:
74 case VIDEO_FORMAT_xRGB:
75 case VIDEO_FORMAT_ARGB:
76 case VIDEO_FORMAT_xBGR:
77 case VIDEO_FORMAT_ABGR:
78 case VIDEO_FORMAT_r210:
79 case VIDEO_FORMAT_Y410:
80 case VIDEO_FORMAT_VUYA:
81 case VIDEO_FORMAT_BGR10A2_LE:
82 case VIDEO_FORMAT_BGRx: {
83 mStride = width * 4;
84 mSize = mStride * height;
85 } break;
86
87 default:
88 break;
89 }
90
91 if (mStride <= 0 || mSize <= 0) {
fei.dengb9a1a572023-09-13 01:33:57 +000092 WARNING(mLogCategory,"Unsupport format");
fei.dengf7a0cd32023-08-29 09:36:37 +000093 goto tag_err;
94 }
95
96 fd = createAnonymousFile(mSize);
97 if (fd < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +000098 ERROR(mLogCategory,"create anonymous file fail");
fei.dengf7a0cd32023-08-29 09:36:37 +000099 return NULL;
100 }
101
102 mData = mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
103 if (mData == MAP_FAILED) {
fei.dengb9a1a572023-09-13 01:33:57 +0000104 ERROR(mLogCategory,"mmap failed: %s",strerror(errno));
fei.dengf7a0cd32023-08-29 09:36:37 +0000105 goto tag_err;
106 }
107 //init buffer data,set alpha transparent
108 memset(mData, 0x00, mSize);
109
110 if (mDisplay->getShm() == NULL) {
fei.dengb9a1a572023-09-13 01:33:57 +0000111 ERROR(mLogCategory,"Shm is null");
fei.dengf7a0cd32023-08-29 09:36:37 +0000112 goto tag_err;
113 }
114
115 uint32_t shmFormat;
116 ret = mDisplay->toShmBufferFormat(format, &shmFormat);
fei.dengb9a1a572023-09-13 01:33:57 +0000117 if (ret != NO_ERROR) {
118 ERROR(mLogCategory,"video format to shm format fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000119 goto tag_err;
120 }
121
122 pool = wl_shm_create_pool(mDisplay->getShm(), fd, mSize);
123 mWlBuffer = wl_shm_pool_create_buffer(pool, 0,
124 width, height,
125 mStride, shmFormat);
126
127 wl_shm_pool_destroy(pool);
128 close(fd);
129 fd = -1;
130 return mWlBuffer;
131
132tag_err:
133 if (fd > 0) {
134 close(fd);
135 fd = -1;
136 }
137 return NULL;
138}
139
140int WaylandShmBuffer::createAnonymousFile(off_t size)
141{
142 char filename[1024];
143 const char *path;
144 static int init = 0;
145 int fd = -1;
146 int ret;
147
148 path = getenv("XDG_RUNTIME_DIR");
149 if (!path) {
fei.dengb9a1a572023-09-13 01:33:57 +0000150 WARNING(mLogCategory,"not set XDG_RUNTIME_DIR env");
fei.dengf7a0cd32023-08-29 09:36:37 +0000151 goto tag_err;
152 }
153
154 /* allocate shm pool */
155 snprintf (filename, 1024, "%s/%s-%d-%s", path, "wayland-shm", init++, "XXXXXX");
156
157 fd = mkstemp(filename);
158 if (fd < 0) {
fei.dengb9a1a572023-09-13 01:33:57 +0000159 ERROR(mLogCategory,"make anonymous file fail");
fei.dengf7a0cd32023-08-29 09:36:37 +0000160 goto tag_err;
161 }
162
163 unlink(filename);
164
165 //set cloexec
166 {
167 long flags;
168
169 flags = fcntl(fd, F_GETFD);
170 if (flags == -1)
171 goto tag_err;
172
173 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
174 goto tag_err;
175 }
176
177 do {
178 ret = ftruncate(fd, size);
179 } while (ret < 0 && errno == EINTR);
180 if (ret < 0) {
181 goto tag_err;
182 }
183
184 return fd;
185
186tag_err:
187 if (fd > 0) {
188 close(fd);
189 fd = -1;
190 }
191
192 return -1;
193}