• 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     param.fd = bufFD;
489     param.offset = 0;
490     param.len = bufLen;
491     param.hostptr = (unsigned int)bufPtr;
492     param.memtype = KGSL_USER_MEM_TYPE_ION;
493     param.reserved = 0;
494     param.gpuaddr = 0;
495 
496     if (!ioctl(mKgslFd, IOCTL_KGSL_MAP_USER_MEM, &param, sizeof(param))) {
497         ALOGV("mapping successful for buffer %p size %d\n",
498                bufPtr, bufLen);
499         return (void *)param.gpuaddr;
500     }
501     ALOGE("mapping failed w/ errno %s", strerror(errno));
502     return NULL;
503 }
504 
unmapGPUAddr(uint32_t gAddr)505 bool C2DColorConverter::unmapGPUAddr(uint32_t gAddr)
506 {
507    int rc = 0;
508    struct kgsl_sharedmem_free param;
509    memset(&param, 0, sizeof(param));
510    param.gpuaddr = gAddr;
511 
512    rc = ioctl(mKgslFd, IOCTL_KGSL_SHAREDMEM_FREE, (void *)&param,
513      sizeof(param));
514    if (rc < 0) {
515      ALOGE("%s: IOCTL_KGSL_SHAREDMEM_FREE failed rc = %d\n", __func__, rc);
516      return false;
517    }
518    return true;
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         //add bpp?
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         ALOGV("output req->size = %d\n", req->size);
546     }
547     return 0;
548 }
549 
calcLumaAlign(ColorConvertFormat format)550 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
551     if (!isYUVSurface(format)) return 1; //no requirement
552 
553     switch (format) {
554         case NV12_2K:
555           return ALIGN2K;
556         default:
557           ALOGE("unknown format passed for luma alignment number");
558           return 1;
559     }
560 }
561 
calcSizeAlign(ColorConvertFormat format)562 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
563     if (!isYUVSurface(format)) return 1; //no requirement
564 
565     switch (format) {
566         case YCbCr420SP: //OR NV12
567         case YCbCr420P:
568         case NV12_2K:
569           return ALIGN4K;
570         default:
571           ALOGE("unknown format passed for size alignment number");
572           return 1;
573     }
574 }
575 
dumpOutput(char * filename,char mode)576 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
577     int fd;
578     size_t stride, sliceHeight;
579     if (!filename) return -1;
580 
581     int flags = O_RDWR | O_CREAT;
582     if (mode == 'a') {
583       flags |= O_APPEND;
584     }
585 
586     if ((fd = open(filename, flags)) < 0) {
587         ALOGE("open dump file failed w/ errno %s", strerror(errno));
588         return -1;
589     }
590 
591     int ret = 0;
592     if (isYUVSurface(mDstFormat)) {
593       C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
594       uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
595       stride = dstSurfaceDef->stride0;
596       sliceHeight = dstSurfaceDef->height;
597       /* dump luma */
598       for (size_t i = 0; i < sliceHeight; i++) {
599         ret = write(fd, base, mDstWidth); //will work only for the 420 ones
600         if (ret < 0) goto cleanup;
601         base += stride;
602       }
603 
604       if (mDstFormat == YCbCr420P ||
605           mDstFormat == YCrCb420P) {
606           printf("Dump Cb and Cr separately for Planar\n");
607           //dump Cb/Cr
608           base = (uint8_t *)dstSurfaceDef->plane1;
609           stride = dstSurfaceDef->stride1;
610           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
611             ret = write(fd, base, mDstWidth/2);
612             if (ret < 0) goto cleanup;
613             base += stride;
614           }
615 
616           //dump Cr/Cb
617           base = (uint8_t *)dstSurfaceDef->plane2;
618           stride = dstSurfaceDef->stride2;
619 
620           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
621             ret = write(fd, base, mDstWidth/2);
622             if (ret < 0) goto cleanup;
623             base += stride;
624           }
625 
626       } else {
627           /* dump chroma */
628           base = (uint8_t *)dstSurfaceDef->plane1;
629           stride = dstSurfaceDef->stride1;
630           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
631             ret = write(fd, base, mDstWidth);
632             if (ret < 0) goto cleanup;
633             base += stride;
634           }
635       }
636     } else {
637       C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
638       uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
639       stride = dstSurfaceDef->stride;
640       sliceHeight = dstSurfaceDef->height;
641 
642       printf("rgb surface base is %p", base);
643       printf("rgb surface dumpsslice height is %d\n", sliceHeight);
644       printf("rgb surface dump stride is %d\n", stride);
645 
646       int bpp = 1; //bytes per pixel
647       if (mDstFormat == RGB565) {
648         bpp = 2;
649       } else if (mDstFormat == RGBA8888) {
650         bpp = 4;
651       }
652 
653       int count = 0;
654       for (size_t i = 0; i < sliceHeight; i++) {
655         ret = write(fd, base, mDstWidth*bpp);
656         if (ret < 0) {
657           printf("write failed, count = %d\n", count);
658           goto cleanup;
659         }
660         base += stride;
661         count += stride;
662       }
663     }
664  cleanup:
665     if (ret < 0) {
666       ALOGE("file write failed w/ errno %s", strerror(errno));
667     }
668     close(fd);
669     return ret < 0 ? ret : 0;
670 }
671 
createC2DColorConverter(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags)672 extern "C" C2DColorConverterBase* createC2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags)
673 {
674     return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags);
675 }
676 
destroyC2DColorConverter(C2DColorConverterBase * C2DCC)677 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC)
678 {
679     delete C2DCC;
680 }
681 
682 }
683