1 /* copyright (c) 2012, code aurora forum. all rights reserved.
2 *
3 * redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * neither the name of code aurora forum, inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * this software is provided "as is" and any express or implied
17 * warranties, including, but not limited to, the implied warranties of
18 * merchantability, fitness for a particular purpose and non-infringement
19 * are disclaimed. in no event shall the copyright owner or contributors
20 * be liable for any direct, indirect, incidental, special, exemplary, or
21 * consequential damages (including, but not limited to, procurement of
22 * substitute goods or services; loss of use, data, or profits; or
23 * business interruption) however caused and on any theory of liability,
24 * whether in contract, strict liability, or tort (including negligence
25 * or otherwise) arising in any way out of the use of this software, even
26 * if advised of the possibility of such damage.
27 *
28 */
29 /*--------------------------------------------------------------------------
30 Copyright (c) 2012 Code Aurora Forum. All rights reserved.
31 --------------------------------------------------------------------------*/
32
33 #include <C2DColorConverter.h>
34 #include <arm_neon.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <linux/msm_kgsl.h>
38 #include <sys/ioctl.h>
39 #include <utils/Log.h>
40 #include <dlfcn.h>
41
42 #undef LOG_TAG
43 #define LOG_TAG "C2DColorConvert"
44 #define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
45 #define ALIGN8K 8192
46 #define ALIGN4K 4096
47 #define ALIGN2K 2048
48 #define ALIGN128 128
49 #define ALIGN32 32
50 #define ALIGN16 16
51
52 //-----------------------------------------------------
53 namespace android {
54
55 class C2DColorConverter : public C2DColorConverterBase {
56
57 public:
58 C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags);
59 int32_t getBuffReq(int32_t port, C2DBuffReq *req);
60 int32_t dumpOutput(char * filename, char mode);
61 protected:
62 virtual ~C2DColorConverter();
63 virtual int convertC2D(int srcFd, void * srcData, int dstFd, void * dstData);
64
65 private:
66 virtual bool isYUVSurface(ColorConvertFormat format);
67 virtual void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource);
68 virtual C2D_STATUS updateYUVSurfaceDef(int fd, void * data, bool isSource);
69 virtual C2D_STATUS updateRGBSurfaceDef(int fd, void * data, bool isSource);
70 virtual uint32_t getC2DFormat(ColorConvertFormat format);
71 virtual size_t calcStride(ColorConvertFormat format, size_t width);
72 virtual size_t calcYSize(ColorConvertFormat format, size_t width, size_t height);
73 virtual size_t calcSize(ColorConvertFormat format, size_t width, size_t height);
74 virtual void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen);
75 virtual bool unmapGPUAddr(uint32_t gAddr);
76 virtual size_t calcLumaAlign(ColorConvertFormat format);
77 virtual size_t calcSizeAlign(ColorConvertFormat format);
78
79 void *mC2DLibHandle;
80 LINK_c2dCreateSurface mC2DCreateSurface;
81 LINK_c2dUpdateSurface mC2DUpdateSurface;
82 LINK_c2dReadSurface mC2DReadSurface;
83 LINK_c2dDraw mC2DDraw;
84 LINK_c2dFlush mC2DFlush;
85 LINK_c2dFinish mC2DFinish;
86 LINK_c2dWaitTimestamp mC2DWaitTimestamp;
87 LINK_c2dDestroySurface mC2DDestroySurface;
88
89 int32_t mKgslFd;
90 uint32_t mSrcSurface, mDstSurface;
91 void * mSrcSurfaceDef;
92 void * mDstSurfaceDef;
93
94 C2D_OBJECT mBlit;
95 size_t mSrcWidth;
96 size_t mSrcHeight;
97 size_t mDstWidth;
98 size_t mDstHeight;
99 size_t mSrcSize;
100 size_t mDstSize;
101 size_t mSrcYSize;
102 size_t mDstYSize;
103 enum ColorConvertFormat mSrcFormat;
104 enum ColorConvertFormat mDstFormat;
105 int32_t mFlags;
106
107 int mError;
108 };
109
C2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags)110 C2DColorConverter::C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags)
111 {
112 mError = 0;
113 mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW);
114 if (!mC2DLibHandle) {
115 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
116 mError = -1;
117 return;
118 }
119 mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface");
120 mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface");
121 mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface");
122 mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw");
123 mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush");
124 mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish");
125 mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp");
126 mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface");
127
128 if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface
129 || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp
130 || !mC2DDestroySurface) {
131 ALOGE("%s: dlsym ERROR", __FUNCTION__);
132 mError = -1;
133 return;
134 }
135
136 mSrcWidth = srcWidth;
137 mSrcHeight = srcHeight;
138 mDstWidth = dstWidth;
139 mDstHeight = dstHeight;
140 mSrcFormat = srcFormat;
141 mDstFormat = dstFormat;
142 mSrcSize = calcSize(srcFormat, srcWidth, srcHeight);
143 mDstSize = calcSize(dstFormat, dstWidth, dstHeight);
144 mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight);
145 mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight);
146
147 mFlags = flags; // can be used for rotation
148 mKgslFd = open("/dev/kgsl-2d0", O_RDWR | O_SYNC);
149 if (mKgslFd < 0) {
150 ALOGE("Cannot open device kgsl-2d0, trying kgsl-3d0\n");
151 mKgslFd = open("/dev/kgsl-3d0", O_RDWR | O_SYNC);
152 if (mKgslFd < 0) {
153 ALOGE("Failed to open device kgsl-3d0\n");
154 mError = -1;
155 return;
156 }
157 }
158
159 mSrcSurfaceDef = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true);
160 mDstSurfaceDef = getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false);
161
162 memset((void*)&mBlit,0,sizeof(C2D_OBJECT));
163 mBlit.source_rect.x = 0 << 16;
164 mBlit.source_rect.y = 0 << 16;
165 mBlit.source_rect.width = srcWidth << 16;
166 mBlit.source_rect.height = srcHeight << 16;
167 mBlit.target_rect.x = 0 << 16;
168 mBlit.target_rect.y = 0 << 16;
169 mBlit.target_rect.width = dstWidth << 16;
170 mBlit.target_rect.height = dstHeight << 16;
171 mBlit.config_mask = C2D_ALPHA_BLEND_NONE | C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | C2D_TARGET_RECT_BIT;
172 mBlit.surface_id = mSrcSurface;
173 }
174
~C2DColorConverter()175 C2DColorConverter::~C2DColorConverter()
176 {
177 if (mError) {
178 if (mC2DLibHandle) {
179 dlclose(mC2DLibHandle);
180 }
181 return;
182 }
183
184 mC2DDestroySurface(mDstSurface);
185 mC2DDestroySurface(mSrcSurface);
186 if (isYUVSurface(mSrcFormat)) {
187 delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
188 } else {
189 delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
190 }
191
192 if (isYUVSurface(mDstFormat)) {
193 delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
194 } else {
195 delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef);
196 }
197
198 dlclose(mC2DLibHandle);
199 close(mKgslFd);
200 }
201
convertC2D(int srcFd,void * srcData,int dstFd,void * dstData)202 int C2DColorConverter::convertC2D(int srcFd, void * srcData, int dstFd, void * dstData)
203 {
204 C2D_STATUS ret;
205
206 if (mError) {
207 ALOGE("C2D library initialization failed\n");
208 return mError;
209 }
210
211 if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) {
212 ALOGE("Incorrect input parameters\n");
213 return -1;
214 }
215
216 if (isYUVSurface(mSrcFormat)) {
217 ret = updateYUVSurfaceDef(srcFd, srcData, true);
218 } else {
219 ret = updateRGBSurfaceDef(srcFd, srcData, true);
220 }
221
222 if (ret != C2D_STATUS_OK) {
223 ALOGE("Update src surface def failed\n");
224 return -ret;
225 }
226
227 if (isYUVSurface(mDstFormat)) {
228 ret = updateYUVSurfaceDef(dstFd, dstData, false);
229 } else {
230 ret = updateRGBSurfaceDef(dstFd, dstData, false);
231 }
232
233 if (ret != C2D_STATUS_OK) {
234 ALOGE("Update dst surface def failed\n");
235 return -ret;
236 }
237
238 mBlit.surface_id = mSrcSurface;
239 ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1);
240 mC2DFinish(mDstSurface);
241
242 bool unmappedSrcSuccess;
243 if (isYUVSurface(mSrcFormat)) {
244 unmappedSrcSuccess = unmapGPUAddr((uint32_t)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0);
245 } else {
246 unmappedSrcSuccess = unmapGPUAddr((uint32_t)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys);
247 }
248
249 bool unmappedDstSuccess;
250 if (isYUVSurface(mDstFormat)) {
251 unmappedDstSuccess = unmapGPUAddr((uint32_t)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0);
252 } else {
253 unmappedDstSuccess = unmapGPUAddr((uint32_t)((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef)->phys);
254 }
255
256 if (ret != C2D_STATUS_OK) {
257 ALOGE("C2D Draw failed\n");
258 return -ret; //c2d err values are positive
259 } else {
260 if (!unmappedSrcSuccess || !unmappedDstSuccess) {
261 ALOGE("unmapping GPU address failed\n");
262 return -1;
263 }
264 return ret;
265 }
266 }
267
isYUVSurface(ColorConvertFormat format)268 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format)
269 {
270 switch (format) {
271 case YCbCr420Tile:
272 case YCbCr420SP:
273 case YCbCr420P:
274 case YCrCb420P:
275 case NV12_2K:
276 return true;
277 case RGB565:
278 case RGBA8888:
279 default:
280 return false;
281 }
282 }
283
getDummySurfaceDef(ColorConvertFormat format,size_t width,size_t height,bool isSource)284 void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource)
285 {
286 if (isYUVSurface(format)) {
287 C2D_YUV_SURFACE_DEF * surfaceDef = new C2D_YUV_SURFACE_DEF;
288 surfaceDef->format = getC2DFormat(format);
289 surfaceDef->width = width;
290 surfaceDef->height = height;
291 surfaceDef->plane0 = (void *)0xaaaaaaaa;
292 surfaceDef->phys0 = (void *)0xaaaaaaaa;
293 surfaceDef->stride0 = calcStride(format, width);
294 surfaceDef->plane1 = (void *)0xaaaaaaaa;
295 surfaceDef->phys1 = (void *)0xaaaaaaaa;
296 surfaceDef->stride1 = calcStride(format, width);
297
298 if (format == YCbCr420P ||
299 format == YCrCb420P) {
300 printf("half stride for Cb Cr planes \n");
301 surfaceDef->stride1 = calcStride(format, width) / 2;
302 surfaceDef->phys2 = (void *)0xaaaaaaaa;
303 surfaceDef->stride2 = calcStride(format, width) / 2;
304 }
305 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
306 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
307 &(*surfaceDef));
308 return ((void *)surfaceDef);
309 } else {
310 C2D_RGB_SURFACE_DEF * surfaceDef = new C2D_RGB_SURFACE_DEF;
311 surfaceDef->format = getC2DFormat(format);
312 surfaceDef->width = width;
313 surfaceDef->height = height;
314 surfaceDef->buffer = (void *)0xaaaaaaaa;
315 surfaceDef->phys = (void *)0xaaaaaaaa;
316 surfaceDef->stride = calcStride(format, width);
317 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
318 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
319 &(*surfaceDef));
320 return ((void *)surfaceDef);
321 }
322 }
323
updateYUVSurfaceDef(int fd,void * data,bool isSource)324 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(int fd, void * data, bool isSource)
325 {
326 if (isSource) {
327 C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
328 srcSurfaceDef->plane0 = data;
329 srcSurfaceDef->phys0 = getMappedGPUAddr(fd, data, mSrcSize);
330 srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
331 srcSurfaceDef->phys1 = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
332 srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
333 srcSurfaceDef->phys2 = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
334
335 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
336 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
337 &(*srcSurfaceDef));
338 } else {
339 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
340 dstSurfaceDef->plane0 = data;
341 dstSurfaceDef->phys0 = getMappedGPUAddr(fd, data, mDstSize);
342 dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
343 dstSurfaceDef->phys1 = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
344 dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
345 dstSurfaceDef->phys2 = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
346
347 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
348 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
349 &(*dstSurfaceDef));
350 }
351 }
352
updateRGBSurfaceDef(int fd,void * data,bool isSource)353 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(int fd, void * data, bool isSource)
354 {
355 if (isSource) {
356 C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
357 srcSurfaceDef->buffer = data;
358 srcSurfaceDef->phys = getMappedGPUAddr(fd, data, mSrcSize);
359 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
360 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
361 &(*srcSurfaceDef));
362 } else {
363 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
364 dstSurfaceDef->buffer = data;
365 ALOGV("dstSurfaceDef->buffer = %p\n", data);
366 dstSurfaceDef->phys = getMappedGPUAddr(fd, data, mDstSize);
367 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
368 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
369 &(*dstSurfaceDef));
370 }
371 }
372
getC2DFormat(ColorConvertFormat format)373 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format)
374 {
375 switch (format) {
376 case RGB565:
377 return C2D_COLOR_FORMAT_565_RGB;
378 case RGBA8888:
379 return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS;
380 case YCbCr420Tile:
381 return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
382 case YCbCr420SP:
383 case NV12_2K:
384 return C2D_COLOR_FORMAT_420_NV12;
385 case YCbCr420P:
386 return C2D_COLOR_FORMAT_420_I420;
387 case YCrCb420P:
388 return C2D_COLOR_FORMAT_420_YV12;
389 default:
390 ALOGE("Format not supported , %d\n", format);
391 return -1;
392 }
393 }
394
calcStride(ColorConvertFormat format,size_t width)395 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
396 {
397 switch (format) {
398 case RGB565:
399 return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
400 case RGBA8888:
401 return ALIGN(width, ALIGN32) * 4;
402 case YCbCr420Tile:
403 return ALIGN(width, ALIGN128);
404 case YCbCr420SP:
405 return ALIGN(width, ALIGN32);
406 case NV12_2K:
407 return ALIGN(width, ALIGN16);
408 case YCbCr420P:
409 return width;
410 case YCrCb420P:
411 return ALIGN(width, ALIGN16);
412 default:
413 return 0;
414 }
415 }
416
calcYSize(ColorConvertFormat format,size_t width,size_t height)417 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height)
418 {
419 switch (format) {
420 case YCbCr420SP:
421 return (ALIGN(width, ALIGN32) * height);
422 case YCbCr420P:
423 return width * height;
424 case YCrCb420P:
425 return ALIGN(width, ALIGN16) * height;
426 case YCbCr420Tile:
427 return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K);
428 case NV12_2K: {
429 size_t alignedw = ALIGN(width, ALIGN16);
430 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
431 return lumaSize;
432 }
433 default:
434 return 0;
435 }
436 }
437
calcSize(ColorConvertFormat format,size_t width,size_t height)438 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height)
439 {
440 int32_t alignedw = 0;
441 int32_t alignedh = 0;
442 int32_t size = 0;
443
444 switch (format) {
445 case RGB565:
446 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 2;
447 size = ALIGN(size, ALIGN4K);
448 break;
449 case RGBA8888:
450 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 4;
451 size = ALIGN(size, ALIGN4K);
452 break;
453 case YCbCr420SP:
454 alignedw = ALIGN(width, ALIGN32);
455 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K);
456 break;
457 case YCbCr420P:
458 size = ALIGN((width * height * 3 / 2), ALIGN4K);
459 break;
460 case YCrCb420P:
461 alignedw = ALIGN(width, ALIGN16);
462 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
463 break;
464 case YCbCr420Tile:
465 alignedw = ALIGN(width, ALIGN128);
466 alignedh = ALIGN(height, ALIGN32);
467 size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K);
468 break;
469 case NV12_2K: {
470 alignedw = ALIGN(width, ALIGN16);
471 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
472 size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
473 size = ALIGN(lumaSize + chromaSize, ALIGN4K);
474 ALOGV("NV12_2k, width = %d, height = %d, size = %d", width, height, size);
475 }
476 break;
477 default:
478 break;
479 }
480 return size;
481 }
482 /*
483 * Tells GPU to map given buffer and returns a physical address of mapped buffer
484 */
getMappedGPUAddr(int bufFD,void * bufPtr,size_t bufLen)485 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
486 {
487 struct kgsl_map_user_mem param;
488 param.fd = bufFD;
489 param.offset = 0;
490 param.len = bufLen;
491 param.hostptr = (unsigned int)bufPtr;
492 param.memtype = KGSL_USER_MEM_TYPE_ION;
493 param.reserved = 0;
494 param.gpuaddr = 0;
495
496 if (!ioctl(mKgslFd, IOCTL_KGSL_MAP_USER_MEM, ¶m, sizeof(param))) {
497 ALOGV("mapping successful for buffer %p size %d\n",
498 bufPtr, bufLen);
499 return (void *)param.gpuaddr;
500 }
501 ALOGE("mapping failed w/ errno %s", strerror(errno));
502 return NULL;
503 }
504
unmapGPUAddr(uint32_t gAddr)505 bool C2DColorConverter::unmapGPUAddr(uint32_t gAddr)
506 {
507 int rc = 0;
508 struct kgsl_sharedmem_free param;
509 memset(¶m, 0, sizeof(param));
510 param.gpuaddr = gAddr;
511
512 rc = ioctl(mKgslFd, IOCTL_KGSL_SHAREDMEM_FREE, (void *)¶m,
513 sizeof(param));
514 if (rc < 0) {
515 ALOGE("%s: IOCTL_KGSL_SHAREDMEM_FREE failed rc = %d\n", __func__, rc);
516 return false;
517 }
518 return true;
519 }
520
getBuffReq(int32_t port,C2DBuffReq * req)521 int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
522 if (!req) return -1;
523
524 if (port != C2D_INPUT && port != C2D_OUTPUT) return -1;
525
526 memset(req, 0, sizeof(C2DBuffReq));
527 if (port == C2D_INPUT) {
528 req->width = mSrcWidth;
529 req->height = mSrcHeight;
530 req->stride = calcStride(mSrcFormat, mSrcWidth);
531 req->sliceHeight = mSrcHeight;
532 req->lumaAlign = calcLumaAlign(mSrcFormat);
533 req->sizeAlign = calcSizeAlign(mSrcFormat);
534 req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
535 //add bpp?
536 ALOGV("input req->size = %d\n", req->size);
537 } else if (port == C2D_OUTPUT) {
538 req->width = mDstWidth;
539 req->height = mDstHeight;
540 req->stride = calcStride(mDstFormat, mDstWidth);
541 req->sliceHeight = mDstHeight;
542 req->lumaAlign = calcLumaAlign(mDstFormat);
543 req->sizeAlign = calcSizeAlign(mDstFormat);
544 req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
545 ALOGV("output req->size = %d\n", req->size);
546 }
547 return 0;
548 }
549
calcLumaAlign(ColorConvertFormat format)550 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
551 if (!isYUVSurface(format)) return 1; //no requirement
552
553 switch (format) {
554 case NV12_2K:
555 return ALIGN2K;
556 default:
557 ALOGE("unknown format passed for luma alignment number");
558 return 1;
559 }
560 }
561
calcSizeAlign(ColorConvertFormat format)562 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
563 if (!isYUVSurface(format)) return 1; //no requirement
564
565 switch (format) {
566 case YCbCr420SP: //OR NV12
567 case YCbCr420P:
568 case NV12_2K:
569 return ALIGN4K;
570 default:
571 ALOGE("unknown format passed for size alignment number");
572 return 1;
573 }
574 }
575
dumpOutput(char * filename,char mode)576 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
577 int fd;
578 size_t stride, sliceHeight;
579 if (!filename) return -1;
580
581 int flags = O_RDWR | O_CREAT;
582 if (mode == 'a') {
583 flags |= O_APPEND;
584 }
585
586 if ((fd = open(filename, flags)) < 0) {
587 ALOGE("open dump file failed w/ errno %s", strerror(errno));
588 return -1;
589 }
590
591 int ret = 0;
592 if (isYUVSurface(mDstFormat)) {
593 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
594 uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
595 stride = dstSurfaceDef->stride0;
596 sliceHeight = dstSurfaceDef->height;
597 /* dump luma */
598 for (size_t i = 0; i < sliceHeight; i++) {
599 ret = write(fd, base, mDstWidth); //will work only for the 420 ones
600 if (ret < 0) goto cleanup;
601 base += stride;
602 }
603
604 if (mDstFormat == YCbCr420P ||
605 mDstFormat == YCrCb420P) {
606 printf("Dump Cb and Cr separately for Planar\n");
607 //dump Cb/Cr
608 base = (uint8_t *)dstSurfaceDef->plane1;
609 stride = dstSurfaceDef->stride1;
610 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
611 ret = write(fd, base, mDstWidth/2);
612 if (ret < 0) goto cleanup;
613 base += stride;
614 }
615
616 //dump Cr/Cb
617 base = (uint8_t *)dstSurfaceDef->plane2;
618 stride = dstSurfaceDef->stride2;
619
620 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
621 ret = write(fd, base, mDstWidth/2);
622 if (ret < 0) goto cleanup;
623 base += stride;
624 }
625
626 } else {
627 /* dump chroma */
628 base = (uint8_t *)dstSurfaceDef->plane1;
629 stride = dstSurfaceDef->stride1;
630 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
631 ret = write(fd, base, mDstWidth);
632 if (ret < 0) goto cleanup;
633 base += stride;
634 }
635 }
636 } else {
637 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
638 uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
639 stride = dstSurfaceDef->stride;
640 sliceHeight = dstSurfaceDef->height;
641
642 printf("rgb surface base is %p", base);
643 printf("rgb surface dumpsslice height is %d\n", sliceHeight);
644 printf("rgb surface dump stride is %d\n", stride);
645
646 int bpp = 1; //bytes per pixel
647 if (mDstFormat == RGB565) {
648 bpp = 2;
649 } else if (mDstFormat == RGBA8888) {
650 bpp = 4;
651 }
652
653 int count = 0;
654 for (size_t i = 0; i < sliceHeight; i++) {
655 ret = write(fd, base, mDstWidth*bpp);
656 if (ret < 0) {
657 printf("write failed, count = %d\n", count);
658 goto cleanup;
659 }
660 base += stride;
661 count += stride;
662 }
663 }
664 cleanup:
665 if (ret < 0) {
666 ALOGE("file write failed w/ errno %s", strerror(errno));
667 }
668 close(fd);
669 return ret < 0 ? ret : 0;
670 }
671
createC2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags)672 extern "C" C2DColorConverterBase* createC2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags)
673 {
674 return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags);
675 }
676
destroyC2DColorConverter(C2DColorConverterBase * C2DCC)677 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC)
678 {
679 delete C2DCC;
680 }
681
682 }
683