diff options
Diffstat (limited to 'liboverlay/overlay.cpp')
-rw-r--r-- | liboverlay/overlay.cpp | 1490 |
1 files changed, 0 insertions, 1490 deletions
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp deleted file mode 100644 index 6220106..0000000 --- a/liboverlay/overlay.cpp +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * 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. - */ - -/*#define LOG_NDEBUG 0*/ -#define LOG_TAG "SEC_Overlay" - -#include <hardware/hardware.h> -#include <hardware/overlay.h> - -extern "C" { -#include "v4l2_utils.h" -} - -#include <pthread.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <unistd.h> -#include <linux/videodev.h> - -#include <cutils/log.h> -#include <cutils/ashmem.h> -#include <cutils/atomic.h> - -#include "linux/fb.h" - -/*****************************************************************************/ - -#define LOG_FUNCTION_NAME LOGV(" %s %s", __FILE__, __func__) - -#define NUM_OVERLAY_BUFFERS_REQUESTED (3) -/* OVRLYSHM on phone keypad*/ -#define SHARED_DATA_MARKER (0x68759746) - -/* These values should come from Surface Flinger */ -unsigned int g_lcd_width = 480; -unsigned int g_lcd_height = 800; -unsigned int g_lcd_bpp = 32; - -#define CACHEABLE_BUFFERS 0x1 - -/* shared with Camera/Video Playback HAL */ -#define ALL_BUFFERS_FLUSHED -66 - -uint32_t phyAddr; -s5p_fimc_t g_s5p_fimc; - -typedef struct -{ - uint32_t posX; - uint32_t posY; - uint32_t posW; - uint32_t posH; - uint32_t rotation; - uint32_t flip; - - uint32_t posX_org; - uint32_t posY_org; - uint32_t posW_org; - uint32_t posH_org; - -} overlay_ctrl_t; - -typedef struct -{ - uint32_t cropX; - uint32_t cropY; - uint32_t cropW; - uint32_t cropH; -} overlay_data_t; - -typedef struct -{ - uint32_t marker; - uint32_t size; - - volatile int32_t refCnt; - - uint32_t controlReady; /* Only updated by the control side */ - uint32_t dataReady; /* Only updated by the data side */ - - pthread_mutex_t lock; - pthread_mutexattr_t attr; - - uint32_t streamEn; - uint32_t streamingReset; - - uint32_t dispW; - uint32_t dispH; - -} overlay_shared_t; - -/* Only one instance is created per platform */ -struct overlay_control_context_t { - struct overlay_control_device_t device; - /* our private state goes below here */ - struct overlay_t* overlay_video1; - struct overlay_t* overlay_video2; -}; - -/* A separate instance is created per overlay data side user*/ -struct overlay_data_context_t { - struct overlay_data_device_t device; - /* our private state goes below here */ - int ctl_fd; - int shared_fd; - int shared_size; - int width; - int height; - int format; - int num_buffers; - size_t *buffers_len; - void **buffers; - - overlay_data_t data; - overlay_shared_t *shared; - struct mapping_data *mapping_data; - /* Need to count Qd buffers - to be sure we don't block DQ'ing when exiting */ - int qd_buf_count; - int cacheable_buffers; - - bool zerocopy; -}; - -static int create_shared_data(overlay_shared_t **shared); -static void destroy_shared_data(int shared_fd, overlay_shared_t *shared, - bool closefd); -static int open_shared_data(overlay_data_context_t *ctx); -static void close_shared_data(overlay_data_context_t *ctx); -enum { LOCK_REQUIRED = 1, NO_LOCK_NEEDED = 0 }; -static int enable_streaming(overlay_shared_t *shared, int ovly_fd, - int lock_required ); - -static int overlay_device_open(const struct hw_module_t* module, - const char* name, struct hw_device_t** device); - -static int check_fimc_dst_constraints(s5p_fimc_t *s5p_fimc, - unsigned int rotation); -static int check_fimc_src_constraints(s5p_fimc_t *s5p_fimc); - -static struct hw_module_methods_t overlay_module_methods = { -open: overlay_device_open -}; - -struct overlay_module_t HAL_MODULE_INFO_SYM = { -common: { -tag: HARDWARE_MODULE_TAG, - version_major: 1, - version_minor: 0, - id: OVERLAY_HARDWARE_MODULE_ID, - name: "SEC Overlay module", - author: "The Android Open Source Project", - methods: &overlay_module_methods, - } -}; - -/*****************************************************************************/ - -/* - * This is the overlay_t object, it is returned to the user and represents - * an overlay. here we use a subclass, where we can store our own state. - * This handles will be passed across processes and possibly given to other - * HAL modules (for instance video decode modules). - */ -struct handle_t : public native_handle { - /* add the data fields we need here, for instance: */ - int ctl_fd; - int shared_fd; - int width; - int height; - int format; - int num_buffers; - int shared_size; -}; - -static int handle_format(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->format; -} - -static int handle_ctl_fd(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->ctl_fd; -} - -static int handle_shared_fd(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->shared_fd; -} - -static int handle_num_buffers(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->num_buffers; -} - -static int handle_width(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->width; -} - -static int handle_height(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->height; -} - -static int handle_shared_size(const overlay_handle_t overlay) { - return static_cast<const struct handle_t *>(overlay)->shared_size; -} - -/* A separate instance of this class is created per overlay */ -class overlay_object : public overlay_t -{ - handle_t mHandle; - - overlay_ctrl_t mCtl; - overlay_ctrl_t mCtlStage; - overlay_shared_t *mShared; - - static overlay_handle_t getHandleRef(struct overlay_t* overlay) { - /* returns a reference to the handle, caller doesn't take ownership */ - return &(static_cast<overlay_object *>(overlay)->mHandle); - } - - public: - overlay_object(int ctl_fd, int shared_fd, int shared_size, int w, int h, - int format, int num_buffers) { - this->overlay_t::getHandleRef = getHandleRef; - mHandle.version = sizeof(native_handle); - mHandle.numFds = 2; - mHandle.numInts = 5; /* extra ints we have in our handle */ - mHandle.ctl_fd = ctl_fd; - mHandle.shared_fd = shared_fd; - mHandle.width = w; - mHandle.height = h; - mHandle.format = format; - mHandle.num_buffers = num_buffers; - mHandle.shared_size = shared_size; - this->w = w; - this->h = h; - this->format = format; - - memset( &mCtl, 0, sizeof( mCtl ) ); - memset( &mCtlStage, 0, sizeof( mCtlStage ) ); - } - - int ctl_fd() { return mHandle.ctl_fd; } - int shared_fd() { return mHandle.shared_fd; } - overlay_ctrl_t* data() { return &mCtl; } - overlay_ctrl_t* staging() { return &mCtlStage; } - overlay_shared_t* getShared() { return mShared; } - void setShared( overlay_shared_t *p ) { mShared = p; } -}; - -/***************************************************************************** - * Local Functions - *****************************************************************************/ - -static int create_shared_data(overlay_shared_t **shared) -{ - int fd; - /* assuming sizeof(overlay_shared_t) < a single page */ - int size = getpagesize(); - overlay_shared_t *p; - - if ((fd = ashmem_create_region("overlay_data", size)) < 0) { - LOGE("Failed to Create Overlay Shared Data!\n"); - return fd; - } - - p = (overlay_shared_t*)mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (p == MAP_FAILED) { - LOGE("Failed to Map Overlay Shared Data!\n"); - close(fd); - return -1; - } - - memset(p, 0, size); - p->marker = SHARED_DATA_MARKER; - p->size = size; - p->refCnt = 1; - if (pthread_mutexattr_init(&p->attr) != 0) { - LOGE("Failed to initialize overlay mutex attr"); - goto MutexAttrErr; - } - if (pthread_mutexattr_setpshared(&p->attr, PTHREAD_PROCESS_SHARED) != 0) { - LOGE("Failed to set the overlay mutex attr to be shared across-processes"); - goto MutexAttrSetErr; - } - if (pthread_mutex_init(&p->lock, &p->attr) != 0) { - LOGE("Failed to initialize overlay mutex\n"); - goto MutexErr; - } - - *shared = p; - return fd; - -MutexErr: -MutexAttrSetErr: - pthread_mutexattr_destroy(&p->attr); -MutexAttrErr: - munmap(p, size); - close(fd); - return -1; -} - -static void destroy_shared_data(int shared_fd, overlay_shared_t *shared, - bool closefd ) -{ - if (shared == NULL) - return; - - /* Last side deallocated releases the mutex, otherwise the remaining */ - /* side will deadlock trying to use an already released mutex */ - if (android_atomic_dec(&shared->refCnt) == 1) { - if (pthread_mutex_destroy(&shared->lock)) { - LOGE("Failed to uninitialize overlay mutex!\n"); - } - - if (pthread_mutexattr_destroy(&shared->attr)) { - LOGE("Failed to uninitialize the overlay mutex attr!\n"); - } - shared->marker = 0; - } - - if (munmap(shared, shared->size)) { - LOGE("Failed to Unmap Overlay Shared Data!\n"); - } - - if (closefd && close(shared_fd)) { - LOGE("Failed to Close Overlay Shared Data!\n"); - } -} - -static int open_shared_data( overlay_data_context_t *ctx ) -{ - int rc = -1; - int mode = PROT_READ | PROT_WRITE; - int fd = ctx->shared_fd; - int size = ctx->shared_size; - - if (ctx->shared != NULL) { - /* Already open, return success */ - LOGI("Overlay Shared Data Already Open\n"); - return 0; - } - ctx->shared = (overlay_shared_t*)mmap(0, size, mode, MAP_SHARED, fd, 0); - - if (ctx->shared == MAP_FAILED) { - LOGE("Failed to Map Overlay Shared Data!\n"); - } else if ( ctx->shared->marker != SHARED_DATA_MARKER ) { - LOGE("Invalid Overlay Shared Marker!\n"); - munmap( ctx->shared, size); - } else if ( (int)ctx->shared->size != size ) { - LOGE("Invalid Overlay Shared Size!\n"); - munmap(ctx->shared, size); - } else { - android_atomic_inc(&ctx->shared->refCnt); - rc = 0; - } - - return rc; -} - -static void close_shared_data(overlay_data_context_t *ctx) -{ - destroy_shared_data(ctx->shared_fd, ctx->shared, false); - ctx->shared = NULL; -} - -static int enable_streaming_locked(overlay_shared_t *shared, int ovly_fd) -{ - int rc = 0; - - if (!shared->controlReady || !shared->dataReady) { - LOGI("Postponing Stream Enable/%d/%d\n", shared->controlReady, - shared->dataReady); - } else { - shared->streamEn = 1; - rc = v4l2_overlay_stream_on(ovly_fd); - if (rc) { - LOGE("Stream Enable Failed!/%d\n", rc); - shared->streamEn = 0; - } - } - - return rc; -} - -static int enable_streaming(overlay_shared_t *shared, int ovly_fd) -{ - int ret; - - pthread_mutex_lock(&shared->lock); - ret = enable_streaming_locked(shared, ovly_fd); - pthread_mutex_unlock(&shared->lock); - return ret; -} - -static int disable_streaming_locked(overlay_shared_t *shared, int ovly_fd) -{ - int ret = 0; - - if (shared->streamEn) { - ret = v4l2_overlay_stream_off( ovly_fd ); - if (ret) { - LOGE("Stream Off Failed!/%d\n", ret); - } else { - shared->streamingReset = 1; - shared->streamEn = 0; - } - } - - return ret; -} - -static void set_color_space(unsigned int overlay_color_format, unsigned int *v4l2_color_format) -{ - switch (overlay_color_format) { - case OVERLAY_FORMAT_RGB_565: - *v4l2_color_format = V4L2_PIX_FMT_RGB565; - break; - - case OVERLAY_FORMAT_YCbYCr_422_I: - case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: - *v4l2_color_format = V4L2_PIX_FMT_YUYV; - break; - - case OVERLAY_FORMAT_CbYCrY_422_I: - case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: - *v4l2_color_format = V4L2_PIX_FMT_UYVY; - break; - - case HAL_PIXEL_FORMAT_YCbCr_420_P: - *v4l2_color_format = V4L2_PIX_FMT_YUV420; - break; - - case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: - *v4l2_color_format = V4L2_PIX_FMT_NV12T; - break; - - case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: - *v4l2_color_format = V4L2_PIX_FMT_NV21; - break; - - default : - LOGE("unsupported pixel format (0x%x)", overlay_color_format); - *v4l2_color_format = -1; - } -} - -/**************************************************************************** - * Control module - *****************************************************************************/ - -static int overlay_get(struct overlay_control_device_t *dev, int name) -{ - int result = -1; - - switch (name) { - /* 0 = no limit */ - case OVERLAY_MINIFICATION_LIMIT: result = 0; break; - /* 0 = no limit */ - case OVERLAY_MAGNIFICATION_LIMIT: result = 0; break; - /* 0 = infinite */ - case OVERLAY_SCALING_FRAC_BITS: result = 0; break; - /* 90 rotation steps (for instance) */ - case OVERLAY_ROTATION_STEP_DEG: result = 90; break; - /* 1-pixel alignment */ - case OVERLAY_HORIZONTAL_ALIGNMENT: result = 1; break; - /* 1-pixel alignment */ - case OVERLAY_VERTICAL_ALIGNMENT: result = 1; break; - /* 1-pixel alignment */ - case OVERLAY_WIDTH_ALIGNMENT: result = 1; break; - case OVERLAY_HEIGHT_ALIGNMENT: break; - } - - return result; -} - -static int get_fb_var_screeninfo( struct fb_var_screeninfo *info ) -{ - int fd = -1; - int i=0; - char name[64]; - int ret = 0; - - char const * const device_template[] = { - "/dev/graphics/fb%u", - "/dev/fb%u", - 0 }; - - while ((fd==-1) && device_template[i]) { - snprintf(name, 64, device_template[i], 0); - fd = open(name, O_RDWR, 0); - i++; - } - - if (fd < 0) - ret = -EINVAL; - - if (ioctl(fd, FBIOGET_VSCREENINFO, info) == -1) - ret = -EINVAL; - - if (fd > 0) - close(fd); - - return 0; -} -static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, - uint32_t w, uint32_t h, int32_t format) -{ - LOGD("overlay_createOverlay:IN w=%d h=%d format=%d\n", w, h, format); - LOG_FUNCTION_NAME; - - overlay_object *overlay; - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_shared_t *shared; - - int ret; - uint32_t num = NUM_OVERLAY_BUFFERS_REQUESTED; - int fd; - int shared_fd; - struct fb_var_screeninfo info; - bool zerocopy = false; - - phyAddr = 0; - - if (format == OVERLAY_FORMAT_DEFAULT) { - LOGV("format == OVERLAY_FORMAT_DEFAULT\n"); - LOGV("set to HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP\n"); - format = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP; - } - - if (ctx->overlay_video1) { - LOGE("Error - overlays already in use\n"); - return NULL; - } - - shared_fd = create_shared_data(&shared); - if (shared_fd < 0) { - LOGE("Failed to create shared data"); - return NULL; - } - - fd = v4l2_overlay_open(V4L2_OVERLAY_PLANE_VIDEO1); - if (fd < 0) { - LOGE("Failed to open overlay device : %s\n", strerror(errno)); - goto error; - } - - g_s5p_fimc.params.src.full_width = w; - g_s5p_fimc.params.src.full_height = h; - g_s5p_fimc.params.src.width = w; - g_s5p_fimc.params.src.height = h; - set_color_space(format, &g_s5p_fimc.params.src.color_space); - ret = check_fimc_src_constraints(&g_s5p_fimc); - if(ret != 0) { - if(ret < 0) { - LOGE("Not supported source image size"); - goto error1; - } else { - LOGD("src width, height are changed [w= %d, h= %d]->[w=%d, h= %d]" - , w, h, g_s5p_fimc.params.src.width - , g_s5p_fimc.params.src.height); - w = g_s5p_fimc.params.src.width; - h = g_s5p_fimc.params.src.height; - } - } - - if (v4l2_overlay_init(fd, w, h, format, phyAddr)) { - LOGE("Failed initializing overlays\n"); - goto error1; - } - - if (v4l2_overlay_set_crop(fd, 0, 0, w, h)) { - LOGE("Failed defaulting crop window\n"); - goto error1; - } - - if (v4l2_overlay_set_flip(fd, 0)) { - LOGE("Failed defaulting flip\n"); - goto error1; - } - - if (v4l2_overlay_set_rotation(fd, 0, 0)) { - LOGE("Failed defaulting rotation\n"); - goto error1; - } - - if (format >= HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP - && format < HAL_PIXEL_FORMAT_CUSTOM_MAX) - zerocopy = true; - - if (v4l2_overlay_req_buf(fd, &num, 0, (int)zerocopy)) { - LOGE("Failed requesting buffers\n"); - goto error1; - } - - v4l2_overlay_init_fimc(fd, &g_s5p_fimc); - - overlay = new overlay_object(fd, shared_fd, shared->size, - w, h, format, num); - if (overlay == NULL) { - LOGE("Failed to create overlay object\n"); - goto error1; - } - ctx->overlay_video1 = overlay; - - overlay->setShared(shared); - - shared->controlReady = 0; - shared->streamEn = 0; - shared->streamingReset = 0; - - /* get lcd size from kernel framebuffer */ - if(get_fb_var_screeninfo(&info) == 0) { - shared->dispW = info.xres; - shared->dispH = info.yres; - g_lcd_width = info.xres; - g_lcd_height = info.yres; - g_lcd_bpp = info.bits_per_pixel; - } else { - shared->dispW = g_lcd_width; /* Need to determine this properly */ - shared->dispH = g_lcd_height; /* Need to determine this properly */ - } - - LOGI("Opened video1/fd=%d/obj=%08lx/shm=%d/size=%d", fd, - (unsigned long)overlay, shared_fd, shared->size); - - return overlay; - -error1: - close(fd); -error: - destroy_shared_data(shared_fd, shared, true); - return NULL; -} - -static void overlay_destroyOverlay(struct overlay_control_device_t *dev, - overlay_t* overlay) -{ - LOGD("overlay_destroyOverlay:IN dev (%p) and overlay (%p)", dev, overlay); - LOG_FUNCTION_NAME; - - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object *obj = static_cast<overlay_object *>(overlay); - - int rc; - int fd = obj->ctl_fd(); - uint32_t num = 0; - - overlay_shared_t *shared = obj->getShared(); - - if (shared == NULL) { - LOGE("Overlay was already destroyed - nothing needs to be done\n"); - return; - } - - pthread_mutex_lock(&shared->lock); - - disable_streaming_locked(shared, fd); - - pthread_mutex_unlock(&shared->lock); - - destroy_shared_data(obj->shared_fd(), shared, true); - obj->setShared(NULL); - - if (v4l2_overlay_req_buf(fd, &num, 0, 0)) { - LOGE("Failed requesting buffers\n"); - } - - LOGI("Destroying overlay/fd=%d/obj=%08lx", fd, (unsigned long)overlay); - - if (close(fd)) { - LOGE( "Error closing overly fd/%d\n", errno); - } - - if (overlay) { - if (ctx->overlay_video1 == overlay) - ctx->overlay_video1 = NULL; - delete overlay; - overlay = NULL; - } - LOGD("overlay_destroyOverlay:OUT"); -} - -static int overlay_setPosition(struct overlay_control_device_t *dev, - overlay_t* overlay, int x, int y, uint32_t w, - uint32_t h) -{ - LOG_FUNCTION_NAME; - - overlay_object *obj = static_cast<overlay_object *>(overlay); - - overlay_ctrl_t *stage = obj->staging(); - overlay_shared_t *shared = obj->getShared(); - - int rc = 0; - int temp_x = x, temp_y = y, temp_w = w, temp_h = h; - - /* - * This logic here is to return an error if the rectangle is not fully - * within the display, unless we have not received a valid position yet, - * in which case we will do our best to adjust the rectangle to be within - * the display. - */ - - /* Require a minimum size */ - if (temp_w < 16) - temp_w = 16; - if (temp_h < 8) - temp_h = 8; - - if (!shared->controlReady) { - if ( temp_x < 0 ) temp_x = 0; - if ( temp_y < 0 ) temp_y = 0; - if ( temp_w > shared->dispW ) temp_w = shared->dispW; - if ( temp_h > shared->dispH ) temp_h = shared->dispH; - if ( (temp_x + temp_w) > shared->dispW ) temp_w = shared->dispW - temp_x; - if ( (temp_y + temp_h) > shared->dispH ) temp_h = shared->dispH - temp_y; - } else if (temp_x < 0 || temp_y < 0 || (temp_x + temp_w) > shared->dispW || - (temp_y + temp_h) > shared->dispH) { - /* Return an error */ - rc = -1; - } - - if (rc == 0) { - stage->posX = temp_x; - stage->posY = temp_y; - stage->posW = temp_w; - stage->posH = temp_h; - - stage->posX_org = x; - stage->posY_org = y; - stage->posW_org = w; - stage->posH_org = h; - } - - return rc; -} - -static int overlay_getPosition(struct overlay_control_device_t *dev, - overlay_t* overlay, int* x, int* y, uint32_t* w, - uint32_t* h) -{ - LOG_FUNCTION_NAME; - - overlay_object *obj = static_cast<overlay_object *>(overlay); - overlay_ctrl_t *stage = obj->staging(); - - *x = stage->posX_org; - *y = stage->posY_org; - *w = stage->posW_org; - *h = stage->posH_org; - - return 0; -} - -static int overlay_setParameter(struct overlay_control_device_t *dev, - overlay_t* overlay, int param, int value) -{ - LOG_FUNCTION_NAME; - - overlay_ctrl_t *stage = static_cast<overlay_object *>(overlay)->staging(); - int rc = 0; - - switch (param) { - case OVERLAY_DITHER: - break; - - case OVERLAY_TRANSFORM: - switch ( value ) - { - case 0: - stage->rotation = 0; - stage->flip = 0; - break; - case OVERLAY_TRANSFORM_ROT_90: - stage->rotation = 90; - stage->flip = 0; - break; - case OVERLAY_TRANSFORM_ROT_180: - stage->rotation = 180; - stage->flip = 0; - break; - case OVERLAY_TRANSFORM_ROT_270: - stage->rotation = 270; - stage->flip = 0; - break; - // FIMC VFLIP = android overlay FLIP_H. - case OVERLAY_TRANSFORM_FLIP_H: - stage->rotation = 0; - stage->flip = V4L2_CID_VFLIP; - break; - case OVERLAY_TRANSFORM_FLIP_V: - stage->rotation = 0; - stage->flip = V4L2_CID_HFLIP; - break; - // FIMC rotates first but android flips first. - case OVERLAY_TRANSFORM_ROT_90+OVERLAY_TRANSFORM_FLIP_H: - stage->rotation = 90; - stage->flip = V4L2_CID_HFLIP; - break; - case OVERLAY_TRANSFORM_ROT_90+OVERLAY_TRANSFORM_FLIP_V: - stage->rotation = 90; - stage->flip = V4L2_CID_VFLIP; - break; - - default: - rc = -EINVAL; - break; - } - break; - } - - return rc; -} - -static int overlay_stage(struct overlay_control_device_t *dev, - overlay_t* overlay) { - return 0; -} - -static int overlay_commit(struct overlay_control_device_t *dev, - overlay_t* overlay) { - LOG_FUNCTION_NAME; - - overlay_object *obj = static_cast<overlay_object *>(overlay); - - overlay_ctrl_t *data = obj->data(); - overlay_ctrl_t *stage = obj->staging(); - overlay_shared_t *shared = obj->getShared(); - - int ret = 0; - int fd = obj->ctl_fd(); - - if (shared == NULL) { - LOGI("Shared Data Not Init'd!\n"); - return -1; - } - - pthread_mutex_lock(&shared->lock); - - if (!shared->controlReady) { - shared->controlReady = 1; - } - - g_s5p_fimc.params.dst.full_width = g_lcd_width; - g_s5p_fimc.params.dst.full_height = g_lcd_height; - g_s5p_fimc.params.dst.width = stage->posW; - g_s5p_fimc.params.dst.height = stage->posH; - if (g_lcd_bpp == 32) - g_s5p_fimc.params.dst.color_space = V4L2_PIX_FMT_RGB32; - else - g_s5p_fimc.params.dst.color_space = V4L2_PIX_FMT_RGB565; - ret = check_fimc_dst_constraints(&g_s5p_fimc, stage->rotation); - if (ret != 0) { - if (ret < 0) { - LOGE("Unsupported destination image size"); - goto end; - } else { - LOGD("dst width, height have changed [w= %d, h= %d] -> [w=%d, h= %d]", - stage->posW, stage->posH, g_s5p_fimc.params.dst.width, - g_s5p_fimc.params.dst.height); - stage->posW = g_s5p_fimc.params.dst.width; - stage->posH = g_s5p_fimc.params.dst.height; - } - } - - if (data->posX == stage->posX && data->posY == stage->posY && - data->posW == stage->posW && data->posH == stage->posH && - data->rotation == stage->rotation && - data->flip == stage->flip) { - LOGI("Nothing to do!\n"); - goto end; - } - - LOGV("Position/X%d/Y%d/W%d/H%d\n", data->posX, data->posY, data->posW, - data->posH); - LOGV("Adjusted Position/X%d/Y%d/W%d/H%d\n", stage->posX, stage->posY, - stage->posW, stage->posH); - LOGV("Rotation/%d\n", stage->rotation ); - - if ((ret = disable_streaming_locked(shared, fd))) - goto end; - - if (stage->flip != data->flip) { - ret = v4l2_overlay_set_flip(fd, stage->flip); - if (ret) { - LOGE("Set Flip Failed!/%d\n", ret); - goto end; - } - } - - if (stage->rotation != data->rotation) { - ret = v4l2_overlay_set_rotation(fd, stage->rotation, 0); - if (ret) { - LOGE("Set Rotation Failed!/%d\n", ret); - goto end; - } - v4l2_overlay_s_fbuf(fd, stage->rotation); - } - - ret = v4l2_overlay_set_position(fd, stage->posX, stage->posY, - stage->posW, stage->posH, stage->rotation); - if (ret) { - LOGE("Set Position Failed!/%d\n", ret); - goto end; - } - - data->posX = stage->posX; - data->posY = stage->posY; - data->posW = stage->posW; - data->posH = stage->posH; - data->rotation = stage->rotation; - data->flip = stage->flip; - - ret = enable_streaming_locked(shared, fd); - -end: - pthread_mutex_unlock(&shared->lock); - - return ret; -} - -static int overlay_control_close(struct hw_device_t *dev) -{ - LOG_FUNCTION_NAME; - - struct overlay_control_context_t* ctx = - (struct overlay_control_context_t*)dev; - overlay_object *overlay_v1; - - if (ctx) { - overlay_v1 = static_cast<overlay_object *>(ctx->overlay_video1); - - overlay_destroyOverlay((struct overlay_control_device_t *)ctx, - overlay_v1); - - free(ctx); - } - return 0; -} - -static int get_pixel_format_type(unsigned int pixelformat) -{ - switch(pixelformat) { - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_RGB565: - return PFT_RGB; - - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV12T: - case V4L2_PIX_FMT_NV21: - case V4L2_PIX_FMT_YUV420: - return PFT_YUV420; - - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_YVYU: - case V4L2_PIX_FMT_VYUY: - case V4L2_PIX_FMT_NV16: - case V4L2_PIX_FMT_NV61: - case V4L2_PIX_FMT_YUV422P: - return PFT_YUV422; - - default: - return PFT_YUV444; - } -} - -/* check the constraints of destination image size */ -static int check_fimc_dst_constraints(s5p_fimc_t *s5p_fimc, - unsigned int rotation) -{ - int tmp = 0; - - if((s5p_fimc->params.dst.height > 0) && (s5p_fimc->params.dst.height < 16)) - s5p_fimc->params.dst.height = 16; - - if(s5p_fimc->params.dst.width%8 != 0) { - tmp = s5p_fimc->params.dst.width - (s5p_fimc->params.dst.width%8); - if(tmp <= 0) - return -1; - else - s5p_fimc->params.dst.width = tmp; - } - - return 1; -} -/* check the constraints of source image size */ -static int check_fimc_src_constraints(s5p_fimc_t *s5p_fimc) -{ - int format_type = 0; - - if(s5p_fimc->params.src.full_width < 16 || - s5p_fimc->params.src.full_height < 8 ) - return -1; - - if(s5p_fimc->hw_ver == 0x50) { - format_type = get_pixel_format_type(s5p_fimc->params.src.color_space); - switch (format_type) { - case PFT_YUV420: - if (s5p_fimc->params.src.height%2 != 0) - s5p_fimc->params.src.height = s5p_fimc->params.src.height - - (s5p_fimc->params.src.height)%2; - - if (s5p_fimc->params.src.width%2 != 0) - s5p_fimc->params.src.width = s5p_fimc->params.src.width - - (s5p_fimc->params.src.width)%2; - break; - - case PFT_YUV422: - if (s5p_fimc->params.src.width%2 != 0) - s5p_fimc->params.src.width = s5p_fimc->params.src.width - - (s5p_fimc->params.src.width)%2; - } - } else { - if (s5p_fimc->params.src.height < 8) { - s5p_fimc->params.src.height = 8; - } - - if (s5p_fimc->params.src.width%16 != 0) { - s5p_fimc->params.src.width = s5p_fimc->params.src.width - - (s5p_fimc->params.src.width)%16; - } - } - - return 1; -} - -/**************************************************************************** - * Data module - *****************************************************************************/ - -int overlay_initialize(struct overlay_data_device_t *dev, - overlay_handle_t handle) -{ - LOG_FUNCTION_NAME; - - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - struct stat stat; - - int i; - int rc = -1; - - ctx->num_buffers = handle_num_buffers(handle); - ctx->width = handle_width(handle); - ctx->height = handle_height(handle); - ctx->format = handle_format(handle); - ctx->ctl_fd = handle_ctl_fd(handle); - ctx->shared_fd = handle_shared_fd(handle); - ctx->shared_size = handle_shared_size(handle); - ctx->shared = NULL; - ctx->qd_buf_count = 0; - ctx->cacheable_buffers = 0; - - if (ctx->format >= HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP - && ctx->format < HAL_PIXEL_FORMAT_CUSTOM_MAX) - ctx->zerocopy = true; - else - ctx->zerocopy = false; - - if (fstat(ctx->ctl_fd, &stat)) { - LOGE("Error = %s from %s\n", strerror(errno), "overlay initialize"); - return -1; - } - - if (open_shared_data(ctx)) { - return -1; - } - - ctx->shared->dataReady = 0; - - ctx->mapping_data = new struct mapping_data; - ctx->buffers = new void* [ctx->num_buffers]; - ctx->buffers_len = new size_t[ctx->num_buffers]; - - if (!ctx->buffers || !ctx->buffers_len || !ctx->mapping_data) { - LOGE("Failed alloc'ing buffer arrays\n"); - goto error; - } else { - - /* - * in the zero copy case, - * don't need to mmap buffer for source - */ - if (ctx->zerocopy) - rc = 0; - else { - for (i = 0; i < ctx->num_buffers; i++) { - rc = v4l2_overlay_map_buf(ctx->ctl_fd, i, &ctx->buffers[i], - &ctx->buffers_len[i]); - if (rc) { - LOGE("Failed mapping buffers\n"); - goto error; - } - } - } - } - - v4l2_overlay_init_fimc(ctx->ctl_fd, &g_s5p_fimc); - - return ( rc ); - -error: - - if(ctx->mapping_data) - delete (ctx->mapping_data); - if(ctx->buffers) - delete [] ctx->buffers; - if(ctx->buffers_len) - delete [] ctx->buffers_len; - - close_shared_data( ctx ); - - return -1; -} - -static int overlay_resizeInput(struct overlay_data_device_t *dev, uint32_t w, - uint32_t h) -{ - int rc = -1; - int ret = 0; - - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - if ((ctx->width == (int)w) && (ctx->width == (int)h)) { - LOGV("same as current width and height. so do nothing"); - return 0; - } - - if (!ctx->shared) { - LOGI("Shared Data Not Init'd!\n"); - return -1; - } - - if (ctx->shared->dataReady) { - LOGV("Either setCrop() or queueBuffer() was called prior to this!" - "Therefore failing this call.\n"); - return -1; - } - - pthread_mutex_lock(&ctx->shared->lock); - - if ((rc = disable_streaming_locked(ctx->shared, ctx->ctl_fd))) - goto end; - - if (!ctx->zerocopy) { - for (int i = 0; i < ctx->num_buffers; i++) { - v4l2_overlay_unmap_buf(ctx->buffers[i], ctx->buffers_len[i]); - } - } - - g_s5p_fimc.params.src.full_width = w; - g_s5p_fimc.params.src.full_height = h; - g_s5p_fimc.params.src.width = w; - g_s5p_fimc.params.src.height = h; - set_color_space(ctx->format, &g_s5p_fimc.params.src.color_space); - ret = check_fimc_src_constraints(&g_s5p_fimc); - - if(ret != 0) { - if(ret < 0) { - LOGE("Not supported source image size"); - goto end; - } else { - LOGD("src width, height are changed [w= %d, h= %d] -> [w=%d, h= %d]" - , w, h, g_s5p_fimc.params.src.width - , g_s5p_fimc.params.src.height); - w = g_s5p_fimc.params.src.width; - h = g_s5p_fimc.params.src.height; - } - } - - rc = v4l2_overlay_init(ctx->ctl_fd, w, h, ctx->format, phyAddr); - if (rc) { - LOGE("Error initializing overlay"); - goto end; - } - rc = v4l2_overlay_set_crop(ctx->ctl_fd, 0, 0, w, h); - if (rc) { - LOGE("Error setting crop window\n"); - goto end; - } - rc = v4l2_overlay_req_buf(ctx->ctl_fd, (uint32_t *)(&ctx->num_buffers), - ctx->cacheable_buffers, (int)ctx->zerocopy); - if (rc) { - LOGE("Error creating buffers"); - goto end; - } - - if (!ctx->zerocopy) { - for (int i = 0; i < ctx->num_buffers; i++) - v4l2_overlay_map_buf(ctx->ctl_fd, i, &ctx->buffers[i], - &ctx->buffers_len[i]); - } - - rc = enable_streaming_locked(ctx->shared, ctx->ctl_fd); - -end: - pthread_mutex_unlock(&ctx->shared->lock); - - return rc; -} - - -static int overlay_data_setParameter(struct overlay_data_device_t *dev, - int param, int value) -{ - int ret = 0; - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - if (ctx->shared == NULL) { - LOGI("Shared Data Not Init'd!\n"); - return -1; - } - - if (ctx->shared->dataReady) { - LOGI("Too late. Cant set it now!\n"); - return -1; - } - - if (param == CACHEABLE_BUFFERS) - ctx->cacheable_buffers = value; - - return ( ret ); -} - - -static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, - uint32_t y, uint32_t w, uint32_t h) { - LOG_FUNCTION_NAME; - - int rc = 0; - int cnt = 0; - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - if (ctx->shared == NULL) { - LOGI("Shared Data Not Init'd!\n"); - return -1; - } - - pthread_mutex_lock(&ctx->shared->lock); - - ctx->shared->dataReady = 1; - - if (ctx->data.cropX == x && ctx->data.cropY == y && ctx->data.cropW == w - && ctx->data.cropH == h) { - goto end; - } - - ctx->data.cropX = x; - ctx->data.cropY = y; - ctx->data.cropW = w; - ctx->data.cropH = h; - - LOGV("Crop Win/X%d/Y%d/W%d/H%d\n", x, y, w, h ); - - if ((rc = disable_streaming_locked(ctx->shared, ctx->ctl_fd))) - goto end; - - rc = v4l2_overlay_set_crop(ctx->ctl_fd, x, y, w, h); - if (rc) { - LOGE("Set Crop Window Failed!/%d\n", rc); - } - - rc = enable_streaming_locked(ctx->shared, ctx->ctl_fd); - -end: - pthread_mutex_unlock(&ctx->shared->lock); - return rc; -} - -static int overlay_getCrop(struct overlay_data_device_t *dev , uint32_t* x, - uint32_t* y, uint32_t* w, uint32_t* h) { - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - return v4l2_overlay_get_crop(ctx->ctl_fd, x, y, w, h); -} - -int overlay_dequeueBuffer(struct overlay_data_device_t *dev, - overlay_buffer_t *buffer) { - /* blocks until a buffer is available and return an opaque structure - * representing this buffer. - */ - - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - int rc=0; - int i = -1; - uint32_t num = 0; - int cnt = 0; - - pthread_mutex_lock(&ctx->shared->lock); - if ( ctx->shared->streamingReset ) { - ctx->shared->streamingReset = 0; - pthread_mutex_unlock(&ctx->shared->lock); - return ALL_BUFFERS_FLUSHED; - } - pthread_mutex_unlock(&ctx->shared->lock); - - /* If we are not streaming dequeue will fail, - skip to prevent error printouts */ - if (ctx->shared->streamEn && ctx->qd_buf_count) { - if ((rc = v4l2_overlay_dq_buf( ctx->ctl_fd, &i ,ctx->zerocopy)) != 0) { - LOGE("Failed to DQ/%d\n", rc); - } - else if (i < 0 || i > ctx->num_buffers) { - rc = -EINVAL; - } else { - *((int *)buffer) = i; - ctx->qd_buf_count --; - } - } else { - rc = -1; - } - - return rc; -} - -int overlay_queueBuffer(struct overlay_data_device_t *dev, - overlay_buffer_t buffer) { - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - int cnt = 0; - - pthread_mutex_lock(&ctx->shared->lock); - if ( ctx->shared->streamingReset ) { - ctx->shared->streamingReset = 0; - pthread_mutex_unlock(&ctx->shared->lock); - return ALL_BUFFERS_FLUSHED; - } - pthread_mutex_unlock(&ctx->shared->lock); - - /* Catch the case where the data side had no need to set the crop window */ - if (!ctx->shared->dataReady) { - ctx->shared->dataReady = 1; - enable_streaming(ctx->shared, ctx->ctl_fd); - } - - if (!ctx->shared->controlReady) return -1; - int rc = v4l2_overlay_q_buf( ctx->ctl_fd, (int)buffer, (int) ctx->zerocopy ); - if (rc == 0 && ctx->qd_buf_count < ctx->num_buffers) { - ctx->qd_buf_count ++; - } - - return rc; -} - -void *overlay_getBufferAddress(struct overlay_data_device_t *dev, - overlay_buffer_t buffer) -{ - LOG_FUNCTION_NAME; - - /* this may fail (NULL) if this feature is not supported. In that case, - * presumably, there is some other HAL module that can fill the buffer, - * using a DSP for instance - */ - int ret; - struct v4l2_buffer buf; - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - if (ctx->zerocopy) - return NULL; - - if ((int)buffer >= 0 && (int)buffer < ctx->num_buffers) - return (void*) ctx->buffers[(int)buffer]; - else - return NULL; -} - -int overlay_getBufferCount(struct overlay_data_device_t *dev) -{ - LOG_FUNCTION_NAME; - - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - - return (ctx->num_buffers); -} - -static int overlay_data_close(struct hw_device_t *dev) { - - LOG_FUNCTION_NAME; - - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - int rc; - - if (ctx) { - overlay_data_device_t *overlay_dev = &ctx->device; - int buf; - int i; - - pthread_mutex_lock(&ctx->shared->lock); - - if (!ctx->zerocopy) - for (i = 0; i < ctx->num_buffers; i++) { - LOGV("Unmap Buffer/%d/%08lx/%d", i, (unsigned long)ctx->buffers[i], - ctx->buffers_len[i] ); - rc = v4l2_overlay_unmap_buf(ctx->buffers[i], ctx->buffers_len[i]); - if (rc != 0) { - LOGE("Error unmapping the buffer/%d/%d", i, rc); - } - } - - delete (ctx->mapping_data); - delete [] ctx->buffers; - delete [] ctx->buffers_len; - - pthread_mutex_unlock(&ctx->shared->lock); - - ctx->shared->dataReady = 0; - close_shared_data( ctx ); - - free(ctx); - } - - return 0; -} - -/*****************************************************************************/ - -static int overlay_device_open(const struct hw_module_t* module, - const char* name, struct hw_device_t** device) -{ - LOG_FUNCTION_NAME; - int status = -EINVAL; - - if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { - struct overlay_control_context_t *dev; - dev = (overlay_control_context_t*)malloc(sizeof(*dev)); - - /* initialize our state here */ - memset(dev, 0, sizeof(*dev)); - - /* initialize the procs */ - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = const_cast<hw_module_t*>(module); - dev->device.common.close = overlay_control_close; - - dev->device.get = overlay_get; - dev->device.createOverlay = overlay_createOverlay; - dev->device.destroyOverlay = overlay_destroyOverlay; - dev->device.setPosition = overlay_setPosition; - dev->device.getPosition = overlay_getPosition; - dev->device.setParameter = overlay_setParameter; - dev->device.stage = overlay_stage; - dev->device.commit = overlay_commit; - - *device = &dev->device.common; - status = 0; - } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) { - struct overlay_data_context_t *dev; - dev = (overlay_data_context_t*)malloc(sizeof(*dev)); - - /* initialize our state here */ - memset(dev, 0, sizeof(*dev)); - - /* initialize the procs */ - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = const_cast<hw_module_t*>(module); - dev->device.common.close = overlay_data_close; - - dev->device.initialize = overlay_initialize; - dev->device.resizeInput = overlay_resizeInput; - dev->device.setCrop = overlay_setCrop; - dev->device.getCrop = overlay_getCrop; - dev->device.setParameter = overlay_data_setParameter; - dev->device.dequeueBuffer = overlay_dequeueBuffer; - dev->device.queueBuffer = overlay_queueBuffer; - dev->device.getBufferAddress = overlay_getBufferAddress; - dev->device.getBufferCount = overlay_getBufferCount; - - *device = &dev->device.common; - status = 0; - } - return status; -} |