Home | History | Annotate | Download | only in libc2dcolorconvert
      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 <stdlib.h>
     32 #include <fcntl.h>
     33 #include <linux/msm_kgsl.h>
     34 #include <sys/ioctl.h>
     35 #include <utils/Log.h>
     36 #include <dlfcn.h>
     37 #include <string.h>
     38 #include <errno.h>
     39 #include <media/msm_media_info.h>
     40 
     41 #undef LOG_TAG
     42 #define LOG_TAG "C2DColorConvert"
     43 #define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1)))
     44 #define ALIGN8K 8192
     45 #define ALIGN4K 4096
     46 #define ALIGN2K 2048
     47 #define ALIGN128 128
     48 #define ALIGN32 32
     49 #define ALIGN16 16
     50 
     51 //-----------------------------------------------------
     52 namespace android {
     53 
     54 class C2DColorConverter : public C2DColorConverterBase {
     55 
     56 public:
     57     C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags,size_t srcStride);
     58     int32_t getBuffReq(int32_t port, C2DBuffReq *req);
     59     int32_t dumpOutput(char * filename, char mode);
     60 protected:
     61     virtual ~C2DColorConverter();
     62     virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData);
     63 
     64 private:
     65     bool isYUVSurface(ColorConvertFormat format);
     66     void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource);
     67     C2D_STATUS updateYUVSurfaceDef(uint8_t *addr, void *base, void * data, bool isSource);
     68     C2D_STATUS updateRGBSurfaceDef(uint8_t *addr, void * data, bool isSource);
     69     uint32_t getC2DFormat(ColorConvertFormat format);
     70     size_t calcStride(ColorConvertFormat format, size_t width);
     71     size_t calcYSize(ColorConvertFormat format, size_t width, size_t height);
     72     size_t calcSize(ColorConvertFormat format, size_t width, size_t height);
     73     void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen);
     74     bool unmapGPUAddr(unsigned long gAddr);
     75     size_t calcLumaAlign(ColorConvertFormat format);
     76     size_t calcSizeAlign(ColorConvertFormat format);
     77     C2DBytesPerPixel calcBytesPerPixel(ColorConvertFormat format);
     78 
     79     void *mC2DLibHandle;
     80     LINK_c2dCreateSurface mC2DCreateSurface;
     81     LINK_c2dUpdateSurface mC2DUpdateSurface;
     82     LINK_c2dReadSurface mC2DReadSurface;
     83     LINK_c2dDraw mC2DDraw;
     84     LINK_c2dFlush mC2DFlush;
     85     LINK_c2dFinish mC2DFinish;
     86     LINK_c2dWaitTimestamp mC2DWaitTimestamp;
     87     LINK_c2dDestroySurface mC2DDestroySurface;
     88     LINK_c2dMapAddr mC2DMapAddr;
     89     LINK_c2dUnMapAddr mC2DUnMapAddr;
     90 
     91     void *mAdrenoUtilsHandle;
     92     LINK_AdrenoComputeAlignedWidthAndHeight mAdrenoComputeAlignedWidthAndHeight;
     93 
     94     uint32_t mSrcSurface, mDstSurface;
     95     void * mSrcSurfaceDef;
     96     void * mDstSurfaceDef;
     97 
     98     C2D_OBJECT mBlit;
     99     size_t mSrcWidth;
    100     size_t mSrcHeight;
    101     size_t mSrcStride;
    102     size_t mDstWidth;
    103     size_t mDstHeight;
    104     size_t mSrcSize;
    105     size_t mDstSize;
    106     size_t mSrcYSize;
    107     size_t mDstYSize;
    108     enum ColorConvertFormat mSrcFormat;
    109     enum ColorConvertFormat mDstFormat;
    110     int32_t mFlags;
    111 
    112     int mError;
    113 };
    114 
    115 C2DColorConverter::C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride)
    116 {
    117      mError = 0;
    118      if (NV12_UBWC == dstFormat) {
    119          ALOGE("%s: FATAL ERROR: could not support UBWC output formats ", __FUNCTION__);
    120          mError = -1;
    121          return;
    122      }
    123      mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW);
    124      if (!mC2DLibHandle) {
    125          ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
    126          mError = -1;
    127          return;
    128      }
    129      mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface");
    130      mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface");
    131      mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface");
    132      mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw");
    133      mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush");
    134      mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish");
    135      mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp");
    136      mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface");
    137      mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr");
    138      mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr");
    139 
    140      if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface
    141         || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp
    142         || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) {
    143          ALOGE("%s: dlsym ERROR", __FUNCTION__);
    144          mError = -1;
    145          return;
    146      }
    147 
    148      mAdrenoUtilsHandle =  dlopen("libadreno_utils.so", RTLD_NOW);
    149      if (!mAdrenoUtilsHandle) {
    150          ALOGE("FATAL ERROR: could not dlopen libadreno_utils.so: %s", dlerror());
    151          mError = -1;
    152          return;
    153      }
    154 
    155      mAdrenoComputeAlignedWidthAndHeight = (LINK_AdrenoComputeAlignedWidthAndHeight)dlsym(mAdrenoUtilsHandle, "compute_aligned_width_and_height");
    156      if (!mAdrenoComputeAlignedWidthAndHeight) {
    157          ALOGE("%s: dlsym ERROR", __FUNCTION__);
    158          mError = -1;
    159          return;
    160      }
    161 
    162     mSrcWidth = srcWidth;
    163     mSrcHeight = srcHeight;
    164     mSrcStride = srcStride;;
    165     mDstWidth = dstWidth;
    166     mDstHeight = dstHeight;
    167     mSrcFormat = srcFormat;
    168     mDstFormat = dstFormat;
    169     mSrcSize = calcSize(srcFormat, srcWidth, srcHeight);
    170     mDstSize = calcSize(dstFormat, dstWidth, dstHeight);
    171     mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight);
    172     mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight);
    173 
    174     mFlags = flags; // can be used for rotation
    175 
    176     mSrcSurfaceDef = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true);
    177     mDstSurfaceDef = getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false);
    178 
    179     memset((void*)&mBlit,0,sizeof(C2D_OBJECT));
    180     mBlit.source_rect.x = 0 << 16;
    181     mBlit.source_rect.y = 0 << 16;
    182     mBlit.source_rect.width = srcWidth << 16;
    183     mBlit.source_rect.height = srcHeight << 16;
    184     mBlit.target_rect.x = 0 << 16;
    185     mBlit.target_rect.y = 0 << 16;
    186     mBlit.target_rect.width = dstWidth << 16;
    187     mBlit.target_rect.height = dstHeight << 16;
    188     mBlit.config_mask = C2D_ALPHA_BLEND_NONE | C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | C2D_TARGET_RECT_BIT;
    189     mBlit.surface_id = mSrcSurface;
    190 }
    191 
    192 C2DColorConverter::~C2DColorConverter()
    193 {
    194     if (mError) {
    195         if (mC2DLibHandle) {
    196             dlclose(mC2DLibHandle);
    197         }
    198         return;
    199     }
    200 
    201     mC2DDestroySurface(mDstSurface);
    202     mC2DDestroySurface(mSrcSurface);
    203     if (isYUVSurface(mSrcFormat)) {
    204         delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef);
    205     } else {
    206         delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef);
    207     }
    208 
    209     if (isYUVSurface(mDstFormat)) {
    210         delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef);
    211     } else {
    212         delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef);
    213     }
    214 
    215     dlclose(mC2DLibHandle);
    216 }
    217 
    218 int C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData)
    219 {
    220     C2D_STATUS ret;
    221     uint8_t *srcMappedGpuAddr = nullptr;
    222     uint8_t *dstMappedGpuAddr = nullptr;
    223 
    224     if (mError) {
    225         ALOGE("C2D library initialization failed\n");
    226         return mError;
    227     }
    228 
    229     if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) {
    230         ALOGE("Incorrect input parameters\n");
    231         return -1;
    232     }
    233 
    234     srcMappedGpuAddr = (uint8_t *)getMappedGPUAddr(srcFd, srcData, mSrcSize);
    235     if (!srcMappedGpuAddr)
    236         return -1;
    237 
    238     if (isYUVSurface(mSrcFormat)) {
    239         ret = updateYUVSurfaceDef(srcMappedGpuAddr, srcBase, srcData, true);
    240     } else {
    241         ret = updateRGBSurfaceDef(srcMappedGpuAddr, srcData, true);
    242     }
    243 
    244     if (ret != C2D_STATUS_OK) {
    245         ALOGE("Update src surface def failed\n");
    246         unmapGPUAddr((unsigned long)srcMappedGpuAddr);
    247         return -ret;
    248     }
    249 
    250     dstMappedGpuAddr = (uint8_t *)getMappedGPUAddr(dstFd, dstData, mDstSize);
    251     if (!dstMappedGpuAddr) {
    252         unmapGPUAddr((unsigned long)srcMappedGpuAddr);
    253         return -1;
    254     }
    255 
    256     if (isYUVSurface(mDstFormat)) {
    257         ret = updateYUVSurfaceDef(dstMappedGpuAddr, dstBase, dstData, false);
    258     } else {
    259         ret = updateRGBSurfaceDef(dstMappedGpuAddr, dstData, false);
    260     }
    261 
    262     if (ret != C2D_STATUS_OK) {
    263         ALOGE("Update dst surface def failed\n");
    264         unmapGPUAddr((unsigned long)srcMappedGpuAddr);
    265         unmapGPUAddr((unsigned long)dstMappedGpuAddr);
    266         return -ret;
    267     }
    268 
    269     mBlit.surface_id = mSrcSurface;
    270     ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1);
    271     mC2DFinish(mDstSurface);
    272 
    273     bool unmappedSrcSuccess;
    274     unmappedSrcSuccess = unmapGPUAddr((unsigned long)srcMappedGpuAddr);
    275 
    276     bool unmappedDstSuccess;
    277     unmappedDstSuccess = unmapGPUAddr((unsigned long)dstMappedGpuAddr);
    278 
    279     if (ret != C2D_STATUS_OK) {
    280         ALOGE("C2D Draw failed\n");
    281         return -ret; //c2d err values are positive
    282     } else {
    283         if (!unmappedSrcSuccess || !unmappedDstSuccess) {
    284             ALOGE("unmapping GPU address failed\n");
    285             return -1;
    286         }
    287         return ret;
    288     }
    289 }
    290 
    291 bool C2DColorConverter::isYUVSurface(ColorConvertFormat format)
    292 {
    293     switch (format) {
    294         case YCbCr420Tile:
    295         case YCbCr420SP:
    296         case YCbCr420P:
    297         case YCrCb420P:
    298         case NV12_2K:
    299         case NV12_128m:
    300         case NV12_UBWC:
    301             return true;
    302         case RGB565:
    303         case RGBA8888:
    304         default:
    305             return false;
    306     }
    307 }
    308 
    309 void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource)
    310 {
    311     if (isYUVSurface(format)) {
    312         C2D_YUV_SURFACE_DEF * surfaceDef = new C2D_YUV_SURFACE_DEF;
    313         surfaceDef->format = getC2DFormat(format);
    314         surfaceDef->width = width;
    315         surfaceDef->height = height;
    316         surfaceDef->plane0 = (void *)0xaaaaaaaa;
    317         surfaceDef->phys0 = (void *)0xaaaaaaaa;
    318         surfaceDef->stride0 = calcStride(format, width);
    319         surfaceDef->plane1 = (void *)0xaaaaaaaa;
    320         surfaceDef->phys1 = (void *)0xaaaaaaaa;
    321         surfaceDef->stride1 = calcStride(format, width);
    322         surfaceDef->phys2 = NULL;
    323         surfaceDef->plane2 = NULL;
    324 
    325         if (format == YCbCr420P ||
    326             format == YCrCb420P) {
    327           printf("half stride for Cb Cr planes \n");
    328           surfaceDef->stride1 = calcStride(format, width) / 2;
    329           surfaceDef->phys2 = (void *)0xaaaaaaaa;
    330           surfaceDef->stride2 = calcStride(format, width) / 2;
    331         }
    332         mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
    333                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
    334                         &(*surfaceDef));
    335         return ((void *)surfaceDef);
    336     } else {
    337         C2D_RGB_SURFACE_DEF * surfaceDef = new C2D_RGB_SURFACE_DEF;
    338         surfaceDef->format = getC2DFormat(format);
    339         surfaceDef->width = width;
    340         surfaceDef->height = height;
    341         surfaceDef->buffer = (void *)0xaaaaaaaa;
    342         surfaceDef->phys = (void *)0xaaaaaaaa;
    343         surfaceDef->stride = calcStride(format, width);
    344         mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET,
    345                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
    346                         &(*surfaceDef));
    347         return ((void *)surfaceDef);
    348     }
    349 }
    350 
    351 C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(uint8_t *gpuAddr, void *base, void *data, bool isSource)
    352 {
    353     if (isSource) {
    354         C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef;
    355         srcSurfaceDef->plane0 = data;
    356         srcSurfaceDef->phys0  = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
    357         srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize;
    358         srcSurfaceDef->phys1  = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize;
    359         if (srcSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
    360                srcSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
    361             srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4;
    362             srcSurfaceDef->phys2  = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4;
    363         }
    364         return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
    365                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
    366                         &(*srcSurfaceDef));
    367     } else {
    368         C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
    369         dstSurfaceDef->plane0 = data;
    370         dstSurfaceDef->phys0  = gpuAddr + ((uint8_t *)data - (uint8_t *)base);
    371         dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize;
    372         dstSurfaceDef->phys1  = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize;
    373         if (dstSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 ||
    374                dstSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) {
    375             dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4;
    376             dstSurfaceDef->phys2  = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4;
    377         }
    378 
    379         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
    380                         (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
    381                         &(*dstSurfaceDef));
    382     }
    383 }
    384 
    385 C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(uint8_t *gpuAddr, void * data, bool isSource)
    386 {
    387     if (isSource) {
    388         C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef;
    389         srcSurfaceDef->buffer = data;
    390         srcSurfaceDef->phys = gpuAddr;
    391         return  mC2DUpdateSurface(mSrcSurface, C2D_SOURCE,
    392                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
    393                         &(*srcSurfaceDef));
    394     } else {
    395         C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
    396         dstSurfaceDef->buffer = data;
    397         ALOGV("dstSurfaceDef->buffer = %p\n", data);
    398         dstSurfaceDef->phys = gpuAddr;
    399         return mC2DUpdateSurface(mDstSurface, C2D_TARGET,
    400                         (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS),
    401                         &(*dstSurfaceDef));
    402     }
    403 }
    404 
    405 uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format)
    406 {
    407     switch (format) {
    408         case RGB565:
    409             return C2D_COLOR_FORMAT_565_RGB;
    410         case RGBA8888:
    411             return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED;
    412         case YCbCr420Tile:
    413             return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED);
    414         case YCbCr420SP:
    415         case NV12_2K:
    416         case NV12_128m:
    417             return C2D_COLOR_FORMAT_420_NV12;
    418         case YCbCr420P:
    419             return C2D_COLOR_FORMAT_420_I420;
    420         case YCrCb420P:
    421             return C2D_COLOR_FORMAT_420_YV12;
    422         case NV12_UBWC:
    423             return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_UBWC_COMPRESSED;
    424         default:
    425             ALOGE("Format not supported , %d\n", format);
    426             return -1;
    427     }
    428 }
    429 
    430 size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width)
    431 {
    432     switch (format) {
    433         case RGB565:
    434             return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice
    435         case RGBA8888:
    436 	if (mSrcStride)
    437 		return mSrcStride * 4;
    438 	else
    439 		return ALIGN(width, ALIGN32) * 4;
    440         case YCbCr420Tile:
    441             return ALIGN(width, ALIGN128);
    442         case YCbCr420SP:
    443             return ALIGN(width, ALIGN16);
    444         case NV12_2K:
    445             return ALIGN(width, ALIGN16);
    446         case NV12_128m:
    447             return ALIGN(width, ALIGN128);
    448         case YCbCr420P:
    449             return ALIGN(width, ALIGN16);
    450         case YCrCb420P:
    451             return ALIGN(width, ALIGN16);
    452         case NV12_UBWC:
    453             return VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width);
    454         default:
    455             return 0;
    456     }
    457 }
    458 
    459 size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height)
    460 {
    461     switch (format) {
    462         case YCbCr420SP:
    463             return (ALIGN(width, ALIGN16) * height);
    464         case YCbCr420P:
    465             return ALIGN(width, ALIGN16) * height;
    466         case YCrCb420P:
    467             return ALIGN(width, ALIGN16) * height;
    468         case YCbCr420Tile:
    469             return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K);
    470         case NV12_2K: {
    471             size_t alignedw = ALIGN(width, ALIGN16);
    472             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
    473             return lumaSize;
    474         }
    475         case NV12_128m:
    476             return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32);
    477         case NV12_UBWC:
    478             return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width) *
    479                     VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K) +
    480                  ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, width) *
    481                    VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K);
    482         default:
    483             return 0;
    484     }
    485 }
    486 
    487 size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height)
    488 {
    489     int32_t alignedw = 0;
    490     int32_t alignedh = 0;
    491     int32_t size = 0;
    492     int32_t tile_mode = 0;
    493     int32_t raster_mode = 0;
    494     int32_t padding_threshold = 512; /* hardcode for RGB formats */
    495     int32_t bpp = 0;
    496 
    497     switch (format) {
    498         case RGB565:
    499             bpp = 2;
    500             mAdrenoComputeAlignedWidthAndHeight(width, height, bpp, tile_mode, raster_mode, padding_threshold,
    501                                                 &alignedw, &alignedh);
    502             size = alignedw * alignedh * bpp;
    503             size = ALIGN(size, ALIGN4K);
    504             break;
    505         case RGBA8888:
    506             bpp = 4;
    507             mAdrenoComputeAlignedWidthAndHeight(width, height, bpp, tile_mode, raster_mode, padding_threshold,
    508                                                 &alignedw, &alignedh);
    509             if (mSrcStride)
    510               size = mSrcStride *  alignedh * bpp;
    511             else
    512               size = alignedw * alignedh * bpp;
    513             size = ALIGN(size, ALIGN4K);
    514             break;
    515         case YCbCr420SP:
    516             alignedw = ALIGN(width, ALIGN16);
    517             size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K);
    518             break;
    519         case YCbCr420P:
    520             alignedw = ALIGN(width, ALIGN16);
    521             size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
    522             break;
    523         case YCrCb420P:
    524             alignedw = ALIGN(width, ALIGN16);
    525             size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K);
    526             break;
    527         case YCbCr420Tile:
    528             alignedw = ALIGN(width, ALIGN128);
    529             alignedh = ALIGN(height, ALIGN32);
    530             size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K);
    531             break;
    532         case NV12_2K: {
    533             alignedw = ALIGN(width, ALIGN16);
    534             size_t lumaSize = ALIGN(alignedw * height, ALIGN2K);
    535             size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K);
    536             size = ALIGN(lumaSize + chromaSize, ALIGN4K);
    537             ALOGV("NV12_2k, width = %d, height = %d, size = %d", width, height, size);
    538             }
    539             break;
    540         case NV12_128m:
    541             alignedw = ALIGN(width, ALIGN128);
    542             alignedh = ALIGN(height, ALIGN32);
    543             size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K);
    544             break;
    545         case NV12_UBWC:
    546             size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
    547         default:
    548             break;
    549     }
    550     return size;
    551 }
    552 /*
    553  * Tells GPU to map given buffer and returns a physical address of mapped buffer
    554  */
    555 void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen)
    556 {
    557     C2D_STATUS status;
    558     void *gpuaddr = NULL;
    559 
    560     status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION,
    561             &gpuaddr);
    562     if (status != C2D_STATUS_OK) {
    563         ALOGE("c2dMapAddr failed: status %d fd %d ptr %p len %d flags %d\n",
    564                 status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION);
    565         return NULL;
    566     }
    567     ALOGV("c2d mapping created: gpuaddr %p fd %d ptr %p len %d\n",
    568             gpuaddr, bufFD, bufPtr, bufLen);
    569 
    570     return gpuaddr;
    571 }
    572 
    573 bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr)
    574 {
    575 
    576     C2D_STATUS status = mC2DUnMapAddr((void*)gAddr);
    577 
    578     if (status != C2D_STATUS_OK)
    579         ALOGE("c2dUnMapAddr failed: status %d gpuaddr %08lx\n", status, gAddr);
    580 
    581     return (status == C2D_STATUS_OK);
    582 }
    583 
    584 int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) {
    585     if (!req) return -1;
    586 
    587     if (port != C2D_INPUT && port != C2D_OUTPUT) return -1;
    588 
    589     memset(req, 0, sizeof(C2DBuffReq));
    590     if (port == C2D_INPUT) {
    591         req->width = mSrcWidth;
    592         req->height = mSrcHeight;
    593         req->stride = calcStride(mSrcFormat, mSrcWidth);
    594         req->sliceHeight = mSrcHeight;
    595         req->lumaAlign = calcLumaAlign(mSrcFormat);
    596         req->sizeAlign = calcSizeAlign(mSrcFormat);
    597         req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight);
    598         req->bpp = calcBytesPerPixel(mSrcFormat);
    599         ALOGV("input req->size = %d\n", req->size);
    600     } else if (port == C2D_OUTPUT) {
    601         req->width = mDstWidth;
    602         req->height = mDstHeight;
    603         req->stride = calcStride(mDstFormat, mDstWidth);
    604         req->sliceHeight = mDstHeight;
    605         req->lumaAlign = calcLumaAlign(mDstFormat);
    606         req->sizeAlign = calcSizeAlign(mDstFormat);
    607         req->size = calcSize(mDstFormat, mDstWidth, mDstHeight);
    608         req->bpp = calcBytesPerPixel(mDstFormat);
    609         ALOGV("output req->size = %d\n", req->size);
    610     }
    611     return 0;
    612 }
    613 
    614 size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) {
    615     if (!isYUVSurface(format)) return 1; //no requirement
    616 
    617     switch (format) {
    618         case NV12_2K:
    619           return ALIGN2K;
    620         case NV12_128m:
    621           return 1;
    622         case NV12_UBWC:
    623           return ALIGN4K;
    624         default:
    625           ALOGE("unknown format passed for luma alignment number");
    626           return 1;
    627     }
    628 }
    629 
    630 size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) {
    631     if (!isYUVSurface(format)) return 1; //no requirement
    632 
    633     switch (format) {
    634         case YCbCr420SP: //OR NV12
    635         case YCbCr420P:
    636         case NV12_2K:
    637         case NV12_128m:
    638         case NV12_UBWC:
    639           return ALIGN4K;
    640         default:
    641           ALOGE("unknown format passed for size alignment number");
    642           return 1;
    643     }
    644 }
    645 
    646 C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) {
    647     C2DBytesPerPixel bpp;
    648     bpp.numerator = 0;
    649     bpp.denominator = 1;
    650 
    651     switch (format) {
    652         case RGB565:
    653             bpp.numerator = 2;
    654             break;
    655         case RGBA8888:
    656             bpp.numerator = 4;
    657             break;
    658         case YCbCr420SP:
    659         case YCbCr420P:
    660         case YCrCb420P:
    661         case YCbCr420Tile:
    662         case NV12_2K:
    663         case NV12_128m:
    664         case NV12_UBWC:
    665             bpp.numerator = 3;
    666             bpp.denominator = 2;
    667             break;
    668         default:
    669             break;
    670     }
    671     return bpp;
    672 }
    673 
    674 int32_t C2DColorConverter::dumpOutput(char * filename, char mode) {
    675     int fd;
    676     size_t stride, sliceHeight;
    677     if (!filename) return -1;
    678 
    679     int flags = O_RDWR | O_CREAT;
    680     if (mode == 'a') {
    681       flags |= O_APPEND;
    682     }
    683 
    684     if ((fd = open(filename, flags)) < 0) {
    685         ALOGE("open dump file failed w/ errno %s", strerror(errno));
    686         return -1;
    687     }
    688 
    689     int ret = 0;
    690     if (isYUVSurface(mDstFormat)) {
    691       C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef;
    692       uint8_t * base = (uint8_t *)dstSurfaceDef->plane0;
    693       stride = dstSurfaceDef->stride0;
    694       sliceHeight = dstSurfaceDef->height;
    695       /* dump luma */
    696       for (size_t i = 0; i < sliceHeight; i++) {
    697         ret = write(fd, base, mDstWidth); //will work only for the 420 ones
    698         if (ret < 0) goto cleanup;
    699         base += stride;
    700       }
    701 
    702       if (mDstFormat == YCbCr420P ||
    703           mDstFormat == YCrCb420P) {
    704           printf("Dump Cb and Cr separately for Planar\n");
    705           //dump Cb/Cr
    706           base = (uint8_t *)dstSurfaceDef->plane1;
    707           stride = dstSurfaceDef->stride1;
    708           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
    709             ret = write(fd, base, mDstWidth/2);
    710             if (ret < 0) goto cleanup;
    711             base += stride;
    712           }
    713 
    714           //dump Cr/Cb
    715           base = (uint8_t *)dstSurfaceDef->plane2;
    716           stride = dstSurfaceDef->stride2;
    717 
    718           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
    719             ret = write(fd, base, mDstWidth/2);
    720             if (ret < 0) goto cleanup;
    721             base += stride;
    722           }
    723 
    724       } else {
    725           /* dump chroma */
    726           base = (uint8_t *)dstSurfaceDef->plane1;
    727           stride = dstSurfaceDef->stride1;
    728           for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones
    729             ret = write(fd, base, mDstWidth);
    730             if (ret < 0) goto cleanup;
    731             base += stride;
    732           }
    733       }
    734     } else {
    735       C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef;
    736       uint8_t * base = (uint8_t *)dstSurfaceDef->buffer;
    737       stride = dstSurfaceDef->stride;
    738       sliceHeight = dstSurfaceDef->height;
    739 
    740       printf("rgb surface base is %p", base);
    741       printf("rgb surface dumpsslice height is %lu\n", (unsigned long)sliceHeight);
    742       printf("rgb surface dump stride is %lu\n", (unsigned long)stride);
    743 
    744       int bpp = 1; //bytes per pixel
    745       if (mDstFormat == RGB565) {
    746         bpp = 2;
    747       } else if (mDstFormat == RGBA8888) {
    748         bpp = 4;
    749       }
    750 
    751       int count = 0;
    752       for (size_t i = 0; i < sliceHeight; i++) {
    753         ret = write(fd, base, mDstWidth*bpp);
    754         if (ret < 0) {
    755           printf("write failed, count = %d\n", count);
    756           goto cleanup;
    757         }
    758         base += stride;
    759         count += stride;
    760       }
    761     }
    762  cleanup:
    763     if (ret < 0) {
    764       ALOGE("file write failed w/ errno %s", strerror(errno));
    765     }
    766     close(fd);
    767     return ret < 0 ? ret : 0;
    768 }
    769 
    770 extern "C" C2DColorConverterBase* createC2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride)
    771 {
    772     return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags, srcStride);
    773 }
    774 
    775 extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC)
    776 {
    777     delete C2DCC;
    778 }
    779 
    780 }
    781