| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * Copyright@ Samsung Electronics Co. LTD |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /*! |
| * \file libscaler.cpp |
| * \brief source file for Scaler HAL |
| * \author Sunyoung Kang (sy0816.kang@samsung.com) |
| * \date 2013/02/01 |
| * |
| * <b>Revision History: </b> |
| * - 2013.02.01 : Sunyoung Kang (sy0816.kang@samsung.com) \n |
| * Create |
| * - 2013.04.10 : Cho KyongHo (pullip.cho@samsung.com) \n |
| * Refactoring |
| * |
| */ |
| |
| #include <sys/types.h> |
| #include <sys/ioctl.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <system/graphics.h> |
| |
| #include "exynos_scaler.h" |
| |
| #include "libscaler-common.h" |
| #include "libscalerblend-v4l2.h" |
| #include "libscaler-v4l2.h" |
| #include "libscaler-m2m1shot.h" |
| |
| int hal_pixfmt_to_v4l2(int hal_pixel_format) |
| { |
| int v4l2_pixel_format = -1; |
| |
| switch (hal_pixel_format) { |
| case HAL_PIXEL_FORMAT_RGBA_8888: |
| case HAL_PIXEL_FORMAT_RGBX_8888: |
| v4l2_pixel_format = V4L2_PIX_FMT_RGB32; |
| break; |
| |
| case HAL_PIXEL_FORMAT_RGB_888: |
| v4l2_pixel_format = V4L2_PIX_FMT_RGB24; |
| break; |
| |
| case HAL_PIXEL_FORMAT_RGB_565: |
| v4l2_pixel_format = V4L2_PIX_FMT_RGB565; |
| break; |
| |
| case HAL_PIXEL_FORMAT_BGRA_8888: |
| v4l2_pixel_format = V4L2_PIX_FMT_BGR32; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: |
| v4l2_pixel_format = V4L2_PIX_FMT_YVU420M; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: |
| v4l2_pixel_format = V4L2_PIX_FMT_YUV420M; |
| break; |
| |
| case HAL_PIXEL_FORMAT_YV12: |
| v4l2_pixel_format = V4L2_PIX_FMT_YVU420; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P: |
| v4l2_pixel_format = V4L2_PIX_FMT_YUV420; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN: |
| v4l2_pixel_format = V4L2_PIX_FMT_YUV420N; |
| break; |
| |
| case HAL_PIXEL_FORMAT_YCbCr_422_SP: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV16; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12N; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12M; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12N_10B; |
| break; |
| |
| case HAL_PIXEL_FORMAT_YCbCr_422_I: |
| v4l2_pixel_format = V4L2_PIX_FMT_YUYV; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_CbYCrY_422_I: |
| v4l2_pixel_format = V4L2_PIX_FMT_UYVY; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_SP: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV61; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV21M; |
| break; |
| |
| case HAL_PIXEL_FORMAT_YCrCb_420_SP: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV21; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED: |
| #ifdef USES_FIMC |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12MT; |
| #else |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12MT_16X16; |
| #endif |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12NT; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I: |
| v4l2_pixel_format = V4L2_PIX_FMT_YVYU; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_CrYCbY_422_I: |
| v4l2_pixel_format = V4L2_PIX_FMT_VYUY; |
| break; |
| |
| case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M: |
| v4l2_pixel_format = V4L2_PIX_FMT_NV12M_P010; |
| break; |
| |
| default: |
| ALOGE("%s::unmatched HAL_PIXEL_FORMAT color_space(0x%x)\n", |
| __func__, hal_pixel_format); |
| break; |
| } |
| |
| return v4l2_pixel_format; |
| } |
| |
| static bool find_pixel(unsigned int sc_pxfmt, unsigned int __out *v4l2_pxfmt) |
| { |
| const static unsigned int sc_fmt_tbl[][2] = { |
| {EXYNOS_SC_FMT_RGB32, V4L2_PIX_FMT_RGB32}, |
| {EXYNOS_SC_FMT_BGR32, V4L2_PIX_FMT_BGR32}, |
| {EXYNOS_SC_FMT_RGB565, V4L2_PIX_FMT_RGB565}, |
| {EXYNOS_SC_FMT_RGB555X, V4L2_PIX_FMT_RGB555X}, |
| {EXYNOS_SC_FMT_RGB444, V4L2_PIX_FMT_RGB444}, |
| }; |
| |
| for (size_t i = 0; i < ARRSIZE(sc_fmt_tbl); i++) { |
| if (sc_pxfmt == sc_fmt_tbl[i][0]) { |
| *v4l2_pxfmt = sc_fmt_tbl[i][1]; |
| return true; |
| } |
| } |
| |
| SC_LOGE("Unknown format value %d", sc_pxfmt); |
| |
| return false; |
| } |
| |
| bool exynos_sc_copy_pixels(exynos_sc_pxinfo *pxinfo, int dev_num) |
| { |
| unsigned int srcfmt; |
| unsigned int dstfmt; |
| |
| CScalerM2M1SHOT sc(dev_num); |
| |
| if (!sc.Valid()) |
| return false; |
| |
| if (!find_pixel(pxinfo->src.pxfmt, &srcfmt)) |
| return false; |
| |
| if (!find_pixel(pxinfo->dst.pxfmt, &dstfmt)) |
| return false; |
| |
| if (!sc.SetSrcFormat(pxinfo->src.width, pxinfo->src.height, srcfmt)) |
| return false; |
| |
| if (!sc.SetDstFormat(pxinfo->dst.width, pxinfo->dst.height, dstfmt)) |
| return false; |
| |
| if (!sc.SetSrcCrop(pxinfo->src.crop_left, pxinfo->src.crop_top, |
| pxinfo->src.crop_width, pxinfo->src.crop_height)) |
| return false; |
| |
| if (!sc.SetDstCrop(pxinfo->dst.crop_left, pxinfo->dst.crop_top, |
| pxinfo->dst.crop_width, pxinfo->dst.crop_height)) |
| return false; |
| |
| if (!sc.SetRotate(pxinfo->rotate, pxinfo->hflip, pxinfo->vflip)) |
| return false; |
| |
| // the first argument ot CScalerM2M1SHOT.SetXXXAddr() must be void *[3] |
| // it is safe to pass void *[1] which is not an array actually |
| // because CScalerM2M1SHOT.SetAddr() just accesses the array elements |
| // that are used for the specified format and this function just specifies |
| // RGB formats with one planar. |
| void *addr[SC_NUM_OF_PLANES]; |
| for (size_t i = 1; i < SC_NUM_OF_PLANES; i++) |
| addr[i] = NULL; |
| |
| addr[0] = pxinfo->src.addr; |
| if (!sc.SetSrcAddr(addr, V4L2_MEMORY_USERPTR)) |
| return false; |
| |
| addr[0] = pxinfo->dst.addr; |
| if (!sc.SetDstAddr(addr, V4L2_MEMORY_USERPTR)) |
| return false; |
| |
| return sc.Run(); |
| } |
| |
| #ifdef SCALER_USE_M2M1SHOT |
| typedef CScalerM2M1SHOT CScalerNonStream; |
| #else |
| typedef CScalerV4L2 CScalerNonStream; |
| #endif |
| |
| static CScalerNonStream *GetNonStreamScaler(void *handle) |
| { |
| if (handle == NULL) { |
| SC_LOGE("NULL Scaler handle"); |
| return NULL; |
| } |
| |
| CScalerNonStream *sc = reinterpret_cast<CScalerNonStream *>(handle); |
| if (!sc->Valid()) { |
| SC_LOGE("Invalid Scaler handle %p", handle); |
| return NULL; |
| } |
| |
| return sc; |
| } |
| |
| void *exynos_sc_create(int dev_num) |
| { |
| CScalerNonStream *sc = new CScalerNonStream(dev_num); |
| |
| if (!sc) { |
| SC_LOGE("Failed to allocate a Scaler handle for instance %d", dev_num); |
| return NULL; |
| } |
| |
| if (!sc->Valid()) { |
| SC_LOGE("Failed to create a Scaler handle for instance %d", dev_num); |
| delete sc; |
| return NULL; |
| } |
| |
| return reinterpret_cast<void *>(sc); |
| } |
| |
| int exynos_sc_destroy(void *handle) |
| { |
| int ret = 0; |
| |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| if (!sc->Stop()) { |
| SC_LOGE("Failed to stop Scaler (handle %p)", handle); |
| ret = -1; |
| } |
| |
| delete sc; |
| |
| return ret; |
| } |
| |
| int exynos_sc_set_csc_property( |
| void *handle, |
| unsigned int csc_range, |
| unsigned int v4l2_colorspace, |
| unsigned int filter) |
| |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| sc->SetCSCWide(csc_range); |
| sc->SetCSCEq(v4l2_colorspace); |
| sc->SetFilter(filter); |
| |
| return 0; |
| } |
| |
| int exynos_sc_set_src_format( |
| void *handle, |
| unsigned int width, |
| unsigned int height, |
| unsigned int crop_left, |
| unsigned int crop_top, |
| unsigned int crop_width, |
| unsigned int crop_height, |
| unsigned int v4l2_colorformat, |
| unsigned int cacheable, |
| unsigned int mode_drm, |
| unsigned int premultiplied) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| sc->SetSrcPremultiplied(premultiplied != 0); |
| sc->SetSrcCacheable(cacheable != 0); |
| sc->SetDRM(mode_drm != 0); |
| |
| if (!sc->SetSrcFormat(width, height, v4l2_colorformat)) |
| return -1; |
| |
| return sc->SetSrcCrop(crop_left, crop_top, crop_width, crop_height) ? 0 : -1; |
| } |
| |
| int exynos_sc_set_dst_format( |
| void *handle, |
| unsigned int width, |
| unsigned int height, |
| unsigned int crop_left, |
| unsigned int crop_top, |
| unsigned int crop_width, |
| unsigned int crop_height, |
| unsigned int v4l2_colorformat, |
| unsigned int cacheable, |
| unsigned int mode_drm, |
| unsigned int premultiplied) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| sc->SetDstPremultiplied(premultiplied != 0); |
| sc->SetDstCacheable(cacheable != 0); |
| sc->SetDRM(mode_drm != 0); |
| |
| if (!sc->SetDstFormat(width, height, v4l2_colorformat)) |
| return -1; |
| |
| if (!sc->SetDstCrop(crop_left, crop_top, crop_width, crop_height)) |
| return -1; |
| |
| return 0; |
| } |
| |
| int exynos_sc_set_rotation( |
| void *handle, |
| int rot, |
| int flip_h, |
| int flip_v) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| return sc->SetRotate(rot, flip_h, flip_v) ? 0 : -1; |
| } |
| |
| void exynos_sc_set_framerate( |
| void *handle, |
| int framerate) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return; |
| |
| sc->SetFrameRate(framerate); |
| } |
| |
| int exynos_sc_set_src_addr( |
| void *handle, |
| void *addr[SC_NUM_OF_PLANES], |
| int mem_type, |
| int __UNUSED__ acquireFenceFd) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| // acquireFenceFd is ignored by blocking mode |
| return sc->SetSrcAddr(addr, mem_type) ? 0 : -1; |
| } |
| |
| int exynos_sc_set_dst_addr( |
| void *handle, |
| void *addr[SC_NUM_OF_PLANES], |
| int mem_type, |
| int __UNUSED__ acquireFenceFd) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| // acquireFenceFd is ignored by blocking mode |
| return sc->SetDstAddr(addr, mem_type) ? 0 : -1; |
| } |
| |
| int exynos_sc_convert(void *handle) |
| { |
| CScalerNonStream *sc = GetNonStreamScaler(handle); |
| if (!sc) |
| return -1; |
| |
| return sc->Run() ? 0 : -1; |
| } |
| |
| static CScalerBlendV4L2 *GetScalerBlend(void *handle) |
| { |
| if (handle == NULL) { |
| SC_LOGE("NULL Scaler handle"); |
| return NULL; |
| } |
| |
| CScalerBlendV4L2 *sc = reinterpret_cast<CScalerBlendV4L2 *>(handle); |
| if (!sc->Valid()) { |
| SC_LOGE("Invalid Scaler handle %p", handle); |
| return NULL; |
| } |
| |
| return sc; |
| } |
| |
| static CScalerV4L2 *GetScaler(void *handle) |
| { |
| if (handle == NULL) { |
| SC_LOGE("NULL Scaler handle"); |
| return NULL; |
| } |
| |
| CScalerV4L2 *sc = reinterpret_cast<CScalerV4L2 *>(handle); |
| if (!sc->Valid()) { |
| SC_LOGE("Invalid Scaler handle %p", handle); |
| return NULL; |
| } |
| |
| return sc; |
| } |
| |
| void *exynos_sc_create_exclusive( |
| int dev_num, |
| int allow_drm |
| ) |
| { |
| CScalerV4L2 *sc; |
| |
| sc = new CScalerV4L2(dev_num, allow_drm); |
| if (!sc) { |
| SC_LOGE("Failed to allocate a Scaler handle for instance %d", dev_num); |
| return NULL; |
| } |
| |
| if (!sc->Valid()) { |
| SC_LOGE("Failed to create a Scaler handle for instance %d", dev_num); |
| delete sc; |
| return NULL; |
| } |
| |
| SC_LOGD("Scaler %d is successfully created", dev_num); |
| return reinterpret_cast<void *>(sc); |
| } |
| |
| int exynos_sc_free_and_close(void *handle) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| int ret = 0; |
| if (!sc->Stop()) { |
| SC_LOGE("Failed to stop Scaler (handle %p)", handle); |
| ret = -1; |
| } |
| |
| delete sc; |
| |
| return ret; |
| } |
| |
| int exynos_sc_stop_exclusive(void *handle) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| if (!sc->Stop()) { |
| SC_LOGE("Failed to stop Scaler (handle %p)", handle); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| int exynos_sc_csc_exclusive(void *handle, |
| unsigned int range_full, |
| unsigned int v4l2_colorspace) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| sc->SetCSCWide(range_full); |
| sc->SetCSCEq(v4l2_colorspace); |
| |
| return 0; |
| } |
| |
| int exynos_sc_config_exclusive( |
| void *handle, |
| exynos_sc_img *src_img, |
| exynos_sc_img *dst_img) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| if (src_img->drmMode && !sc->IsDRMAllowed()) { |
| SC_LOGE("Invalid DRM state request for Scaler%d (s=%d d=%d)", |
| sc->GetScalerID(), src_img->drmMode, dst_img->drmMode); |
| return -1; |
| } |
| |
| unsigned int rot = 0; |
| unsigned int flip_h = 0; |
| unsigned int flip_v = 0; |
| |
| if (dst_img->rot == HAL_TRANSFORM_ROT_270) { |
| rot = 270; |
| } else { |
| if (dst_img->rot & HAL_TRANSFORM_FLIP_H) |
| flip_h = 1; |
| if (dst_img->rot & HAL_TRANSFORM_FLIP_V) |
| flip_v = 1; |
| if (dst_img->rot & HAL_TRANSFORM_ROT_90) |
| rot = 90; |
| } |
| |
| if (!sc->SetRotate(rot, flip_h, flip_v)) { |
| SC_LOGE("Failed to set rotation degree %d, hflip %d, vflip %d", |
| rot, flip_h, flip_v); |
| return -1; |
| } |
| |
| int32_t src_color_space = hal_pixfmt_to_v4l2(src_img->format); |
| int32_t dst_color_space = hal_pixfmt_to_v4l2(dst_img->format); |
| |
| if (!sc->SetSrcFormat(src_img->fw, src_img->fh, src_color_space)) |
| return -1; |
| |
| if (!sc->SetSrcCrop(src_img->x, src_img->y, src_img->w, src_img->h)) |
| return -1; |
| |
| if (!sc->SetDstFormat(dst_img->fw, dst_img->fh, dst_color_space)) |
| return -1; |
| |
| if (!sc->SetDstCrop(dst_img->x, dst_img->y, dst_img->w, dst_img->h)) |
| return -1; |
| |
| sc->SetCSCWide(!dst_img->narrowRgb); |
| |
| sc->SetSrcCacheable(src_img->cacheable != 0); |
| sc->SetDstCacheable(dst_img->cacheable != 0); |
| |
| sc->SetSrcPremultiplied(src_img->pre_multi); |
| sc->SetDstPremultiplied(dst_img->pre_multi); |
| |
| sc->SetDRM(src_img->drmMode != 0 || dst_img->drmMode != 0); |
| |
| return 0; |
| } |
| |
| int exynos_sc_run_exclusive( |
| void *handle, |
| exynos_sc_img *src_img, |
| exynos_sc_img *dst_img) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| void *addr[SC_NUM_OF_PLANES]; |
| |
| addr[0] = (void *)src_img->yaddr; |
| addr[1] = (void *)src_img->uaddr; |
| addr[2] = (void *)src_img->vaddr; |
| sc->SetSrcAddr(addr, src_img->mem_type, src_img->acquireFenceFd); |
| |
| addr[0] = (void *)dst_img->yaddr; |
| addr[1] = (void *)dst_img->uaddr; |
| addr[2] = (void *)dst_img->vaddr; |
| sc->SetDstAddr(addr, dst_img->mem_type, dst_img->acquireFenceFd); |
| |
| if (!sc->DevSetCtrl()) |
| return -1; |
| |
| if (!sc->DevSetFormat()) |
| return -1; |
| |
| if (!sc->ReqBufs()) |
| return -1; |
| |
| int fdSrcReleaseFence, fdDstReleaseFence; |
| |
| if (!sc->QBuf(&fdSrcReleaseFence, &fdDstReleaseFence)) |
| return -1; |
| |
| if (!sc->StreamOn()) { |
| close(fdSrcReleaseFence); |
| close(fdDstReleaseFence); |
| return -1; |
| } |
| |
| src_img->releaseFenceFd = fdSrcReleaseFence; |
| dst_img->releaseFenceFd = fdDstReleaseFence; |
| |
| return 0; |
| } |
| |
| void *exynos_sc_create_blend_exclusive( |
| int dev_num, |
| int allow_drm |
| ) |
| { |
| CScalerBlendV4L2 *sc; |
| |
| sc = new CScalerBlendV4L2(dev_num, allow_drm); |
| if (!sc) { |
| SC_LOGE("Failed to allocate a Scaler blend handle for instance %d", dev_num); |
| return NULL; |
| } |
| |
| if (!sc->Valid()) { |
| SC_LOGE("Failed to create a Scaler blend handle for instance %d", dev_num); |
| delete sc; |
| return NULL; |
| } |
| |
| SC_LOGD("Scaler blend %d is successfully created", dev_num); |
| return reinterpret_cast<void *>(sc); |
| } |
| |
| int exynos_sc_config_blend_exclusive( |
| void *handle, |
| exynos_sc_img *src_img, |
| exynos_sc_img *dst_img, |
| struct SrcBlendInfo *srcblendinfo) |
| { |
| |
| CScalerBlendV4L2 *sc = GetScalerBlend(handle); |
| if (!sc) |
| return -1; |
| |
| if (src_img->drmMode && !sc->IsDRMAllowed()) { |
| SC_LOGE("Invalid DRM state request for Scaler%d (s=%d d=%d)", |
| sc->GetScalerID(), src_img->drmMode, dst_img->drmMode); |
| return -1; |
| } |
| unsigned int rot = 0; |
| unsigned int flip_h = 0; |
| unsigned int flip_v = 0; |
| |
| if (dst_img->rot == HAL_TRANSFORM_ROT_270) { |
| rot = 270; |
| } else { |
| if (dst_img->rot & HAL_TRANSFORM_FLIP_H) |
| flip_h = 1; |
| if (dst_img->rot & HAL_TRANSFORM_FLIP_V) |
| flip_v = 1; |
| if (dst_img->rot & HAL_TRANSFORM_ROT_90) |
| rot = 90; |
| } |
| |
| if (!sc->SetRotate(rot, flip_h, flip_v)) { |
| SC_LOGE("Failed to set rotation degree %d, hflip %d, vflip %d", |
| rot, flip_h, flip_v); |
| return -1; |
| } |
| |
| int32_t src_color_space = hal_pixfmt_to_v4l2(src_img->format); |
| int32_t dst_color_space = hal_pixfmt_to_v4l2(dst_img->format); |
| int32_t src_blend_color_space = hal_pixfmt_to_v4l2(srcblendinfo->srcblendfmt); |
| |
| sc->GetCustomAlphaBlendFmt(src_color_space, src_blend_color_space); |
| if (src_color_space < 0) { |
| SC_LOGE("src blending format not supported"); |
| return -1; |
| } |
| |
| sc->SetSrcBlendOp(srcblendinfo->blop); |
| |
| sc->SetSrcGlobalAlpha(srcblendinfo->globalalpha.val, |
| srcblendinfo->globalalpha.enable); |
| |
| sc->SetSrcBlendVPos(srcblendinfo->srcblendvpos); |
| |
| sc->SetSrcBlendHPos(srcblendinfo->srcblendhpos); |
| |
| sc->SetSrcBlendPremulti(srcblendinfo->srcblendpremulti); |
| |
| sc->SetSrcBlendFmt(src_blend_color_space); |
| |
| sc->SetSrcBlendStride(srcblendinfo->srcblendstride); |
| |
| sc->SetSrcBlendWidth(srcblendinfo->srcblendwidth); |
| |
| sc->SetSrcBlendHeight(srcblendinfo->srcblendheight); |
| |
| sc->SetSrcBlendCSCSpace(srcblendinfo->cscspec.enable, |
| srcblendinfo->cscspec.space, |
| srcblendinfo->cscspec.wide); |
| |
| if (!sc->SetSrcFormat(src_img->fw, src_img->fh, src_color_space)) |
| return -1; |
| |
| if (!sc->SetSrcCrop(src_img->x, src_img->y, src_img->w, src_img->h)) |
| return -1; |
| |
| if (!sc->SetDstFormat(dst_img->fw, dst_img->fh, dst_color_space)) |
| return -1; |
| |
| if (!sc->SetDstCrop(dst_img->x, dst_img->y, dst_img->w, dst_img->h)) |
| return -1; |
| |
| sc->SetSrcCacheable(src_img->cacheable != 0); |
| sc->SetDstCacheable(dst_img->cacheable != 0); |
| |
| sc->SetDRM(src_img->drmMode != 0 || dst_img->drmMode != 0); |
| |
| return 0; |
| } |
| |
| int exynos_sc_wait_frame_done_exclusive( |
| void *handle) |
| { |
| CScalerV4L2 *sc = GetScaler(handle); |
| if (!sc) |
| return -1; |
| |
| return sc->DQBuf() ? 0 : -1; |
| } |