forked from rock64-android/hardware-rockchip-hwcomposer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhwc_ipp.cpp
executable file
·325 lines (281 loc) · 8.67 KB
/
hwc_ipp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/*
* rockchip hwcomposer( 2D graphic acceleration unit) .
*
* Copyright (C) 2015 Rockchip Electronics Co., Ltd.
*/
#include "hwc_ipp.h"
#define ION_SIZE 1024*1024*6
#define ALIGN(n, align) \
( \
((n) + ((align) - 1)) & ~((align) - 1) \
)
struct tVPU_FRAME
{
uint32_t videoAddr[2]; // 0: Y address; 1: UV address;
uint32_t width; // 16 aligned frame width
uint32_t height; // 16 aligned frame height
};
typedef struct ipp_buffer_t
{
int ion_client;
int shared_fd;
unsigned long ion_phy_addr;
ion_user_handle_t ion_hnd;
int ipp_fd;
//ion_buffer_t *pion;
//ion_device_t *ion_device;
uint32_t offset;
uint32_t Yrgb;
uint32_t CbrMst;
} ipp_buffer_t;
static ipp_buffer_t ipp_buffer;
static IPP_FORMAT ipp_get_format(int format)
{
ALOGV("Enter %s", __FUNCTION__);
IPP_FORMAT ipp_format = IPP_IMGTYPE_LIMIT;
switch (format)
{
#if 0 //only surport video,because can get phs addr for video
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
ipp_format = IPP_Y_CBCR_H2V1;
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
ipp_format = IPP_XRGB_8888;
break;
case HAL_PIXEL_FORMAT_RGB_565:
ipp_format = IPP_RGB_565;
break;
case HAL_PIXEL_FORMAT_YV12:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCbCr_NV12:
#endif
case HAL_PIXEL_FORMAT_YCrCb_NV12_VIDEO:
ipp_format = IPP_Y_CBCR_H2V2;
break;
default:
ipp_format = IPP_IMGTYPE_LIMIT;
}
return ipp_format;
}
static ROT_DEG ipp_get_rot(int rot)
{
ALOGV("Enter %s", __FUNCTION__);
ROT_DEG ipp_rot = IPP_ROT_LIMIT;
switch (rot)
{
case HAL_TRANSFORM_FLIP_H:
ipp_rot = IPP_ROT_Y_FLIP;
break;
case HAL_TRANSFORM_FLIP_V:
ipp_rot = IPP_ROT_X_FLIP;
break;
case HAL_TRANSFORM_ROT_90:
ipp_rot = IPP_ROT_90;
break;
case HAL_TRANSFORM_ROT_180:
ipp_rot = IPP_ROT_180;
break;
case HAL_TRANSFORM_ROT_270:
ipp_rot = IPP_ROT_270;
break;
default:
ipp_rot = IPP_ROT_LIMIT;
}
return ipp_rot;
}
static int ipp_x_aligned(int w)
{
return ALIGN(w, 8);
}
static void dump(void* vaddr, int width, int height)
{
static int DumpSurfaceCount1 = 0;
FILE * pfile = NULL;
char layername[100] ;
memset(layername, 0, sizeof(layername));
system("mkdir /data/dump/ && chmod /data/dump/ 777 ");
//mkdir( "/data/dump/",777);
sprintf(layername, "/data/dump/src_fb_dmlayer_%d_%d_%d.bin", width, height, DumpSurfaceCount1);
pfile = fopen(layername, "wb");
if (pfile)
{
fwrite((const void *)vaddr, (size_t)(width*width*3) / 2, 1, pfile);
fclose(pfile);
}
DumpSurfaceCount1++;
}
static int ipp_format_is_supported(int format)
{
ALOGV("Enter %s", __FUNCTION__);
IPP_FORMAT ipp_format = ipp_get_format(format);
return (int)ipp_format;
}
static int ipp_set_req(struct private_handle_t *handle, int tranform, struct rk29_ipp_req *req)
{
#ifdef TARGET_BOARD_PLATFORM_RK30XXB
tVPU_FRAME *pVideo = (tVPU_FRAME *)handle->iBase;
#else
tVPU_FRAME *pVideo = (tVPU_FRAME *)handle->base;
#endif
int width = pVideo->width;
int height = pVideo->height;
int format = GPU_FORMAT;
int rot = tranform;
int ipp_format = ipp_get_format(format);
int ipp_rot = ipp_get_rot(rot);
uint32_t videoLen = (width * height) * 3 / 2;
uint32_t ipp_phys_addr_base = ipp_buffer.ion_phy_addr + ipp_buffer.offset;
if (ipp_phys_addr_base + videoLen >= (ipp_buffer.ion_phy_addr + ION_SIZE))
{
ipp_buffer.offset = 0;
ipp_phys_addr_base = ipp_buffer.ion_phy_addr + ipp_buffer.offset;
}
req->src0.YrgbMst = pVideo->videoAddr[0]; //
req->src0.CbrMst = pVideo->videoAddr[1];//cbcr phys
req->src0.w = width;
req->src0.h = height;
req->src0.fmt = ipp_format;//420
ALOGV(">>IPP:addr(%x,%x),w=%d,h=%d,format=%d,ipp_rot=%d,tranform=%d,src(%d,%d)", req->src0.YrgbMst, req->src0.CbrMst, req->src0.w, req->src0.h, req->src0.fmt, ipp_rot, tranform, pVideo->width, pVideo->height);
req->dst0.YrgbMst = ipp_phys_addr_base;
req->dst0.CbrMst = req->dst0.YrgbMst + width * height;
if (ipp_rot == IPP_ROT_90 || ipp_rot == IPP_ROT_270)
{
req->dst0.w = height;//ipp_x_aligned(pVideo->width);//2¶ÔÆë
req->dst0.h = width;//swith
}
else
{
req->dst0.w = width;
req->dst0.h = height;
}
req->store_clip_mode = 1;//¶ÔÆë
req->src_vir_w = pVideo->width;
req->dst_vir_w = ipp_x_aligned(req->dst0.w);
req->timeout = 50;//ms
req->flag = ipp_rot;//
ipp_buffer.Yrgb = req->dst0.YrgbMst;
ipp_buffer.CbrMst = req->dst0.CbrMst;
ipp_buffer.offset += videoLen;
return 0;
}
static int get_ipp_is_enable()
{
return ipp_buffer.ipp_fd;
}
static int ipp_reset()
{
ipp_buffer.offset = 0;
return 0;
}
static int ipp_rotate_and_scale(struct private_handle_t *handle, \
int tranform, unsigned int* srcPhysical, int *videoWidth, int *videoHeight)
{
if (handle == NULL)
{
ALOGE("handle is NULL.");
return -1;
}
struct rk29_ipp_req ipp_req;
memset(&ipp_req, 0, sizeof(rk29_ipp_req));
int err = ipp_set_req(handle, tranform, &ipp_req);
if (err == 0)
{
int ret = ioctl(ipp_buffer.ipp_fd, IPP_BLIT_SYNC, &ipp_req);
if (ret != 0)
{
ALOGE("ipp IPP_BLIT_SYNC error,ret=%d.", ret);
return -1;
}
srcPhysical[0] = ipp_buffer.Yrgb;
srcPhysical[1] = ipp_buffer.CbrMst;
*videoWidth = ipp_req.dst_vir_w;
*videoHeight = ipp_req.dst0.h;
return 0;
}
else
{
ALOGE("hwc layer to ipp-req fail.");
return -1;
}
}
int ipp_open(ipp_device_t *ippDev)
{
int ipp_fd = open("/dev/rk29-ipp", O_RDWR, 0);
int ret;
if (ipp_fd > 0)
{
ipp_buffer.ipp_fd = ipp_fd;
ipp_buffer.offset = 0;
#if 0
ion_open(ION_SIZE, ION_MODULE_UI, &ipp_buffer.ion_device);
ret = ipp_buffer.ion_device->alloc(ipp_buffer.ion_device, ION_SIZE , _ION_HEAP_RESERVE, &ipp_buffer.pion);
#else
int ion_flags = 0;
// int shared_fd;
//struct ion_handle *ion_hnd;
unsigned int heap_mask = ION_HEAP(ION_CARVEOUT_HEAP_ID);//ION_HEAP(ION_HEAP_SYSTEM_MASK);
ipp_buffer.ion_client = ion_open();
if (ipp_buffer.ion_client < 0)
{
AERR("ion_open failed with %s", strerror(errno));
}
ret = ion_alloc(ipp_buffer.ion_client, ION_SIZE, 0, heap_mask, ion_flags, &ipp_buffer.ion_hnd);
if (ret != 0)
{
AERR("Force to ION_HEAP_SYSTEM_MASK fail ion_client:%d", ipp_buffer.ion_client);
}
ret = ion_share(ipp_buffer.ion_client, ipp_buffer.ion_hnd, &ipp_buffer.shared_fd);
if (ret != 0)
{
AERR("ion_share( %d ) failed", ipp_buffer.ion_client);
if (0 != ion_free(ipp_buffer.ion_client, ipp_buffer.ion_hnd)) AERR("ion_free( %d ) failed", ipp_buffer.ion_client);
}
ion_get_phys(ipp_buffer.shared_fd, ipp_buffer.ion_hnd, &ipp_buffer.ion_phy_addr);
#endif
if (!ret)
{
ippDev->ipp_format_is_surport = &ipp_format_is_supported;
ippDev->ipp_is_enable = &get_ipp_is_enable;
ippDev->ipp_rotate_and_scale = &ipp_rotate_and_scale;
ippDev->ipp_reset = &ipp_reset;
// ALOGD("init ion succ,ion size=%d,ret=%d",ipp_buffer.pion->size,ret);
}
else
{
ALOGE("init ion fail,ion size=%d,err=%d", ION_SIZE, ret);
}
}
else
{
ALOGE("open ipp fail.(ipp_fd=%d)", ipp_fd);
}
return ipp_fd;
}
int ipp_close(ipp_device_t *ippDev)
{
ALOGD("Enter ipp_close.");
close(ipp_buffer.ipp_fd);
#if 0
ipp_buffer.ion_device->free(ipp_buffer.ion_device, ipp_buffer.pion);
ion_close(ipp_buffer.ion_device);
ipp_buffer.ion_device = NULL;
#else
if (ipp_buffer.ion_client)
{
close(ipp_buffer.shared_fd);
if (0 != ion_free(ipp_buffer.ion_client, ipp_buffer.ion_hnd))
AERR("Failed to ion_free( ion_client: %d ion_hnd: %x )", ipp_buffer.ion_client, ipp_buffer.ion_hnd);
if (0 != ion_close(ipp_buffer.ion_client))
AERR("Failed to close ion_client: %d", ipp_buffer.ion_client);
close(ipp_buffer.ion_client);
}
#endif
if (ippDev)
{
delete ippDev;
}
return 0;
}