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