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