diff options
author | Thierry Strudel <tstrudel@google.com> | 2016-12-13 12:19:52 -0800 |
---|---|---|
committer | Thierry Strudel <tstrudel@google.com> | 2016-12-15 12:22:15 -0800 |
commit | 0cfe6f8bff87bcbdeef6fcfdbb91d67d42f33927 (patch) | |
tree | 1c08d488f104ed297fdd31b6c513e8259f8c2876 /msm8998/libc2dcolorconvert | |
parent | b50ee0d49e33884a5f998649944fff0a8e27cda6 (diff) | |
download | media-0cfe6f8bff87bcbdeef6fcfdbb91d67d42f33927.tar.gz |
msm8998: rename msmcobalt to msm8998
Bug: 33556391
Change-Id: I608cbf071aa5862c5c9caf540b9a8597e4363c0d
Diffstat (limited to 'msm8998/libc2dcolorconvert')
-rw-r--r-- | msm8998/libc2dcolorconvert/Android.mk | 25 | ||||
-rw-r--r-- | msm8998/libc2dcolorconvert/C2DColorConverter.cpp | 780 | ||||
-rw-r--r-- | msm8998/libc2dcolorconvert/C2DColorConverter.h | 121 | ||||
-rw-r--r-- | msm8998/libc2dcolorconvert/Makefile.am | 18 |
4 files changed, 944 insertions, 0 deletions
diff --git a/msm8998/libc2dcolorconvert/Android.mk b/msm8998/libc2dcolorconvert/Android.mk new file mode 100644 index 0000000..a505afc --- /dev/null +++ b/msm8998/libc2dcolorconvert/Android.mk @@ -0,0 +1,25 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + C2DColorConverter.cpp + +LOCAL_C_INCLUDES := \ + $(TARGET_OUT_HEADERS)/adreno +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qcom/display +ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true) +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +endif + +LOCAL_SHARED_LIBRARIES := liblog libdl + +LOCAL_MODULE_TAGS := optional + +LOCAL_MODULE := libc2dcolorconvert + +ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true) +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/msm8998/libc2dcolorconvert/C2DColorConverter.cpp b/msm8998/libc2dcolorconvert/C2DColorConverter.cpp new file mode 100644 index 0000000..c9681c7 --- /dev/null +++ b/msm8998/libc2dcolorconvert/C2DColorConverter.cpp @@ -0,0 +1,780 @@ +/* Copyright (c) 2012 - 2016, The Linux Foundation. All rights reserved. + * + * redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * this software is provided "as is" and any express or implied + * warranties, including, but not limited to, the implied warranties of + * merchantability, fitness for a particular purpose and non-infringement + * are disclaimed. in no event shall the copyright owner or contributors + * be liable for any direct, indirect, incidental, special, exemplary, or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or + * business interruption) however caused and on any theory of liability, + * whether in contract, strict liability, or tort (including negligence + * or otherwise) arising in any way out of the use of this software, even + * if advised of the possibility of such damage. + * + */ + +#include <C2DColorConverter.h> +#include <stdlib.h> +#include <fcntl.h> +#include <linux/msm_kgsl.h> +#include <sys/ioctl.h> +#include <utils/Log.h> +#include <dlfcn.h> +#include <string.h> +#include <errno.h> +#include <media/msm_media_info.h> +#include <gralloc_priv.h> + +#undef LOG_TAG +#define LOG_TAG "C2DColorConvert" +#define ALIGN( num, to ) (((num) + (to-1)) & (~(to-1))) +#define ALIGN8K 8192 +#define ALIGN4K 4096 +#define ALIGN2K 2048 +#define ALIGN128 128 +#define ALIGN32 32 +#define ALIGN16 16 + +//----------------------------------------------------- +namespace android { + +class C2DColorConverter : public C2DColorConverterBase { + +public: + C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags,size_t srcStride); + int32_t getBuffReq(int32_t port, C2DBuffReq *req); + int32_t dumpOutput(char * filename, char mode); +protected: + virtual ~C2DColorConverter(); + virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData); + +private: + bool isYUVSurface(ColorConvertFormat format); + void *getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource); + C2D_STATUS updateYUVSurfaceDef(int fd, void *base, void * data, bool isSource); + C2D_STATUS updateRGBSurfaceDef(int fd, void * data, bool isSource); + uint32_t getC2DFormat(ColorConvertFormat format); + size_t calcStride(ColorConvertFormat format, size_t width); + size_t calcYSize(ColorConvertFormat format, size_t width, size_t height); + size_t calcSize(ColorConvertFormat format, size_t width, size_t height); + void *getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen); + bool unmapGPUAddr(unsigned long gAddr); + size_t calcLumaAlign(ColorConvertFormat format); + size_t calcSizeAlign(ColorConvertFormat format); + C2DBytesPerPixel calcBytesPerPixel(ColorConvertFormat format); + + void *mC2DLibHandle; + LINK_c2dCreateSurface mC2DCreateSurface; + LINK_c2dUpdateSurface mC2DUpdateSurface; + LINK_c2dReadSurface mC2DReadSurface; + LINK_c2dDraw mC2DDraw; + LINK_c2dFlush mC2DFlush; + LINK_c2dFinish mC2DFinish; + LINK_c2dWaitTimestamp mC2DWaitTimestamp; + LINK_c2dDestroySurface mC2DDestroySurface; + LINK_c2dMapAddr mC2DMapAddr; + LINK_c2dUnMapAddr mC2DUnMapAddr; + + void *mAdrenoUtilsHandle; + LINK_AdrenoComputeAlignedWidthAndHeight mAdrenoComputeAlignedWidthAndHeight; + + uint32_t mSrcSurface, mDstSurface; + void * mSrcSurfaceDef; + void * mDstSurfaceDef; + + C2D_OBJECT mBlit; + size_t mSrcWidth; + size_t mSrcHeight; + size_t mSrcStride; + size_t mDstWidth; + size_t mDstHeight; + size_t mSrcSize; + size_t mDstSize; + size_t mSrcYSize; + size_t mDstYSize; + enum ColorConvertFormat mSrcFormat; + enum ColorConvertFormat mDstFormat; + int32_t mFlags; + + int mError; +}; + +C2DColorConverter::C2DColorConverter(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride) + : mC2DLibHandle(NULL), + mAdrenoUtilsHandle(NULL) +{ + mError = 0; + if (NV12_UBWC == dstFormat) { + ALOGE("%s: FATAL ERROR: could not support UBWC output formats ", __FUNCTION__); + mError = -1; + return; + } + mC2DLibHandle = dlopen("libC2D2.so", RTLD_NOW); + if (!mC2DLibHandle) { + ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); + mError = -1; + return; + } + mC2DCreateSurface = (LINK_c2dCreateSurface)dlsym(mC2DLibHandle, "c2dCreateSurface"); + mC2DUpdateSurface = (LINK_c2dUpdateSurface)dlsym(mC2DLibHandle, "c2dUpdateSurface"); + mC2DReadSurface = (LINK_c2dReadSurface)dlsym(mC2DLibHandle, "c2dReadSurface"); + mC2DDraw = (LINK_c2dDraw)dlsym(mC2DLibHandle, "c2dDraw"); + mC2DFlush = (LINK_c2dFlush)dlsym(mC2DLibHandle, "c2dFlush"); + mC2DFinish = (LINK_c2dFinish)dlsym(mC2DLibHandle, "c2dFinish"); + mC2DWaitTimestamp = (LINK_c2dWaitTimestamp)dlsym(mC2DLibHandle, "c2dWaitTimestamp"); + mC2DDestroySurface = (LINK_c2dDestroySurface)dlsym(mC2DLibHandle, "c2dDestroySurface"); + mC2DMapAddr = (LINK_c2dMapAddr)dlsym(mC2DLibHandle, "c2dMapAddr"); + mC2DUnMapAddr = (LINK_c2dUnMapAddr)dlsym(mC2DLibHandle, "c2dUnMapAddr"); + + if (!mC2DCreateSurface || !mC2DUpdateSurface || !mC2DReadSurface + || !mC2DDraw || !mC2DFlush || !mC2DFinish || !mC2DWaitTimestamp + || !mC2DDestroySurface || !mC2DMapAddr || !mC2DUnMapAddr) { + ALOGE("%s: dlsym ERROR", __FUNCTION__); + mError = -1; + return; + } + + mAdrenoUtilsHandle = dlopen("libadreno_utils.so", RTLD_NOW); + if (!mAdrenoUtilsHandle) { + ALOGE("FATAL ERROR: could not dlopen libadreno_utils.so: %s", dlerror()); + mError = -1; + return; + } + + mAdrenoComputeAlignedWidthAndHeight = (LINK_AdrenoComputeAlignedWidthAndHeight)dlsym(mAdrenoUtilsHandle, "compute_aligned_width_and_height"); + if (!mAdrenoComputeAlignedWidthAndHeight) { + ALOGE("%s: dlsym ERROR", __FUNCTION__); + mError = -1; + return; + } + + mSrcWidth = srcWidth; + mSrcHeight = srcHeight; + mSrcStride = srcStride;; + mDstWidth = dstWidth; + mDstHeight = dstHeight; + mSrcFormat = srcFormat; + mDstFormat = dstFormat; + mSrcSize = calcSize(srcFormat, srcWidth, srcHeight); + mDstSize = calcSize(dstFormat, dstWidth, dstHeight); + mSrcYSize = calcYSize(srcFormat, srcWidth, srcHeight); + mDstYSize = calcYSize(dstFormat, dstWidth, dstHeight); + + mFlags = flags; // can be used for rotation + + mSrcSurfaceDef = getDummySurfaceDef(srcFormat, srcWidth, srcHeight, true); + mDstSurfaceDef = getDummySurfaceDef(dstFormat, dstWidth, dstHeight, false); + + memset((void*)&mBlit,0,sizeof(C2D_OBJECT)); + mBlit.source_rect.x = 0 << 16; + mBlit.source_rect.y = 0 << 16; + mBlit.source_rect.width = srcWidth << 16; + mBlit.source_rect.height = srcHeight << 16; + mBlit.target_rect.x = 0 << 16; + mBlit.target_rect.y = 0 << 16; + mBlit.target_rect.width = dstWidth << 16; + mBlit.target_rect.height = dstHeight << 16; + mBlit.config_mask = C2D_ALPHA_BLEND_NONE | C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | C2D_TARGET_RECT_BIT; + mBlit.surface_id = mSrcSurface; +} + +C2DColorConverter::~C2DColorConverter() +{ + if (!mError && mC2DLibHandle) { + + mC2DDestroySurface(mDstSurface); + mC2DDestroySurface(mSrcSurface); + if (isYUVSurface(mSrcFormat)) { + delete ((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef); + } else { + delete ((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef); + } + + if (isYUVSurface(mDstFormat)) { + delete ((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef); + } else { + delete ((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef); + } + } + + if (mC2DLibHandle) { + dlclose(mC2DLibHandle); + } + if (mAdrenoUtilsHandle) { + dlclose(mAdrenoUtilsHandle); + } +} + +int C2DColorConverter::convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData) +{ + C2D_STATUS ret; + + if (mError) { + ALOGE("C2D library initialization failed\n"); + return mError; + } + + if ((srcFd < 0) || (dstFd < 0) || (srcData == NULL) || (dstData == NULL)) { + ALOGE("Incorrect input parameters\n"); + return -1; + } + + if (isYUVSurface(mSrcFormat)) { + ret = updateYUVSurfaceDef(srcFd, srcBase, srcData, true); + } else { + ret = updateRGBSurfaceDef(srcFd, srcData, true); + } + + if (ret != C2D_STATUS_OK) { + ALOGE("Update src surface def failed\n"); + return -ret; + } + + if (isYUVSurface(mDstFormat)) { + ret = updateYUVSurfaceDef(dstFd, dstBase, dstData, false); + } else { + ret = updateRGBSurfaceDef(dstFd, dstData, false); + } + + if (ret != C2D_STATUS_OK) { + ALOGE("Update dst surface def failed\n"); + return -ret; + } + + mBlit.surface_id = mSrcSurface; + ret = mC2DDraw(mDstSurface, C2D_TARGET_ROTATE_0, 0, 0, 0, &mBlit, 1); + mC2DFinish(mDstSurface); + + bool unmappedSrcSuccess; + if (isYUVSurface(mSrcFormat)) { + unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef)->phys0); + } else { + unmappedSrcSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef)->phys); + } + + bool unmappedDstSuccess; + if (isYUVSurface(mDstFormat)) { + unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_YUV_SURFACE_DEF *)mDstSurfaceDef)->phys0); + } else { + unmappedDstSuccess = unmapGPUAddr((unsigned long)((C2D_RGB_SURFACE_DEF *)mDstSurfaceDef)->phys); + } + + if (ret != C2D_STATUS_OK) { + ALOGE("C2D Draw failed\n"); + return -ret; //c2d err values are positive + } else { + if (!unmappedSrcSuccess || !unmappedDstSuccess) { + ALOGE("unmapping GPU address failed\n"); + return -1; + } + return ret; + } +} + +bool C2DColorConverter::isYUVSurface(ColorConvertFormat format) +{ + switch (format) { + case YCbCr420Tile: + case YCbCr420SP: + case YCbCr420P: + case YCrCb420P: + case NV12_2K: + case NV12_128m: + case NV12_UBWC: + return true; + case RGB565: + case RGBA8888: + default: + return false; + } +} + +void* C2DColorConverter::getDummySurfaceDef(ColorConvertFormat format, size_t width, size_t height, bool isSource) +{ + if (isYUVSurface(format)) { + C2D_YUV_SURFACE_DEF * surfaceDef = new C2D_YUV_SURFACE_DEF; + surfaceDef->format = getC2DFormat(format); + surfaceDef->width = width; + surfaceDef->height = height; + surfaceDef->plane0 = (void *)0xaaaaaaaa; + surfaceDef->phys0 = (void *)0xaaaaaaaa; + surfaceDef->stride0 = calcStride(format, width); + surfaceDef->plane1 = (void *)0xaaaaaaaa; + surfaceDef->phys1 = (void *)0xaaaaaaaa; + surfaceDef->stride1 = calcStride(format, width); + surfaceDef->stride2 = calcStride(format, width); + surfaceDef->phys2 = NULL; + surfaceDef->plane2 = NULL; + + if (format == YCbCr420P || + format == YCrCb420P) { + printf("half stride for Cb Cr planes \n"); + surfaceDef->stride1 = calcStride(format, width) / 2; + surfaceDef->phys2 = (void *)0xaaaaaaaa; + surfaceDef->stride2 = calcStride(format, width) / 2; + } + mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + &(*surfaceDef)); + return ((void *)surfaceDef); + } else { + C2D_RGB_SURFACE_DEF * surfaceDef = new C2D_RGB_SURFACE_DEF; + surfaceDef->format = getC2DFormat(format); + if (mFlags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) + surfaceDef->format |= C2D_FORMAT_UBWC_COMPRESSED; + surfaceDef->width = width; + surfaceDef->height = height; + surfaceDef->buffer = (void *)0xaaaaaaaa; + surfaceDef->phys = (void *)0xaaaaaaaa; + surfaceDef->stride = calcStride(format, width); + mC2DCreateSurface(isSource ? &mSrcSurface : &mDstSurface, isSource ? C2D_SOURCE : C2D_TARGET, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + &(*surfaceDef)); + return ((void *)surfaceDef); + } +} + +C2D_STATUS C2DColorConverter::updateYUVSurfaceDef(int fd, void *base, void *data, bool isSource) +{ + if (isSource) { + C2D_YUV_SURFACE_DEF * srcSurfaceDef = (C2D_YUV_SURFACE_DEF *)mSrcSurfaceDef; + srcSurfaceDef->plane0 = data; + srcSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mSrcSize) + ((uint8_t *)data - (uint8_t *)base); + srcSurfaceDef->plane1 = (uint8_t *)data + mSrcYSize; + srcSurfaceDef->phys1 = (uint8_t *)srcSurfaceDef->phys0 + mSrcYSize; + if (srcSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 || + srcSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) { + srcSurfaceDef->plane2 = (uint8_t *)srcSurfaceDef->plane1 + mSrcYSize/4; + srcSurfaceDef->phys2 = (uint8_t *)srcSurfaceDef->phys1 + mSrcYSize/4; + } + return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &(*srcSurfaceDef)); + } else { + C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef; + dstSurfaceDef->plane0 = data; + dstSurfaceDef->phys0 = (uint8_t *)getMappedGPUAddr(fd, data, mDstSize) + ((uint8_t *)data - (uint8_t *)base); + dstSurfaceDef->plane1 = (uint8_t *)data + mDstYSize; + dstSurfaceDef->phys1 = (uint8_t *)dstSurfaceDef->phys0 + mDstYSize; + if (dstSurfaceDef->format & C2D_COLOR_FORMAT_420_I420 || + dstSurfaceDef->format & C2D_COLOR_FORMAT_420_YV12) { + dstSurfaceDef->plane2 = (uint8_t *)dstSurfaceDef->plane1 + mDstYSize/4; + dstSurfaceDef->phys2 = (uint8_t *)dstSurfaceDef->phys1 + mDstYSize/4; + } + + return mC2DUpdateSurface(mDstSurface, C2D_TARGET, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &(*dstSurfaceDef)); + } +} + +C2D_STATUS C2DColorConverter::updateRGBSurfaceDef(int fd, void * data, bool isSource) +{ + if (isSource) { + C2D_RGB_SURFACE_DEF * srcSurfaceDef = (C2D_RGB_SURFACE_DEF *)mSrcSurfaceDef; + srcSurfaceDef->buffer = data; + srcSurfaceDef->phys = getMappedGPUAddr(fd, data, mSrcSize); + return mC2DUpdateSurface(mSrcSurface, C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), + &(*srcSurfaceDef)); + } else { + C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef; + dstSurfaceDef->buffer = data; + ALOGV("dstSurfaceDef->buffer = %p\n", data); + dstSurfaceDef->phys = getMappedGPUAddr(fd, data, mDstSize); + return mC2DUpdateSurface(mDstSurface, C2D_TARGET, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), + &(*dstSurfaceDef)); + } +} + +uint32_t C2DColorConverter::getC2DFormat(ColorConvertFormat format) +{ + switch (format) { + case RGB565: + return C2D_COLOR_FORMAT_565_RGB; + case RGBA8888: + return C2D_COLOR_FORMAT_8888_RGBA | C2D_FORMAT_SWAP_ENDIANNESS | C2D_FORMAT_PREMULTIPLIED; + case YCbCr420Tile: + return (C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED); + case YCbCr420SP: + case NV12_2K: + case NV12_128m: + return C2D_COLOR_FORMAT_420_NV12; + case YCbCr420P: + return C2D_COLOR_FORMAT_420_I420; + case YCrCb420P: + return C2D_COLOR_FORMAT_420_YV12; + case NV12_UBWC: + return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_UBWC_COMPRESSED; + default: + ALOGE("Format not supported , %d\n", format); + return -1; + } +} + +size_t C2DColorConverter::calcStride(ColorConvertFormat format, size_t width) +{ + switch (format) { + case RGB565: + return ALIGN(width, ALIGN32) * 2; // RGB565 has width as twice + case RGBA8888: + if (mSrcStride) + return mSrcStride * 4; + else + return ALIGN(width, ALIGN32) * 4; + case YCbCr420Tile: + return ALIGN(width, ALIGN128); + case YCbCr420SP: + return ALIGN(width, ALIGN16); + case NV12_2K: + return ALIGN(width, ALIGN16); + case NV12_128m: + return ALIGN(width, ALIGN128); + case YCbCr420P: + return ALIGN(width, ALIGN16); + case YCrCb420P: + return ALIGN(width, ALIGN16); + case NV12_UBWC: + return VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width); + default: + return 0; + } +} + +size_t C2DColorConverter::calcYSize(ColorConvertFormat format, size_t width, size_t height) +{ + switch (format) { + case YCbCr420SP: + return (ALIGN(width, ALIGN16) * height); + case YCbCr420P: + return ALIGN(width, ALIGN16) * height; + case YCrCb420P: + return ALIGN(width, ALIGN16) * height; + case YCbCr420Tile: + return ALIGN(ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32), ALIGN8K); + case NV12_2K: { + size_t alignedw = ALIGN(width, ALIGN16); + size_t lumaSize = ALIGN(alignedw * height, ALIGN2K); + return lumaSize; + } + case NV12_128m: + return ALIGN(width, ALIGN128) * ALIGN(height, ALIGN32); + case NV12_UBWC: + return ALIGN( VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, width) * + VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K) + + ALIGN( VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, width) * + VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, height), ALIGN4K); + default: + return 0; + } +} + +size_t C2DColorConverter::calcSize(ColorConvertFormat format, size_t width, size_t height) +{ + int32_t alignedw = 0; + int32_t alignedh = 0; + int32_t size = 0; + int32_t tile_mode = 0; + int32_t raster_mode = 0; + int32_t padding_threshold = 512; /* hardcode for RGB formats */ + int32_t bpp = 0; + + switch (format) { + case RGB565: + bpp = 2; + mAdrenoComputeAlignedWidthAndHeight(width, height, bpp, tile_mode, raster_mode, padding_threshold, + &alignedw, &alignedh); + size = alignedw * alignedh * bpp; + size = ALIGN(size, ALIGN4K); + break; + case RGBA8888: + bpp = 4; + mAdrenoComputeAlignedWidthAndHeight(width, height, bpp, tile_mode, raster_mode, padding_threshold, + &alignedw, &alignedh); + if (mSrcStride) + size = mSrcStride * alignedh * bpp; + else + size = alignedw * alignedh * bpp; + size = ALIGN(size, ALIGN4K); + break; + case YCbCr420SP: + alignedw = ALIGN(width, ALIGN16); + size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN32) * (height/2) * 2), ALIGN4K); + break; + case YCbCr420P: + alignedw = ALIGN(width, ALIGN16); + size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K); + break; + case YCrCb420P: + alignedw = ALIGN(width, ALIGN16); + size = ALIGN((alignedw * height) + (ALIGN(width/2, ALIGN16) * (height/2) * 2), ALIGN4K); + break; + case YCbCr420Tile: + alignedw = ALIGN(width, ALIGN128); + alignedh = ALIGN(height, ALIGN32); + size = ALIGN(alignedw * alignedh, ALIGN8K) + ALIGN(alignedw * ALIGN(height/2, ALIGN32), ALIGN8K); + break; + case NV12_2K: { + alignedw = ALIGN(width, ALIGN16); + size_t lumaSize = ALIGN(alignedw * height, ALIGN2K); + size_t chromaSize = ALIGN((alignedw * height)/2, ALIGN2K); + size = ALIGN(lumaSize + chromaSize, ALIGN4K); + ALOGV("NV12_2k, width = %zu, height = %zu, size = %d", width, height, size); + } + break; + case NV12_128m: + alignedw = ALIGN(width, ALIGN128); + alignedh = ALIGN(height, ALIGN32); + size = ALIGN(alignedw * alignedh + (alignedw * ALIGN(height/2, ALIGN16)), ALIGN4K); + break; + case NV12_UBWC: + size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height); + default: + break; + } + return size; +} +/* + * Tells GPU to map given buffer and returns a physical address of mapped buffer + */ +void * C2DColorConverter::getMappedGPUAddr(int bufFD, void *bufPtr, size_t bufLen) +{ + C2D_STATUS status; + void *gpuaddr = NULL; + + status = mC2DMapAddr(bufFD, bufPtr, bufLen, 0, KGSL_USER_MEM_TYPE_ION, + &gpuaddr); + if (status != C2D_STATUS_OK) { + ALOGE("c2dMapAddr failed: status %d fd %d ptr %p len %zu flags %d\n", + status, bufFD, bufPtr, bufLen, KGSL_USER_MEM_TYPE_ION); + return NULL; + } + ALOGV("c2d mapping created: gpuaddr %p fd %d ptr %p len %zu\n", + gpuaddr, bufFD, bufPtr, bufLen); + + return gpuaddr; +} + +bool C2DColorConverter::unmapGPUAddr(unsigned long gAddr) +{ + + C2D_STATUS status = mC2DUnMapAddr((void*)gAddr); + + if (status != C2D_STATUS_OK) + ALOGE("c2dUnMapAddr failed: status %d gpuaddr %08lx\n", status, gAddr); + + return (status == C2D_STATUS_OK); +} + +int32_t C2DColorConverter::getBuffReq(int32_t port, C2DBuffReq *req) { + if (!req) return -1; + + if (port != C2D_INPUT && port != C2D_OUTPUT) return -1; + + memset(req, 0, sizeof(C2DBuffReq)); + if (port == C2D_INPUT) { + req->width = mSrcWidth; + req->height = mSrcHeight; + req->stride = calcStride(mSrcFormat, mSrcWidth); + req->sliceHeight = mSrcHeight; + req->lumaAlign = calcLumaAlign(mSrcFormat); + req->sizeAlign = calcSizeAlign(mSrcFormat); + req->size = calcSize(mSrcFormat, mSrcWidth, mSrcHeight); + req->bpp = calcBytesPerPixel(mSrcFormat); + ALOGV("input req->size = %d\n", req->size); + } else if (port == C2D_OUTPUT) { + req->width = mDstWidth; + req->height = mDstHeight; + req->stride = calcStride(mDstFormat, mDstWidth); + req->sliceHeight = mDstHeight; + req->lumaAlign = calcLumaAlign(mDstFormat); + req->sizeAlign = calcSizeAlign(mDstFormat); + req->size = calcSize(mDstFormat, mDstWidth, mDstHeight); + req->bpp = calcBytesPerPixel(mDstFormat); + ALOGV("output req->size = %d\n", req->size); + } + return 0; +} + +size_t C2DColorConverter::calcLumaAlign(ColorConvertFormat format) { + if (!isYUVSurface(format)) return 1; //no requirement + + switch (format) { + case NV12_2K: + return ALIGN2K; + case NV12_128m: + return 1; + case NV12_UBWC: + return ALIGN4K; + default: + ALOGE("unknown format passed for luma alignment number"); + return 1; + } +} + +size_t C2DColorConverter::calcSizeAlign(ColorConvertFormat format) { + if (!isYUVSurface(format)) return 1; //no requirement + + switch (format) { + case YCbCr420SP: //OR NV12 + case YCbCr420P: + case NV12_2K: + case NV12_128m: + case NV12_UBWC: + return ALIGN4K; + default: + ALOGE("unknown format passed for size alignment number"); + return 1; + } +} + +C2DBytesPerPixel C2DColorConverter::calcBytesPerPixel(ColorConvertFormat format) { + C2DBytesPerPixel bpp; + bpp.numerator = 0; + bpp.denominator = 1; + + switch (format) { + case RGB565: + bpp.numerator = 2; + break; + case RGBA8888: + bpp.numerator = 4; + break; + case YCbCr420SP: + case YCbCr420P: + case YCrCb420P: + case YCbCr420Tile: + case NV12_2K: + case NV12_128m: + case NV12_UBWC: + bpp.numerator = 3; + bpp.denominator = 2; + break; + default: + break; + } + return bpp; +} + +int32_t C2DColorConverter::dumpOutput(char * filename, char mode) { + int fd; + size_t stride, sliceHeight; + if (!filename) return -1; + + int flags = O_RDWR | O_CREAT; + if (mode == 'a') { + flags |= O_APPEND; + } + + if ((fd = open(filename, flags)) < 0) { + ALOGE("open dump file failed w/ errno %s", strerror(errno)); + return -1; + } + + int ret = 0; + if (isYUVSurface(mDstFormat)) { + C2D_YUV_SURFACE_DEF * dstSurfaceDef = (C2D_YUV_SURFACE_DEF *)mDstSurfaceDef; + uint8_t * base = (uint8_t *)dstSurfaceDef->plane0; + stride = dstSurfaceDef->stride0; + sliceHeight = dstSurfaceDef->height; + /* dump luma */ + for (size_t i = 0; i < sliceHeight; i++) { + ret = write(fd, base, mDstWidth); //will work only for the 420 ones + if (ret < 0) goto cleanup; + base += stride; + } + + if (mDstFormat == YCbCr420P || + mDstFormat == YCrCb420P) { + printf("Dump Cb and Cr separately for Planar\n"); + //dump Cb/Cr + base = (uint8_t *)dstSurfaceDef->plane1; + stride = dstSurfaceDef->stride1; + for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones + ret = write(fd, base, mDstWidth/2); + if (ret < 0) goto cleanup; + base += stride; + } + + //dump Cr/Cb + base = (uint8_t *)dstSurfaceDef->plane2; + stride = dstSurfaceDef->stride2; + + for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones + ret = write(fd, base, mDstWidth/2); + if (ret < 0) goto cleanup; + base += stride; + } + + } else { + /* dump chroma */ + base = (uint8_t *)dstSurfaceDef->plane1; + stride = dstSurfaceDef->stride1; + for (size_t i = 0; i < sliceHeight/2;i++) { //will work only for the 420 ones + ret = write(fd, base, mDstWidth); + if (ret < 0) goto cleanup; + base += stride; + } + } + } else { + C2D_RGB_SURFACE_DEF * dstSurfaceDef = (C2D_RGB_SURFACE_DEF *)mDstSurfaceDef; + uint8_t * base = (uint8_t *)dstSurfaceDef->buffer; + stride = dstSurfaceDef->stride; + sliceHeight = dstSurfaceDef->height; + + printf("rgb surface base is %p", base); + printf("rgb surface dumpsslice height is %lu\n", (unsigned long)sliceHeight); + printf("rgb surface dump stride is %lu\n", (unsigned long)stride); + + int bpp = 1; //bytes per pixel + if (mDstFormat == RGB565) { + bpp = 2; + } else if (mDstFormat == RGBA8888) { + bpp = 4; + } + + int count = 0; + for (size_t i = 0; i < sliceHeight; i++) { + ret = write(fd, base, mDstWidth*bpp); + if (ret < 0) { + printf("write failed, count = %d\n", count); + goto cleanup; + } + base += stride; + count += stride; + } + } + cleanup: + if (ret < 0) { + ALOGE("file write failed w/ errno %s", strerror(errno)); + } + close(fd); + return ret < 0 ? ret : 0; +} + +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) +{ + return new C2DColorConverter(srcWidth, srcHeight, dstWidth, dstHeight, srcFormat, dstFormat, flags, srcStride); +} + +extern "C" void destroyC2DColorConverter(C2DColorConverterBase* C2DCC) +{ + delete C2DCC; +} + +} diff --git a/msm8998/libc2dcolorconvert/C2DColorConverter.h b/msm8998/libc2dcolorconvert/C2DColorConverter.h new file mode 100644 index 0000000..1885f1e --- /dev/null +++ b/msm8998/libc2dcolorconvert/C2DColorConverter.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2012 - 2013, 2015 The Linux Foundation. All rights reserved. + * + * redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * this software is provided "as is" and any express or implied + * warranties, including, but not limited to, the implied warranties of + * merchantability, fitness for a particular purpose and non-infringement + * are disclaimed. in no event shall the copyright owner or contributors + * be liable for any direct, indirect, incidental, special, exemplary, or + * consequential damages (including, but not limited to, procurement of + * substitute goods or services; loss of use, data, or profits; or + * business interruption) however caused and on any theory of liability, + * whether in contract, strict liability, or tort (including negligence + * or otherwise) arising in any way out of the use of this software, even + * if advised of the possibility of such damage. + * + */ + +#ifndef C2D_ColorConverter_H_ +#define C2D_ColorConverter_H_ + +#include <c2d2.h> +#include <sys/types.h> + +typedef C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +typedef C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +typedef C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id, + C2D_SURFACE_TYPE surface_type, + void *surface_definition, + int32 x, int32 y ); + +typedef C2D_STATUS (*LINK_c2dDraw)( uint32 target_id, + uint32 target_config, C2D_RECT *target_scissor, + uint32 target_mask_id, uint32 target_color_key, + C2D_OBJECT *objects_list, uint32 num_objects ); + +typedef C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp); + +typedef C2D_STATUS (*LINK_c2dFinish)( uint32 target_id); + +typedef C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp ); + +typedef C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id ); + +typedef C2D_STATUS (*LINK_c2dMapAddr)( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr); + +typedef C2D_STATUS (*LINK_c2dUnMapAddr)(void * gpuaddr); + +typedef void (*LINK_AdrenoComputeAlignedWidthAndHeight) (int width, int height, int bpp, int tile_mode, int raster_mode, + int padding_threshold, int *aligned_width, int * aligned_height); + +namespace android { + +/*TODO: THIS NEEDS TO ENABLED FOR JB PLUS*/ +enum ColorConvertFormat { + RGB565 = 1, + YCbCr420Tile, + YCbCr420SP, + YCbCr420P, + YCrCb420P, + RGBA8888, + NV12_2K, + NV12_128m, + NV12_UBWC, +}; + +typedef struct { + int32_t numerator; + int32_t denominator; +} C2DBytesPerPixel; + +typedef struct { + int32_t width; + int32_t height; + int32_t stride; + int32_t sliceHeight; + int32_t lumaAlign; + int32_t sizeAlign; + int32_t size; + C2DBytesPerPixel bpp; +} C2DBuffReq; + +typedef enum { + C2D_INPUT = 0, + C2D_OUTPUT, +} C2D_PORT; + +class C2DColorConverterBase { + +public: + virtual ~C2DColorConverterBase(){}; + virtual int convertC2D(int srcFd, void *srcBase, void * srcData, int dstFd, void *dstBase, void * dstData) = 0; + virtual int32_t getBuffReq(int32_t port, C2DBuffReq *req) = 0; + virtual int32_t dumpOutput(char * filename, char mode) = 0; +}; + +typedef C2DColorConverterBase* createC2DColorConverter_t(size_t srcWidth, size_t srcHeight, size_t dstWidth, size_t dstHeight, ColorConvertFormat srcFormat, ColorConvertFormat dstFormat, int32_t flags, size_t srcStride); +typedef void destroyC2DColorConverter_t(C2DColorConverterBase*); + +} + +#endif // C2D_ColorConverter_H_ diff --git a/msm8998/libc2dcolorconvert/Makefile.am b/msm8998/libc2dcolorconvert/Makefile.am new file mode 100644 index 0000000..63fd717 --- /dev/null +++ b/msm8998/libc2dcolorconvert/Makefile.am @@ -0,0 +1,18 @@ +AM_CFLAGS = -Wall +AM_CFLAGS += -Wundef +AM_CFLAGS += -Wstrict-prototypes +AM_CFLAGS += -Wno-trigraphs +AM_CFLAGS += -g -O3 +AM_CFLAGS += "-include stdint.h" +AM_CFLAGS += "-std=c++11" + + +AM_CPPFLAGS = $(CPPFLAGS) + +c_sources = C2DColorConverter.cpp +h_sources = C2DColorConverter.h + +lib_LTLIBRARIES = libc2dcolorconvert.la +libc2dcolorconvert_la_SOURCES = $(c_sources) $(h_sources) +libc2dcolorconvert_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) -fPIC +libc2dcolorconvert_la_LIBADD = -ldl -lpthread -llog |