1 /*
2 * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
3 * Authors:
4 * Zhiqin Wei <wzq@rock-chips.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #define LOG_NDEBUG 0
20 #ifdef LOG_TAG
21 #undef LOG_TAG
22 #define LOG_TAG "rockchiprga"
23 #endif
24
25 #include <stdint.h>
26 #include <sys/types.h>
27 #include <sys/ioctl.h>
28 #include <math.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <time.h>
32
33 #ifdef ANDROID
34 #include <utils/misc.h>
35 #include <cutils/properties.h>
36 #include "core/NormalRga.h"
37
38 #ifndef ANDROID_8
39 #include <gui/Surface.h>
40 #include <binder/IPCThreadState.h>
41 #include <gui/SurfaceComposerClient.h>
42 #endif
43
44 #include <android/log.h>
45 #include <log/log_main.h>
46 #include <utils/Atomic.h>
47 #include <utils/Errors.h>
48 #include <utils/Log.h>
49 #include <utils/Mutex.h>
50 #include <utils/Singleton.h>
51 #include <ui/PixelFormat.h>
52 #include <ui/GraphicBufferMapper.h>
53 #endif
54
55 #include "RockchipRga.h"
56
57 #ifdef LINUX
58 #include "NormalRga.h"
59 #include "drm.h"
60 #include "drm_mode.h"
61 #endif
62
63 #include "im2d_api/im2d.h"
64
65 #ifdef LINUX
local_drmIoctl(int fd,unsigned long request,void * arg)66 static int local_drmIoctl(int fd, unsigned long request, void *arg) {
67 int ret;
68
69 do {
70 ret = ioctl(fd, request, arg);
71 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
72 return ret;
73 }
74
local_drmPrimeHandleToFD(int fd,uint32_t handle,uint32_t flags,int * prime_fd)75 static int local_drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd) {
76 struct drm_prime_handle args;
77 int ret;
78
79 memset(&args, 0, sizeof(args));
80 args.fd = -1;
81 args.handle = handle;
82 args.flags = flags;
83 ret = local_drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
84 if (ret)
85 return ret;
86
87 *prime_fd = args.fd;
88 return 0;
89 }
90 #endif
91
92 #ifdef ANDROID
93 namespace android {
94 // ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(RockchipRga)95 ANDROID_SINGLETON_STATIC_INSTANCE(RockchipRga)
96 #else
97 RGA_SINGLETON_STATIC_INSTANCE(RockchipRga)
98 #endif
99
100 RockchipRga::RockchipRga():
101 mSupportRga(false),
102 mLogOnce(0),
103 mLogAlways(0),
104 mContext(NULL) {
105 RkRgaInit();
106
107 #ifdef ANDROID
108 property_set("vendor.rga_api.version", RGA_API_VERSION);
109 #endif
110 ALOGE("%s", RGA_API_FULL_VERSION);
111 }
112
~RockchipRga()113 RockchipRga::~RockchipRga() {
114 RgaDeInit(&mContext);
115 }
116
RkRgaInit()117 int RockchipRga::RkRgaInit() {
118 int ret = 0;
119
120 if (mSupportRga)
121 return 0;
122
123 ret = RgaInit(&mContext);
124 if(ret == 0)
125 mSupportRga = true;
126 else
127 mSupportRga = false;
128
129 return ret;
130 }
131
RkRgaDeInit()132 void RockchipRga::RkRgaDeInit() {
133 if (mSupportRga)
134 RgaDeInit(&mContext);
135
136 mSupportRga = false;
137 }
138
RkRgaGetContext(void ** ctx)139 void RockchipRga::RkRgaGetContext(void **ctx) {
140 *ctx = mContext;
141 }
142
143 #ifdef LINUX
RkRgaAllocBuffer(int drm_fd,bo_t * bo_info,int width,int height,int bpp,int flags)144 int RockchipRga::RkRgaAllocBuffer(int drm_fd, bo_t *bo_info, int width,
145 int height, int bpp, int flags) {
146 struct drm_mode_create_dumb arg;
147 int ret;
148
149 memset(&arg, 0, sizeof(arg));
150 arg.bpp = bpp;
151 arg.width = width;
152 arg.height = height;
153 arg.flags = flags;
154
155 ret = local_drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
156 if (ret) {
157 fprintf(stderr, "failed to create dumb buffer: %s\n", strerror(errno));
158 return ret;
159 }
160
161 bo_info->handle = arg.handle;
162 bo_info->size = arg.size;
163 bo_info->pitch = arg.pitch;
164
165 return 0;
166 }
167
RkRgaFreeBuffer(int drm_fd,bo_t * bo_info)168 int RockchipRga::RkRgaFreeBuffer(int drm_fd, bo_t *bo_info) {
169 struct drm_mode_destroy_dumb arg;
170 int ret;
171
172 if (bo_info->handle <= 0)
173 return -EINVAL;
174 memset(&arg, 0, sizeof(arg));
175 arg.handle = bo_info->handle;
176 ret = local_drmIoctl(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
177 if (ret) {
178 fprintf(stderr, "failed to destroy dumb buffer: %s\n", strerror(errno));
179 return -errno;
180 }
181 bo_info->handle = 0;
182
183 return 0;
184
185 }
186
RkRgaGetAllocBufferExt(bo_t * bo_info,int width,int height,int bpp,int flags)187 int RockchipRga::RkRgaGetAllocBufferExt(bo_t *bo_info, int width, int height, int bpp, int flags) {
188 static const char* card = "/dev/dri/card0";
189 int ret;
190 int drm_fd;
191 int flag = O_RDWR;
192 #ifdef O_CLOEXEC
193 flag |= O_CLOEXEC;
194 #endif
195 bo_info->fd = -1;
196 bo_info->handle = 0;
197 drm_fd = open(card, flag);
198 if (drm_fd < 0) {
199 fprintf(stderr, "Fail to open %s: %m\n", card);
200 return -errno;
201 }
202 ret = RkRgaAllocBuffer(drm_fd, bo_info, width, height, bpp, flags);
203 if (ret) {
204 close(drm_fd);
205 return ret;
206 }
207 bo_info->fd = drm_fd;
208 return 0;
209 }
210
RkRgaGetAllocBuffer(bo_t * bo_info,int width,int height,int bpp)211 int RockchipRga::RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp) {
212 return RkRgaGetAllocBufferExt(bo_info, width, height, bpp, 0);
213 }
214
RkRgaGetAllocBufferCache(bo_t * bo_info,int width,int height,int bpp)215 int RockchipRga::RkRgaGetAllocBufferCache(bo_t *bo_info, int width, int height, int bpp) {
216 return RkRgaGetAllocBufferExt(bo_info, width, height, bpp, ROCKCHIP_BO_CACHABLE);
217 }
218
RkRgaGetMmap(bo_t * bo_info)219 int RockchipRga::RkRgaGetMmap(bo_t *bo_info) {
220 struct drm_mode_map_dumb arg;
221 void *map;
222 int ret;
223
224 memset(&arg, 0, sizeof(arg));
225 arg.handle = bo_info->handle;
226 ret = local_drmIoctl(bo_info->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
227 if (ret)
228 return ret;
229 map = mmap64(0, bo_info->size, PROT_READ | PROT_WRITE, MAP_SHARED, bo_info->fd, arg.offset);
230 if (map == MAP_FAILED)
231 return -EINVAL;
232 bo_info->ptr = map;
233 return 0;
234 }
235
RkRgaUnmap(bo_t * bo_info)236 int RockchipRga::RkRgaUnmap(bo_t *bo_info) {
237 munmap(bo_info->ptr, bo_info->size);
238 bo_info->ptr = NULL;
239 return 0;
240 }
241
RkRgaFree(bo_t * bo_info)242 int RockchipRga::RkRgaFree(bo_t *bo_info) {
243 int ret;
244 if (bo_info->fd < 0)
245 return -EINVAL;
246 ret = RkRgaFreeBuffer(bo_info->fd, bo_info);
247 close(bo_info->fd);
248 bo_info->fd = -1;
249 return ret;
250 }
251
RkRgaGetBufferFd(bo_t * bo_info,int * fd)252 int RockchipRga::RkRgaGetBufferFd(bo_t *bo_info, int *fd) {
253 int ret = 0;
254 ret = local_drmPrimeHandleToFD(bo_info->fd, bo_info->handle, DRM_CLOEXEC | DRM_RDWR, fd);
255 return ret;
256 }
257 #endif
258
259 #ifdef ANDROID
RkRgaGetBufferFd(buffer_handle_t handle,int * fd)260 int RockchipRga::RkRgaGetBufferFd(buffer_handle_t handle, int *fd) {
261 int ret = 0;
262 ret = RkRgaGetHandleFd(handle, fd);
263 return ret;
264 }
265
RkRgaGetHandleMapCpuAddress(buffer_handle_t handle,void ** buf)266 int RockchipRga::RkRgaGetHandleMapCpuAddress(buffer_handle_t handle, void **buf) {
267 int ret = 0;
268 ret = RkRgaGetHandleMapAddress(handle, buf);
269 return ret;
270 }
271 #endif
272
RkRgaBlit(rga_info * src,rga_info * dst,rga_info * src1)273 int RockchipRga::RkRgaBlit(rga_info *src, rga_info *dst, rga_info *src1) {
274 int ret = 0;
275 ret = RgaBlit(src, dst, src1);
276 if (ret) {
277 RkRgaLogOutUserPara(src);
278 RkRgaLogOutUserPara(dst);
279 RkRgaLogOutUserPara(src1);
280 ALOGE("This output the user parameters when rga call blit fail");
281 }
282 return ret;
283 }
284
RkRgaFlush()285 int RockchipRga::RkRgaFlush() {
286 int ret = 0;
287 ret = RgaFlush();
288 if (ret) {
289 ALOGE("RgaFlush Failed");
290 }
291 return ret;
292 }
293
RkRgaCollorFill(rga_info * dst)294 int RockchipRga::RkRgaCollorFill(rga_info *dst) {
295 int ret = 0;
296 ret = RgaCollorFill(dst);
297 return ret;
298 }
299
RkRgaCollorPalette(rga_info * src,rga_info * dst,rga_info * lut)300 int RockchipRga::RkRgaCollorPalette(rga_info *src, rga_info *dst, rga_info *lut) {
301 int ret = 0;
302 ret = RgaCollorPalette(src, dst, lut);
303 if (ret) {
304 RkRgaLogOutUserPara(src);
305 RkRgaLogOutUserPara(dst);
306 ALOGE("This output the user parameters when rga call CollorPalette fail");
307 }
308 return ret;
309 }
310
RkRgaLogOutUserPara(rga_info * rgaInfo)311 int RockchipRga::RkRgaLogOutUserPara(rga_info *rgaInfo) {
312 if (!rgaInfo)
313 return -EINVAL;
314
315 ALOGE("handl-fd-vir-phy-hnd-format[%d, %d, %p, %p, %lx, %d]",
316 rgaInfo->handle, rgaInfo->fd, rgaInfo->virAddr, rgaInfo->phyAddr,
317 (unsigned long)rgaInfo->hnd, rgaInfo->format);
318 ALOGE("rect[%d, %d, %d, %d, %d, %d, %d, %d]",
319 rgaInfo->rect.xoffset, rgaInfo->rect.yoffset,
320 rgaInfo->rect.width, rgaInfo->rect.height, rgaInfo->rect.wstride,
321 rgaInfo->rect.hstride, rgaInfo->rect.format, rgaInfo->rect.size);
322 ALOGE("f-blend-size-rotation-col-log-mmu[%d, %x, %d, %d, %d, %d, %d]",
323 rgaInfo->format, rgaInfo->blend, rgaInfo->bufferSize,
324 rgaInfo->rotation, rgaInfo->color, rgaInfo->testLog, rgaInfo->mmuFlag);
325 return 0;
326 }
327
328 // ---------------------------------------------------------------------------
329 #ifdef ANDROID
330 }; // namespace android
331 #endif
332
333