diff options
Diffstat (limited to 'minui21/graphics_overlay.c')
-rw-r--r-- | minui21/graphics_overlay.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/minui21/graphics_overlay.c b/minui21/graphics_overlay.c new file mode 100644 index 000000000..c42e9c18a --- /dev/null +++ b/minui21/graphics_overlay.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2013, 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 <stdbool.h> +#include <stdlib.h> +#include <unistd.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/types.h> + +#include <linux/fb.h> +#include <linux/kd.h> + +#ifdef MSM_BSP +#include <linux/msm_mdp.h> +#include <linux/msm_ion.h> +#endif + +#include <pixelflinger/pixelflinger.h> + +#include "minui.h" + +#define MDP_V4_0 400 + +#ifdef MSM_BSP +#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) + +typedef struct { + unsigned char *mem_buf; + int size; + int ion_fd; + int mem_fd; + struct ion_handle_data handle_data; +} memInfo; + +static int overlay_id = MSMFB_NEW_REQUEST; +static memInfo mem_info; + +static int map_mdp_pixel_format() +{ + int format = MDP_RGB_565; +#if defined(RECOVERY_BGRA) + format = MDP_BGRA_8888; +#elif defined(RECOVERY_RGBA) + format = MDP_RGBA_8888; +#elif defined(RECOVERY_RGBX) + format = MDP_RGBA_8888; +#endif + return format; +} + +static bool overlay_supported = false; + +bool target_has_overlay(char *version) +{ + int ret; + int mdp_version; + + if (strlen(version) >= 8) { + if(!strncmp(version, "msmfb", strlen("msmfb"))) { + char str_ver[4]; + memcpy(str_ver, version + strlen("msmfb"), 3); + str_ver[3] = '\0'; + mdp_version = atoi(str_ver); + if (mdp_version >= MDP_V4_0) { + overlay_supported = true; + } + } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) { + overlay_supported = true; + } + } + + return overlay_supported; +} + +int free_ion_mem(void) { + if (!overlay_supported) + return -EINVAL; + + int ret = 0; + + if (mem_info.mem_buf) + munmap(mem_info.mem_buf, mem_info.size); + + if (mem_info.ion_fd >= 0) { + ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data); + if (ret < 0) + perror("free_mem failed "); + } + + if (mem_info.mem_fd >= 0) + close(mem_info.mem_fd); + if (mem_info.ion_fd >= 0) + close(mem_info.ion_fd); + + memset(&mem_info, 0, sizeof(mem_info)); + mem_info.mem_fd = -1; + mem_info.ion_fd = -1; + return 0; +} + +int alloc_ion_mem(unsigned int size) +{ + if (!overlay_supported) + return -EINVAL; + int result; + struct ion_fd_data fd_data; + struct ion_allocation_data ionAllocData; + + mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC); + if (mem_info.ion_fd < 0) { + perror("ERROR: Can't open ion "); + return -errno; + } + + ionAllocData.flags = 0; + ionAllocData.len = size; + ionAllocData.align = sysconf(_SC_PAGESIZE); +#ifdef NEW_ION_HEAP + ionAllocData.heap_id_mask = +#else + ionAllocData.heap_mask = +#endif + ION_HEAP(ION_IOMMU_HEAP_ID) | + ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID); + + result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC, &ionAllocData); + if(result){ + perror("ION_IOC_ALLOC Failed "); + close(mem_info.ion_fd); + return result; + } + + fd_data.handle = ionAllocData.handle; + mem_info.handle_data.handle = ionAllocData.handle; + result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data); + if (result) { + perror("ION_IOC_MAP Failed "); + free_ion_mem(); + return result; + } + mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ | + PROT_WRITE, MAP_SHARED, fd_data.fd, 0); + mem_info.mem_fd = fd_data.fd; + + if (!mem_info.mem_buf) { + perror("ERROR: mem_buf MAP_FAILED "); + free_ion_mem(); + return -ENOMEM; + } + + return 0; +} + +int allocate_overlay(int fd, GGLSurface gr_fb[]) +{ + if (!overlay_supported) + return -EINVAL; + + struct mdp_overlay overlay; + int ret = 0; + + memset(&overlay, 0 , sizeof (struct mdp_overlay)); + + /* Fill Overlay Data */ + + overlay.src.width = ALIGN(gr_fb[0].width, 32); + overlay.src.height = gr_fb[0].height; + overlay.src.format = map_mdp_pixel_format(); + overlay.src_rect.w = gr_fb[0].width; + overlay.src_rect.h = gr_fb[0].height; + overlay.dst_rect.w = gr_fb[0].width; + overlay.dst_rect.h = gr_fb[0].height; + overlay.alpha = 0xFF; + overlay.transp_mask = MDP_TRANSP_NOP; + overlay.id = MSMFB_NEW_REQUEST; + ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlay); + if (ret < 0) { + perror("Overlay Set Failed"); + return ret; + } + + overlay_id = overlay.id; + return 0; +} + +int free_overlay(int fd) +{ + if (!overlay_supported) + return -EINVAL; + + int ret = 0; + struct mdp_display_commit ext_commit; + + if (overlay_id != MSMFB_NEW_REQUEST) { + ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlay_id); + if (ret) { + perror("Overlay Unset Failed"); + overlay_id = MSMFB_NEW_REQUEST; + return ret; + } + + memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); + ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; + ext_commit.wait_for_finish = 1; + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit); + if (ret < 0) { + perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!"); + overlay_id = MSMFB_NEW_REQUEST; + return ret; + } + + overlay_id = MSMFB_NEW_REQUEST; + } + return 0; +} + +int overlay_display_frame(int fd, GGLubyte* data, size_t size) +{ + if (!overlay_supported) + return -EINVAL; + int ret = 0; + struct msmfb_overlay_data ovdata; + struct mdp_display_commit ext_commit; + + if (overlay_id == MSMFB_NEW_REQUEST) { + perror("display_frame failed, no overlay\n"); + return 0; + } + + memcpy(mem_info.mem_buf, data, size); + + memset(&ovdata, 0, sizeof(struct msmfb_overlay_data)); + + ovdata.id = overlay_id; + ovdata.data.flags = 0; + ovdata.data.offset = 0; + ovdata.data.memory_id = mem_info.mem_fd; + ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdata); + if (ret < 0) { + perror("overlay_display_frame failed, overlay play Failed\n"); + return 0; + } + + memset(&ext_commit, 0, sizeof(struct mdp_display_commit)); + ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY; + ext_commit.wait_for_finish = 1; + ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit); + if (ret < 0) { + perror("overlay_display_frame failed, overlay commit Failed\n!"); + return 0; + } + + return 0; +} + +#else + +bool target_has_overlay(char *version) { + return false; +} + +int free_ion_mem(void) { + return -EINVAL; +} + +int alloc_ion_mem(unsigned int size) +{ + return -EINVAL; +} + +int allocate_overlay(int fd, GGLSurface gr_fb[]) +{ + return -EINVAL; +} + +int free_overlay(int fd) +{ + return -EINVAL; +} + +int overlay_display_frame(int fd, GGLubyte* data, size_t size) +{ + return -EINVAL; +} + +#endif //#ifdef MSM_BSP |