SRB2/tools/SDL-1.2.14-gc/SDL-1.2.14-gc.patch

642 lines
16 KiB
Diff
Raw Permalink Normal View History

2014-03-15 16:59:03 +00:00
From 8e6ada7bc33e3cc4e1c17821ea171bf0815a505d Mon Sep 17 00:00:00 2001
From: Alam Arias <Alam.GBC@gmail.com>
Date: Tue, 1 Dec 2009 19:31:57 -0500
Subject: [PATCH] SDL GC hack
---
configure.in | 17 ++
include/SDL_config.h.in | 1 +
src/video/fbcon/SDL_fbgc.c | 471 +++++++++++++++++++++++++++++++++++++++++
src/video/fbcon/SDL_fbgc.h | 35 +++
src/video/fbcon/SDL_fbvideo.c | 10 +
src/video/fbcon/SDL_fbvideo.h | 11 +
6 files changed, 545 insertions(+), 0 deletions(-)
create mode 100644 src/video/fbcon/SDL_fbgc.c
create mode 100644 src/video/fbcon/SDL_fbgc.h
diff --git a/configure.in b/configure.in
index a7e9b18..a8961ba 100644
--- a/configure.in
+++ b/configure.in
@@ -1227,6 +1227,22 @@ AC_HELP_STRING([--enable-video-fbcon], [use framebuffer console video driver [[d
fi
}
+dnl See if we're running on Linux for the Nintendo GameCube/Wii
+dnl FIXME, perform a real test here...
+CheckGC()
+{
+ AC_ARG_ENABLE(video-gc,
+AC_HELP_STRING([--enable-video-gc], [enable GameCube video support in FB [[default=no]]]),
+ , enable_video_gc=no)
+ if test x$enable_video = xyes -a x$enable_video_gc = xyes -a x$video_fbcon = xyes; then
+ video_gc=yes
+ AC_MSG_RESULT($video_gc)
+ if test x$video_gc = xyes; then
+ AC_DEFINE(SDL_VIDEO_DRIVER_GC)
+ fi
+ fi
+}
+
dnl Find DirectFB
CheckDirectFB()
{
@@ -2322,6 +2338,7 @@ case "$host" in
CheckX11
CheckNANOX
CheckFBCON
+ CheckGC
CheckDirectFB
CheckPS2GS
CheckPS3
diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in
index 58593ca..e523e9b 100644
--- a/include/SDL_config.h.in
+++ b/include/SDL_config.h.in
@@ -262,6 +262,7 @@
#undef SDL_VIDEO_DRIVER_DUMMY
#undef SDL_VIDEO_DRIVER_FBCON
#undef SDL_VIDEO_DRIVER_GAPI
+#undef SDL_VIDEO_DRIVER_GC
#undef SDL_VIDEO_DRIVER_GEM
#undef SDL_VIDEO_DRIVER_GGI
#undef SDL_VIDEO_DRIVER_IPOD
diff --git a/src/video/fbcon/SDL_fbgc.c b/src/video/fbcon/SDL_fbgc.c
new file mode 100644
index 0000000..b3b72bb
--- /dev/null
+++ b/src/video/fbcon/SDL_fbgc.c
@@ -0,0 +1,471 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#ifdef SDL_VIDEO_DRIVER_GC
+#include <errno.h>
+#include "SDL_video.h"
+#include "../SDL_blit.h"
+#include "SDL_fbgc.h"
+
+static Uint32 r_Yr[256];
+static Uint32 g_Yg_[256];
+static Uint32 b_Yb[256];
+static Uint32 r_Ur[256];
+static Uint32 g_Ug_[256];
+static Uint32 b_Ub[256];
+/* static Uint32 r_Vr[256]; // space and cache optimisation */
+#define r_Vr b_Ub
+static Uint32 g_Vg_[256];
+static Uint32 b_Vb[256];
+
+static Uint8 RGB16toY[1 << 16];
+static Uint8 RGB16toU[1 << 16];
+static Uint8 RGB16toV[1 << 16];
+
+#ifndef FBIOFLIPHACK
+#define FBIOFLIPHACK 0x4623 /* gc-linux */
+#endif
+
+#ifndef GC_BLACK
+#define GC_BLACK 0x00800080
+#endif
+
+#ifdef GC_DEBUG
+# define GC_DPRINTF(fmt, args...) \
+ fprintf(stderr,"DDD|%s: " fmt, __FUNCTION__ , ## args)
+#else
+# define GC_DPRINTF(fmt, args...)
+#endif
+
+SDL_bool GC_Test(_THIS)
+{
+ int fliptest;
+ if (ioctl(console_fd, FBIOFLIPHACK, &fliptest))
+ return SDL_TRUE;
+ return SDL_FALSE;
+}
+
+SDL_bool GC_Available(void)
+{
+ if (access("/sys/bus/of_platform/drivers/gcn-vifb", 0) == 0)
+ return SDL_TRUE;
+
+ return SDL_FALSE;
+}
+
+/*
+ *
+ * Color space handling.
+ */
+
+#define RGB2YUV_SHIFT 16
+#define RGB2YUV_LUMA 16
+#define RGB2YUV_CHROMA 128
+
+#define Yr ((int)( 0.299*(1<<RGB2YUV_SHIFT)))
+#define Yg ((int)( 0.587*(1<<RGB2YUV_SHIFT)))
+#define Yb ((int)( 0.114*(1<<RGB2YUV_SHIFT)))
+
+#define Ur ((int)(-0.169*(1<<RGB2YUV_SHIFT)))
+#define Ug ((int)(-0.331*(1<<RGB2YUV_SHIFT)))
+#define Ub ((int)( 0.500*(1<<RGB2YUV_SHIFT)))
+
+#define Vr ((int)( 0.500*(1<<RGB2YUV_SHIFT))) /* same as Ub */
+#define Vg ((int)(-0.419*(1<<RGB2YUV_SHIFT)))
+#define Vb ((int)(-0.081*(1<<RGB2YUV_SHIFT)))
+
+#define clamp(x, y, z) ((z < x) ? x : ((z > y) ? y : z))
+
+static void GC_InitRGB2YUVTables(void)
+{
+ unsigned int i;
+ unsigned int r, g, b;
+
+ for (i = 0; i < 256; i++) {
+ r_Yr[i] = Yr * i;
+ g_Yg_[i] = Yg * i + (RGB2YUV_LUMA << RGB2YUV_SHIFT);
+ b_Yb[i] = Yb * i;
+ r_Ur[i] = Ur * i;
+ g_Ug_[i] = Ug * i + (RGB2YUV_CHROMA << RGB2YUV_SHIFT);
+ b_Ub[i] = Ub * i;
+ r_Vr[i] = Vr * i;
+ g_Vg_[i] = Vg * i + (RGB2YUV_CHROMA << RGB2YUV_SHIFT);
+ b_Vb[i] = Vb * i;
+ }
+
+ for (i = 0; i < 1 << 16; i++) {
+ /* RGB565 */
+ r = ((i >> 8) & 0xf8);
+ g = ((i >> 3) & 0xfc);
+ b = ((i << 3) & 0xf8);
+ /* extend to 8bit */
+ r |= (r >> 5);
+ g |= (g >> 6);
+ b |= (b >> 5);
+
+ RGB16toY[i] =
+ clamp(16, 235,
+ (r_Yr[r] + g_Yg_[g] + b_Yb[b]) >> RGB2YUV_SHIFT);
+ RGB16toU[i] =
+ clamp(16, 240,
+ (r_Ur[r] + g_Ug_[g] + b_Ub[b]) >> RGB2YUV_SHIFT);
+ RGB16toV[i] =
+ clamp(16, 240,
+ (r_Vr[r] + g_Vg_[g] + b_Vb[b]) >> RGB2YUV_SHIFT);
+ }
+}
+
+static inline Uint32 rgbrgb16toyuy2(Uint16 rgb1, Uint16 rgb2)
+{
+ register int Y1, Cb, Y2, Cr;
+ Uint16 rgb;
+
+ /* fast path, thanks to bohdy */
+ if (!(rgb1 | rgb2)) {
+ return GC_BLACK; /* black, black */
+ }
+
+ if (rgb1 == rgb2) {
+ /* fast path, thanks to isobel */
+ Y1 = Y2 = RGB16toY[rgb1];
+ Cb = RGB16toU[rgb1];
+ Cr = RGB16toV[rgb1];
+ } else {
+ Y1 = RGB16toY[rgb1];
+ Y2 = RGB16toY[rgb2];
+
+ /* RGB565 average */
+ rgb = ((rgb1 >> 1) & 0xFBEF) + ((rgb2 >> 1) & 0xFBEF) +
+ ((rgb1 & rgb2) & 0x0821);
+
+ Cb = RGB16toU[rgb];
+ Cr = RGB16toV[rgb];
+ }
+
+ return (((char)Y1) << 24) | (((char)Cb) << 16) | (((char)Y2) << 8)
+ | (((char)Cr) << 0);
+}
+
+/*
+ *
+ * Blitters.
+ */
+static void GC_UpdateRectRGB16(_THIS, SDL_Rect * rect, int pitch)
+{
+ int width, height, left, i, mod, mod32;
+ Uint8 *src, *dst;
+ Uint32 *src32, *dst32;
+ Uint16 *rgb;
+
+ /* XXX case width < 2 needs special treatment */
+
+ /* in pixel units */
+ left = rect->x & ~1; /* 2 pixel align */
+ width = (rect->w + 1) & ~1; /* 2 pixel align in excess */
+ height = rect->h;
+
+ /* in bytes, src and dest are 16bpp */
+ src = shadow_mem + (rect->y * pitch) + left * 2;
+ dst = flip_address[back_page] + page_offset +
+ (rect->y * pitch) + left * 2;
+ mod = pitch - width * 2;
+
+ src32 = (Uint32 *) src;
+ dst32 = (Uint32 *) dst;
+ mod32 = mod / 4;
+
+ while (height--) {
+ i = width / 2;
+
+ while (i--) {
+ rgb = (Uint16 *) src32;
+ *dst32++ = rgbrgb16toyuy2(rgb[0], rgb[1]);
+ src32++;
+ }
+ src32 += mod32;
+ dst32 += mod32;
+ }
+}
+
+void GC_Init(_THIS, SDL_PixelFormat *vformat)
+{
+ GC_InitRGB2YUVTables();
+
+ /* 16 bits per pixel */
+ vformat->BitsPerPixel = 16;
+ vformat->BytesPerPixel = 2;
+ /* RGB565 */
+ vformat->Rmask = 0x0000f800;
+ vformat->Gmask = 0x000007e0;
+ vformat->Bmask = 0x0000001f;
+
+ shadow_fb = 1;
+}
+
+/*
+ *
+ * Video mode handling.
+ */
+
+/* only 640x480 16bpp is currently supported */
+const static SDL_Rect RECT_640x480 = { 0, 0, 640, 480 };
+const static SDL_Rect *vid_modes[] = {
+ &RECT_640x480,
+ NULL
+};
+
+static SDL_Rect **GC_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
+{
+ switch (format->BitsPerPixel) {
+ case 16:
+ return (SDL_Rect **) vid_modes;
+ default:
+ return NULL;
+ }
+}
+
+SDL_Surface *GC_SetVideoMode(_THIS, SDL_Surface * current,
+ int width, int height, int bpp, Uint32 flags)
+{
+ struct fb_fix_screeninfo finfo;
+ struct fb_var_screeninfo vinfo;
+ int i;
+ Uint32 Rmask;
+ Uint32 Gmask;
+ Uint32 Bmask;
+ Uint32 *p, *q;
+ Uint32 yres;
+
+ GC_DPRINTF("Setting %dx%d %dbpp %smode\n", width, height, bpp,
+ (flags & SDL_DOUBLEBUF)?"(doublebuf) ":"");
+
+ /* Set the terminal into graphics mode */
+ if (FB_EnterGraphicsMode(this) < 0) {
+ return (NULL);
+ }
+
+ /* Restore the original palette */
+ //FB_RestorePalette(this);
+
+ /* Set the video mode and get the final screen format */
+ if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
+ SDL_SetError("Couldn't get console screen info");
+ return (NULL);
+ }
+
+ yres = vinfo.yres;
+
+ /* hack to center 640x480 resolution on PAL cubes */
+ if (vinfo.xres == 640 && vinfo.yres == 576) {
+ page_offset = ((576 - 480) / 2) * 640 * ((bpp + 7) / 8);
+ } else {
+ page_offset = 0;
+ }
+
+ /* clear all video memory */
+ p = (Uint32 *)mapped_mem;
+ q = (Uint32 *)(mapped_mem + mapped_memlen);
+ while (p < q)
+ *p++ = GC_BLACK;
+
+ if ((vinfo.xres != width) || (vinfo.yres != height) ||
+ (vinfo.bits_per_pixel != bpp)) {
+ vinfo.activate = FB_ACTIVATE_NOW;
+ vinfo.accel_flags = 0;
+ vinfo.bits_per_pixel = bpp;
+ vinfo.xres = width;
+ vinfo.xres_virtual = width;
+ /* do not modify yres*, we use a fake 640x480 mode in PAL */
+ //vinfo.yres = height;
+ //vinfo.yres_virtual = 2*height;
+ vinfo.xoffset = 0;
+ vinfo.yoffset = 0;
+ vinfo.red.length = vinfo.red.offset = 0;
+ vinfo.green.length = vinfo.green.offset = 0;
+ vinfo.blue.length = vinfo.blue.offset = 0;
+ vinfo.transp.length = vinfo.transp.offset = 0;
+
+ if (ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
+ SDL_SetError("Couldn't set console screen info");
+ return (NULL);
+ }
+ } else {
+ int maxheight;
+
+ /* Figure out how much video memory is available */
+ maxheight = 2*yres;
+ if (vinfo.yres_virtual > maxheight) {
+ vinfo.yres_virtual = maxheight;
+ }
+ }
+ cache_vinfo = vinfo;
+
+ Rmask = 0;
+ for (i = 0; i < vinfo.red.length; ++i) {
+ Rmask <<= 1;
+ Rmask |= (0x00000001 << vinfo.red.offset);
+ }
+ Gmask = 0;
+ for (i = 0; i < vinfo.green.length; ++i) {
+ Gmask <<= 1;
+ Gmask |= (0x00000001 << vinfo.green.offset);
+ }
+ Bmask = 0;
+ for (i = 0; i < vinfo.blue.length; ++i) {
+ Bmask <<= 1;
+ Bmask |= (0x00000001 << vinfo.blue.offset);
+ }
+ if (!SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0)) {
+ return (NULL);
+ }
+
+ /* Get the fixed information about the console hardware.
+ This is necessary since finfo.line_length changes.
+ */
+ if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
+ SDL_SetError("Couldn't get console hardware info");
+ return (NULL);
+ }
+
+ /* Save hardware palette, if needed */
+ //FB_SavePalette(this, &finfo, &vinfo);
+
+ /* Set up the new mode framebuffer */
+ current->flags = SDL_FULLSCREEN;
+ current->w = width;
+ current->h = height;
+ current->pitch = width * ((bpp + 7) / 8);
+ current->pixels = shadow_mem;
+
+ flip_address[0] = mapped_mem;
+ flip_address[1] = mapped_mem + current->pitch * yres;
+
+ back_page = 1;
+ if (flags & SDL_DOUBLEBUF) {
+ current->flags |= SDL_DOUBLEBUF;
+ flip_pending = 1;
+ } else {
+ flip_pending = 0;
+ /* make page 0 both the visible and back page */
+ back_page = ioctl(console_fd, FBIOFLIPHACK, &back_page);
+ if (back_page < 0)
+ back_page = 0;
+ }
+
+ /* Set the update rectangle function */
+ switch (bpp) {
+ case 16:
+ GC_DPRINTF("Using 16bpp blitter\n");
+ this->hidden->UpdateRect = GC_UpdateRectRGB16;
+ break;
+ default:
+ GC_DPRINTF("Using NO blitter\n");
+ this->hidden->UpdateRect = NULL;
+ break;
+ }
+
+ /* Handle OpenGL support */
+#ifdef HAVE_OPENGL
+ if (flags & SDL_OPENGL) {
+ if (GC_GL_CreateWindow(this, width, height) == 0) {
+ current->flags |= (SDL_OPENGL | SDL_FULLSCREEN);
+ } else {
+ current = NULL;
+ }
+ }
+#endif /* HAVE_OPENGL */
+
+ /* We're done */
+ return (current);
+}
+
+static int GC_FlipHWSurface(_THIS, SDL_Surface * surface)
+{
+ if (flip_pending) {
+ /* SDL_UpdateRect was not called */
+ SDL_UpdateRect(this->screen, 0, 0, 0, 0);
+ }
+
+ /* flip video page as soon as possible */
+ ioctl(console_fd, FBIOFLIPHACK, NULL);
+ flip_pending = 1;
+
+ return (0);
+}
+
+static void GC_WaitForFlipCompletion(_THIS)
+{
+ int visible_page;
+ int result;
+
+ if (flip_pending) {
+ flip_pending = 0;
+ back_page ^= 1;
+ visible_page = back_page;
+ while (visible_page == back_page) {
+ /* wait until back_page is not visible */
+ result = ioctl(console_fd, FBIOFLIPHACK, &back_page);
+ if (result < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ return; /* ioctl unsupported ... */
+ }
+ visible_page = result;
+ }
+ /*
+ * At this point the back_page is not visible. We can safely
+ * write to it without tearing.
+ */
+ }
+}
+
+static void GC_UpdateRects(_THIS, int numrects, SDL_Rect * rects)
+{
+ SDL_Surface *screen;
+ int pitch;
+
+ /* external yuy2 fb is 16bpp */
+
+ screen = this->screen;
+ pitch = screen->pitch; /* this is the pitch of the shadow buffer */
+
+ if (this->hidden->UpdateRect) {
+ GC_WaitForFlipCompletion(this);
+ while (numrects--) {
+ if (rects->w <= 0 || rects->h <= 0)
+ continue;
+ this->hidden->UpdateRect(this, rects, pitch);
+ rects++;
+ }
+ }
+}
+
+void GC_CreateDevice(SDL_VideoDevice *this)
+{
+ this->ListModes = GC_ListModes;
+ this->SetVideoMode = GC_SetVideoMode;
+ this->FlipHWSurface = GC_FlipHWSurface;
+ this->UpdateRects = GC_UpdateRects;
+}
+
+#endif
diff --git a/src/video/fbcon/SDL_fbgc.h b/src/video/fbcon/SDL_fbgc.h
new file mode 100644
index 0000000..534a73e
--- /dev/null
+++ b/src/video/fbcon/SDL_fbgc.h
@@ -0,0 +1,35 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2009 Sam Lantinga
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Sam Lantinga
+ slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+
+#ifdef SDL_VIDEO_DRIVER_GC
+/* Gamecube/Wii hardware setup for the SDL framebuffer console driver */
+
+#include "SDL_fbvideo.h"
+
+extern SDL_bool GC_Available(void);
+extern void GC_CreateDevice(SDL_VideoDevice *this);
+
+extern SDL_bool GC_Test(_THIS);
+extern void GC_Init(_THIS, SDL_PixelFormat *vformat);
+#endif
diff --git a/src/video/fbcon/SDL_fbvideo.c b/src/video/fbcon/SDL_fbvideo.c
index 81a89da..328790e 100644
--- a/src/video/fbcon/SDL_fbvideo.c
+++ b/src/video/fbcon/SDL_fbvideo.c
@@ -272,6 +272,11 @@ static SDL_VideoDevice *FB_CreateDevice(int devindex)
this->free = FB_DeleteDevice;
+#ifdef SDL_VIDEO_DRIVER_GC
+ if (GC_Available(this))
+ GC_CreateDevice(this);
+#endif
+
return this;
}
@@ -784,6 +789,11 @@ static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat)
}
}
+#ifdef SDL_VIDEO_DRIVER_GC
+ if (GC_Test(this))
+ GC_Init(this, vformat);
+#endif
+
if (shadow_fb) {
shadow_mem = (char *)SDL_malloc(mapped_memlen);
if (shadow_mem == NULL) {
diff --git a/src/video/fbcon/SDL_fbvideo.h b/src/video/fbcon/SDL_fbvideo.h
index 03b9e94..74d1460 100644
--- a/src/video/fbcon/SDL_fbvideo.h
+++ b/src/video/fbcon/SDL_fbvideo.h
@@ -106,6 +106,12 @@ struct SDL_PrivateVideoData {
void (*wait_vbl)(_THIS);
void (*wait_idle)(_THIS);
+#ifdef SDL_VIDEO_DRIVER_GC
+ void (*UpdateRect) (_THIS, SDL_Rect * rect, int pitch);
+ int back_page;
+ int page_offset;
+ int flip_pending;
+#endif
};
/* Old variable names */
#define console_fd (this->hidden->console_fd)
@@ -147,6 +153,11 @@ struct SDL_PrivateVideoData {
#define screen_palette (this->hidden->screen_palette)
#define wait_vbl (this->hidden->wait_vbl)
#define wait_idle (this->hidden->wait_idle)
+#ifdef SDL_VIDEO_DRIVER_GC
+#define back_page (this->hidden->back_page)
+#define page_offset (this->hidden->page_offset)
+#define flip_pending (this->hidden->flip_pending)
+#endif
/* Accelerator types that are supported by the driver, but are not
necessarily in the kernel headers on the system we compile on.
--
1.6.5