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