diff --git a/lib/framebuffer_qcom_overlay.c b/lib/framebuffer_qcom_overlay.c index 98148991..b735cd11 100644 --- a/lib/framebuffer_qcom_overlay.c +++ b/lib/framebuffer_qcom_overlay.c @@ -29,6 +29,7 @@ #include #include "framebuffer.h" +#include "framebuffer_qcom_overlay.h" #include "log.h" #include "util.h" @@ -38,37 +39,6 @@ #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) #define MAX_DISPLAY_DIM 2048 -#define NUM_BUFFERS 3 - -struct fb_qcom_overlay_mem_info { - uint8_t *mem_buf; - int size; - int ion_fd; - int mem_fd; - int offset; - struct ion_handle_data handle_data; -}; - -struct fb_qcom_vsync { - int fb_fd; - int enabled; - volatile int _run_thread; - pthread_t thread; - pthread_mutex_t mutex; - pthread_cond_t cond; - struct timespec time; -}; - -struct fb_qcom_overlay_data { - struct fb_qcom_overlay_mem_info mem_info[NUM_BUFFERS]; - struct fb_qcom_vsync *vsync; - int active_mem; - int overlayL_id; - int overlayR_id; - int leftSplit; - int rightSplit; - int width; -}; #define VSYNC_PREFIX "VSYNC=" @@ -257,6 +227,29 @@ static int isDisplaySplit(struct fb_qcom_overlay_data *data) return 0; } +static void has_roi_merge(struct fb_qcom_overlay_data *data) +{ + char temp[128]; + FILE* fp; + int found = 0; + + fp = fopen("/sys/class/graphics/fb0/msm_fb_panel_info", "re"); + if(fp) + { + found |= FILE_FOUND; + while(fgets(temp, sizeof(temp), fp) != NULL) + { + if((strstr(temp, "roi_merge")) != NULL) + found |= ROI_MERGE; + if((strstr(temp, "pu_en")) != NULL) + found |= PARTIAL_UPDATE; + } + fclose(fp); + } + + data->roi_merge = found; +} + static int free_ion_mem(struct fb_qcom_overlay_data *data) { int ret = 0, i; @@ -461,7 +454,6 @@ static int allocate_overlay(struct fb_qcom_overlay_data *data, int fd, int width static int free_overlay(struct fb_qcom_overlay_data *data, int fd) { int ret = 0; - struct mdp_display_commit ext_commit; if(!isDisplaySplit(data)) { @@ -501,13 +493,42 @@ static int free_overlay(struct fb_qcom_overlay_data *data, int fd) } } - memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); - ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; - - data->overlayL_id = MSMFB_NEW_REQUEST; - data->overlayR_id = MSMFB_NEW_REQUEST; + if(data->roi_merge > 1) + { + struct mdp_display_commit_lr ext_commit_lr; + + memset(&ext_commit_lr, 0, sizeof(struct mdp_display_commit_lr)); + ext_commit_lr.flags = MDP_DISPLAY_COMMIT_OVERLAY; + + data->overlayL_id = MSMFB_NEW_REQUEST; + data->overlayR_id = MSMFB_NEW_REQUEST; + + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT_LR, &ext_commit_lr); + } + else if(data->roi_merge == 1) + { + struct mdp_display_commit_s ext_commit_s; + + memset(&ext_commit_s, 0, sizeof(struct mdp_display_commit_s)); + ext_commit_s.flags = MDP_DISPLAY_COMMIT_OVERLAY; + + data->overlayL_id = MSMFB_NEW_REQUEST; + data->overlayR_id = MSMFB_NEW_REQUEST; + + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT_S, &ext_commit_s); + } + else + { + struct mdp_display_commit_n ext_commit_n; + memset(&ext_commit_n, 0, sizeof(struct mdp_display_commit_n)); + ext_commit_n.flags = MDP_DISPLAY_COMMIT_OVERLAY; + + data->overlayL_id = MSMFB_NEW_REQUEST; + data->overlayR_id = MSMFB_NEW_REQUEST; + + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT_N, &ext_commit_n); + } - ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit); if(ret < 0) { ERROR("Clear MSMFB_DISPLAY_COMMIT failed!"); @@ -526,6 +547,7 @@ static int impl_open(struct framebuffer *fb) data->leftSplit = data->width / 2; setDisplaySplit(data); + has_roi_merge(data); #ifdef TW_SCREEN_BLANK_ON_BOOT ioctl(fb->fd, FBIOBLANK, FB_BLANK_POWERDOWN); @@ -565,7 +587,6 @@ static int impl_update(struct framebuffer *fb) { int ret = 0; struct msmfb_overlay_data ovdataL, ovdataR; - struct mdp_display_commit ext_commit; struct fb_qcom_overlay_data *data = fb->impl_data; struct fb_qcom_overlay_mem_info *info = &data->mem_info[data->active_mem]; @@ -631,18 +652,43 @@ static int impl_update(struct framebuffer *fb) } } - memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); - ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; + if(data->roi_merge > 1) + { + struct mdp_display_commit_lr ext_commit_lr; + memset(&ext_commit_lr, 0, sizeof(struct mdp_display_commit_lr)); + ext_commit_lr.flags = MDP_DISPLAY_COMMIT_OVERLAY; + + fb_qcom_vsync_wait(data->vsync); + + ret = ioctl(fb->fd, MSMFB_DISPLAY_COMMIT_LR, &ext_commit_lr); + } + else if(data->roi_merge == 1) + { + struct mdp_display_commit_s ext_commit_s; + memset(&ext_commit_s, 0, sizeof(struct mdp_display_commit_s)); + ext_commit_s.flags = MDP_DISPLAY_COMMIT_OVERLAY; + + fb_qcom_vsync_wait(data->vsync); + + ret = ioctl(fb->fd, MSMFB_DISPLAY_COMMIT_S, &ext_commit_s); + } + else + { + struct mdp_display_commit_n ext_commit_n; + memset(&ext_commit_n, 0, sizeof(struct mdp_display_commit_n)); + ext_commit_n.flags = MDP_DISPLAY_COMMIT_OVERLAY; - fb_qcom_vsync_wait(data->vsync); + fb_qcom_vsync_wait(data->vsync); - ret = ioctl(fb->fd, MSMFB_DISPLAY_COMMIT, &ext_commit); + ret = ioctl(fb->fd, MSMFB_DISPLAY_COMMIT_N, &ext_commit_n); + } + if(ret < 0) { ERROR("overlay_display_frame failed, overlay commit Failed\n!"); return -1; } - + if(++data->active_mem >= NUM_BUFFERS) data->active_mem = 0; diff --git a/lib/framebuffer_qcom_overlay.h b/lib/framebuffer_qcom_overlay.h new file mode 100644 index 00000000..657e5ba1 --- /dev/null +++ b/lib/framebuffer_qcom_overlay.h @@ -0,0 +1,96 @@ +/* + * This file is part of MultiROM. + * + * MultiROM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MultiROM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MultiROM. If not, see . + */ + +#ifndef H_FRAMEBUFFER_QCOM_OVERLAY +#define H_FRAMEBUFFER_QCOM_OVERLAY + +#include + +#include "framebuffer.h" + +#ifdef MR_QCOM_OVERLAY_HEADER +#include MR_QCOM_OVERLAY_HEADER +#endif + +#define NUM_BUFFERS 3 + +#define MSMFB_DISPLAY_COMMIT_N _IOW(MSMFB_IOCTL_MAGIC, 164, \ + struct mdp_display_commit_n) +#define MSMFB_DISPLAY_COMMIT_S _IOW(MSMFB_IOCTL_MAGIC, 164, \ + struct mdp_display_commit_s) +#define MSMFB_DISPLAY_COMMIT_LR _IOW(MSMFB_IOCTL_MAGIC, 164, \ + struct mdp_display_commit_lr) + +enum { + FILE_FOUND = 0x01, + ROI_MERGE = 0x02, + PARTIAL_UPDATE = 0x04 +}; + +struct fb_qcom_overlay_mem_info { + uint8_t *mem_buf; + int size; + int ion_fd; + int mem_fd; + int offset; + struct ion_handle_data handle_data; +}; + +struct fb_qcom_vsync { + int fb_fd; + int enabled; + volatile int _run_thread; + pthread_t thread; + pthread_mutex_t mutex; + pthread_cond_t cond; + struct timespec time; +}; + +struct fb_qcom_overlay_data { + struct fb_qcom_overlay_mem_info mem_info[NUM_BUFFERS]; + struct fb_qcom_vsync *vsync; + int active_mem; + int overlayL_id; + int overlayR_id; + int leftSplit; + int rightSplit; + int width; + int roi_merge; +}; + +struct mdp_display_commit_n { + uint32_t flags; + uint32_t wait_for_finish; + struct fb_var_screeninfo var; +}; + +struct mdp_display_commit_s { + uint32_t flags; + uint32_t wait_for_finish; + struct fb_var_screeninfo var; + struct mdp_rect roi; +}; + +struct mdp_display_commit_lr { + uint32_t flags; + uint32_t wait_for_finish; + struct fb_var_screeninfo var; + struct mdp_rect l_roi; + struct mdp_rect r_roi; +}; + +#endif