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