1 /* Copyright (c) 2012 - 2013, The Linux Foundation. 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 The Linux Foundation 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 #include <C2DColorConverter.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <linux/msm_kgsl.h>
35 #include <sys/ioctl.h>
36 #include <utils/Log.h>
37 #include <dlfcn.h>
38 #include <string.h>
39 #include <errno.h>
40
41 #undef LOG_TAG
42 #define LOG_TAG "C2DColorConvert"
43 #define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
44 #define ALIGN8K 8192
45 #define ALIGN4K 4096
46 #define ALIGN2K 2048
47 #define ALIGN128 128
48 #define ALIGN32 32
49 #define ALIGN16 16
50
51 //-----------------------------------------------------
52 namespace android {
53
54 class C2DColorConverter : public C2DColorConverterBase {
55
56 public:
57 C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags,size_t srcStride);
58 int32_t getBuffReq(int32_t port, C2DBuffReq *req);
59 int32_t dumpOutput(char * filename, char mode);
60 protected:
61 virtual ~C2DColorConverter();
62 virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData);
63
64 private:
65 bool isYUVSurface(ColorConvertFormat format);
66 void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource);
67 C2D_STATUS updateYUVSurfaceDef(int fd, void *base, void * data, bool isSource);
68 C2D_STATUS updateRGBSurfaceDef(int fd, void * data, bool isSource);
69 uint32_t getC2DFormat(ColorConvertFormat format);
70 size_t calcStride(ColorConvertFormat format, size_t width);
71 size_t calcYSize(ColorConvertFormat format, size_t width, size_t height);
72 size_t calcSize(ColorConvertFormat format, size_t width, size_t height);
73 void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen);
74 bool unmapGPUAddr(unsigned long gAddr);
75 size_t calcLumaAlign(ColorConvertFormat format);
76 size_t calcSizeAlign(ColorConvertFormat format);
77 C2DBytesPerPixel calcBytesPerPixel(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 LINK_c2dMapAddr mC2DMapAddr;
89 LINK_c2dUnMapAddr mC2DUnMapAddr;
90
91 uint32_t mSrcSurface, mDstSurface;
92 void * mSrcSurfaceDef;
93 void * mDstSurfaceDef;
94
95 C2D_OBJECT mBlit;
96 size_t mSrcWidth;
97 size_t mSrcHeight;
98 size_t mSrcStride;
99 size_t mDstWidth;
100 size_t mDstHeight;
101 size_t mSrcSize;
102 size_t mDstSize;
103 size_t mSrcYSize;
104 size_t mDstYSize;
105 enum ColorConvertFormat mSrcFormat;
106 enum ColorConvertFormat mDstFormat;
107 int32_t mFlags;
108
109 int mError;
110 };
111
C2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)112 C2DColorConverter::C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride)
113 {
114 mError = 0;
115 mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW);
116 if (!mC2DLibHandle) {
117 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
118 mError = -1;
119 return;
120 }
121 mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface");
122 mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface");
123 mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface");
124 mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw");
125 mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush");
126 mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish");
127 mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp");
128 mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface");
129 mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr");
130 mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr");
131
132 if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface
133 || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp
134 || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) {
135 ALOGE("%s: dlsym ERROR", __FUNCTION__);
136 mError = -1;
137 return;
138 }
139
140 mSrcWidth = srcWidth;
141 mSrcHeight = srcHeight;
142 mSrcStride = srcStride;;
143 mDstWidth = dstWidth;
144 mDstHeight = dstHeight;
145 mSrcFormat = srcFormat;
146 mDstFormat = dstFormat;
147 mSrcSize = calcSize(srcFormat, srcWidth, srcHeight);
148 mDstSize = calcSize(dstFormat, dstWidth, dstHeight);
149 mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight);
150 mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight);
151
152 mFlags = flags; // can be used for rotation
153
154 mSrcSurfaceDef = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true);
155 mDstSurfaceDef = getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false);
156
157 memset((void*)&mBlit,0,sizeof(C2D_OBJECT));
158 mBlit.source_rect.x = 0 << 16;
159 mBlit.source_rect.y = 0 << 16;
160 mBlit.source_rect.width = srcWidth << 16;
161 mBlit.source_rect.height = srcHeight << 16;
162 mBlit.target_rect.x = 0 << 16;
163 mBlit.target_rect.y = 0 << 16;
164 mBlit.target_rect.width = dstWidth << 16;
165 mBlit.target_rect.height = dstHeight << 16;
166 mBlit.config_mask = C2D_ALPHA_BLEND_NONE | C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | C2D_TARGET_RECT_BIT;
167 mBlit.surface_id = mSrcSurface;
168 }
169
~C2DColorConverter()170 C2DColorConverter::~C2DColorConverter()
171 {
172 if (mError) {
173 if (mC2DLibHandle) {
174 dlclose(mC2DLibHandle);
175 }
176 return;
177 }
178
179 mC2DDestroySurface(mDstSurface);
180 mC2DDestroySurface(mSrcSurface);
181
182 if (mSrcSurfaceDef) {
183 free(mSrcSurfaceDef);
184 }
185
186 if (mDstSurfaceDef) {
187 free(mDstSurfaceDef);
188 }
189
190 dlclose(mC2DLibHandle);
191 }
192
convertC2D(int srcFd,void * srcBase,void * srcData,int dstFd,void * dstBase,void * dstData)193 int C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData)
194 {
195 C2D_STATUS ret;
196
197 if (mError) {
198 ALOGE("C2D library initialization failed\n");
199 return mError;
200 }
201
202 if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) {
203 ALOGE("Incorrect input parameters\n");
204 return -1;
205 }
206
207 if (isYUVSurface(mSrcFormat)) {
208 ret = updateYUVSurfaceDef(srcFd, srcBase, srcData, true);
209 } else {
210 ret = updateRGBSurfaceDef(srcFd, srcData, true);
211 }
212
213 if (ret != C2D_STATUS_OK) {
214 ALOGE("Update src surface def failed\n");
215 return -ret;
216 }
217
218 if (isYUVSurface(mDstFormat)) {
219 ret = updateYUVSurfaceDef(dstFd, dstBase, dstData, false);
220 } else {
221 ret = updateRGBSurfaceDef(dstFd, dstData, false);
222 }
223
224 if (ret != C2D_STATUS_OK) {
225 ALOGE("Update dst surface def failed\n");
226 return -ret;
227 }
228
229 mBlit.surface_id = mSrcSurface;
230 ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1);
231 mC2DFinish(mDstSurface);
232
233 bool unmappedSrcSuccess;
234 if (isYUVSurface(mSrcFormat)) {
235 unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0);
236 } else {
237 unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys);
238 }
239
240 bool unmappedDstSuccess;
241 if (isYUVSurface(mDstFormat)) {
242 unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0);
243 } else {
244 unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef)->phys);
245 }
246
247 if (ret != C2D_STATUS_OK) {
248 ALOGE("C2D Draw failed\n");
249 return -ret; //c2d err values are positive
250 } else {
251 if (!unmappedSrcSuccess || !unmappedDstSuccess) {
252 ALOGE("unmapping GPU address failed\n");
253 return -1;
254 }
255 return ret;
256 }
257 }
258
isYUVSurface(ColorConvertFormat format)259 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format)
260 {
261 switch (format) {
262 case YCbCr420Tile:
263 case YCbCr420SP:
264 case YCbCr420P:
265 case YCrCb420P:
266 case NV12_2K:
267 case NV12_128m:
268 return true;
269 case RGB565:
270 case RGBA8888:
271 default:
272 return false;
273 }
274 }
275
getDummySurfaceDef(ColorConvertFormat format,size_t width,size_t height,bool isSource)276 void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource)
277 {
278 if (isYUVSurface(format)) {
279 C2D_YUV_SURFACE_DEF * surfaceDef = (C2D_YUV_SURFACE_DEF *)malloc(sizeof(C2D_YUV_SURFACE_DEF));
280 memset(surfaceDef, 0x0, sizeof(C2D_YUV_SURFACE_DEF));
281 surfaceDef->format = getC2DFormat(format);
282 surfaceDef->width = width;
283 surfaceDef->height = height;
284 surfaceDef->plane0 = (void *)0xaaaaaaaa;
285 surfaceDef->phys0 = (void *)0xaaaaaaaa;
286 surfaceDef->stride0 = calcStride(format, width);
287 surfaceDef->plane1 = (void *)0xaaaaaaaa;
288 surfaceDef->phys1 = (void *)0xaaaaaaaa;
289 surfaceDef->stride1 = calcStride(format, width);
290
291 if (format == YCbCr420P ||
292 format == YCrCb420P) {
293 printf("half stride for Cb Cr planes \n");
294 surfaceDef->stride1 = calcStride(format, width) / 2;
295 surfaceDef->phys2 = (void *)0xaaaaaaaa;
296 surfaceDef->stride2 = calcStride(format, width) / 2;
297 }
298 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
299 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
300 &(*surfaceDef));
301 return ((void *)surfaceDef);
302 } else {
303 C2D_RGB_SURFACE_DEF * surfaceDef = (C2D_RGB_SURFACE_DEF *)malloc(sizeof(C2D_RGB_SURFACE_DEF));
304 memset(surfaceDef, 0x0, sizeof(C2D_RGB_SURFACE_DEF));
305 surfaceDef->format = getC2DFormat(format);
306 surfaceDef->width = width;
307 surfaceDef->height = height;
308 surfaceDef->buffer = (void *)0xaaaaaaaa;
309 surfaceDef->phys = (void *)0xaaaaaaaa;
310 surfaceDef->stride = calcStride(format, width);
311 mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
312 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
313 &(*surfaceDef));
314 return ((void *)surfaceDef);
315 }
316 }
317
updateYUVSurfaceDef(int fd,void * base,void * data,bool isSource)318 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(int fd, void *base, void *data, bool isSource)
319 {
320 if (isSource) {
321 C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
322 srcSurfaceDef->plane0 = data;
323 srcSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mSrcSize) + ((uint8_t *)data - (uint8_t *)base);
324 srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
325 srcSurfaceDef->phys1 = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
326 srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
327 srcSurfaceDef->phys2 = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
328
329 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
330 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
331 &(*srcSurfaceDef));
332 } else {
333 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
334 dstSurfaceDef->plane0 = data;
335 dstSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mDstSize) + ((uint8_t *)data - (uint8_t *)base);
336 dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
337 dstSurfaceDef->phys1 = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
338 dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
339 dstSurfaceDef->phys2 = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
340
341 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
342 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
343 &(*dstSurfaceDef));
344 }
345 }
346
updateRGBSurfaceDef(int fd,void * data,bool isSource)347 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(int fd, void * data, bool isSource)
348 {
349 if (isSource) {
350 C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
351 srcSurfaceDef->buffer = data;
352 srcSurfaceDef->phys = getMappedGPUAddr(fd, data, mSrcSize);
353 return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
354 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
355 &(*srcSurfaceDef));
356 } else {
357 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
358 dstSurfaceDef->buffer = data;
359 ALOGV("dstSurfaceDef->buffer = %p\n", data);
360 dstSurfaceDef->phys = getMappedGPUAddr(fd, data, mDstSize);
361 return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
362 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
363 &(*dstSurfaceDef));
364 }
365 }
366
getC2DFormat(ColorConvertFormat format)367 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format)
368 {
369 switch (format) {
370 case RGB565:
371 return C2D_COLOR_FORMAT_565_RGB;
372 case RGBA8888:
373 return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED;
374 case YCbCr420Tile:
375 return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
376 case YCbCr420SP:
377 case NV12_2K:
378 case NV12_128m:
379 return C2D_COLOR_FORMAT_420_NV12;
380 case YCbCr420P:
381 return C2D_COLOR_FORMAT_420_I420;
382 case YCrCb420P:
383 return C2D_COLOR_FORMAT_420_YV12;
384 default:
385 ALOGE("Format not supported , %d\n", format);
386 return -1;
387 }
388 }
389
calcStride(ColorConvertFormat format,size_t width)390 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
391 {
392 switch (format) {
393 case RGB565:
394 return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
395 case RGBA8888:
396 if (mSrcStride)
397 return mSrcStride * 4;
398 else
399 return ALIGN(width, ALIGN32) * 4;
400 case YCbCr420Tile:
401 return ALIGN(width, ALIGN128);
402 case YCbCr420SP:
403 return ALIGN(width, ALIGN16);
404 case NV12_2K:
405 return ALIGN(width, ALIGN16);
406 case NV12_128m:
407 return ALIGN(width, ALIGN128);
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, ALIGN16) * 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 case NV12_128m:
434 return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32);
435 default:
436 return 0;
437 }
438 }
439
calcSize(ColorConvertFormat format,size_t width,size_t height)440 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height)
441 {
442 int32_t alignedw = 0;
443 int32_t alignedh = 0;
444 int32_t size = 0;
445
446 switch (format) {
447 case RGB565:
448 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 2;
449 size = ALIGN(size, ALIGN4K);
450 break;
451 case RGBA8888:
452 if (mSrcStride)
453 size = mSrcStride * ALIGN(height, ALIGN32) * 4;
454 else
455 size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 4;
456 size = ALIGN(size, ALIGN4K);
457 break;
458 case YCbCr420SP:
459 alignedw = ALIGN(width, ALIGN16);
460 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K);
461 break;
462 case YCbCr420P:
463 size = ALIGN((width * height * 3 / 2), ALIGN4K);
464 break;
465 case YCrCb420P:
466 alignedw = ALIGN(width, ALIGN16);
467 size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
468 break;
469 case YCbCr420Tile:
470 alignedw = ALIGN(width, ALIGN128);
471 alignedh = ALIGN(height, ALIGN32);
472 size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K);
473 break;
474 case NV12_2K: {
475 alignedw = ALIGN(width, ALIGN16);
476 size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
477 size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
478 size = ALIGN(lumaSize + chromaSize, ALIGN4K);
479 ALOGV("NV12_2k, width = %d, height = %d, size = %d", width, height, size);
480 }
481 break;
482 case NV12_128m:
483 alignedw = ALIGN(width, ALIGN128);
484 alignedh = ALIGN(height, ALIGN32);
485 size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K);
486 break;
487 default:
488 break;
489 }
490 return size;
491 }
492 /*
493 * Tells GPU to map given buffer and returns a physical address of mapped buffer
494 */
getMappedGPUAddr(int bufFD,void * bufPtr,size_t bufLen)495 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
496 {
497 C2D_STATUS status;
498 void *gpuaddr = NULL;
499
500 status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION,
501 &gpuaddr);
502 if (status != C2D_STATUS_OK) {
503 ALOGE("c2dMapAddr failed: status %d fd %d ptr %p len %d flags %d\n",
504 status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION);
505 return NULL;
506 }
507 ALOGV("c2d mapping created: gpuaddr %p fd %d ptr %p len %d\n",
508 gpuaddr, bufFD, bufPtr, bufLen);
509
510 return gpuaddr;
511 }
512
unmapGPUAddr(unsigned long gAddr)513 bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr)
514 {
515
516 C2D_STATUS status = mC2DUnMapAddr((void*)gAddr);
517
518 if (status != C2D_STATUS_OK)
519 ALOGE("c2dUnMapAddr failed: status %d gpuaddr %08lx\n", status, gAddr);
520
521 return (status == C2D_STATUS_OK);
522 }
523
getBuffReq(int32_t port,C2DBuffReq * req)524 int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
525 if (!req) return -1;
526
527 if (port != C2D_INPUT && port != C2D_OUTPUT) return -1;
528
529 memset(req, 0, sizeof(C2DBuffReq));
530 if (port == C2D_INPUT) {
531 req->width = mSrcWidth;
532 req->height = mSrcHeight;
533 req->stride = calcStride(mSrcFormat, mSrcWidth);
534 req->sliceHeight = mSrcHeight;
535 req->lumaAlign = calcLumaAlign(mSrcFormat);
536 req->sizeAlign = calcSizeAlign(mSrcFormat);
537 req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
538 req->bpp = calcBytesPerPixel(mSrcFormat);
539 ALOGV("input req->size = %d\n", req->size);
540 } else if (port == C2D_OUTPUT) {
541 req->width = mDstWidth;
542 req->height = mDstHeight;
543 req->stride = calcStride(mDstFormat, mDstWidth);
544 req->sliceHeight = mDstHeight;
545 req->lumaAlign = calcLumaAlign(mDstFormat);
546 req->sizeAlign = calcSizeAlign(mDstFormat);
547 req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
548 req->bpp = calcBytesPerPixel(mDstFormat);
549 ALOGV("output req->size = %d\n", req->size);
550 }
551 return 0;
552 }
553
calcLumaAlign(ColorConvertFormat format)554 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
555 if (!isYUVSurface(format)) return 1; //no requirement
556
557 switch (format) {
558 case NV12_2K:
559 return ALIGN2K;
560 case NV12_128m:
561 case YCbCr420SP: //OR NV12
562 case YCbCr420P:
563 return 1;
564 default:
565 ALOGE("unknown format passed for luma alignment number");
566 return 1;
567 }
568 }
569
calcSizeAlign(ColorConvertFormat format)570 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
571 if (!isYUVSurface(format)) return 1; //no requirement
572
573 switch (format) {
574 case YCbCr420SP: //OR NV12
575 case YCbCr420P:
576 case NV12_2K:
577 case NV12_128m:
578 return ALIGN4K;
579 default:
580 ALOGE("unknown format passed for size alignment number");
581 return 1;
582 }
583 }
584
calcBytesPerPixel(ColorConvertFormat format)585 C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) {
586 C2DBytesPerPixel bpp;
587 bpp.numerator = 0;
588 bpp.denominator = 1;
589
590 switch (format) {
591 case RGB565:
592 bpp.numerator = 2;
593 break;
594 case RGBA8888:
595 bpp.numerator = 4;
596 break;
597 case YCbCr420SP:
598 case YCbCr420P:
599 case YCrCb420P:
600 case YCbCr420Tile:
601 case NV12_2K:
602 case NV12_128m:
603 bpp.numerator = 3;
604 bpp.denominator = 2;
605 break;
606 default:
607 break;
608 }
609 return bpp;
610 }
611
dumpOutput(char * filename,char mode)612 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
613 int fd;
614 size_t stride, sliceHeight;
615 if (!filename) return -1;
616
617 int flags = O_RDWR | O_CREAT;
618 if (mode == 'a') {
619 flags |= O_APPEND;
620 }
621
622 if ((fd = open(filename, flags)) < 0) {
623 ALOGE("open dump file failed w/ errno %s", strerror(errno));
624 return -1;
625 }
626
627 int ret = 0;
628 if (isYUVSurface(mDstFormat)) {
629 C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
630 uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
631 stride = dstSurfaceDef->stride0;
632 sliceHeight = dstSurfaceDef->height;
633 /* dump luma */
634 for (size_t i = 0; i < sliceHeight; i++) {
635 ret = write(fd, base, mDstWidth); //will work only for the 420 ones
636 if (ret < 0) goto cleanup;
637 base += stride;
638 }
639
640 if (mDstFormat == YCbCr420P ||
641 mDstFormat == YCrCb420P) {
642 printf("Dump Cb and Cr separately for Planar\n");
643 //dump Cb/Cr
644 base = (uint8_t *)dstSurfaceDef->plane1;
645 stride = dstSurfaceDef->stride1;
646 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
647 ret = write(fd, base, mDstWidth/2);
648 if (ret < 0) goto cleanup;
649 base += stride;
650 }
651
652 //dump Cr/Cb
653 base = (uint8_t *)dstSurfaceDef->plane2;
654 stride = dstSurfaceDef->stride2;
655
656 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
657 ret = write(fd, base, mDstWidth/2);
658 if (ret < 0) goto cleanup;
659 base += stride;
660 }
661
662 } else {
663 /* dump chroma */
664 base = (uint8_t *)dstSurfaceDef->plane1;
665 stride = dstSurfaceDef->stride1;
666 for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
667 ret = write(fd, base, mDstWidth);
668 if (ret < 0) goto cleanup;
669 base += stride;
670 }
671 }
672 } else {
673 C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
674 uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
675 stride = dstSurfaceDef->stride;
676 sliceHeight = dstSurfaceDef->height;
677
678 printf("rgb surface base is %p", base);
679 printf("rgb surface dumpsslice height is %lu\n", (unsigned long)sliceHeight);
680 printf("rgb surface dump stride is %lu\n", (unsigned long)stride);
681
682 int bpp = 1; //bytes per pixel
683 if (mDstFormat == RGB565) {
684 bpp = 2;
685 } else if (mDstFormat == RGBA8888) {
686 bpp = 4;
687 }
688
689 int count = 0;
690 for (size_t i = 0; i < sliceHeight; i++) {
691 ret = write(fd, base, mDstWidth*bpp);
692 if (ret < 0) {
693 printf("write failed, count = %d\n", count);
694 goto cleanup;
695 }
696 base += stride;
697 count += stride;
698 }
699 }
700 cleanup:
701 if (ret < 0) {
702 ALOGE("file write failed w/ errno %s", strerror(errno));
703 }
704 close(fd);
705 return ret < 0 ? ret : 0;
706 }
707
createC2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)708 extern "C" C2DColorConverterBase* createC2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride)
709 {
710 return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags, srcStride);
711 }
712
destroyC2DColorConverter(C2DColorConverterBase * C2DCC)713 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC)
714 {
715 delete C2DCC;
716 }
717
718 }
719