Added framebuffer mapping. gsoc2009_ps3
authorMartin Lowinski <martin@goldtopf.org>
Thu, 12 Nov 2009 21:44:14 +0000
branchgsoc2009_ps3
changeset 3159 2632b7453516
parent 3158 30f3b987fec3
child 4406 ab53c78e0f3b
Added framebuffer mapping.
src/video/fbcon-1.3/SDL_fbmodes.c
src/video/fbcon-1.3/SDL_fbmodes_c.h
src/video/fbcon-1.3/SDL_fbrender.c
src/video/fbcon-1.3/SDL_fbvideo.c
src/video/fbcon-1.3/SDL_fbvideo.h
--- a/src/video/fbcon-1.3/SDL_fbmodes.c	Sat Nov 07 11:35:19 2009 +0000
+++ b/src/video/fbcon-1.3/SDL_fbmodes.c	Thu Nov 12 21:44:14 2009 +0000
@@ -21,110 +21,35 @@
 */
 #include "SDL_config.h"
 
-#include "SDL_ps3video.h"
+#include "SDL_fbvideo.h"
 
 void
-PS3_InitModes(_THIS)
+FB_InitModes(_THIS)
 {
-    deprintf(1, "+PS3_InitModes()\n");
+    deprintf(1, "+FB_InitModes()\n");
     SDL_VideoDisplay display;
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
     SDL_DisplayMode mode;
-    PS3_DisplayModeData *modedata;
-    unsigned long vid = 0;
-
-    modedata = (PS3_DisplayModeData *) SDL_malloc(sizeof(*modedata));
-    if (!modedata) {
-        return;
-    }
-
-    /* Setting up the DisplayMode based on current settings */
-    struct ps3fb_ioctl_res res;
-    if (ioctl(data->fbdev, PS3FB_IOCTL_SCREENINFO, &res)) {
-        SDL_SetError("Can't get PS3FB_IOCTL_SCREENINFO");
-    }
-    mode.format = SDL_PIXELFORMAT_RGB888;
-    mode.refresh_rate = 0;
-    mode.w = res.xres;
-    mode.h = res.yres;
-
-    /* Setting up driver specific mode data,
-     * Get the current ps3 specific videmode number */
-    if (ioctl(data->fbdev, PS3FB_IOCTL_GETMODE, (unsigned long)&vid)) {
-        SDL_SetError("Can't get PS3FB_IOCTL_GETMODE");
-    }
-    deprintf(2, "PS3FB_IOCTL_GETMODE = %u\n", vid);
-    modedata->mode = vid;
-    mode.driverdata = modedata;
-
-    /* Set display's videomode and add it */
-    SDL_zero(display);
-    display.desktop_mode = mode;
-    display.current_mode = mode;
-
-    SDL_AddVideoDisplay(&display);
-    deprintf(1, "-PS3_InitModes()\n");
+    deprintf(1, "-FB_InitModes()\n");
 }
 
-/* DisplayModes available on the PS3 */
-static SDL_DisplayMode ps3fb_modedb[] = {
-    /* VESA */
-    {SDL_PIXELFORMAT_RGB888, 1280, 768, 0, NULL}, // WXGA
-    {SDL_PIXELFORMAT_RGB888, 1280, 1024, 0, NULL}, // SXGA
-    {SDL_PIXELFORMAT_RGB888, 1920, 1200, 0, NULL}, // WUXGA
-    /* Native resolutions (progressive, "fullscreen") */
-    {SDL_PIXELFORMAT_RGB888, 720, 480, 0, NULL}, // 480p
-    {SDL_PIXELFORMAT_RGB888, 1280, 720, 0, NULL}, // 720p
-    {SDL_PIXELFORMAT_RGB888, 1920, 1080, 0, NULL} // 1080p
-};
-
-/* PS3 videomode number according to ps3fb_modedb */
-static PS3_DisplayModeData ps3fb_data[] = {
-    {11}, {12}, {13}, {130}, {131}, {133}, 
-};
-
 void
-PS3_GetDisplayModes(_THIS) {
-    deprintf(1, "+PS3_GetDisplayModes()\n");
-    SDL_DisplayMode mode;
-    unsigned int nummodes;
-
-    nummodes = sizeof(ps3fb_modedb) / sizeof(SDL_DisplayMode);
-
-    int n;
-    for (n=0; n<nummodes; ++n) {
-        /* Get driver specific mode data */
-        ps3fb_modedb[n].driverdata = &ps3fb_data[n];
-
-        /* Add DisplayMode to list */
-        deprintf(2, "Adding resolution %u x %u\n", ps3fb_modedb[n].w, ps3fb_modedb[n].h);
-        SDL_AddDisplayMode(_this->current_display, &ps3fb_modedb[n]);
-    }
-    deprintf(1, "-PS3_GetDisplayModes()\n");
+FB_GetDisplayModes(_THIS) {
+    deprintf(1, "+FB_GetDisplayModes()\n");
+    deprintf(1, "-FB_GetDisplayModes()\n");
 }
 
 int
-PS3_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
+FB_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
 {
-    deprintf(1, "+PS3_SetDisplayMode()\n");
-    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
-    PS3_DisplayModeData *dispdata = (PS3_DisplayModeData *) mode->driverdata;
-
-    /* Set the new DisplayMode */
-    deprintf(2, "Setting PS3FB_MODE to %u\n", dispdata->mode);
-    if (ioctl(data->fbdev, PS3FB_IOCTL_SETMODE, (unsigned long)&dispdata->mode)) {
-        deprintf(2, "Could not set PS3FB_MODE\n");
-        SDL_SetError("Could not set PS3FB_MODE\n");
-        return -1;
-    }
-
-    deprintf(1, "-PS3_SetDisplayMode()\n");
+    deprintf(1, "+FB_SetDisplayMode()\n");
+    deprintf(1, "-FB_SetDisplayMode()\n");
     return 0;
 }
 
 void
-PS3_QuitModes(_THIS) {
-    deprintf(1, "+PS3_QuitModes()\n");
+FB_QuitModes(_THIS) {
+    deprintf(1, "+FB_QuitModes()\n");
 
     /* There was no mem allocated for driverdata */
     int i, j;
@@ -135,7 +60,7 @@
         }
     }
 
-    deprintf(1, "-PS3_QuitModes()\n");
+    deprintf(1, "-FB_QuitModes()\n");
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/fbcon-1.3/SDL_fbmodes_c.h	Sat Nov 07 11:35:19 2009 +0000
+++ b/src/video/fbcon-1.3/SDL_fbmodes_c.h	Thu Nov 12 21:44:14 2009 +0000
@@ -21,14 +21,14 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_ps3modes_h
-#define _SDL_ps3modes_h
+#ifndef _SDL_fbmodes_h
+#define _SDL_fbmodes_h
 
-extern void PS3_InitModes(_THIS);
-extern void PS3_GetDisplayModes(_THIS);
-extern int PS3_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
-extern void PS3_QuitModes(_THIS);
+extern void FB_InitModes(_THIS);
+extern void FB_GetDisplayModes(_THIS);
+extern int FB_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
+extern void FB_QuitModes(_THIS);
 
-#endif /* SDL_ps3modes_h */
+#endif /* SDL_fbmodes_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/fbcon-1.3/SDL_fbrender.c	Sat Nov 07 11:35:19 2009 +0000
+++ b/src/video/fbcon-1.3/SDL_fbrender.c	Thu Nov 12 21:44:14 2009 +0000
@@ -232,14 +232,6 @@
     SDL_FB_RenderData *data =
         (SDL_FB_RenderData *) renderer->driverdata;
 
-    /* Send the data to the display */
-    if (SDL_getenv("SDL_VIDEO_FB_SAVE_FRAMES")) {
-        char file[128];
-        SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
-                     renderer->window, ++frame_number);
-        SDL_SaveBMP(data->screens[data->current_screen], file);
-    }
-
     /* Update the flipping chain, if any */
     if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
         data->current_screen = (data->current_screen + 1) % 2;
--- a/src/video/fbcon-1.3/SDL_fbvideo.c	Sat Nov 07 11:35:19 2009 +0000
+++ b/src/video/fbcon-1.3/SDL_fbvideo.c	Thu Nov 12 21:44:14 2009 +0000
@@ -54,9 +54,37 @@
 
 /* Initialization/Query functions */
 static int FB_VideoInit(_THIS);
-static int FB_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
 static void FB_VideoQuit(_THIS);
 
+static int
+SDL_getpagesize(void)
+{
+#ifdef HAVE_GETPAGESIZE
+    return getpagesize();
+#elif defined(PAGE_SIZE)
+    return PAGE_SIZE;
+#else
+#error Can not determine system page size.
+    /* this is what it USED to be in Linux... */
+    return 4096;
+#endif
+}
+
+
+/* Small wrapper for mmap() so we can play nicely with no-mmu hosts
+ * (non-mmu hosts disallow the MAP_SHARED flag) */
+static void *
+do_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+    void *ret;
+    ret = mmap(start, length, prot, flags, fd, offset);
+    if (ret == (char *) -1 && (flags & MAP_SHARED)) {
+        ret = mmap(start, length, prot,
+                   (flags & ~MAP_SHARED) | MAP_PRIVATE, fd, offset);
+    }
+    return ret;
+}
+
 /* bootstrap functions */
 static int
 FB_Available(void)
@@ -133,7 +161,7 @@
     return device;
 }
 
-VideoBootStrap FB_bootstrap = {
+VideoBootStrap FBCON_bootstrap = {
 	FBVID_DRIVER_NAME, "Linux framebuffer video driver",
 	FB_Available, FB_CreateDevice
 };
@@ -146,12 +174,14 @@
 	SDL_DisplayMode mode;
     struct fb_fix_screeninfo finfo;
     const char *SDL_fbdev;
+    const int pagesize = SDL_getpagesize();
 
     /* Initialize the library */
     SDL_fbdev = SDL_getenv("SDL_FBDEV");
     if (SDL_fbdev == NULL) {
         SDL_fbdev = "/dev/fb0";
     }
+    /* Open the device */
     data->console_fd = open(SDL_fbdev, O_RDWR, 0);
     if (data->console_fd < 0) {
         SDL_SetError("Unable to open %s", SDL_fbdev);
@@ -174,6 +204,41 @@
         return -1;
     }
 
+    switch (finfo.visual) {
+		case FB_VISUAL_TRUECOLOR:
+		case FB_VISUAL_PSEUDOCOLOR:
+		case FB_VISUAL_STATIC_PSEUDOCOLOR:
+		case FB_VISUAL_DIRECTCOLOR:
+			break;
+		default:
+			SDL_SetError("Unsupported console hardware");
+			FB_VideoQuit(_this);
+			return -1;
+    }
+
+    /* Check if the user wants to disable hardware acceleration
+	 * FIXME: Maybe better in fbrenderer? */
+    {
+        const char *fb_accel;
+        fb_accel = SDL_getenv("SDL_FBACCEL");
+        if (fb_accel) {
+            finfo.accel = SDL_atoi(fb_accel);
+        }
+    }
+
+    /* Memory map the device, compensating for buggy PPC mmap() */
+    data->mapped_offset = (((long) finfo.smem_start) -
+                     (((long) finfo.smem_start) & ~(pagesize - 1)));
+    data->mapped_memlen = finfo.smem_len + data->mapped_offset;
+    data->mapped_mem = (char*) do_mmap(NULL, data->mapped_memlen,
+                         PROT_READ | PROT_WRITE, MAP_SHARED, data->console_fd, 0);
+    if (data->mapped_mem == (char *) -1) {
+        SDL_SetError("Unable to memory map the video hardware");
+        data->mapped_mem = NULL;
+        FB_VideoQuit(_this);
+        return -1;
+    }
+
 	/* Use a fake 32-bpp desktop mode */
 	mode.format = SDL_PIXELFORMAT_RGB888;
 	mode.w = 1024;
@@ -191,18 +256,31 @@
 	return 0;
 }
 
-static int
-FB_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
-{
-    deprintf(1, "+FB_SetDisplayMode()\n");
-    deprintf(1, "-FB_SetDisplayMode()\n");
-	return 0;
-}
-
 void
 FB_VideoQuit(_THIS)
 {
     deprintf(1, "+FB_VideoQuit()\n");
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+    /* Clear the lock mutex */
+    if (data->hw_lock) {
+        SDL_DestroyMutex(data->hw_lock);
+        data->hw_lock = NULL;
+    }
+
+    /* Close console and input file descriptors */
+    if (data->console_fd > 0) {
+        /* Unmap the video framebuffer and I/O registers */
+        if (data->mapped_mem) {
+            munmap(data->mapped_mem, data->mapped_memlen);
+            data->mapped_mem = NULL;
+        }
+
+        /* We're all done with the framebuffer */
+        close(data->console_fd);
+        data->console_fd = -1;
+    }
+
     deprintf(1, "-FB_VideoQuit()\n");
 }
 
--- a/src/video/fbcon-1.3/SDL_fbvideo.h	Sat Nov 07 11:35:19 2009 +0000
+++ b/src/video/fbcon-1.3/SDL_fbvideo.h	Thu Nov 12 21:44:14 2009 +0000
@@ -58,6 +58,10 @@
     int console_fd;
     /* hardware surface lock mutex */
     SDL_mutex *hw_lock;
+    /* Framebuffer */
+    char *mapped_mem;
+    int mapped_memlen;
+    int mapped_offset;
 } SDL_VideoData;
 
 #endif /* _SDL_fbvideo_h */