X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fvideo%2Fomapdss%2Fosdl_video.c;h=9cc6252d78ad87a3c85dd31ef6e4aa3045cfdcd3;hb=HEAD;hp=b6abb93d0c372ae510e7fcbbd0368b4043597a56;hpb=090bcb85b9cebd193299c9e93f4de8c5888094f4;p=sdl_omap.git diff --git a/src/video/omapdss/osdl_video.c b/src/video/omapdss/osdl_video.c index b6abb93..9cc6252 100644 --- a/src/video/omapdss/osdl_video.c +++ b/src/video/omapdss/osdl_video.c @@ -22,13 +22,55 @@ #include "linux/fbdev.h" #include "linux/xenv.h" +#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) + 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; + int tv_layer; }; +static int read_sysfs(const char *fname, char *buff, size_t size); + +static int switch_tv_layer(struct omapfb_state *ostate, int layer) +{ + const char *tmp; + struct stat st; + char buf[128]; + int ret; + + tmp = getenv("SDL_OMAP_NO_PANDORA_TV"); + if (tmp != NULL && !!strtol(tmp, NULL, 0)) + return 0; + + if (stat("/proc/pandora", &st) != 0) + /* not pandora, don't mess with stuff */ + return 0; + + ret = read_sysfs("/sys/devices/platform/omapdss/display1/enabled", + buf, sizeof(buf)); + if (ret < 0) { + err("couldn't check display1 state"); + return -1; + } + + if (strtol(buf, NULL, 0) == 0) + /* TV-out not enabled */ + return 0; + + snprintf(buf, sizeof(buf), + "sudo -n /usr/pandora/scripts/op_tvout.sh -l %d", layer); + ret = system(buf); + if (ret >= 0) { + ostate->tv_layer = layer; + ret = 0; + } + + return ret; +} + static const char *get_fb_device(void) { const char *fbname = getenv("SDL_FBDEV"); @@ -44,6 +86,7 @@ static int osdl_setup_omapfb(struct omapfb_state *ostate, int fd, int enabled, struct omapfb_plane_info pi; struct omapfb_mem_info mi; int mem_blocks = *buffer_count; + unsigned int size_cur; int ret; memset(&pi, 0, sizeof(pi)); @@ -60,6 +103,7 @@ static int osdl_setup_omapfb(struct omapfb_state *ostate, int fd, int enabled, err_perror("QUERY_MEM"); return -1; } + size_cur = mi.size; /* must disable when changing stuff */ if (pi.enabled) { @@ -69,19 +113,20 @@ static int osdl_setup_omapfb(struct omapfb_state *ostate, int fd, int enabled, err_perror("SETUP_PLANE"); } - if (mi.size < mem * mem_blocks) { - for (; mem_blocks > 0; mem_blocks--) { - mi.size = mem * mem_blocks; - ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); - if (ret == 0) - break; - } - if (ret != 0 || mem_blocks <= 0) { - err("failed to allocate at least %d bytes of vram:\n", mem); - err_perror("SETUP_MEM"); - return -1; - } + /* allocate more mem, if needed */ + for (; size_cur < mem * mem_blocks && mem_blocks > 0; mem_blocks--) { + mi.size = mem * mem_blocks; + ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi); + if (ret == 0) + break; + mi.size = size_cur; + } + if (mem_blocks <= 0) { + err("failed to allocate at least %d bytes of vram:\n", mem); + err_perror("SETUP_MEM"); + return -1; } + *buffer_count = mem_blocks; pi.pos_x = x; @@ -102,6 +147,21 @@ static int osdl_setup_omapfb(struct omapfb_state *ostate, int fd, int enabled, return 0; } +static int osdl_setup_omapfb_enable(struct omapfb_state *ostate, + int fd, int enabled) +{ + int ret; + + switch_tv_layer(ostate, 1); + + ostate->pi.enabled = enabled; + ret = ioctl(fd, OMAPFB_SETUP_PLANE, &ostate->pi); + if (ret != 0) + err_perror("SETUP_PLANE"); + + return ret; +} + static int read_sysfs(const char *fname, char *buff, size_t size) { FILE *f; @@ -277,7 +337,7 @@ static int osdl_setup_omap_layer(struct SDL_PrivateVideoData *pdata, } /* FIXME: assuming layer doesn't change here */ - if (pdata->saved_layer == NULL) { + if (pdata->layer_state == NULL) { struct omapfb_state *slayer; slayer = calloc(1, sizeof(*slayer)); if (slayer == NULL) @@ -295,18 +355,33 @@ static int osdl_setup_omap_layer(struct SDL_PrivateVideoData *pdata, goto out; } - pdata->saved_layer = slayer; + pdata->layer_state = slayer; } tmp = getenv("SDL_OMAP_LAYER_SIZE"); if (tmp != NULL) { - if (strcasecmp(tmp, "fullscreen") == 0) + if (strcasecmp(tmp, "fullscreen") == 0) { w = screen_w, h = screen_h; - else if (sscanf(tmp, "%dx%d", &tmp_w, &tmp_h) == 2) + } + else if (strcasecmp(tmp, "scaled") == 0) { + float factor = MIN(((float)screen_w) / width, ((float)screen_h) / height); + w = (int)(factor*width), h = (int)(factor*height); + } + else if (strcasecmp(tmp, "pixelperfect") == 0) { + 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); + } + } + else if (sscanf(tmp, "%dx%d", &tmp_w, &tmp_h) == 2) { w = tmp_w, h = tmp_h; - else + } + else { err("layer size specified incorrectly, " "should be like 800x480"); + } } /* the layer can't be set larger than screen */ @@ -320,7 +395,7 @@ static int osdl_setup_omap_layer(struct SDL_PrivateVideoData *pdata, x = screen_w / 2 - w / 2; y = screen_h / 2 - h / 2; - ret = osdl_setup_omapfb(pdata->saved_layer, fd, 1, x, y, w, h, + ret = osdl_setup_omapfb(pdata->layer_state, fd, 0, x, y, w, h, width * height * ((bpp + 7) / 8), buffer_count); if (ret == 0) { pdata->layer_x = x; @@ -386,6 +461,13 @@ void *osdl_video_set_mode(struct SDL_PrivateVideoData *pdata, } } + ret = osdl_setup_omapfb_enable(pdata->layer_state, + vout_fbdev_get_fd(pdata->fbdev), 1); + if (ret != 0) { + err("layer enable failed"); + goto fail; + } + if (buffers_try != buffers_set) { log("only %d/%d buffers available, expect tearing\n", buffers_set, buffers_try); @@ -414,9 +496,17 @@ void *osdl_video_flip(struct SDL_PrivateVideoData *pdata) return ret; } +void *osdl_video_get_active_buffer(struct SDL_PrivateVideoData *pdata) +{ + if (pdata->fbdev == NULL) + return NULL; + + return vout_fbdev_get_active_mem(pdata->fbdev); +} + int osdl_video_pause(struct SDL_PrivateVideoData *pdata, int is_pause) { - struct omapfb_state *state = pdata->saved_layer; + struct omapfb_state *state = pdata->layer_state; struct omapfb_plane_info pi; struct omapfb_mem_info mi; int enabled; @@ -477,6 +567,11 @@ int osdl_video_pause(struct SDL_PrivateVideoData *pdata, int is_pause) return 0; } +int osdl_video_get_window(void **display, int *screen, void **window) +{ + return xenv_get_window(display, screen, window); +} + void osdl_video_finish(struct SDL_PrivateVideoData *pdata) { static const char *fbname; @@ -488,10 +583,13 @@ void osdl_video_finish(struct SDL_PrivateVideoData *pdata) } /* restore the OMAP layer */ - if (pdata->saved_layer != NULL) { - struct omapfb_state *slayer = pdata->saved_layer; + if (pdata->layer_state != NULL) { + struct omapfb_state *slayer = pdata->layer_state; int fd; + if (slayer->tv_layer) + switch_tv_layer(slayer, 0); + fd = open(fbname, O_RDWR); if (fd != -1) { int enabled = slayer->pi_old.enabled; @@ -507,7 +605,7 @@ void osdl_video_finish(struct SDL_PrivateVideoData *pdata) close(fd); } free(slayer); - pdata->saved_layer = NULL; + pdata->layer_state = NULL; } if (pdata->xenv_up) {