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