mirror of https://github.com/snes9xgit/snes9x.git
Add opengl backend support to SDL target.
This commit is contained in:
parent
5fd51d76f5
commit
281e5eca52
File diff suppressed because it is too large
Load Diff
|
@ -111,6 +111,21 @@ AC_S9X_COMPILER_FLAG([-Wall], [Wall])
|
||||||
AC_S9X_COMPILER_FLAG([-W], [W])
|
AC_S9X_COMPILER_FLAG([-W], [W])
|
||||||
AC_S9X_COMPILER_FLAG([-Wno-unused-parameter], [Wno_unused_parameter])
|
AC_S9X_COMPILER_FLAG([-Wno-unused-parameter], [Wno_unused_parameter])
|
||||||
|
|
||||||
|
# Enable OpenGL backend
|
||||||
|
|
||||||
|
S9XOPENGL="#S9XOPENGL=1"
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([opengl],
|
||||||
|
[AS_HELP_STRING([--enable-opengl],
|
||||||
|
[enable opengl (default: yes)])],
|
||||||
|
[], [enable_opengl="yes"])
|
||||||
|
|
||||||
|
if test "x$enable_opengl" = "xyes"; then
|
||||||
|
S9XOPENGL="S9XOPENGL=1"
|
||||||
|
S9XDEFS="$S9XDEFS -DUSE_OPENGL"
|
||||||
|
S9XLIBS="$S9XLIBS -lGL"
|
||||||
|
fi
|
||||||
|
|
||||||
# Enable debugger.
|
# Enable debugger.
|
||||||
|
|
||||||
S9XDEBUGGER="#S9XDEBUGGER=1"
|
S9XDEBUGGER="#S9XDEBUGGER=1"
|
||||||
|
@ -389,6 +404,7 @@ defines.............. $S9XDEFS
|
||||||
libs................. $S9XLIBS
|
libs................. $S9XLIBS
|
||||||
|
|
||||||
features:
|
features:
|
||||||
|
opengl support....... $enable_opengl
|
||||||
screenshot support... $enable_screenshot
|
screenshot support... $enable_screenshot
|
||||||
netplay support...... $enable_netplay
|
netplay support...... $enable_netplay
|
||||||
GZIP support......... $enable_gzip
|
GZIP support......... $enable_gzip
|
||||||
|
|
159
sdl/sdlvideo.cpp
159
sdl/sdlvideo.cpp
|
@ -52,6 +52,11 @@
|
||||||
|
|
||||||
#include "sdl_snes9x.h"
|
#include "sdl_snes9x.h"
|
||||||
|
|
||||||
|
// grkenn - opengl backend
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
#include <SDL/SDL_opengl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct GUIData
|
struct GUIData
|
||||||
{
|
{
|
||||||
SDL_Surface *sdl_screen;
|
SDL_Surface *sdl_screen;
|
||||||
|
@ -59,7 +64,15 @@ struct GUIData
|
||||||
uint8 *blit_screen;
|
uint8 *blit_screen;
|
||||||
uint32 blit_screen_pitch;
|
uint32 blit_screen_pitch;
|
||||||
int video_mode;
|
int video_mode;
|
||||||
|
|
||||||
bool8 fullscreen;
|
bool8 fullscreen;
|
||||||
|
bool8 double_buffer;
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
bool8 opengl;
|
||||||
|
GLint gl_filter;
|
||||||
|
GLuint texture;
|
||||||
|
GLuint displaylist;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static struct GUIData GUI;
|
static struct GUIData GUI;
|
||||||
|
|
||||||
|
@ -96,7 +109,12 @@ static void Repaint (bool8);
|
||||||
|
|
||||||
void S9xExtraDisplayUsage (void)
|
void S9xExtraDisplayUsage (void)
|
||||||
{
|
{
|
||||||
S9xMessage(S9X_INFO, S9X_USAGE, "-fullscreen fullscreen mode (without scaling)");
|
S9xMessage(S9X_INFO, S9X_USAGE, "-fullscreen fullscreen mode");
|
||||||
|
S9xMessage(S9X_INFO, S9X_USAGE, "-double_buffer SDL double-buffering");
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
S9xMessage(S9X_INFO, S9X_USAGE, "-opengl opengl scaling (no filter)");
|
||||||
|
S9xMessage(S9X_INFO, S9X_USAGE, "-opengl_linear opengl scaling (bilinear)");
|
||||||
|
#endif
|
||||||
S9xMessage(S9X_INFO, S9X_USAGE, "");
|
S9xMessage(S9X_INFO, S9X_USAGE, "");
|
||||||
S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)");
|
S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)");
|
||||||
S9xMessage(S9X_INFO, S9X_USAGE, "-v2 Video mode: TV");
|
S9xMessage(S9X_INFO, S9X_USAGE, "-v2 Video mode: TV");
|
||||||
|
@ -111,6 +129,23 @@ void S9xExtraDisplayUsage (void)
|
||||||
|
|
||||||
void S9xParseDisplayArg (char **argv, int &i, int argc)
|
void S9xParseDisplayArg (char **argv, int &i, int argc)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
if (!strncasecmp(argv[i], "-opengl", 7))
|
||||||
|
{
|
||||||
|
GUI.opengl = TRUE;
|
||||||
|
GUI.gl_filter = GL_NEAREST;
|
||||||
|
if (!strncasecmp(argv[i], "-opengl_linear", 14))
|
||||||
|
{
|
||||||
|
GUI.gl_filter = GL_LINEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (!strncasecmp(argv[i], "-double_buffer", 14))
|
||||||
|
{
|
||||||
|
GUI.double_buffer = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
if (!strncasecmp(argv[i], "-fullscreen", 11))
|
if (!strncasecmp(argv[i], "-fullscreen", 11))
|
||||||
{
|
{
|
||||||
GUI.fullscreen = TRUE;
|
GUI.fullscreen = TRUE;
|
||||||
|
@ -186,11 +221,17 @@ void S9xInitDisplay (int argc, char **argv)
|
||||||
* FIXME: The secreen size should be flexible
|
* FIXME: The secreen size should be flexible
|
||||||
* FIXME: Check if the SDL screen is really in RGB565 mode. screen->fmt
|
* FIXME: Check if the SDL screen is really in RGB565 mode. screen->fmt
|
||||||
*/
|
*/
|
||||||
|
// grkenn - mode flags should be either OPENGL or (hwsurface with (double-buffer or none))
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
int MODE_FLAGS = (GUI.opengl == TRUE ? SDL_OPENGL : SDL_HWSURFACE | (GUI.double_buffer == TRUE ? SDL_DOUBLEBUF : 0));
|
||||||
|
#else
|
||||||
|
int MODE_FLAGS = SDL_HWSURFACE | (GUI.double_buffer == TRUE ? SDL_DOUBLEBUF : 0);
|
||||||
|
#endif
|
||||||
if (GUI.fullscreen == TRUE)
|
if (GUI.fullscreen == TRUE)
|
||||||
{
|
{
|
||||||
GUI.sdl_screen = SDL_SetVideoMode(0, 0, 16, SDL_FULLSCREEN);
|
GUI.sdl_screen = SDL_SetVideoMode(0, 0, 16, SDL_FULLSCREEN | MODE_FLAGS);
|
||||||
} else {
|
} else {
|
||||||
GUI.sdl_screen = SDL_SetVideoMode(SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 16, 0);
|
GUI.sdl_screen = SDL_SetVideoMode(SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 16, MODE_FLAGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GUI.sdl_screen == NULL)
|
if (GUI.sdl_screen == NULL)
|
||||||
|
@ -199,6 +240,18 @@ void S9xInitDisplay (int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grkenn - set up opengl params
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
if (GUI.opengl == TRUE)
|
||||||
|
{
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 0 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, (GUI.double_buffer == TRUE) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* domaemon
|
* domaemon
|
||||||
*
|
*
|
||||||
|
@ -233,16 +286,99 @@ static void SetupImage (void)
|
||||||
{
|
{
|
||||||
TakedownImage();
|
TakedownImage();
|
||||||
|
|
||||||
|
// FIXME: grkenn - SDL offers nice methods for creating (possibly hw-accel)
|
||||||
|
// drawing surfaces, we should use those instead of a raw buffer o' bytes
|
||||||
|
|
||||||
// domaemon: The whole unix code basically assumes output=(original * 2);
|
// domaemon: The whole unix code basically assumes output=(original * 2);
|
||||||
// This way the code can handle the SNES filters, which does the 2X.
|
// This way the code can handle the SNES filters, which does the 2X.
|
||||||
GFX.Pitch = SNES_WIDTH * 2 * 2;
|
int SNES_FULL_WIDTH = SNES_WIDTH * 2;
|
||||||
GUI.snes_buffer = (uint8 *) calloc(GFX.Pitch * ((SNES_HEIGHT_EXTENDED + 4) * 2), 1);
|
int SNES_FULL_HEIGHT = (SNES_HEIGHT_EXTENDED + 4) * 2;
|
||||||
|
GFX.Pitch = SNES_FULL_WIDTH * 2;
|
||||||
|
GUI.snes_buffer = (uint8 *) calloc(GFX.Pitch * SNES_FULL_HEIGHT, 1);
|
||||||
if (!GUI.snes_buffer)
|
if (!GUI.snes_buffer)
|
||||||
FatalError("Failed to allocate GUI.snes_buffer.");
|
FatalError("Failed to allocate GUI.snes_buffer.");
|
||||||
|
|
||||||
// domaemon: Add 2 lines before drawing.
|
// domaemon: Add 2 lines before drawing.
|
||||||
GFX.Screen = (uint16 *) (GUI.snes_buffer + (GFX.Pitch * 2 * 2));
|
GFX.Screen = (uint16 *) (GUI.snes_buffer + (GFX.Pitch * 2 * 2));
|
||||||
|
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
if (GUI.opengl == TRUE)
|
||||||
|
{
|
||||||
|
// enable GL texturing
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
// create opengl texture
|
||||||
|
glGenTextures(1, &GUI.texture);
|
||||||
|
// attach to texture
|
||||||
|
glBindTexture(GL_TEXTURE_2D, GUI.texture);
|
||||||
|
// set texture parameters
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GUI.gl_filter); // Filter modes
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GUI.gl_filter);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
// Compute next-highest power-of-2 for holding SNES buffer output
|
||||||
|
int tex_width = 1;
|
||||||
|
while(tex_width < SNES_FULL_WIDTH) tex_width *= 2;
|
||||||
|
int tex_height = 1;
|
||||||
|
while(tex_height < SNES_FULL_HEIGHT) tex_width *= 2;
|
||||||
|
|
||||||
|
// Fill the texture with empty data first
|
||||||
|
uint16 *empty = (uint16 *)calloc(tex_width*tex_height,sizeof(uint16));
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, empty);
|
||||||
|
free(empty);
|
||||||
|
|
||||||
|
// Setup screen view based on display size.
|
||||||
|
// Set the clear color to all black (0, 0, 0)
|
||||||
|
glClearColor(0.0f,0.0f,0.0f,1.0f);
|
||||||
|
|
||||||
|
SDL_Surface *screen = SDL_GetVideoSurface();
|
||||||
|
glViewport(0,0,screen->w,screen->h);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
//glLoadIdentity();
|
||||||
|
// Compute the actual screen aspect ratio, and letter/pillarbox glOrtho to fit.
|
||||||
|
double screenAspect = (double)screen->w/screen->h;
|
||||||
|
double snesAspect = (double)SNES_FULL_WIDTH/SNES_FULL_HEIGHT;
|
||||||
|
|
||||||
|
GLuint x_off=0,y_off=0;
|
||||||
|
|
||||||
|
if (screenAspect > snesAspect)
|
||||||
|
{
|
||||||
|
// widescreen monitor, 4:3 snes
|
||||||
|
// match height, scale width
|
||||||
|
glOrtho(0,SNES_FULL_HEIGHT*screenAspect,SNES_FULL_HEIGHT,0,-1.0f,1.0f);
|
||||||
|
x_off=((SNES_FULL_HEIGHT*screenAspect)-SNES_FULL_WIDTH) / 2;
|
||||||
|
} else {
|
||||||
|
// narrow monitor, 4:3 snes
|
||||||
|
// match width, scale height
|
||||||
|
// grkenn FIXME: TODO: this calculation is wrong wrong wrong
|
||||||
|
glOrtho(0,SNES_FULL_WIDTH,SNES_FULL_WIDTH*screenAspect,0,-1.0f,1.0f);
|
||||||
|
y_off = ((SNES_FULL_WIDTH*screenAspect)-SNES_FULL_HEIGHT) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
//glLoadIdentity();
|
||||||
|
|
||||||
|
// Create the display list to draw to the screen.
|
||||||
|
GUI.displaylist = glGenLists(1);
|
||||||
|
glNewList(GUI.displaylist,GL_COMPILE);
|
||||||
|
// clear screen
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0,0);
|
||||||
|
glVertex2i(x_off,y_off);
|
||||||
|
glTexCoord2f(1,0);
|
||||||
|
glVertex2i(x_off+SNES_FULL_WIDTH,y_off);
|
||||||
|
glTexCoord2f(1,1);
|
||||||
|
glVertex2i(x_off+SNES_FULL_WIDTH,y_off+SNES_FULL_HEIGHT);
|
||||||
|
glTexCoord2f(0,1);
|
||||||
|
glVertex2i(x_off,y_off+SNES_FULL_HEIGHT);
|
||||||
|
glEnd();
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
// All set!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (GUI.fullscreen == TRUE)
|
if (GUI.fullscreen == TRUE)
|
||||||
{
|
{
|
||||||
int offset_height_pix;
|
int offset_height_pix;
|
||||||
|
@ -326,6 +462,15 @@ void S9xPutImage (int width, int height)
|
||||||
// domaemon: this is place where the rendering buffer size should be changed?
|
// domaemon: this is place where the rendering buffer size should be changed?
|
||||||
blitFn((uint8 *) GFX.Screen, GFX.Pitch, GUI.blit_screen, GUI.blit_screen_pitch, width, height);
|
blitFn((uint8 *) GFX.Screen, GFX.Pitch, GUI.blit_screen, GUI.blit_screen_pitch, width, height);
|
||||||
|
|
||||||
|
// grkenn: TODO: no idea. But I did put opengl code here so that's something : )
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
if (GUI.opengl)
|
||||||
|
{
|
||||||
|
// update texture
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (uint8 *) GFX.Screen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// domaemon: does the height change on the fly?
|
// domaemon: does the height change on the fly?
|
||||||
if (height < prevHeight)
|
if (height < prevHeight)
|
||||||
{
|
{
|
||||||
|
@ -346,6 +491,10 @@ void S9xPutImage (int width, int height)
|
||||||
|
|
||||||
static void Repaint (bool8 isFrameBoundry)
|
static void Repaint (bool8 isFrameBoundry)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
if (GUI.opengl) { glCallList(GUI.displaylist); SDL_GL_SwapBuffers(); }
|
||||||
|
else
|
||||||
|
#endif
|
||||||
SDL_Flip(GUI.sdl_screen);
|
SDL_Flip(GUI.sdl_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue