• 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 <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