#include <fcntl.h>
#include <sys/ioctl.h>
+#include "../arm/neon_scale2x.h"
+#include "../arm/neon_scale3x.h"
+#include "../arm/neon_eagle2x.h"
#include "linux/fbdev.h"
#include "linux/xenv.h"
};
struct vout_fbdev *fb;
+static void *fb_current;
+static int bounce_buf[400 * 272 * 2 / 4];
+static int src_w = 240, src_h = 160;
+static enum software_filter {
+ SWFILTER_NONE = 0,
+ SWFILTER_SCALE2X,
+ SWFILTER_SCALE3X,
+ SWFILTER_EAGLE2X,
+} sw_filter;
-static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h, int first_call)
+// (240*3 * 160*3 * 2 * 3)
+#define MAX_VRAM_SIZE (400*2 * 272*2 * 2 * 3)
+
+
+static int omap_setup_layer(int fd, int enabled, int x, int y, int w, int h)
{
struct omapfb_plane_info pi = { 0, };
struct omapfb_mem_info mi = { 0, };
perror("SETUP_PLANE");
}
- if (first_call) {
- mi.size = 640*512*3*3;
+ /* alloc enough for 3x scaled tripple buffering */
+ if (mi.size < MAX_VRAM_SIZE) {
+ mi.size = MAX_VRAM_SIZE;
ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
if (ret != 0) {
perror("SETUP_MEM");
exit(1);
}
- ret = omap_setup_layer(fd, 0, 0, 0, 400, 272, 1);
+ ret = omap_setup_layer(fd, 0, 0, 0, 400, 272);
close(fd);
if (ret != 0) {
fprintf(stderr, "failed to set up layer, exiting.\n");
exit(1);
}
- w = 240;
- h = 160;
- fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 4);
+ // double of original menu size
+ w = 400*2;
+ h = 272*2;
+ fb = vout_fbdev_init("/dev/fb1", &w, &h, 16, 3);
if (fb == NULL) {
fprintf(stderr, "vout_fbdev_init failed\n");
exit(1);
void gpsp_plat_quit(void)
{
xenv_finish();
- omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0, 0);
+ omap_setup_layer(vout_fbdev_get_fd(fb), 0, 0, 0, 0, 0);
vout_fbdev_finish(fb);
SDL_Quit();
}
void *fb_flip_screen(void)
{
- return vout_fbdev_flip(fb);
+ void *ret = bounce_buf;
+ void *s = bounce_buf;
+
+ switch (sw_filter) {
+ case SWFILTER_SCALE2X:
+ neon_scale2x_16_16(s, fb_current, src_w, src_w*2, src_w*2*2, src_h);
+ break;
+ case SWFILTER_SCALE3X:
+ neon_scale3x_16_16(s, fb_current, src_w, src_w*2, src_w*3*2, src_h);
+ break;
+ case SWFILTER_EAGLE2X:
+ neon_eagle2x_16_16(s, fb_current, src_w, src_w*2, src_w*2*2, src_h);
+ break;
+ case SWFILTER_NONE:
+ default:
+ break;
+ }
+
+ fb_current = vout_fbdev_flip(fb);
+ if (sw_filter == SWFILTER_NONE)
+ ret = fb_current;
+
+ return ret;
}
void fb_wait_vsync(void)
vout_fbdev_wait_vsync(fb);
}
-void fb_set_mode(int w, int h, int buffers, int scale, int filter)
+void fb_set_mode(int w, int h, int buffers, int scale,
+ int filter, int filter2)
{
int lx, ly, lw = w, lh = h;
+ int multiplier;
+
switch (scale) {
case 0:
lw = w;
lh = 480;
break;
case 15:
- lw = w * 2;
- lh = h + h /2;
+ lw = 800;
+ lh = 480;
break;
default:
fprintf(stderr, "unknown scale: %d\n", scale);
lx = 800 / 2 - lw / 2;
ly = 480 / 2 - lh / 2;
- omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh, 0);
+ omap_setup_layer(vout_fbdev_get_fd(fb), 1, lx, ly, lw, lh);
set_filter(filter);
- vout_fbdev_resize(fb, w, h, 16, 0, 0, 0, 0, buffers);
+ sw_filter = filter2;
+ if (w != 240) // menu
+ sw_filter = SWFILTER_SCALE2X;
+
+ switch (sw_filter) {
+ case SWFILTER_SCALE2X:
+ multiplier = 2;
+ break;
+ case SWFILTER_SCALE3X:
+ multiplier = 3;
+ break;
+ case SWFILTER_EAGLE2X:
+ multiplier = 2;
+ break;
+ case SWFILTER_NONE:
+ default:
+ multiplier = 1;
+ break;
+ }
+
+ fb_current = vout_fbdev_resize(fb, w * multiplier, h * multiplier,
+ 16, 0, 0, 0, 0, buffers);
+ src_w = w;
+ src_h = h;
}
// vim:shiftwidth=2:expandtab