• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012 - 2020, 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 
swap(size_t & x,size_t & y)32 void swap(size_t &x, size_t &y)
33 {
34     x = x ^ y;
35     y = x ^ y;
36     x = x ^ y;
37 }
38 
C2DColorConverter()39 C2DColorConverter::C2DColorConverter()
40     : mC2DLibHandle(NULL),
41       mAdrenoUtilsHandle(NULL)
42 {
43 
44     enabled = true;
45     mSrcSurface = 0;
46     mDstSurface = 0;
47 
48     mSrcWidth = 0;
49     mSrcHeight = 0;
50     mSrcStride = 0;
51     mDstWidth = 0;
52     mDstHeight = 0;
53     mRotation = C2D_TARGET_ROTATE_0;
54     mSrcFormat = NO_COLOR_FORMAT;
55     mDstFormat = NO_COLOR_FORMAT;
56     mSrcSurfaceDef = NULL;
57     mDstSurfaceDef = NULL;
58 
59     mConversionNeeded = false;
60 
61     pthread_mutex_init(&mLock, NULL);
62 
63     mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW);
64     if (!mC2DLibHandle) {
65         ALOGE("%s: ERROR: could not dlopen libc2d2.so: %s. C2D is disabled.",
66                                                     __FUNCTION__, dlerror());
67         enabled = false;
68         return;
69     }
70     mAdrenoUtilsHandle = dlopen("libadreno_utils.so", RTLD_NOW);
71     if (!mAdrenoUtilsHandle) {
72         ALOGE("%s: ERROR: could not dlopen libadreno_utils.so: %s.. C2D is disabled.",
73                                                     __FUNCTION__, dlerror());
74         enabled = false;
75         return;
76     }
77 
78     mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface");
79     mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface");
80     mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface");
81     mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw");
82     mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush");
83     mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish");
84     mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp");
85     mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface");
86     mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr");
87     mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr");
88 
89     if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface
90         || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp
91         || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) {
92         ALOGE("%s: dlsym ERROR. C2D is disabled. mC2DCreateSurface[%p] mC2DUpdateSurface[%p] "
93               "mC2DReadSurface[%p] mC2DDraw[%p] mC2DFlush[%p] mC2DFinish[%p] mC2DWaitTimestamp[%p] "
94               "mC2DDestroySurface[%p] mC2DMapAddr[%p] mC2DUnMapAddr[%p]", __FUNCTION__,
95               mC2DCreateSurface, mC2DUpdateSurface, mC2DReadSurface, mC2DDraw, mC2DFlush, mC2DFinish,
96               mC2DWaitTimestamp, mC2DDestroySurface, mC2DMapAddr, mC2DUnMapAddr);
97         enabled = false;
98         return;
99     }
100 
101     mAdrenoComputeFmtAlignedWidthAndHeight = (LINK_adreno_compute_fmt_aligned_width_and_height)dlsym(mAdrenoUtilsHandle, "compute_fmt_aligned_width_and_height");
102     if (!mAdrenoComputeFmtAlignedWidthAndHeight) {
103         ALOGE("%s: dlsym compute_aligned_width_and_height ERROR. C2D is disabled.", __FUNCTION__);
104         enabled = false;
105         return;
106     }
107 }
108 
~C2DColorConverter()109 C2DColorConverter::~C2DColorConverter()
110 {
111     if (enabled) {
112 
113         if (mDstSurface) {
114             mC2DDestroySurface(mDstSurface);
115             mDstSurface = 0;
116         }
117         if (mSrcSurface) {
118             mC2DDestroySurface(mSrcSurface);
119             mSrcSurface = 0;
120         }
121 
122         if (mSrcSurfaceDef) {
123             if (isYUVSurface(mSrcFormat)) {
124                 delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
125             } else {
126                 delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
127             }
128         }
129 
130         if (mDstSurfaceDef) {
131             if (isYUVSurface(mDstFormat)) {
132                 delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
133             } else {
134                 delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef);
135             }
136         }
137         mSrcSurfaceDef = NULL;
138         mDstSurfaceDef = NULL;
139     }
140 
141     if (mC2DLibHandle) {
142         dlclose(mC2DLibHandle);
143         mC2DLibHandle = NULL;
144     }
145     if (mAdrenoUtilsHandle) {
146         dlclose(mAdrenoUtilsHandle);
147         mAdrenoUtilsHandle = NULL;
148     }
149 
150 }
151 
isPropChanged(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)152 bool C2DColorConverter::isPropChanged(size_t srcWidth, size_t srcHeight, size_t dstWidth,
153                                       size_t dstHeight, ColorConvertFormat srcFormat,
154                                       ColorConvertFormat dstFormat, int32_t flags,
155                                       size_t srcStride)
156 {
157     return (mSrcWidth  != srcWidth   ||
158             mSrcHeight != srcHeight  ||
159             mDstWidth  != dstWidth   ||
160             mDstHeight != dstHeight  ||
161             mSrcFormat != srcFormat  ||
162             mDstFormat != dstFormat  ||
163             mSrcStride != srcStride  ||
164             (mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)  !=
165                       (flags  & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED));
166 }
167 
setResolution(size_t srcWidth,size_t srcHeight,size_t dstWidth,size_t dstHeight,ColorConvertFormat srcFormat,ColorConvertFormat dstFormat,int32_t flags,size_t srcStride)168 bool C2DColorConverter::setResolution(size_t srcWidth, size_t srcHeight,
169                                       size_t dstWidth, size_t dstHeight,
170                                       ColorConvertFormat srcFormat,
171                                       ColorConvertFormat dstFormat,
172                                       int32_t flags, size_t srcStride)
173 {
174     int32_t retval = -1;
175     if (enabled) {
176         pthread_mutex_lock(&mLock);
177 
178         ClearSurfaces();
179 
180         mSrcWidth = srcWidth;
181         mSrcHeight = srcHeight;
182         mSrcStride = srcStride;
183         mDstWidth = dstWidth;
184         mDstHeight = dstHeight;
185         mSrcFormat = srcFormat;
186         mDstFormat = dstFormat;
187 
188         if (mRotation == C2D_TARGET_ROTATE_90 ||
189             mRotation == C2D_TARGET_ROTATE_270) {
190                 swap(mDstWidth, mDstHeight);
191         }
192         mSrcSize = calcSize(srcFormat, mSrcWidth, mSrcHeight);
193         mDstSize = calcSize(dstFormat, mDstWidth, mDstHeight);
194         mSrcYSize = calcYSize(srcFormat, mSrcWidth, mSrcHeight);
195         mDstYSize = calcYSize(dstFormat, mDstWidth, mDstHeight);
196         mFlags = flags;
197 
198         retval = getDummySurfaceDef(srcFormat, mSrcWidth, mSrcHeight, true);
199         retval |= getDummySurfaceDef(dstFormat, mDstWidth, mDstHeight, false);
200 
201         if (retval == 0) {
202             memset((void*)&mBlit,0,sizeof(C2D_OBJECT));
203             mBlit.source_rect.x = 0 << 16;
204             mBlit.source_rect.y = 0 << 16;
205             mBlit.source_rect.width = srcWidth << 16;
206             mBlit.source_rect.height = srcHeight << 16;
207             mBlit.target_rect.x = 0 << 16;
208             mBlit.target_rect.y = 0 << 16;
209             mBlit.target_rect.width = dstWidth << 16;
210             mBlit.target_rect.height = dstHeight << 16;
211             mBlit.config_mask = C2D_ALPHA_BLEND_NONE    |
212                 C2D_NO_BILINEAR_BIT     |
213                 C2D_NO_ANTIALIASING_BIT |
214                 C2D_TARGET_RECT_BIT;
215             mBlit.surface_id = mSrcSurface;
216         }
217 
218         pthread_mutex_unlock(&mLock);
219     }
220 
221     return retval == 0? true:false;
222 }
223 
setRotation(int32_t rotation)224 void C2DColorConverter::setRotation(int32_t rotation) {
225     // C2D does rotation in anticlock wise, where as VPE rotates in clockwise
226     // Hence swapping the 90 and 270 angles to rotate in clockwise
227     switch (rotation) {
228         case 90:
229             mRotation  = C2D_TARGET_ROTATE_270;
230             break;
231         case 180:
232             mRotation  = C2D_TARGET_ROTATE_180;
233             break;
234         case 270:
235             mRotation  = C2D_TARGET_ROTATE_90;
236             break;
237         default:
238             mRotation = C2D_TARGET_ROTATE_0;
239             break;
240     }
241 }
convertC2D(int srcFd,void * srcBase,void * srcData,int dstFd,void * dstBase,void * dstData)242 bool C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData,
243                                    int dstFd, void *dstBase, void * dstData)
244 {
245   C2D_STATUS ret;
246   uint8_t *srcMappedGpuAddr = nullptr;
247   uint8_t *dstMappedGpuAddr = nullptr;
248   bool status = false;
249 
250   if (enabled) {
251     pthread_mutex_lock(&mLock);
252     if (srcFd < 0 || dstFd < 0
253                 || srcData == NULL || dstData == NULL
254                 || srcBase == NULL || dstBase == NULL) {
255       ALOGE("%s: Color conversion failed. Incorrect input parameters FD (%d:%d) Data (%p:%p) Base (%p:%p)",
256             __FUNCTION__, srcFd, dstFd, srcData, dstData, srcBase, dstBase);
257       status = false;
258     } else {
259 
260       srcMappedGpuAddr = (uint8_t *)getMappedGPUAddr(srcFd, srcData, mSrcSize);
261       if (!srcMappedGpuAddr) {
262           pthread_mutex_unlock(&mLock);
263           return false;
264       }
265 
266       if (isYUVSurface(mSrcFormat)) {
267         ret = updateYUVSurfaceDef(srcMappedGpuAddr, srcBase, srcData, true);
268       } else {
269         ret = updateRGBSurfaceDef(srcMappedGpuAddr, srcData, true);
270       }
271 
272       if (ret == C2D_STATUS_OK) {
273 
274         dstMappedGpuAddr = (uint8_t *)getMappedGPUAddr(dstFd, dstData, mDstSize);
275         if (!dstMappedGpuAddr) {
276           unmapGPUAddr((unsigned long)srcMappedGpuAddr);
277           pthread_mutex_unlock(&mLock);
278           return false;
279         }
280 
281         if (isYUVSurface(mDstFormat)) {
282           ret = updateYUVSurfaceDef(dstMappedGpuAddr, dstBase, dstData, false);
283         } else {
284           ret = updateRGBSurfaceDef(dstMappedGpuAddr, dstData, false);
285         }
286 
287         if (ret == C2D_STATUS_OK) {
288 
289           mBlit.surface_id = mSrcSurface;
290           ret = mC2DDraw(mDstSurface, mRotation, 0, 0, 0, &mBlit, 1);
291           mC2DFinish(mDstSurface);
292 
293           if (ret == C2D_STATUS_OK) {
294             bool unmappedSrcSuccess;
295             unmappedSrcSuccess = unmapGPUAddr((unsigned long)srcMappedGpuAddr);
296 
297             bool unmappedDstSuccess;
298             unmappedDstSuccess = unmapGPUAddr((unsigned long)dstMappedGpuAddr);
299 
300             if (!unmappedSrcSuccess || !unmappedDstSuccess) {
301               ALOGE("%s: unmapping GPU address failed (%d:%d)", __FUNCTION__,
302                     unmappedSrcSuccess, unmappedDstSuccess);
303               status = false;
304             } else {
305               status = true;
306             }
307           } else {
308             ALOGE("%s: C2D Draw failed (%d)", __FUNCTION__, ret);
309             status = false;
310           }
311         } else {
312           ALOGE("%s: Update dst surface def failed (%d)", __FUNCTION__, ret);
313           unmapGPUAddr((unsigned long)srcMappedGpuAddr);
314           unmapGPUAddr((unsigned long)dstMappedGpuAddr);
315           status = false;
316         }
317       } else {
318         ALOGE("%s: Update src surface def failed (%d)", __FUNCTION__, ret);
319         unmapGPUAddr((unsigned long)srcMappedGpuAddr);
320         status = false;
321       }
322     }
323 
324     pthread_mutex_unlock(&mLock);
325   }
326 
327   return status;
328 }
329 
isYUVSurface(ColorConvertFormat format)330 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format)
331 {
332     switch (format) {
333         case YCbCr420Tile:
334         case YCbCr420SP:
335         case YCbCr420P:
336         case YCrCb420P:
337         case NV12_2K:
338         case NV12_512:
339         case NV12_128m:
340         case NV12_UBWC:
341         case TP10_UBWC:
342         case P010:
343         case VENUS_P010:
344             return true;
345         default:
346             return false;
347     }
348 }
349 
ClearSurfaces()350 void C2DColorConverter::ClearSurfaces()
351 {
352         if (mSrcSurface) {
353             mC2DDestroySurface(mSrcSurface);
354             mSrcSurface = 0;
355         }
356 
357          if (mSrcSurfaceDef) {
358             if (isYUVSurface(mSrcFormat)) {
359                 delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
360             } else {
361                 delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
362             }
363             mSrcSurfaceDef = NULL;
364         }
365 
366         if (mDstSurface) {
367             mC2DDestroySurface(mDstSurface);
368             mDstSurface = 0;
369         }
370 
371         if (mDstSurfaceDef) {
372             if (isYUVSurface(mDstFormat)) {
373                 delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
374             } else {
375                 delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef);
376             }
377             mDstSurfaceDef = NULL;
378         }
379 }
380 
getDummySurfaceDef(ColorConvertFormat format,size_t width,size_t height,bool isSource)381 int32_t C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format,
382                                             size_t width, size_t height,
383                                             bool isSource)
384 {
385     void *surfaceDef = NULL;
386     C2D_SURFACE_TYPE hostSurfaceType;
387     C2D_STATUS ret;
388 
389     if (isYUVSurface(format)) {
390         C2D_YUV_SURFACE_DEF **surfaceYUVDef = (C2D_YUV_SURFACE_DEF **)
391                                   (isSource ? &mSrcSurfaceDef : &mDstSurfaceDef);
392         if (*surfaceYUVDef == NULL) {
393             *surfaceYUVDef = (C2D_YUV_SURFACE_DEF *)
394                                   calloc(1, sizeof(C2D_YUV_SURFACE_DEF));
395             if (*surfaceYUVDef == NULL) {
396                 ALOGE("%s: surfaceYUVDef allocation failed", __FUNCTION__);
397                 return -1;
398             }
399         } else {
400             memset(*surfaceYUVDef, 0, sizeof(C2D_YUV_SURFACE_DEF));
401         }
402         (*surfaceYUVDef)->format = getC2DFormat(format, isSource);
403         (*surfaceYUVDef)->width = width;
404         (*surfaceYUVDef)->height = height;
405         (*surfaceYUVDef)->plane0 = (void *)0xaaaaaaaa;
406         (*surfaceYUVDef)->phys0 = (void *)0xaaaaaaaa;
407         (*surfaceYUVDef)->stride0 = calcStride(format, width);
408         (*surfaceYUVDef)->plane1 = (void *)0xaaaaaaaa;
409         (*surfaceYUVDef)->phys1 = (void *)0xaaaaaaaa;
410         (*surfaceYUVDef)->stride1 = calcStride(format, width);
411         (*surfaceYUVDef)->stride2 = calcStride(format, width);
412         (*surfaceYUVDef)->phys2 = NULL;
413         (*surfaceYUVDef)->plane2 = NULL;
414 
415         if (mFlags & private_handle_t::PRIV_FLAGS_ITU_R_601_FR) {
416             (*surfaceYUVDef)->format |= C2D_FORMAT_BT601_FULLRANGE;
417         }
418 
419         if (format == YCbCr420P ||
420             format == YCrCb420P) {
421           ALOGI("%s: half stride for Cb Cr planes \n", __FUNCTION__);
422           (*surfaceYUVDef)->stride1 = calcStride(format, width) / 2;
423           (*surfaceYUVDef)->phys2 = (void *)0xaaaaaaaa;
424           (*surfaceYUVDef)->stride2 = calcStride(format, width) / 2;
425         }
426 
427         surfaceDef = *surfaceYUVDef;
428         hostSurfaceType = C2D_SURFACE_YUV_HOST;
429     } else {
430         C2D_RGB_SURFACE_DEF **surfaceRGBDef = (C2D_RGB_SURFACE_DEF **)
431                                   (isSource ? &mSrcSurfaceDef : &mDstSurfaceDef);
432         if (*surfaceRGBDef == NULL) {
433             *surfaceRGBDef = (C2D_RGB_SURFACE_DEF *)
434                                   calloc(1, sizeof(C2D_RGB_SURFACE_DEF));
435             if (*surfaceRGBDef == NULL) {
436                 ALOGE("%s: surfaceRGBDef allocation failed", __FUNCTION__);
437                 return -1;
438             }
439         } else {
440             memset(*surfaceRGBDef, 0, sizeof(C2D_RGB_SURFACE_DEF));
441         }
442         (*surfaceRGBDef)->format = getC2DFormat(format, isSource);
443 
444         if (mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED ||
445             mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED_PI)
446             (*surfaceRGBDef)->format |= C2D_FORMAT_UBWC_COMPRESSED;
447         (*surfaceRGBDef)->width = width;
448         (*surfaceRGBDef)->height = height;
449         (*surfaceRGBDef)->buffer = (void *)0xaaaaaaaa;
450         (*surfaceRGBDef)->phys = (void *)0xaaaaaaaa;
451         (*surfaceRGBDef)->stride = calcStride(format, width);
452 
453         surfaceDef = *surfaceRGBDef;
454         hostSurfaceType = C2D_SURFACE_RGB_HOST;
455     }
456 
457     ret = mC2DCreateSurface(isSource ? &mSrcSurface :
458                       &mDstSurface,
459                       isSource ? C2D_SOURCE : C2D_TARGET,
460                       (C2D_SURFACE_TYPE)(hostSurfaceType
461                                          | C2D_SURFACE_WITH_PHYS
462                                          | C2D_SURFACE_WITH_PHYS_DUMMY),
463                       surfaceDef);
464     return (int32_t) ret;
465 }
466 
updateYUVSurfaceDef(uint8_t * gpuAddr,void * base,void * data,bool isSource)467 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(uint8_t *gpuAddr, void *base,
468                                                   void *data, bool isSource)
469 {
470     if (isSource) {
471         C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
472         srcSurfaceDef->plane0 = data;
473         srcSurfaceDef->phys0  = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
474         srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
475         srcSurfaceDef->phys1  = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
476         if (srcSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
477                srcSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
478             srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
479             srcSurfaceDef->phys2  = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
480         }
481         return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
482                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
483                         &(*srcSurfaceDef));
484     } else {
485         C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
486         dstSurfaceDef->plane0 = data;
487         dstSurfaceDef->phys0  = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
488         dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
489         dstSurfaceDef->phys1  = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
490         if (dstSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
491                dstSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
492             dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
493             dstSurfaceDef->phys2  = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
494         }
495 
496         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
497                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
498                         &(*dstSurfaceDef));
499     }
500 }
501 
updateRGBSurfaceDef(uint8_t * gpuAddr,void * data,bool isSource)502 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(uint8_t *gpuAddr, void * data, bool isSource)
503 {
504     if (isSource) {
505         C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
506         srcSurfaceDef->buffer = data;
507         srcSurfaceDef->phys = gpuAddr;
508         return  mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
509                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
510                         &(*srcSurfaceDef));
511     } else {
512         C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
513         dstSurfaceDef->buffer = data;
514         ALOGV("%s: dstSurfaceDef->buffer = %p", __FUNCTION__, data);
515         dstSurfaceDef->phys = gpuAddr;
516         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
517                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
518                         &(*dstSurfaceDef));
519     }
520 }
521 
getC2DFormat(ColorConvertFormat format,bool isSource)522 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format, bool isSource)
523 {
524     uint32_t C2DFormat;
525     switch (format) {
526         case RGB565:
527             return C2D_COLOR_FORMAT_565_RGB;
528         case RGBA8888:
529             C2DFormat = C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS;
530             if (isSource)
531                 C2DFormat |= C2D_FORMAT_PREMULTIPLIED;
532             return C2DFormat;
533         case RGBA8888_UBWC:
534             C2DFormat = C2D_COLOR_FORMAT_8888_RGBA |
535                         C2D_FORMAT_SWAP_ENDIANNESS |
536                         C2D_FORMAT_UBWC_COMPRESSED;
537             if (isSource)
538                 C2DFormat |= C2D_FORMAT_PREMULTIPLIED;
539             return C2DFormat;
540         case YCbCr420Tile:
541             return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
542         case YCbCr420SP:
543         case NV12_2K:
544         case NV12_512:
545         case NV12_128m:
546             return C2D_COLOR_FORMAT_420_NV12;
547         case YCbCr420P:
548             return C2D_COLOR_FORMAT_420_I420;
549         case YCrCb420P:
550             return C2D_COLOR_FORMAT_420_YV12;
551         case NV12_UBWC:
552             return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_UBWC_COMPRESSED;
553         case TP10_UBWC:
554             return C2D_COLOR_FORMAT_420_TP10 | C2D_FORMAT_UBWC_COMPRESSED;
555         case P010:
556         case VENUS_P010:
557             return C2D_COLOR_FORMAT_420_P010;
558         default:
559             ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
560             return -1;
561     }
562 }
563 
calcStride(ColorConvertFormat format,size_t width)564 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
565 {
566     switch (format) {
567         case RGB565:
568             return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
569         case RGBA8888:
570             if (mSrcStride)
571                 return mSrcStride * 4;
572             else
573                 return ALIGN(width, ALIGN32) * 4;
574         case YCbCr420Tile:
575             return ALIGN(width, ALIGN128);
576         case YCbCr420SP:
577             return ALIGN(width, ALIGN16);
578         case NV12_2K:
579             return ALIGN(width, ALIGN16);
580         case NV12_512:
581             return ALIGN(width, ALIGN512);
582         case NV12_128m: {
583             int32_t stride_alignment = VENUS_Y_STRIDE(COLOR_FMT_NV12, 1);
584             return ALIGN(width, stride_alignment);
585         }
586         case YCbCr420P:
587             return ALIGN(width, ALIGN16);
588         case YCrCb420P:
589             return ALIGN(width, ALIGN16);
590         case NV12_UBWC:
591             return VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
592         case TP10_UBWC:
593             return VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width);
594         case P010:
595             return ALIGN(width*2, ALIGN64);
596         case VENUS_P010:
597             return ALIGN(width*2, ALIGN256);
598         default:
599             ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
600             return 0;
601     }
602 }
603 
calcYSize(ColorConvertFormat format,size_t width,size_t height)604 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height)
605 {
606     switch (format) {
607         case YCbCr420SP:
608             return (ALIGN(width, ALIGN16) * height);
609         case YCbCr420P:
610             return ALIGN(width, ALIGN16) * height;
611         case YCrCb420P:
612             return ALIGN(width, ALIGN16) * height;
613         case YCbCr420Tile:
614             return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K);
615         case NV12_2K: {
616             size_t alignedw = ALIGN(width, ALIGN16);
617             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
618             return lumaSize;
619         }
620         case NV12_512:
621             return ALIGN(width, ALIGN512) * ALIGN(height, ALIGN512);
622         case NV12_128m: {
623             int32_t stride_alignment = VENUS_Y_STRIDE(COLOR_FMT_NV12, 1);
624             int32_t scanline_alignment = VENUS_Y_SCANLINES(COLOR_FMT_NV12, 1);
625             return ALIGN(width, stride_alignment) * ALIGN(height, scanline_alignment);
626         }
627         case NV12_UBWC:
628             return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width) *
629                     VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K) +
630                  ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, width) *
631                    VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K);
632         case TP10_UBWC:
633             return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) *
634                           VENUS_Y_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height), ALIGN4K) +
635                 ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_BPP10_UBWC, width) *
636                        VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_BPP10_UBWC, height), ALIGN4K);
637         case P010:
638             return (ALIGN(width*2, ALIGN64) * height);
639         case VENUS_P010:
640             return (ALIGN(width*2, ALIGN256) * ALIGN(height, ALIGN32));
641         default:
642             ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
643             return 0;
644     }
645 }
646 
calcSize(ColorConvertFormat format,size_t width,size_t height)647 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height)
648 {
649     int32_t alignedw = 0;
650     int32_t alignedh = 0;
651     int32_t size = 0;
652     int32_t tile_mode = 0;
653     int32_t raster_mode = 0;
654     int32_t padding_threshold = 512; /* hardcode for RGB formats */
655     int32_t bpp = 0;
656 
657     switch (format) {
658         case RGB565:
659             bpp = 2;
660             mAdrenoComputeFmtAlignedWidthAndHeight(width, height,
661                                                    0, ADRENO_PIXELFORMAT_B5G6R5,
662                                                    1, tile_mode, raster_mode,
663                                                    padding_threshold,
664                                                    &alignedw, &alignedh);
665             ALOGV("%s: alignedw %d alignedh %d", __FUNCTION__,alignedw, alignedh);
666             size = alignedw * alignedh * bpp;
667             size = ALIGN(size, ALIGN4K);
668             break;
669         case RGBA8888:
670             bpp = 4;
671             mAdrenoComputeFmtAlignedWidthAndHeight(width, height,
672                                                    0, ADRENO_PIXELFORMAT_R8G8B8A8 ,
673                                                    1, tile_mode, raster_mode,
674                                                    padding_threshold,
675                                                    &alignedw, &alignedh);
676             ALOGV("%s: alignedw %d alignedh %d", __FUNCTION__,alignedw, alignedh);
677             if (mSrcStride)
678               size = mSrcStride *  alignedh * bpp;
679             else
680               size = alignedw * alignedh * bpp;
681             size = ALIGN(size, ALIGN4K);
682             break;
683         case YCbCr420SP:
684             alignedw = ALIGN(width, ALIGN16);
685             size = ALIGN((alignedw * height) + (ALIGN((width+1)/2, ALIGN32) * ((height+1)/2) * 2), ALIGN4K);
686             break;
687         case YCbCr420P:
688             alignedw = ALIGN(width, ALIGN16);
689             size = ALIGN((alignedw * height) + (ALIGN((width+1)/2, ALIGN16) * ((height+1)/2) * 2), ALIGN4K);
690             break;
691         case YCrCb420P:
692             alignedw = ALIGN(width, ALIGN16);
693             size = ALIGN((alignedw * height) + (ALIGN((width+1)/2, ALIGN16) * ((height+1)/2) * 2), ALIGN4K);
694             break;
695         case YCbCr420Tile:
696             alignedw = ALIGN(width, ALIGN128);
697             alignedh = ALIGN(height, ALIGN32);
698             size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN((height+1)/2, ALIGN32), ALIGN8K);
699             break;
700         case NV12_2K: {
701             alignedw = ALIGN(width, ALIGN16);
702             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
703             size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
704             size = ALIGN(lumaSize + chromaSize, ALIGN4K);
705             ALOGV("%s: NV12_2k, width = %zu, height = %zu, size = %d",
706                                                    __FUNCTION__, width, height, size);
707             }
708             break;
709         case NV12_512:
710             alignedw = ALIGN(width, ALIGN512);
711             alignedh = ALIGN(height, ALIGN512);
712             size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN256)), ALIGN4K);
713             break;
714         case NV12_128m:
715             alignedw = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
716             alignedh = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
717             size = ALIGN(alignedw * alignedh + (alignedw * ALIGN((height+1)/2, VENUS_Y_SCANLINES(COLOR_FMT_NV12, 1)/2)), ALIGN4K);
718             break;
719         case NV12_UBWC:
720             size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
721             break;
722         case TP10_UBWC:
723             size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
724             break;
725         case P010:
726             alignedw = ALIGN(width*2, ALIGN64);
727             size = (alignedw * height) + (alignedw * height / 2);
728             break;
729         case VENUS_P010:
730             // Y plane
731             alignedw = ALIGN(width*2, ALIGN256);
732             alignedh = ALIGN(height, ALIGN32);
733             size = (alignedw * alignedh);
734             // UV plane
735             alignedw = ALIGN(width*2, ALIGN256);
736             alignedh = ALIGN(height/2, ALIGN16);
737             size = ALIGN(size + (alignedw * alignedh), ALIGN4K);
738             break;
739         default:
740             ALOGW("%s: Format not supported , %d", __FUNCTION__, format);
741             break;
742     }
743     return size;
744 }
745 /*
746  * Tells GPU to map given buffer and returns a physical address of mapped buffer
747  */
getMappedGPUAddr(int bufFD,void * bufPtr,size_t bufLen)748 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
749 {
750     C2D_STATUS status;
751     void *gpuaddr = NULL;
752     status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION,
753                          &gpuaddr);
754     if (status != C2D_STATUS_OK) {
755         ALOGE("%s: c2dMapAddr failed: status %d fd %d ptr %p len %zu flags %d",
756               __FUNCTION__, status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION);
757         return NULL;
758     }
759     ALOGV("%s: c2d mapping created: gpuaddr %p fd %d ptr %p len %zu",
760           __FUNCTION__, gpuaddr, bufFD, bufPtr, bufLen);
761     return gpuaddr;
762 }
763 
unmapGPUAddr(unsigned long gAddr)764 bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr)
765 {
766 
767     C2D_STATUS status = mC2DUnMapAddr((void*)gAddr);
768 
769     if (status != C2D_STATUS_OK)
770         ALOGE("%s: c2dUnMapAddr failed: status %d gpuaddr %08lx",
771                                      __FUNCTION__, status, gAddr);
772 
773     return (status == C2D_STATUS_OK);
774 }
775 
getBuffSize(int32_t port)776 int32_t C2DColorConverter::getBuffSize(int32_t port)
777 {
778   if (enabled) {
779     if (port == C2D_INPUT) {
780       return calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
781     } else if (port == C2D_OUTPUT) {
782       return calcSize(mDstFormat, mDstWidth, mDstHeight);
783     }
784   }
785   return 0;
786 }
787 
getBuffFilledLen(int32_t port,unsigned int & filled_length)788 bool C2DColorConverter::getBuffFilledLen(int32_t port, unsigned int &filled_length)
789 {
790   bool ret = false;
791   C2DBuffReq req;
792   if (enabled) {
793     ret = getBuffReq(port, &req);
794     if (ret) {
795       filled_length = req.size;
796     }
797   }
798 
799   return ret;
800 }
801 
getBuffReq(int32_t port,C2DBuffReq * req)802 bool C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
803     if (!req
804         || (port != C2D_INPUT
805             && port != C2D_OUTPUT)) return false;
806 
807     memset(req, 0, sizeof(C2DBuffReq));
808     if (port == C2D_INPUT) {
809         req->width = mSrcWidth;
810         req->height = mSrcHeight;
811         req->stride = calcStride(mSrcFormat, mSrcWidth);
812         req->sliceHeight = mSrcHeight;
813         req->lumaAlign = calcLumaAlign(mSrcFormat);
814         req->sizeAlign = calcSizeAlign(mSrcFormat);
815         req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
816         req->bpp = calcBytesPerPixel(mSrcFormat);
817         ALOGV("%s: input req->size = %d", __FUNCTION__, req->size);
818     } else if (port == C2D_OUTPUT) {
819         req->width = mDstWidth;
820         req->height = mDstHeight;
821         req->stride = calcStride(mDstFormat, mDstWidth);
822         req->sliceHeight = mDstHeight;
823         req->lumaAlign = calcLumaAlign(mDstFormat);
824         req->sizeAlign = calcSizeAlign(mDstFormat);
825         req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
826         req->bpp = calcBytesPerPixel(mDstFormat);
827         ALOGV("%s: output req->size = %d", __FUNCTION__, req->size);
828     }
829     return true;
830 }
831 
calcLumaAlign(ColorConvertFormat format)832 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
833     if (!isYUVSurface(format)) return 1; //no requirement
834 
835     switch (format) {
836         case NV12_2K:
837           return ALIGN2K;
838         case NV12_512:
839           return ALIGN512;
840         case NV12_128m:
841           return 1;
842         case NV12_UBWC:
843         case TP10_UBWC:
844         case P010:
845         case VENUS_P010:
846           return ALIGN4K;
847         default:
848           ALOGW("%s: unknown format (%d) passed for luma alignment number.",
849                                                        __FUNCTION__, format);
850           return 1;
851     }
852 }
853 
calcSizeAlign(ColorConvertFormat format)854 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
855     if (!isYUVSurface(format)) return 1; //no requirement
856 
857     switch (format) {
858         case YCbCr420SP: //OR NV12
859         case YCbCr420P:
860         case NV12_2K:
861         case NV12_512:
862         case NV12_128m:
863         case NV12_UBWC:
864         case TP10_UBWC:
865         case P010:
866         case VENUS_P010:
867           return ALIGN4K;
868         default:
869           ALOGW("%s: unknown format (%d) passed for size alignment number",
870                                                       __FUNCTION__, format);
871           return 1;
872     }
873 }
874 
calcBytesPerPixel(ColorConvertFormat format)875 C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) {
876     C2DBytesPerPixel bpp;
877     bpp.numerator = 0;
878     bpp.denominator = 1;
879 
880     switch (format) {
881         case RGB565:
882             bpp.numerator = 2;
883             break;
884         case RGBA8888:
885         case RGBA8888_UBWC:
886             bpp.numerator = 4;
887             break;
888         case YCbCr420SP:
889         case YCbCr420P:
890         case YCrCb420P:
891         case YCbCr420Tile:
892         case NV12_2K:
893         case NV12_512:
894         case NV12_128m:
895         case NV12_UBWC:
896         case TP10_UBWC:
897         case P010:
898         case VENUS_P010:
899             bpp.numerator = 3;
900             bpp.denominator = 2;
901             break;
902         default:
903             ALOGW("%s: unknown format (%d) passed.", __FUNCTION__, format);
904             break;
905     }
906     return bpp;
907 }
908 
dumpOutput(char * filename,char mode)909 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
910     int fd;
911     size_t stride, sliceHeight;
912     if (!filename) return -1;
913 
914     int flags = O_RDWR | O_CREAT;
915     if (mode == 'a') {
916       flags |= O_APPEND;
917     }
918 
919     if ((fd = open(filename, flags)) < 0) {
920         ALOGE("%s: open dump file failed w/ errno %s", __FUNCTION__, strerror(errno));
921         return -1;
922     }
923 
924     int ret = 0;
925     if (isYUVSurface(mDstFormat)) {
926       C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
927       uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
928       stride = dstSurfaceDef->stride0;
929       sliceHeight = dstSurfaceDef->height;
930       /* dump luma */
931       for (size_t i = 0; i < sliceHeight; i++) {
932         ret = write(fd, base, mDstWidth); //will work only for the 420 ones
933         if (ret < 0) goto cleanup;
934         base += stride;
935       }
936 
937       if (mDstFormat == YCbCr420P ||
938           mDstFormat == YCrCb420P) {
939           ALOGI("%s: Dump Cb and Cr separately for Planar\n", __FUNCTION__);
940           //dump Cb/Cr
941           base = (uint8_t *)dstSurfaceDef->plane1;
942           stride = dstSurfaceDef->stride1;
943           for (size_t i = 0; i < (sliceHeight+1)/2;i++) { //will work only for the 420 ones
944             ret = write(fd, base, (mDstWidth+1)/2);
945             if (ret < 0) goto cleanup;
946             base += stride;
947           }
948 
949           //dump Cr/Cb
950           base = (uint8_t *)dstSurfaceDef->plane2;
951           stride = dstSurfaceDef->stride2;
952 
953           for (size_t i = 0; i < (sliceHeight+1)/2;i++) { //will work only for the 420 ones
954             ret = write(fd, base, (mDstWidth+1)/2);
955             if (ret < 0) goto cleanup;
956             base += stride;
957           }
958 
959       } else {
960           /* dump chroma */
961           base = (uint8_t *)dstSurfaceDef->plane1;
962           stride = dstSurfaceDef->stride1;
963           for (size_t i = 0; i < (sliceHeight+1)/2;i++) { //will work only for the 420 ones
964             ret = write(fd, base, mDstWidth);
965             if (ret < 0) goto cleanup;
966             base += stride;
967           }
968       }
969     } else {
970       C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
971       uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
972       stride = dstSurfaceDef->stride;
973       sliceHeight = dstSurfaceDef->height;
974 
975       ALOGI("%s: rgb surface base is %p", __FUNCTION__, base);
976       ALOGI("%s: rgb surface dumpsslice height is %lu\n",
977                                    __FUNCTION__, (unsigned long)sliceHeight);
978       ALOGI("%s: rgb surface dump stride is %lu\n",
979                                    __FUNCTION__, (unsigned long)stride);
980 
981       int bpp = 1; //bytes per pixel
982       if (mDstFormat == RGB565) {
983         bpp = 2;
984       } else if (mDstFormat == RGBA8888  || mDstFormat == RGBA8888_UBWC) {
985         bpp = 4;
986       }
987 
988       int count = 0;
989       for (size_t i = 0; i < sliceHeight; i++) {
990         ret = write(fd, base, mDstWidth*bpp);
991         if (ret < 0) {
992           ALOGI("%s: write failed, count = %d\n", __FUNCTION__, count);
993           goto cleanup;
994         }
995         base += stride;
996         count += stride;
997       }
998     }
999  cleanup:
1000     if (ret < 0) {
1001       ALOGE("%s: file write failed w/ errno %s", __FUNCTION__, strerror(errno));
1002     }
1003     close(fd);
1004     return ret < 0 ? ret : 0;
1005 }
1006