• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <arm_neon.h>
32 #include <stdlib.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 
39 #undef LOG_TAG
40 #define LOG_TAG "C2DColorConvert"
41 #define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
42 #define ALIGN8K 8192
43 #define ALIGN4K 4096
44 #define ALIGN2K 2048
45 #define ALIGN128 128
46 #define ALIGN32 32
47 #define ALIGN16 16
48 
49 //-----------------------------------------------------
50 namespace android {
51 
52 class C2DColorConverter : public C2DColorConverterBase {
53 
54 public:
55     C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags,size_t srcStride);
56     int32_t getBuffReq(int32_t port, C2DBuffReq *req);
57     int32_t dumpOutput(char * filename, char mode);
58 protected:
59     virtual ~C2DColorConverter();
60     virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData);
61 
62 private:
63     virtual bool isYUVSurface(ColorConvertFormat format);
64     virtual void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource);
65     virtual C2D_STATUS updateYUVSurfaceDef(int fd, void *base, void * data, bool isSource);
66     virtual C2D_STATUS updateRGBSurfaceDef(int fd, void * data, bool isSource);
67     virtual uint32_t getC2DFormat(ColorConvertFormat format);
68     virtual size_t calcStride(ColorConvertFormat format, size_t width);
69     virtual size_t calcYSize(ColorConvertFormat format, size_t width, size_t height);
70     virtual size_t calcSize(ColorConvertFormat format, size_t width, size_t height);
71     virtual void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen);
72     virtual bool unmapGPUAddr(uint32_t gAddr);
73     virtual size_t calcLumaAlign(ColorConvertFormat format);
74     virtual size_t calcSizeAlign(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     if (isYUVSurface(mSrcFormat)) {
179         delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
180     } else {
181         delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
182     }
183 
184     if (isYUVSurface(mDstFormat)) {
185         delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
186     } else {
187         delete ((C2D_RGB_SURFACE_DEF *)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((uint32_t)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0);
236     } else {
237         unmappedSrcSuccess = unmapGPUAddr((uint32_t)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys);
238     }
239 
240     bool unmappedDstSuccess;
241     if (isYUVSurface(mDstFormat)) {
242         unmappedDstSuccess = unmapGPUAddr((uint32_t)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0);
243     } else {
244         unmappedDstSuccess = unmapGPUAddr((uint32_t)((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 = new C2D_YUV_SURFACE_DEF;
280         surfaceDef->format = getC2DFormat(format);
281         surfaceDef->width = width;
282         surfaceDef->height = height;
283         surfaceDef->plane0 = (void *)0xaaaaaaaa;
284         surfaceDef->phys0 = (void *)0xaaaaaaaa;
285         surfaceDef->stride0 = calcStride(format, width);
286         surfaceDef->plane1 = (void *)0xaaaaaaaa;
287         surfaceDef->phys1 = (void *)0xaaaaaaaa;
288         surfaceDef->stride1 = calcStride(format, width);
289 
290         if (format == YCbCr420P ||
291             format == YCrCb420P) {
292           printf("half stride for Cb Cr planes \n");
293           surfaceDef->stride1 = calcStride(format, width) / 2;
294           surfaceDef->phys2 = (void *)0xaaaaaaaa;
295           surfaceDef->stride2 = calcStride(format, width) / 2;
296         }
297         mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
298                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
299                         &(*surfaceDef));
300         return ((void *)surfaceDef);
301     } else {
302         C2D_RGB_SURFACE_DEF * surfaceDef = new C2D_RGB_SURFACE_DEF;
303         surfaceDef->format = getC2DFormat(format);
304         surfaceDef->width = width;
305         surfaceDef->height = height;
306         surfaceDef->buffer = (void *)0xaaaaaaaa;
307         surfaceDef->phys = (void *)0xaaaaaaaa;
308         surfaceDef->stride = calcStride(format, width);
309         mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
310                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
311                         &(*surfaceDef));
312         return ((void *)surfaceDef);
313     }
314 }
315 
updateYUVSurfaceDef(int fd,void * base,void * data,bool isSource)316 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(int fd, void *base, void *data, bool isSource)
317 {
318     if (isSource) {
319         C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
320         srcSurfaceDef->plane0 = data;
321         srcSurfaceDef->phys0  = getMappedGPUAddr(fd, data, mSrcSize) + ((uint8_t *)data - (uint8_t *)base);
322         srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
323         srcSurfaceDef->phys1  = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
324         srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
325         srcSurfaceDef->phys2  = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
326 
327         return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
328                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
329                         &(*srcSurfaceDef));
330     } else {
331         C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
332         dstSurfaceDef->plane0 = data;
333         dstSurfaceDef->phys0  = getMappedGPUAddr(fd, data, mDstSize) + ((uint8_t *)data - (uint8_t *)base);
334         dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
335         dstSurfaceDef->phys1  = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
336         dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
337         dstSurfaceDef->phys2  = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
338 
339         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
340                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
341                         &(*dstSurfaceDef));
342     }
343 }
344 
updateRGBSurfaceDef(int fd,void * data,bool isSource)345 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(int fd, void * data, bool isSource)
346 {
347     if (isSource) {
348         C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
349         srcSurfaceDef->buffer = data;
350         srcSurfaceDef->phys = getMappedGPUAddr(fd, data, mSrcSize);
351         return  mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
352                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
353                         &(*srcSurfaceDef));
354     } else {
355         C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
356         dstSurfaceDef->buffer = data;
357         ALOGV("dstSurfaceDef->buffer = %p\n", data);
358         dstSurfaceDef->phys = getMappedGPUAddr(fd, data, mDstSize);
359         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
360                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
361                         &(*dstSurfaceDef));
362     }
363 }
364 
getC2DFormat(ColorConvertFormat format)365 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format)
366 {
367     switch (format) {
368         case RGB565:
369             return C2D_COLOR_FORMAT_565_RGB;
370         case RGBA8888:
371             return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED;
372         case YCbCr420Tile:
373             return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
374         case YCbCr420SP:
375         case NV12_2K:
376         case NV12_128m:
377             return C2D_COLOR_FORMAT_420_NV12;
378         case YCbCr420P:
379             return C2D_COLOR_FORMAT_420_I420;
380         case YCrCb420P:
381             return C2D_COLOR_FORMAT_420_YV12;
382         default:
383             ALOGE("Format not supported , %d\n", format);
384             return -1;
385     }
386 }
387 
calcStride(ColorConvertFormat format,size_t width)388 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
389 {
390     switch (format) {
391         case RGB565:
392             return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
393         case RGBA8888:
394 	if (mSrcStride)
395 		return mSrcStride * 4;
396 	else
397 		return ALIGN(width, ALIGN32) * 4;
398         case YCbCr420Tile:
399             return ALIGN(width, ALIGN128);
400         case YCbCr420SP:
401             return ALIGN(width, ALIGN32);
402         case NV12_2K:
403             return ALIGN(width, ALIGN16);
404         case NV12_128m:
405             return ALIGN(width, ALIGN128);
406         case YCbCr420P:
407             return width;
408         case YCrCb420P:
409             return ALIGN(width, ALIGN16);
410         default:
411             return 0;
412     }
413 }
414 
calcYSize(ColorConvertFormat format,size_t width,size_t height)415 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height)
416 {
417     switch (format) {
418         case YCbCr420SP:
419             return (ALIGN(width, ALIGN32) * height);
420         case YCbCr420P:
421             return width * height;
422         case YCrCb420P:
423             return ALIGN(width, ALIGN16) * height;
424         case YCbCr420Tile:
425             return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K);
426         case NV12_2K: {
427             size_t alignedw = ALIGN(width, ALIGN16);
428             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
429             return lumaSize;
430         }
431         case NV12_128m:
432             return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32);
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             if (mSrcStride)
451               size = mSrcStride *  ALIGN(height, ALIGN32) * 4;
452             else
453               size = ALIGN(width, ALIGN32) * ALIGN(height, ALIGN32) * 4;
454             size = ALIGN(size, ALIGN4K);
455             break;
456         case YCbCr420SP:
457             alignedw = ALIGN(width, ALIGN32);
458             size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K);
459             break;
460         case YCbCr420P:
461             size = ALIGN((width * height * 3 / 2), ALIGN4K);
462             break;
463         case YCrCb420P:
464             alignedw = ALIGN(width, ALIGN16);
465             size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
466             break;
467         case YCbCr420Tile:
468             alignedw = ALIGN(width, ALIGN128);
469             alignedh = ALIGN(height, ALIGN32);
470             size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K);
471             break;
472         case NV12_2K: {
473             alignedw = ALIGN(width, ALIGN16);
474             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
475             size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
476             size = ALIGN(lumaSize + chromaSize, ALIGN4K);
477             ALOGV("NV12_2k, width = %d, height = %d, size = %d", width, height, size);
478             }
479             break;
480         case NV12_128m:
481             alignedw = ALIGN(width, ALIGN128);
482             alignedh = ALIGN(height, ALIGN32);
483             size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K);
484             break;
485         default:
486             break;
487     }
488     return size;
489 }
490 /*
491  * Tells GPU to map given buffer and returns a physical address of mapped buffer
492  */
getMappedGPUAddr(int bufFD,void * bufPtr,size_t bufLen)493 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
494 {
495     C2D_STATUS status;
496     void *gpuaddr = NULL;
497 
498     status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION,
499             &gpuaddr);
500     if (status != C2D_STATUS_OK) {
501         ALOGE("c2dMapAddr failed: status %d fd %d ptr %p len %d flags %d\n",
502                 status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION);
503         return NULL;
504     }
505     ALOGV("c2d mapping created: gpuaddr %p fd %d ptr %p len %d\n",
506             gpuaddr, bufFD, bufPtr, bufLen);
507 
508     return gpuaddr;
509 }
510 
unmapGPUAddr(uint32_t gAddr)511 bool C2DColorConverter::unmapGPUAddr(uint32_t gAddr)
512 {
513 
514     C2D_STATUS status = mC2DUnMapAddr((void*)gAddr);
515 
516     if (status != C2D_STATUS_OK)
517         ALOGE("c2dUnMapAddr failed: status %d gpuaddr %08x\n", status, gAddr);
518 
519     return (status == C2D_STATUS_OK);
520 }
521 
getBuffReq(int32_t port,C2DBuffReq * req)522 int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
523     if (!req) return -1;
524 
525     if (port != C2D_INPUT && port != C2D_OUTPUT) return -1;
526 
527     memset(req, 0, sizeof(C2DBuffReq));
528     if (port == C2D_INPUT) {
529         req->width = mSrcWidth;
530         req->height = mSrcHeight;
531         req->stride = calcStride(mSrcFormat, mSrcWidth);
532         req->sliceHeight = mSrcHeight;
533         req->lumaAlign = calcLumaAlign(mSrcFormat);
534         req->sizeAlign = calcSizeAlign(mSrcFormat);
535         req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
536         //add bpp?
537         ALOGV("input req->size = %d\n", req->size);
538     } else if (port == C2D_OUTPUT) {
539         req->width = mDstWidth;
540         req->height = mDstHeight;
541         req->stride = calcStride(mDstFormat, mDstWidth);
542         req->sliceHeight = mDstHeight;
543         req->lumaAlign = calcLumaAlign(mDstFormat);
544         req->sizeAlign = calcSizeAlign(mDstFormat);
545         req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
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           return 1;
559         default:
560           ALOGE("unknown format passed for luma alignment number");
561           return 1;
562     }
563 }
564 
calcSizeAlign(ColorConvertFormat format)565 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
566     if (!isYUVSurface(format)) return 1; //no requirement
567 
568     switch (format) {
569         case YCbCr420SP: //OR NV12
570         case YCbCr420P:
571         case NV12_2K:
572         case NV12_128m:
573           return ALIGN4K;
574         default:
575           ALOGE("unknown format passed for size alignment number");
576           return 1;
577     }
578 }
579 
dumpOutput(char * filename,char mode)580 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
581     int fd;
582     size_t stride, sliceHeight;
583     if (!filename) return -1;
584 
585     int flags = O_RDWR | O_CREAT;
586     if (mode == 'a') {
587       flags |= O_APPEND;
588     }
589 
590     if ((fd = open(filename, flags)) < 0) {
591         ALOGE("open dump file failed w/ errno %s", strerror(errno));
592         return -1;
593     }
594 
595     int ret = 0;
596     if (isYUVSurface(mDstFormat)) {
597       C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
598       uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
599       stride = dstSurfaceDef->stride0;
600       sliceHeight = dstSurfaceDef->height;
601       /* dump luma */
602       for (size_t i = 0; i < sliceHeight; i++) {
603         ret = write(fd, base, mDstWidth); //will work only for the 420 ones
604         if (ret < 0) goto cleanup;
605         base += stride;
606       }
607 
608       if (mDstFormat == YCbCr420P ||
609           mDstFormat == YCrCb420P) {
610           printf("Dump Cb and Cr separately for Planar\n");
611           //dump Cb/Cr
612           base = (uint8_t *)dstSurfaceDef->plane1;
613           stride = dstSurfaceDef->stride1;
614           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
615             ret = write(fd, base, mDstWidth/2);
616             if (ret < 0) goto cleanup;
617             base += stride;
618           }
619 
620           //dump Cr/Cb
621           base = (uint8_t *)dstSurfaceDef->plane2;
622           stride = dstSurfaceDef->stride2;
623 
624           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
625             ret = write(fd, base, mDstWidth/2);
626             if (ret < 0) goto cleanup;
627             base += stride;
628           }
629 
630       } else {
631           /* dump chroma */
632           base = (uint8_t *)dstSurfaceDef->plane1;
633           stride = dstSurfaceDef->stride1;
634           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
635             ret = write(fd, base, mDstWidth);
636             if (ret < 0) goto cleanup;
637             base += stride;
638           }
639       }
640     } else {
641       C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
642       uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
643       stride = dstSurfaceDef->stride;
644       sliceHeight = dstSurfaceDef->height;
645 
646       printf("rgb surface base is %p", base);
647       printf("rgb surface dumpsslice height is %d\n", sliceHeight);
648       printf("rgb surface dump stride is %d\n", stride);
649 
650       int bpp = 1; //bytes per pixel
651       if (mDstFormat == RGB565) {
652         bpp = 2;
653       } else if (mDstFormat == RGBA8888) {
654         bpp = 4;
655       }
656 
657       int count = 0;
658       for (size_t i = 0; i < sliceHeight; i++) {
659         ret = write(fd, base, mDstWidth*bpp);
660         if (ret < 0) {
661           printf("write failed, count = %d\n", count);
662           goto cleanup;
663         }
664         base += stride;
665         count += stride;
666       }
667     }
668  cleanup:
669     if (ret < 0) {
670       ALOGE("file write failed w/ errno %s", strerror(errno));
671     }
672     close(fd);
673     return ret < 0 ? ret : 0;
674 }
675 
createC2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)676 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)
677 {
678     return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags, srcStride);
679 }
680 
destroyC2DColorConverter(C2DColorConverterBase * C2DCC)681 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC)
682 {
683     delete C2DCC;
684 }
685 
686 }
687