From 06aa2ebcfd214922be319e7110c03131ef6a35e7 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Sun, 10 Nov 2013 17:28:04 +0100 Subject: [PATCH] video_omap: complete rework and refactoring of the driver --- Makefile | 2 +- gfx/fbdev.c | 319 -------------- gfx/fbdev.h | 24 -- gfx/omap_gfx.c | 1105 +++++++++++++++++++++++------------------------- gfx/omapfb.h | 427 ------------------- 5 files changed, 539 insertions(+), 1338 deletions(-) delete mode 100644 gfx/fbdev.c delete mode 100644 gfx/fbdev.h delete mode 100644 gfx/omapfb.h diff --git a/Makefile b/Makefile index 9fbcabe787..a3ac596bc2 100644 --- a/Makefile +++ b/Makefile @@ -195,7 +195,7 @@ ifeq ($(HAVE_SDL), 1) endif ifeq ($(HAVE_OMAP), 1) - OBJ += gfx/omap_gfx.o gfx/fbdev.o + OBJ += gfx/omap_gfx.o endif ifeq ($(HAVE_OPENGL), 1) diff --git a/gfx/fbdev.c b/gfx/fbdev.c deleted file mode 100644 index 57f56b1197..0000000000 --- a/gfx/fbdev.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * (C) GraÅžvydas "notaz" Ignotas, 2009-2010 - * - * This work is licensed under the terms of any of these licenses - * (at your option): - * - GNU GPL, version 2 or later. - * - GNU LGPL, version 2.1 or later. - * See the COPYING file in the top-level directory. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fbdev.h" - -#define PFX "fbdev: " - -struct vout_fbdev { - int fd; - void *mem; - size_t mem_size; - struct fb_var_screeninfo fbvar_old; - struct fb_var_screeninfo fbvar_new; - int buffer_write; - int fb_size; - int buffer_count; - int top_border, bottom_border; - void *mem_saved; - size_t mem_saved_size; -}; - -void *vout_fbdev_flip(struct vout_fbdev *fbdev) -{ - int draw_buf; - - if (fbdev->buffer_count < 2) - return fbdev->mem; - - draw_buf = fbdev->buffer_write; - fbdev->buffer_write++; - if (fbdev->buffer_write >= fbdev->buffer_count) - fbdev->buffer_write = 0; - - fbdev->fbvar_new.yoffset = - (fbdev->top_border + fbdev->fbvar_new.yres + fbdev->bottom_border) * draw_buf + - fbdev->top_border; - - ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); - - return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write; -} - -void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev) -{ - int arg = 0; - ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg); -} - -/* it is recommended to call vout_fbdev_clear() before this */ -void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp, - int left_border, int right_border, int top_border, int bottom_border, int buffer_cnt) -{ - int w_total = left_border + w + right_border; - int h_total = top_border + h + bottom_border; - size_t mem_size; - int ret; - - // unblank to be sure the mode is really accepted - ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK); - - if (fbdev->fbvar_new.bits_per_pixel != bpp || - fbdev->fbvar_new.xres != w || - fbdev->fbvar_new.yres != h || - fbdev->fbvar_new.xres_virtual != w_total|| - fbdev->fbvar_new.yres_virtual < h_total || - fbdev->fbvar_new.xoffset != left_border || - fbdev->buffer_count != buffer_cnt) - { - if (fbdev->fbvar_new.bits_per_pixel != bpp || - w != fbdev->fbvar_new.xres || h != fbdev->fbvar_new.yres) - printf(PFX "switching to %dx%d@%d\n", w, h, bpp); - - fbdev->fbvar_new.xres = w; - fbdev->fbvar_new.yres = h; - fbdev->fbvar_new.xres_virtual = w_total; - fbdev->fbvar_new.yres_virtual = h_total * buffer_cnt; - fbdev->fbvar_new.xoffset = left_border; - fbdev->fbvar_new.yoffset = top_border; - fbdev->fbvar_new.bits_per_pixel = bpp; - fbdev->fbvar_new.nonstd = 0; // can set YUV here on omapfb - fbdev->buffer_count = buffer_cnt; - fbdev->buffer_write = buffer_cnt > 1 ? 1 : 0; - - // seems to help a bit to avoid glitches - vout_fbdev_wait_vsync(fbdev); - - ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); - if (ret == -1) { - // retry with no multibuffering - fbdev->fbvar_new.yres_virtual = h_total; - ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); - if (ret == -1) { - perror(PFX "FBIOPUT_VSCREENINFO ioctl"); - return NULL; - } - fbdev->buffer_count = 1; - fbdev->buffer_write = 0; - fprintf(stderr, PFX "Warning: failed to increase virtual resolution, " - "multibuffering disabled\n"); - } - - } - - fbdev->fb_size = w_total * h_total * bpp / 8; - fbdev->top_border = top_border; - fbdev->bottom_border = bottom_border; - - mem_size = fbdev->fb_size * fbdev->buffer_count; - if (fbdev->mem_size >= mem_size) - goto out; - - if (fbdev->mem != NULL) - munmap(fbdev->mem, fbdev->mem_size); - - fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); - if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) { - fprintf(stderr, PFX "Warning: can't map %zd bytes, doublebuffering disabled\n", mem_size); - fbdev->buffer_count = 1; - fbdev->buffer_write = 0; - mem_size = fbdev->fb_size; - fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); - } - if (fbdev->mem == MAP_FAILED) { - fbdev->mem = NULL; - fbdev->mem_size = 0; - perror(PFX "mmap framebuffer"); - return NULL; - } - - fbdev->mem_size = mem_size; - -out: - return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write; -} - -void vout_fbdev_clear(struct vout_fbdev *fbdev) -{ - memset(fbdev->mem, 0, fbdev->mem_size); -} - -void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count) -{ - int stride = fbdev->fbvar_new.xres_virtual * fbdev->fbvar_new.bits_per_pixel / 8; - int i; - - if (y + count > fbdev->top_border + fbdev->fbvar_new.yres) - count = fbdev->top_border + fbdev->fbvar_new.yres - y; - - if (y >= 0 && count > 0) - for (i = 0; i < fbdev->buffer_count; i++) - memset((char *)fbdev->mem + fbdev->fb_size * i + y * stride, 0, stride * count); -} - -void *vout_fbdev_get_active_mem(struct vout_fbdev *fbdev) -{ - int i; - - i = fbdev->buffer_write - 1; - if (i < 0) - i = fbdev->buffer_count - 1; - - return (char *)fbdev->mem + fbdev->fb_size * i; -} - -int vout_fbdev_get_fd(struct vout_fbdev *fbdev) -{ - if (fbdev == NULL) return -1; - - return fbdev->fd; -} - -struct vout_fbdev *vout_fbdev_preinit(int fbdev_fd) -{ - struct vout_fbdev *fbdev; - - fbdev = calloc(1, sizeof(*fbdev)); - if (fbdev == NULL) return NULL; - - fbdev->fd = fbdev_fd; - - return fbdev; -} - -int vout_fbdev_init(struct vout_fbdev *fbdev, int *w, int *h, int bpp, int buffer_cnt) -{ - int req_w, req_h; - void *pret; - int ret; - - ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old); - if (ret == -1) { - perror(PFX "FBIOGET_VSCREENINFO ioctl"); - return -1; - } - - fbdev->fbvar_new = fbdev->fbvar_old; - - req_w = fbdev->fbvar_new.xres; - if (*w != 0) - req_w = *w; - req_h = fbdev->fbvar_new.yres; - if (*h != 0) - req_h = *h; - - pret = vout_fbdev_resize(fbdev, req_w, req_h, bpp, 0, 0, 0, 0, buffer_cnt); - if (pret == NULL) - return -1; - - printf(PFX "%ix%i@%d\n", fbdev->fbvar_new.xres, - fbdev->fbvar_new.yres, fbdev->fbvar_new.bits_per_pixel); - *w = fbdev->fbvar_new.xres; - *h = fbdev->fbvar_new.yres; - - memset(fbdev->mem, 0, fbdev->mem_size); - - // some checks - ret = 0; - ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret); - if (ret != 0) - fprintf(stderr, PFX "Warning: vsync doesn't seem to be supported\n"); - - if (fbdev->buffer_count > 1) { - fbdev->buffer_write = 0; - fbdev->fbvar_new.yoffset = fbdev->fbvar_new.yres * (fbdev->buffer_count - 1); - ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); - if (ret != 0) { - fbdev->buffer_count = 1; - fprintf(stderr, PFX "Warning: can't pan display, doublebuffering disabled\n"); - } - } - - printf("fbdev initialized.\n"); - return 0; -} - -void vout_fbdev_release(struct vout_fbdev *fbdev) -{ - if (fbdev->mem == NULL) return; - - ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old); - if (fbdev->mem != MAP_FAILED) - munmap(fbdev->mem, fbdev->mem_size); - fbdev->mem = NULL; -} - -int vout_fbdev_save(struct vout_fbdev *fbdev) -{ - void *tmp; - - if (fbdev == NULL || fbdev->mem == NULL || fbdev->mem == MAP_FAILED) { - fprintf(stderr, PFX "bad args for save\n"); - return -1; - } - - if (fbdev->mem_saved_size < fbdev->mem_size) { - tmp = realloc(fbdev->mem_saved, fbdev->mem_size); - if (tmp == NULL) - return -1; - fbdev->mem_saved = tmp; - } - memcpy(fbdev->mem_saved, fbdev->mem, fbdev->mem_size); - fbdev->mem_saved_size = fbdev->mem_size; - - vout_fbdev_release(fbdev); - return 0; -} - -int vout_fbdev_restore(struct vout_fbdev *fbdev) -{ - int ret; - - if (fbdev == NULL || fbdev->mem != NULL) { - fprintf(stderr, PFX "bad args/state for restore\n"); - return -1; - } - - fbdev->mem = mmap(0, fbdev->mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); - if (fbdev->mem == MAP_FAILED) { - perror(PFX "restore: memory restore failed"); - return -1; - } - memcpy(fbdev->mem, fbdev->mem_saved, fbdev->mem_size); - - ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); - if (ret == -1) { - perror(PFX "restore: FBIOPUT_VSCREENINFO"); - return -1; - } - - return 0; -} - -void vout_fbdev_teardown(struct vout_fbdev* fbdev) -{ - if (fbdev == NULL) return; - - if (fbdev->fd >= 0) close(fbdev->fd); - fbdev->fd = -1; - free(fbdev); -} diff --git a/gfx/fbdev.h b/gfx/fbdev.h deleted file mode 100644 index a821cbee44..0000000000 --- a/gfx/fbdev.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _FBDEV_H -#define _FBDEV_H - -struct vout_fbdev; - -struct vout_fbdev *vout_fbdev_preinit(int fbdev_fd); -int vout_fbdev_init(struct vout_fbdev *fbdev, int *w, int *h, int bpp, int buffer_cnt); - -void *vout_fbdev_flip(struct vout_fbdev *fbdev); -void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev); -void *vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, int bpp, - int left_border, int right_border, int top_border, int bottom_border, - int buffer_count); -void vout_fbdev_clear(struct vout_fbdev *fbdev); -void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count); -int vout_fbdev_get_fd(struct vout_fbdev *fbdev); -void *vout_fbdev_get_active_mem(struct vout_fbdev *fbdev); -int vout_fbdev_save(struct vout_fbdev *fbdev); -int vout_fbdev_restore(struct vout_fbdev *fbdev); - -void vout_fbdev_release(struct vout_fbdev *fbdev); -void vout_fbdev_teardown(struct vout_fbdev* fbdev); - -#endif diff --git a/gfx/omap_gfx.c b/gfx/omap_gfx.c index 2f51906cfb..e3eed9ffb3 100644 --- a/gfx/omap_gfx.c +++ b/gfx/omap_gfx.c @@ -29,145 +29,104 @@ #include #include #include +#include -#include "omapfb.h" -#include "fbdev.h" +#include +#include #ifdef HAVE_CONFIG_H #include "config.h" #endif -#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) - -enum omap_layer_size { - OMAP_LAYER_UNSCALED, - OMAP_LAYER_FULLSCREEN, - OMAP_LAYER_SCALED, - OMAP_LAYER_PIXELPERFECT, - OMAP_LAYER_CUSTOM -}; +typedef struct omapfb_page { + unsigned yoffset; + void *buf; + bool used; +} omapfb_page_t; typedef struct omapfb_state { struct omapfb_plane_info pi; struct omapfb_mem_info mi; - struct omapfb_plane_info pi_old; - struct omapfb_mem_info mi_old; + struct fb_var_screeninfo si; + void* mem; } omapfb_state_t; -typedef struct osdl_data -{ - struct vout_fbdev *fbdev; - void *front_buffer; - void *saved_layer; - /* physical/native screen size */ - int phys_w, phys_h; - /* layer */ - int layer_x, layer_y, layer_w, layer_h; - enum omap_layer_size layer_size; - bool vsync; -} osdl_data_t; +typedef struct omapfb_data { + const char* fbname; + int fd; -static const char *get_fb_device(void) -{ - const char *fbname = getenv("OMAP_FBDEV"); - if (fbname == NULL) - fbname = "/dev/fb1"; + void *fb_mem; + unsigned fb_framesize; + omapfb_page_t *pages; + int num_pages; + omapfb_page_t *cur_page; + omapfb_page_t *old_page; + + /* current and saved (for later restore) states */ + omapfb_state_t* current_state; + omapfb_state_t* saved_state; + + /* native screen size */ + unsigned nat_w, nat_h; + + /* bytes per pixel */ + unsigned bpp; +} omapfb_data_t; + + +static const char *get_fb_device(void) { + const int fbidx = g_settings.video.monitor_index; + static char fbname[12]; + + if (fbidx == 0) return "/dev/fb0"; + + snprintf(fbname, sizeof(fbname), "/dev/fb%d", fbidx - 1); + RARCH_LOG("video_omap: Using %s as framebuffer device\n", fbname); return fbname; } -static int osdl_setup_omapfb(struct omapfb_state *ostate, int fd, int enabled, - int x, int y, int w, int h, int mem, int buffer_count) -{ - struct omapfb_plane_info pi; - struct omapfb_mem_info mi; - unsigned int size_cur; - int ret; +static omapfb_page_t *get_page(omapfb_data_t *pdata) { + omapfb_page_t *page = NULL; + unsigned i; - RARCH_LOG("in osdl_setup_omapfb\n"); - - memset(&pi, 0, sizeof(pi)); - memset(&mi, 0, sizeof(mi)); - - ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi); - if (ret != 0) { - RARCH_ERR("omapfb: QUERY_PLANE\n"); - return -1; - } - - ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi); - if (ret != 0) { - RARCH_ERR("omapfb: QUERY_MEM\n"); - return -1; - } - size_cur = mi.size; - - /* must disable when changing stuff */ - if (pi.enabled) { - pi.enabled = 0; - ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); - if (ret != 0) - RARCH_ERR("SETUP_PLANE\n"); - } - - /* if needed increase memory allocation */ - if (size_cur < mem * buffer_count) { - mi.size = mem * buffer_count; - ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); - if (ret != 0) { - RARCH_ERR("omapfb: SETUP_MEM\n"); - RARCH_ERR("Failed to allocate %d bytes of vram.\n", mem * buffer_count); - return -1; + for (i = 0; i < pdata->num_pages; ++i) { + if (&pdata->pages[i] == pdata->cur_page) + continue; + if (&pdata->pages[i] == pdata->old_page) + continue; + if (!pdata->pages[i].used) { + RARCH_LOG("video_omap: page %u is free\n", i); + page = &pdata->pages[i]; + break; } } - pi.pos_x = x; - pi.pos_y = y; - pi.out_width = w; - pi.out_height = h; - pi.enabled = enabled; - - ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); - if (ret != 0) { - RARCH_ERR("omapfb: SETUP_PLANE (%d %d %d %d)\n", x, y, w, h); - return -1; - } - - ostate->pi = pi; - ostate->mi = mi; - - return 0; + return page; } -static int osdl_setup_omapfb_enable(struct omapfb_state *ostate, - int fd, int enabled) -{ - int ret; +static void page_flip(omapfb_data_t *pdata) { + ioctl(pdata->fd, OMAPFB_WAITFORGO); - ostate->pi.enabled = enabled; - ret = ioctl(fd, OMAPFB_SETUP_PLANE, &ostate->pi); - if (ret != 0) RARCH_ERR("omapfb: SETUP_PLANE\n"); + /* TODO: should we use the manual update feature of the OMAP here? */ - return ret; + pdata->current_state->si.yoffset = pdata->cur_page->yoffset; + ioctl(pdata->fd, FBIOPAN_DISPLAY, &pdata->current_state->si); + + if (pdata->old_page) + pdata->old_page->used = false; } -static int read_sysfs(const char *fname, char *buff, size_t size) -{ +static int read_sysfs(const char *fname, char *buff, size_t size) { FILE *f; int ret; f = fopen(fname, "r"); - if (f == NULL) { - RARCH_ERR("video_omap: open %s failed\n", fname); - return -1; - } + if (f == NULL) return -1; ret = fread(buff, 1, size - 1, f); fclose(f); - if (ret <= 0) { - RARCH_ERR("video_omap: read %s failed\n", fname); - return -1; - } + if (ret <= 0) return -1; buff[ret] = 0; for (ret--; ret >= 0 && isspace(buff[ret]); ret--) @@ -176,17 +135,7 @@ static int read_sysfs(const char *fname, char *buff, size_t size) return 0; } -static int osdl_fbdev_init(struct osdl_data *pdata, int fd) -{ - pdata->fbdev = vout_fbdev_preinit(fd); - - if (pdata->fbdev == NULL) return -1; - - return 0; -} - -static int osdl_video_detect_screen(struct osdl_data *pdata, const char *fbname) -{ +static int omapfb_detect_screen(omapfb_data_t *pdata) { int fb_id, overlay_id = -1, display_id = -1; char buff[64], manager_name[64], display_name[64]; struct stat status; @@ -194,14 +143,11 @@ static int osdl_video_detect_screen(struct osdl_data *pdata, const char *fbname) int w, h; FILE *f; - pdata->phys_w = pdata->phys_h = 0; - - /* Figure out screen resolution, we need to know default - * resolution for centering stuff. - * The only way to achieve this seems to be walking some sysfs files.. */ - ret = stat(fbname, &status); + /* Find out the native screen resolution, which is needed to + * properly center the scaled image data. */ + ret = stat(pdata->fbname, &status); if (ret != 0) { - RARCH_ERR("video_omap: can't stat %s\n", fbname); + RARCH_ERR("video_omap: can't stat %s\n", pdata->fbname); return -1; } fb_id = minor(status.st_rdev); @@ -280,311 +226,376 @@ static int osdl_video_detect_screen(struct osdl_data *pdata, const char *fbname) return -1; } + if (w <= 0 || h <= 0) { + RARCH_ERR("video_omap: unsane dimensions detected (%dx%d)\n", w, h); + return -1; + } + RARCH_LOG("video_omap: detected %dx%d '%s' (%d) display attached to fb %d and overlay %d\n", w, h, display_name, display_id, fb_id, overlay_id); - pdata->phys_w = w; - pdata->phys_h = h; + pdata->nat_w = w; + pdata->nat_h = h; return 0; } -static int osdl_init(struct osdl_data *pdata) -{ - const char *fbname; - int ret, fb; +static int omapfb_setup_pages(omapfb_data_t *pdata) { + int i; - fbname = get_fb_device(); - ret = osdl_video_detect_screen(pdata, fbname); + if (pdata->pages == NULL) { + pdata->pages = calloc(pdata->num_pages, sizeof(omapfb_page_t)); - if (ret != 0) return ret; + if (pdata->pages == NULL) { + RARCH_ERR("video_omap: pages allocation failed\n"); + return -1; + } + } + + for (i = 0; i < pdata->num_pages; ++i) { + pdata->pages[i].yoffset = i * pdata->current_state->si.yres; + pdata->pages[i].buf = pdata->fb_mem + (i * pdata->fb_framesize); + pdata->pages[i].used = false; + } + + pdata->old_page = NULL; + pdata->cur_page = &pdata->pages[0]; + + memset(pdata->cur_page->buf, 0, pdata->fb_framesize); + + page_flip(pdata); + pdata->cur_page->used = true; + + return 0; +} + +static int omapfb_mmap(omapfb_data_t *pdata) { + assert(pdata->fb_mem == NULL); + + pdata->fb_mem = mmap(NULL, pdata->current_state->mi.size, PROT_WRITE, + MAP_SHARED, pdata->fd, 0); + + if (pdata->fb_mem == MAP_FAILED) { + pdata->fb_mem = NULL; + RARCH_ERR("video_omap: framebuffer mmap failed\n"); - fb = open(fbname, O_RDWR); - if (fb == -1) { - RARCH_ERR("video_omap: can't open fb device\n"); return -1; } - ret = osdl_fbdev_init(pdata, fb); - - return ret; + return 0; } -static int osdl_setup_omap_layer(struct osdl_data *pdata, int width, - int height, int bpp, int buffer_count) -{ - int x = 0, y = 0, w = width, h = height; /* layer size and pos */ - int screen_w = w, screen_h = h; - int tmp_w, tmp_h; - const char *tmp; - int retval = -1; - int ret; - - RARCH_LOG("in osdl_setup_omap_layer\n"); - - const int fd = vout_fbdev_get_fd(pdata->fbdev); - - if (fd == -1) { - RARCH_ERR("got no fbdev fd\n"); - } - - pdata->layer_x = pdata->layer_y = pdata->layer_w = pdata->layer_h = 0; - - if (pdata->phys_w != 0) - screen_w = pdata->phys_w; - if (pdata->phys_h != 0) - screen_h = pdata->phys_h; - - /* FIXME: assuming layer doesn't change here */ - if (pdata->saved_layer == NULL) { - struct omapfb_state *slayer; - slayer = calloc(1, sizeof(*slayer)); - if (slayer == NULL) - goto out; - - ret = ioctl(fd, OMAPFB_QUERY_PLANE, &slayer->pi_old); - if (ret != 0) { - RARCH_ERR("omapfb: QUERY_PLANE\n"); - goto out; - } - - ret = ioctl(fd, OMAPFB_QUERY_MEM, &slayer->mi_old); - if (ret != 0) { - RARCH_ERR("omapfb: QUERY_MEM\n"); - goto out; - } - - pdata->saved_layer = slayer; - } - - switch (pdata->layer_size) { - case OMAP_LAYER_FULLSCREEN: - { - w = screen_w, h = screen_h; - } - break; - - case OMAP_LAYER_SCALED: - { - const float factor = MIN(((float)screen_w) / width, ((float)screen_h) / height); - w = (int)(factor*width), h = (int)(factor*height); - } - break; - - case OMAP_LAYER_PIXELPERFECT: - { - const float factor = MIN(((float)screen_w) / width, ((float)screen_h) / height); - w = ((int)factor) * width, h = ((int)factor) * height; - /* factor < 1.f => 0x0 layer, so fall back to 'scaled' */ - if (!w || !h) { - w = (int)(factor * width), h = (int)(factor * height); - } - } - break; - - // TODO: use g_settings.video.fullscreen_x for this! - case OMAP_LAYER_CUSTOM: - { - tmp = getenv("OMAP_LAYER_SIZE"); - - if (tmp != NULL && sscanf(tmp, "%dx%d", &tmp_w, &tmp_h) == 2) { - w = tmp_w, h = tmp_h; - } else { - RARCH_ERR("omap_video: custom layer size specified incorrectly, " - "should be like 800x480\n"); - } - } - break; - - default: - break; - } - - /* the layer can't be set larger than screen */ - tmp_w = w, tmp_h = h; - if (w > screen_w) w = screen_w; - if (h > screen_h) h = screen_h; - if (w != tmp_w || h != tmp_h) - RARCH_LOG("omap_video: layer resized %dx%d -> %dx%d to fit screen\n", tmp_w, tmp_h, w, h); - - x = screen_w / 2 - w / 2; - y = screen_h / 2 - h / 2; - ret = osdl_setup_omapfb(pdata->saved_layer, fd, 0, x, y, w, h, - width * height * ((bpp + 7) / 8), buffer_count); - - if (ret == 0) { - pdata->layer_x = x; - pdata->layer_y = y; - pdata->layer_w = w; - pdata->layer_h = h; - } - - retval = ret; - -out: - return retval; -} - -static void *osdl_video_flip(struct osdl_data *pdata) -{ - void *ret; - - if (pdata->fbdev == NULL) - return NULL; - - ret = vout_fbdev_flip(pdata->fbdev); - - if (pdata->vsync) - vout_fbdev_wait_vsync(pdata->fbdev); - - return ret; -} - -void osdl_video_finish(struct osdl_data *pdata) -{ - vout_fbdev_release(pdata->fbdev); - - /* restore the OMAP layer */ - if (pdata->saved_layer != NULL) { - struct omapfb_state *slayer = pdata->saved_layer; - int fd = vout_fbdev_get_fd(pdata->fbdev); - - int enabled = slayer->pi_old.enabled; - - /* be sure to disable while setting up */ - slayer->pi_old.enabled = 0; - ioctl(fd, OMAPFB_SETUP_PLANE, &slayer->pi_old); - ioctl(fd, OMAPFB_SETUP_MEM, &slayer->mi_old); - if (enabled) { - slayer->pi_old.enabled = enabled; - ioctl(fd, OMAPFB_SETUP_PLANE, &slayer->pi_old); - } - - free(slayer); - pdata->saved_layer = NULL; - } - - vout_fbdev_teardown(pdata->fbdev); - pdata->fbdev = NULL; -} - -static void *osdl_video_set_mode(struct osdl_data *pdata, int width, - int height, int bpp) -{ - int num_buffers; - void *result; - int ret; - - RARCH_LOG("osdl: setting video mode\n"); - - vout_fbdev_release(pdata->fbdev); - - /* always use triple buffering for reduced chance of tearing */ - num_buffers = 3; - - RARCH_LOG("width = %d, height = %d\n", width, height); - - ret = osdl_setup_omap_layer(pdata, width, height, bpp, num_buffers); - if (ret < 0) - goto fail; - - ret = vout_fbdev_init(pdata->fbdev, &width, &height, bpp, num_buffers); - if (ret == -1) - goto fail; - - result = osdl_video_flip(pdata); - if (result == NULL) - goto fail; - - ret = osdl_setup_omapfb_enable(pdata->saved_layer, - vout_fbdev_get_fd(pdata->fbdev), 1); - if (ret != 0) { - RARCH_ERR("video_omap: layer enable failed\n"); - goto fail; - } - - return result; - -fail: - osdl_video_finish(pdata); - return NULL; -} - -void *osdl_video_get_active_buffer(struct osdl_data *pdata) -{ - if (pdata->fbdev == NULL) return NULL; - - return vout_fbdev_get_active_mem(pdata->fbdev); -} - -int osdl_video_pause(struct osdl_data *pdata, int is_pause) -{ - struct omapfb_state *state = pdata->saved_layer; +static int omapfb_backup_state(omapfb_data_t *pdata) { struct omapfb_plane_info pi; struct omapfb_mem_info mi; - int enabled; - int fd = -1; - int ret; + void* mem; - if (pdata->fbdev != NULL) - fd = vout_fbdev_get_fd(pdata->fbdev); + assert(pdata->saved_state == NULL); + + pdata->saved_state = calloc(1, sizeof(omapfb_state_t)); + if (!pdata->saved_state) return -1; + + if (ioctl(pdata->fd, OMAPFB_QUERY_PLANE, &pdata->saved_state->pi) != 0) { + RARCH_ERR("video_omap: backup layer (plane) failed\n"); + return -1; + } + + if (ioctl(pdata->fd, OMAPFB_QUERY_MEM, &pdata->saved_state->mi) != 0) { + RARCH_ERR("video_omap: backup layer (mem) failed\n"); + return -1; + } + + if (ioctl(pdata->fd, FBIOGET_VSCREENINFO, &pdata->saved_state->si) != 0) { + RARCH_ERR("video_omap: backup layer (screeninfo) failed\n"); + return -1; + } + + pdata->saved_state->mem = malloc(pdata->saved_state->mi.size); + mem = mmap(NULL, pdata->saved_state->mi.size, PROT_WRITE|PROT_READ, + MAP_SHARED, pdata->fd, 0); + if (pdata->saved_state->mem == NULL || mem == MAP_FAILED) { + RARCH_ERR("video_omap: backup layer (mem backup) failed\n"); + munmap(mem, pdata->saved_state->mi.size); + return -1; + } + memcpy(pdata->saved_state->mem, mem, pdata->saved_state->mi.size); + munmap(mem, pdata->saved_state->mi.size); + + return 0; +} + +static int omapfb_alloc_mem(omapfb_data_t *pdata) { + struct omapfb_plane_info pi; + struct omapfb_mem_info mi; + const struct retro_game_geometry *geom; + unsigned mem_size; + void* mem; + + assert(pdata->current_state == NULL); + + pdata->current_state = calloc(1, sizeof(omapfb_state_t)); + if (!pdata->current_state) return -1; + + if (ioctl(pdata->fd, OMAPFB_QUERY_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: alloc mem (query plane) failed\n"); + return -1; + } + + if (ioctl(pdata->fd, OMAPFB_QUERY_MEM, &mi) != 0) { + RARCH_ERR("video_omap: alloc mem (query mem) failed\n"); + return -1; + } + + /* disable plane when changing memory allocation */ + if (pi.enabled) { + pi.enabled = 0; + if (ioctl(pdata->fd, OMAPFB_SETUP_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: alloc mem (disable plane) failed\n"); + return -1; + } + } + + geom = &g_extern.system.av_info.geometry; + mem_size = geom->max_width * geom->max_height * + pdata->bpp * pdata->num_pages; + + mi.size = mem_size; + + if (ioctl(pdata->fd, OMAPFB_SETUP_MEM, &mi) != 0) { + RARCH_ERR("video_omap: allocation of %d bytes of VRAM failed\n", mem_size); + return -1; + } + + mem = mmap(NULL, mi.size, PROT_WRITE|PROT_READ, MAP_SHARED, pdata->fd, 0); + if (mem == MAP_FAILED) { + RARCH_ERR("video_omap: zeroing framebuffer failed\n"); + return -1; + } + memset(mem, 0, mi.size); + munmap(mem, mi.size); + + pdata->current_state->mi = mi; + + /* Don't re-enable the plane here (setup not yet complete) */ + + return 0; +} + +static int omapfb_setup_screeninfo(omapfb_data_t *pdata, int width, int height) { + omapfb_state_t* state = pdata->current_state; + + state->si.xres = width; + state->si.yres = height; + state->si.xres_virtual = width; + state->si.yres_virtual = height * pdata->num_pages; + + state->si.xoffset = 0; + state->si.yoffset = 0; + + state->si.bits_per_pixel = pdata->bpp * 8; + + /* OMAPFB_COLOR_ARGB32 for bpp=4, OMAPFB_COLOR_RGB565 for bpp=2 */ + state->si.nonstd = 0; + + if (ioctl(pdata->fd, FBIOPUT_VSCREENINFO, &state->si) != 0) { + RARCH_ERR("video_omap: setup screeninfo failed\n"); + return -1; + } + + pdata->fb_framesize = width * height * pdata->bpp; + + return 0; +} + +static float omapfb_scaling(omapfb_data_t *pdata, int width, int height) { + const float w_factor = (float)pdata->nat_w / (float)width; + const float h_factor = (float)pdata->nat_h / (float)height; + + return (w_factor < h_factor ? w_factor : h_factor); +} + +static int omapfb_setup_plane(omapfb_data_t *pdata, int width, int height) { + struct omapfb_plane_info pi = {0}; + int x, y, w, h; + float scale; + + scale = omapfb_scaling(pdata, width, height); + w = (int)(scale * width); + h = (int)(scale * height); + + RARCH_LOG("omap_video: scaling %dx%d to %dx%d\n", width, height, w, h); + + x = pdata->nat_w / 2 - w / 2; + y = pdata->nat_h / 2 - h / 2; + + if (width * height * pdata->bpp * pdata->num_pages > pdata->current_state->mi.size) { + RARCH_ERR("omap_video: fb dimensions too large for allocated buffer\n"); + return -1; + } + + if (ioctl(pdata->fd, OMAPFB_QUERY_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: setup plane (query) failed\n"); + return -1; + } + + pi.pos_x = x; + pi.pos_y = y; + pi.out_width = w; + pi.out_height = h; + pi.enabled = 0; /* TODO: do we need to disable the plane for setup? */ + + if (ioctl(pdata->fd, OMAPFB_SETUP_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: setup plane (param = %d %d %d %d) failed\n", x, y, w, h); + return -1; + } + + pdata->current_state->pi = pi; + + return 0; +} + +static int omapfb_enable_plane(omapfb_data_t *pdata) { + struct omapfb_plane_info pi = {0}; + + if (ioctl(pdata->fd, OMAPFB_QUERY_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: enable plane (query) failed\n"); + return -1; + } + + pi.enabled = 1; + + if (ioctl(pdata->fd, OMAPFB_SETUP_PLANE, &pi) != 0) { + RARCH_ERR("video_omap: enable plane failed\n"); + return -1; + } + + return 0; +} + +static int omapfb_init(omapfb_data_t *pdata, unsigned bpp) { + const char *fbname; + int fd; + + fbname = get_fb_device(); + + fd = open(fbname, O_RDWR); if (fd == -1) { - RARCH_ERR("bad fd %d", fd); - return -1; - } - if (state == NULL) { - RARCH_ERR("missing layer state\n"); + RARCH_ERR("video_omap: can't open framebuffer device\n"); return -1; } - if (is_pause) { - ret = vout_fbdev_save(pdata->fbdev); - if (ret != 0) - return ret; - pi = state->pi_old; - mi = state->mi_old; - enabled = pi.enabled; - } else { - pi = state->pi; - mi = state->mi; - enabled = 1; - } - pi.enabled = 0; - ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); - if (ret != 0) { - RARCH_ERR("SETUP_PLANE"); - return -1; - } + pdata->fbname = fbname; + pdata->fd = fd; - ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); - if (ret != 0) - RARCH_ERR("SETUP_MEM"); + if (omapfb_detect_screen(pdata)) { + close(fd); - if (!is_pause) { - ret = vout_fbdev_restore(pdata->fbdev); - if (ret != 0) { - RARCH_ERR("fbdev_restore failed\n"); - return ret; - } - } + pdata->fbname = NULL; + pdata->fd = -1; - if (enabled) { - pi.enabled = 1; - ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi); - if (ret != 0) { - RARCH_ERR("SETUP_PLANE"); - return -1; - } - } + return -1; + } - return 0; + /* always use triple buffering to reduce chance of tearing */ + pdata->bpp = bpp; + pdata->num_pages = 3; + + return 0; +} + +void omapfb_free(omapfb_data_t *pdata) { + /* unmap the framebuffer memory */ + if (pdata->fb_mem != NULL) { + munmap(pdata->fb_mem, pdata->current_state->mi.size); + pdata->fb_mem = NULL; + } + + /* restore the framebuffer state (OMAP plane state, screen info) */ + if (pdata->saved_state != NULL) { + int enabled; + void *mem; + + enabled = pdata->saved_state->pi.enabled; + + /* be sure to disable while setting up */ + pdata->saved_state->pi.enabled = 0; + ioctl(pdata->fd, OMAPFB_SETUP_PLANE, &pdata->saved_state->pi); + ioctl(pdata->fd, OMAPFB_SETUP_MEM, &pdata->saved_state->mi); + if (enabled) { + pdata->saved_state->pi.enabled = enabled; + ioctl(pdata->fd, OMAPFB_SETUP_PLANE, &pdata->saved_state->pi); + } + + /* restore framebuffer content */ + mem = mmap(0, pdata->saved_state->mi.size, PROT_WRITE|PROT_READ, + MAP_SHARED, pdata->fd, 0); + if (mem != MAP_FAILED) { + memcpy(mem, pdata->saved_state->mem, pdata->saved_state->mi.size); + munmap(mem, pdata->saved_state->mi.size); + } + + /* restore screen info */ + ioctl(pdata->fd, FBIOPUT_VSCREENINFO, &pdata->saved_state->si); + + free(pdata->saved_state->mem); + pdata->saved_state->mem = NULL; + + free(pdata->saved_state); + pdata->saved_state = NULL; + } + + free(pdata->current_state); + pdata->current_state = NULL; + + close(pdata->fd); + pdata->fd = -1; +} + +static int omapfb_set_mode(omapfb_data_t *pdata, int width, int height) { + ioctl(pdata->fd, OMAPFB_WAITFORGO); + + if (omapfb_setup_plane(pdata, width, height) != 0) + return -1; + + if (omapfb_setup_screeninfo(pdata, width, height) != 0 || + omapfb_setup_pages(pdata) != 0 || + omapfb_enable_plane(pdata) != 0) { + return -1; + } + + return 0; +} + +static void omapfb_prepare(omapfb_data_t *pdata) { + omapfb_page_t *page; + + /* issue flip before getting free page */ + page_flip(pdata); + page = get_page(pdata); + assert(page != NULL); + + pdata->old_page = pdata->cur_page; + pdata->cur_page = page; + + pdata->cur_page->used = true; +} + +static void omapfb_blit_frame(omapfb_data_t *pdata, const void *src, + unsigned height, unsigned src_pitch) { + unsigned i, dst_pitch; + void *dst; + + dst = pdata->cur_page->buf; + dst_pitch = pdata->current_state->si.xres * pdata->bpp; + + for (i = 0; i < height; i++) { + memcpy(dst + dst_pitch * i, src + src_pitch * i, dst_pitch); + } } -typedef struct omap_video -{ - struct osdl_data osdl; - void* pixels; +typedef struct omap_video { + omapfb_data_t *omap; void *font; const font_renderer_driver_t *font_driver; @@ -592,26 +603,26 @@ typedef struct omap_video uint8_t font_g; uint8_t font_b; - /* current settings */ + unsigned bytes_per_pixel; + + /* current dimensions */ unsigned width; unsigned height; - unsigned bytes_per_pixel; } omap_video_t; -static void omap_gfx_free(void *data) -{ - omap_video_t *vid = (omap_video_t*)data; + +static void omap_gfx_free(void *data) { + omap_video_t *vid = data; if (!vid) return; - osdl_video_finish(&vid->osdl); + omapfb_free(vid->omap); if (vid->font) vid->font_driver->free(vid->font); free(vid); } -static void omap_init_font(omap_video_t *vid, const char *font_path, unsigned font_size) -{ +static void omap_init_font(omap_video_t *vid, const char *font_path, unsigned font_size) { if (!g_settings.video.font_enable) return; if (font_renderer_create_default(&vid->font_driver, &vid->font)) { @@ -627,132 +638,107 @@ static void omap_init_font(omap_video_t *vid, const char *font_path, unsigned fo vid->font_g = g; vid->font_b = b; } else { - RARCH_LOG("Could not initialize fonts.\n"); + RARCH_LOG("video_omap: font init failed\n"); } } -/*static void omap_render_msg(omap_video_t *vid, SDL_Surface *buffer, - const char *msg, unsigned width, unsigned height, const SDL_PixelFormat *fmt) -{ +static void omap_render_msg(omap_video_t *vid, const char *msg) { if (!vid->font) return; - struct font_output_list out; - vid->font_driver->render_msg(vid->font, msg, &out); - struct font_output *head = out.head; + struct font_output_list out; + vid->font_driver->render_msg(vid->font, msg, &out); + struct font_output *head = out.head; - int msg_base_x = g_settings.video.msg_pos_x * width; - int msg_base_y = (1.0 - g_settings.video.msg_pos_y) * height; + return; /* TODO: implement */ - unsigned rshift = fmt->Rshift; - unsigned gshift = fmt->Gshift; - unsigned bshift = fmt->Bshift; + /*int msg_base_x = g_settings.video.msg_pos_x * width; + int msg_base_y = (1.0 - g_settings.video.msg_pos_y) * height; - for (; head; head = head->next) - { - int base_x = msg_base_x + head->off_x; - int base_y = msg_base_y - head->off_y - head->height; + unsigned rshift = fmt->Rshift; + unsigned gshift = fmt->Gshift; + unsigned bshift = fmt->Bshift; - int glyph_width = head->width; - int glyph_height = head->height; + for (; head; head = head->next) { + int base_x = msg_base_x + head->off_x; + int base_y = msg_base_y - head->off_y - head->height; - const uint8_t *src = head->output; + int glyph_width = head->width; + int glyph_height = head->height; - if (base_x < 0) - { - src -= base_x; - glyph_width += base_x; - base_x = 0; + const uint8_t *src = head->output; + + if (base_x < 0) { + src -= base_x; + glyph_width += base_x; + base_x = 0; + } + + if (base_y < 0) { + src -= base_y * (int)head->pitch; + glyph_height += base_y; + base_y = 0; + } + + int max_width = width - base_x; + int max_height = height - base_y; + + if (max_width <= 0 || max_height <= 0) + continue; + + if (glyph_width > max_width) + glyph_width = max_width; + if (glyph_height > max_height) + glyph_height = max_height; + + uint32_t *out = (uint32_t*)buffer->pixels + base_y * (buffer->pitch >> 2) + base_x; + + for (int y = 0; y < glyph_height; y++, src += head->pitch, out += buffer->pitch >> 2) { + for (int x = 0; x < glyph_width; x++) { + unsigned blend = src[x]; + unsigned out_pix = out[x]; + unsigned r = (out_pix >> rshift) & 0xff; + unsigned g = (out_pix >> gshift) & 0xff; + unsigned b = (out_pix >> bshift) & 0xff; + + unsigned out_r = (r * (256 - blend) + vid->font_r * blend) >> 8; + unsigned out_g = (g * (256 - blend) + vid->font_g * blend) >> 8; + unsigned out_b = (b * (256 - blend) + vid->font_b * blend) >> 8; + out[x] = (out_r << rshift) | (out_g << gshift) | (out_b << bshift); } + } + }*/ - if (base_y < 0) - { - src -= base_y * (int)head->pitch; - glyph_height += base_y; - base_y = 0; - } + vid->font_driver->free_output(vid->font, &out); +} - int max_width = width - base_x; - int max_height = height - base_y; +static void *omap_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data) { + omap_video_t *vid = NULL; - if (max_width <= 0 || max_height <= 0) - continue; + /* Don't support filters at the moment since they make estimations * + * on the maximum used resolution difficult. */ + if (g_extern.filter.active) { + RARCH_ERR("video_omap: filters are not supported\n"); + return NULL; + } - if (glyph_width > max_width) - glyph_width = max_width; - if (glyph_height > max_height) - glyph_height = max_height; - - uint32_t *out = (uint32_t*)buffer->pixels + base_y * (buffer->pitch >> 2) + base_x; - - for (int y = 0; y < glyph_height; y++, src += head->pitch, out += buffer->pitch >> 2) - { - for (int x = 0; x < glyph_width; x++) - { - unsigned blend = src[x]; - unsigned out_pix = out[x]; - unsigned r = (out_pix >> rshift) & 0xff; - unsigned g = (out_pix >> gshift) & 0xff; - unsigned b = (out_pix >> bshift) & 0xff; - - unsigned out_r = (r * (256 - blend) + vid->font_r * blend) >> 8; - unsigned out_g = (g * (256 - blend) + vid->font_g * blend) >> 8; - unsigned out_b = (b * (256 - blend) + vid->font_b * blend) >> 8; - out[x] = (out_r << rshift) | (out_g << gshift) | (out_b << bshift); - } - } - } - - vid->font_driver->free_output(vid->font, &out); -}*/ - -static void *omap_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data) -{ - void* ret = NULL; - - omap_video_t *vid = (omap_video_t*)calloc(1, sizeof(*vid)); + vid = calloc(1, sizeof(omap_video_t)); if (!vid) return NULL; - if (osdl_init(&vid->osdl) != 0) { - goto fail; - } + vid->omap = calloc(1, sizeof(omapfb_data_t)); + if (!vid->omap) return NULL; - RARCH_LOG("Detecting native resolution %ux%u.\n", - vid->osdl.phys_w, vid->osdl.phys_h); - - if (!video->fullscreen) - RARCH_LOG("Creating unscaled output @ %ux%u.\n", video->width, video->height); - - if (video->fullscreen) { - vid->osdl.layer_size = video->force_aspect ? - OMAP_LAYER_SCALED : OMAP_LAYER_FULLSCREEN; - } else { - vid->osdl.layer_size = OMAP_LAYER_UNSCALED; - } - - vid->osdl.vsync = video->vsync; vid->bytes_per_pixel = video->rgb32 ? 4 : 2; - // TODO: use geom from geom->base_width / geom->base_height - // const struct retro_game_geometry *geom = &g_extern.system.av_info.geometry; - - RARCH_LOG("calling osdl_video_set_mode with width = %d, height = %d\n", video->width, video->height); - - // TODO: handle width = height = 0 - - ret = osdl_video_set_mode(&vid->osdl, video->width, video->height, - vid->bytes_per_pixel * 8); - - if (ret == NULL) { + if (omapfb_init(vid->omap, vid->bytes_per_pixel) != 0) { goto fail; } - vid->width = video->width; - vid->height = video->height; - vid->pixels = ret; + if (omapfb_backup_state(vid->omap) != 0 || + omapfb_alloc_mem(vid->omap) != 0 || + omapfb_mmap(vid->omap) != 0) goto fail; if (input && input_data) { *input = NULL; - //input_data = NULL; } omap_init_font(vid, g_settings.video.font_path, g_settings.video.font_size); @@ -760,101 +746,86 @@ static void *omap_gfx_init(const video_info_t *video, const input_driver_t **inp return vid; fail: - RARCH_ERR("Failed to init OMAP video output.\n"); + RARCH_ERR("video_omap: initialization failed\n"); omap_gfx_free(vid); return NULL; } -static void omap_blit_frame(omap_video_t *video, const void *src, - unsigned src_pitch) -{ - unsigned i; - const unsigned pitch = video->width * video->bytes_per_pixel; - - RARCH_LOG("in omap_blit_frame\n"); - - for (i = 0; i < video->height; i++) { - memcpy(video->pixels + pitch * i, src + src_pitch * i, pitch); - } -} - static bool omap_gfx_frame(void *data, const void *frame, unsigned width, - unsigned height, unsigned pitch, const char *msg) -{ - if (!frame) return true; + unsigned height, unsigned pitch, const char *msg) { + omap_video_t *vid; - omap_video_t *vid = (omap_video_t*)data; + if (!frame) return true; + vid = data; if (width != vid->width || height != vid->height) { - void* pixels; + if (width == 0 || height == 0) return true; - RARCH_LOG("Dimensions changed -> OMAP reinit\n"); - pixels = osdl_video_set_mode(&vid->osdl, width, height, - vid->bytes_per_pixel * 8); + RARCH_LOG("video_omap: mode set (resolution changed by core)\n"); - if (pixels == NULL) { - RARCH_ERR("OMAP reinit failed\n"); + if (omapfb_set_mode(vid->omap, width, height) != 0) { + RARCH_ERR("video_omap: mode set failed\n"); return false; } - vid->width = width; + vid->width = width; vid->height = height; } - omap_blit_frame(vid, frame, pitch); + omapfb_prepare(vid->omap); + omapfb_blit_frame(vid->omap, frame, vid->height, pitch); + if (msg) omap_render_msg(vid, msg); - /*if (msg) - omap_render_msg(vid, vid->screen, msg, vid->screen->w, vid->screen->h, vid->screen->format);*/ - - vid->pixels = osdl_video_flip(&vid->osdl); g_extern.frame_count++; return true; } -static void omap_gfx_set_nonblock_state(void *data, bool state) -{ - (void)data; /* NOP */ - (void)state; +static void omap_gfx_set_nonblock_state(void *data, bool state) { + /* TODO: add sync flag to omapfb_data and only WAITFORGO when enabled */ + + (void)data; + (void)state; } -static bool omap_gfx_alive(void *data) -{ - (void)data; - return true; /* always alive */ +static bool omap_gfx_alive(void *data) { + (void)data; + return true; /* always alive */ } -static bool omap_gfx_focus(void *data) -{ - (void)data; - return true; /* fb device always has focus */ +static bool omap_gfx_focus(void *data) { + (void)data; + return true; /* fb device always has focus */ } -static void omap_gfx_viewport_info(void *data, struct rarch_viewport *vp) -{ - omap_video_t *vid = (omap_video_t*)data; - vp->x = vp->y = 0; +static void omap_gfx_viewport_info(void *data, struct rarch_viewport *vp) { + omap_video_t *vid = (omap_video_t*)data; + vp->x = vp->y = 0; - // TODO: maybe set full_width,height to phys_w,h - vp->width = vp->full_width = vid->width; - vp->height = vp->full_height = vid->height; + vp->width = vp->full_width = vid->width; + vp->height = vp->full_height = vid->height; } const video_driver_t video_omap = { - omap_gfx_init, - omap_gfx_frame, - omap_gfx_set_nonblock_state, - omap_gfx_alive, - omap_gfx_focus, - NULL, - omap_gfx_free, - "omap", + omap_gfx_init, + omap_gfx_frame, + omap_gfx_set_nonblock_state, + omap_gfx_alive, + omap_gfx_focus, + NULL, /* set_shader */ + omap_gfx_free, + "omap", #ifdef HAVE_MENU - NULL, - NULL, + NULL, /* restart */ #endif - NULL, - omap_gfx_viewport_info, + NULL, /* set_rotation */ + omap_gfx_viewport_info, + NULL, /* read_viewport */ + +#ifdef HAVE_OVERLAY + NULL, /* overlay_interface */ +#endif + NULL /* poke_interface */ }; diff --git a/gfx/omapfb.h b/gfx/omapfb.h deleted file mode 100644 index f156e3a14d..0000000000 --- a/gfx/omapfb.h +++ /dev/null @@ -1,427 +0,0 @@ -/* - * File: arch/arm/plat-omap/include/mach/omapfb.h - * - * Framebuffer driver for TI OMAP boards - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak - * - * This program 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 2 of the License, or (at your - * option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __OMAPFB_H -#define __OMAPFB_H - -#include -#include - -/* IOCTL commands. */ - -#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) -#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) -#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) -#define OMAP_IO(num) _IO('O', num) - -#define OMAPFB_MIRROR OMAP_IOW(31, int) -#define OMAPFB_SYNC_GFX OMAP_IO(37) -#define OMAPFB_VSYNC OMAP_IO(38) -#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) -#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) -#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) -#define OMAPFB_LCD_TEST OMAP_IOW(45, int) -#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) -#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) -#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) -#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) -#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) -#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) -#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) -#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) -#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) -#define OMAPFB_WAITFORVSYNC OMAP_IO(57) -#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) - -#ifndef FBIO_WAITFORVSYNC -#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) -#endif - -#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff -#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 -#define OMAPFB_CAPS_PANEL_MASK 0xff000000 - -#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 -#define OMAPFB_CAPS_TEARSYNC 0x00002000 -#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 -#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 -#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 -#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 -#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 -#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 -#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 - -/* Values from DSP must map to lower 16-bits */ -#define OMAPFB_FORMAT_MASK 0x00ff -#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 -#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 -#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 -#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 -#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 - -#define OMAPFB_EVENT_READY 1 -#define OMAPFB_EVENT_DISABLED 2 - -#define OMAPFB_MEMTYPE_SDRAM 0 -#define OMAPFB_MEMTYPE_SRAM 1 -#define OMAPFB_MEMTYPE_MAX 1 - -enum omapfb_color_format { - OMAPFB_COLOR_RGB565 = 0, - OMAPFB_COLOR_YUV422, - OMAPFB_COLOR_YUV420, - OMAPFB_COLOR_CLUT_8BPP, - OMAPFB_COLOR_CLUT_4BPP, - OMAPFB_COLOR_CLUT_2BPP, - OMAPFB_COLOR_CLUT_1BPP, - OMAPFB_COLOR_RGB444, - OMAPFB_COLOR_YUY422, - - OMAPFB_COLOR_ARGB16, - OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */ - OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */ - OMAPFB_COLOR_ARGB32, - OMAPFB_COLOR_RGBA32, - OMAPFB_COLOR_RGBX32, -}; - -struct omapfb_update_window { - __u32 x, y; - __u32 width, height; - __u32 format; - __u32 out_x, out_y; - __u32 out_width, out_height; - __u32 reserved[8]; -}; - -struct omapfb_update_window_old { - __u32 x, y; - __u32 width, height; - __u32 format; -}; - -enum omapfb_plane { - OMAPFB_PLANE_GFX = 0, - OMAPFB_PLANE_VID1, - OMAPFB_PLANE_VID2, -}; - -enum omapfb_channel_out { - OMAPFB_CHANNEL_OUT_LCD = 0, - OMAPFB_CHANNEL_OUT_DIGIT, -}; - -struct omapfb_plane_info { - __u32 pos_x; - __u32 pos_y; - __u8 enabled; - __u8 channel_out; - __u8 mirror; - __u8 reserved1; - __u32 out_width; - __u32 out_height; - __u32 reserved2[12]; -}; - -struct omapfb_mem_info { - __u32 size; - __u8 type; - __u8 reserved[3]; -}; - -struct omapfb_caps { - __u32 ctrl; - __u32 plane_color; - __u32 wnd_color; -}; - -enum omapfb_color_key_type { - OMAPFB_COLOR_KEY_DISABLED = 0, - OMAPFB_COLOR_KEY_GFX_DST, - OMAPFB_COLOR_KEY_VID_SRC, -}; - -struct omapfb_color_key { - __u8 channel_out; - __u32 background; - __u32 trans_key; - __u8 key_type; -}; - -enum omapfb_update_mode { - OMAPFB_UPDATE_DISABLED = 0, - OMAPFB_AUTO_UPDATE, - OMAPFB_MANUAL_UPDATE -}; - -struct omapfb_memory_read { - __u16 x; - __u16 y; - __u16 w; - __u16 h; - size_t buffer_size; - void *buffer; -}; - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -#include - -#define OMAP_LCDC_INV_VSYNC 0x0001 -#define OMAP_LCDC_INV_HSYNC 0x0002 -#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 -#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 -#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 -#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 - -#define OMAP_LCDC_SIGNAL_MASK 0x003f - -#define OMAP_LCDC_PANEL_TFT 0x0100 - -#define OMAPFB_PLANE_XRES_MIN 8 -#define OMAPFB_PLANE_YRES_MIN 8 - -#ifdef CONFIG_ARCH_OMAP1 -#define OMAPFB_PLANE_NUM 1 -#else -#define OMAPFB_PLANE_NUM 3 -#endif - -struct omapfb_device; - -struct lcd_panel { - const char *name; - int config; /* TFT/STN, signal inversion */ - int bpp; /* Pixel format in fb mem */ - int data_lines; /* Lines on LCD HW interface */ - - int x_res, y_res; - int pixel_clock; /* In kHz */ - int hsw; /* Horizontal synchronization - pulse width */ - int hfp; /* Horizontal front porch */ - int hbp; /* Horizontal back porch */ - int vsw; /* Vertical synchronization - pulse width */ - int vfp; /* Vertical front porch */ - int vbp; /* Vertical back porch */ - int acb; /* ac-bias pin frequency */ - int pcd; /* pixel clock divider. - Obsolete use pixel_clock instead */ - - int (*init) (struct lcd_panel *panel, - struct omapfb_device *fbdev); - void (*cleanup) (struct lcd_panel *panel); - int (*enable) (struct lcd_panel *panel); - void (*disable) (struct lcd_panel *panel); - unsigned long (*get_caps) (struct lcd_panel *panel); - int (*set_bklight_level)(struct lcd_panel *panel, - unsigned int level); - unsigned int (*get_bklight_level)(struct lcd_panel *panel); - unsigned int (*get_bklight_max) (struct lcd_panel *panel); - int (*run_test) (struct lcd_panel *panel, int test_num); -}; - -struct extif_timings { - int cs_on_time; - int cs_off_time; - int we_on_time; - int we_off_time; - int re_on_time; - int re_off_time; - int we_cycle_time; - int re_cycle_time; - int cs_pulse_width; - int access_time; - - int clk_div; - - u32 tim[5]; /* set by extif->convert_timings */ - - int converted; -}; - -struct lcd_ctrl_extif { - int (*init) (struct omapfb_device *fbdev); - void (*cleanup) (void); - void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); - unsigned long (*get_max_tx_rate)(void); - int (*convert_timings) (struct extif_timings *timings); - void (*set_timings) (const struct extif_timings *timings); - void (*set_bits_per_cycle)(int bpc); - void (*write_command) (const void *buf, unsigned int len); - void (*read_data) (void *buf, unsigned int len); - void (*write_data) (const void *buf, unsigned int len); - void (*transfer_area) (int width, int height, - void (callback)(void * data), void *data); - int (*setup_tearsync) (unsigned pin_cnt, - unsigned hs_pulse_time, unsigned vs_pulse_time, - int hs_pol_inv, int vs_pol_inv, int div); - int (*enable_tearsync) (int enable, unsigned line); - - unsigned long max_transmit_size; -}; - -struct omapfb_notifier_block { - struct notifier_block nb; - void *data; - int plane_idx; -}; - -typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, - unsigned long event, - void *fbi); - -struct omapfb_mem_region { - u32 paddr; - void __iomem *vaddr; - unsigned long size; - u8 type; /* OMAPFB_PLANE_MEM_* */ - enum omapfb_color_format format;/* OMAPFB_COLOR_* */ - unsigned format_used:1; /* Must be set when format is set. - * Needed b/c of the badly chosen 0 - * base for OMAPFB_COLOR_* values - */ - unsigned alloc:1; /* allocated by the driver */ - unsigned map:1; /* kernel mapped by the driver */ -}; - -struct omapfb_mem_desc { - int region_cnt; - struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; -}; - -struct lcd_ctrl { - const char *name; - void *data; - - int (*init) (struct omapfb_device *fbdev, - int ext_mode, - struct omapfb_mem_desc *req_md); - void (*cleanup) (void); - void (*bind_client) (struct omapfb_notifier_block *nb); - void (*get_caps) (int plane, struct omapfb_caps *caps); - int (*set_update_mode)(enum omapfb_update_mode mode); - enum omapfb_update_mode (*get_update_mode)(void); - int (*setup_plane) (int plane, int channel_out, - unsigned long offset, - int screen_width, - int pos_x, int pos_y, int width, - int height, int color_mode); - int (*set_rotate) (int angle); - int (*setup_mem) (int plane, size_t size, - int mem_type, unsigned long *paddr); - int (*mmap) (struct fb_info *info, - struct vm_area_struct *vma); - int (*set_scale) (int plane, - int orig_width, int orig_height, - int out_width, int out_height); - int (*enable_plane) (int plane, int enable); - int (*update_window) (struct fb_info *fbi, - struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data); - void (*sync) (void); - void (*suspend) (void); - void (*resume) (void); - int (*run_test) (int test_num); - int (*setcolreg) (u_int regno, u16 red, u16 green, - u16 blue, u16 transp, - int update_hw_mem); - int (*set_color_key) (struct omapfb_color_key *ck); - int (*get_color_key) (struct omapfb_color_key *ck); -}; - -enum omapfb_state { - OMAPFB_DISABLED = 0, - OMAPFB_SUSPENDED= 99, - OMAPFB_ACTIVE = 100 -}; - -struct omapfb_plane_struct { - int idx; - struct omapfb_plane_info info; - enum omapfb_color_format color_mode; - struct omapfb_device *fbdev; -}; - -struct omapfb_device { - int state; - int ext_lcdc; /* Using external - LCD controller */ - struct mutex rqueue_mutex; - - int palette_size; - u32 pseudo_palette[17]; - - struct lcd_panel *panel; /* LCD panel */ - const struct lcd_ctrl *ctrl; /* LCD controller */ - const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ - struct lcd_ctrl_extif *ext_if; /* LCD ctrl external - interface */ - struct device *dev; - struct fb_var_screeninfo new_var; /* for mode changes */ - - struct omapfb_mem_desc mem_desc; - struct fb_info *fb_info[OMAPFB_PLANE_NUM]; -}; - -struct omapfb_platform_data { - struct omap_lcd_config lcd; - struct omapfb_mem_desc mem_desc; - void *ctrl_platform_data; -}; - -#ifdef CONFIG_ARCH_OMAP1 -extern struct lcd_ctrl omap1_lcd_ctrl; -#else -extern struct lcd_ctrl omap2_disp_ctrl; -#endif - -extern void omapfb_set_platform_data(struct omapfb_platform_data *data); - -extern void omapfb_reserve_sdram(void); -extern void omapfb_register_panel(struct lcd_panel *panel); -extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); -extern void omapfb_notify_clients(struct omapfb_device *fbdev, - unsigned long event); -extern int omapfb_register_client(struct omapfb_notifier_block *nb, - omapfb_notifier_callback_t callback, - void *callback_data); -extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); -extern int omapfb_update_window_async(struct fb_info *fbi, - struct omapfb_update_window *win, - void (*callback)(void *), - void *callback_data); - -/* in arch/arm/plat-omap/fb.c */ -extern void omapfb_set_ctrl_platform_data(void *pdata); - -#endif /* __KERNEL__ */ - -#endif /* __OMAPFB_H */