Added a new OpenGL feature (I promise, this is the last new feature before

the 1.4 release :)  The commandline argument '-gl_fsmax true|false' determines
how fullscreen OpenGL mode works:

 - if gl_fsmax is false (the default), the screenmode used will be the closest
   one that matches the image dimensions.  For example, if the image is 740x520
   and the closest matching resolution is 800x600, then 800x600 will be used.
   If your desktop resolution is not 800x600, there will be an (annoying)
   mode change.

 - if gl_fsmax is true, the screenmode used will be the largest one available
   for your videocard/monitor, with the logic being that most people use the
   maximum resolution for their desktop.  In this case, a mode change
   shouldn't be required.  The image is scaled so that there's at least 10%
   black area on all sides, which when used with the gl_aspect argument, can
   provide a very authentic looking emulation experience.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@286 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2004-06-27 22:44:04 +00:00
parent 76e5371bb3
commit b68b555b7a
4 changed files with 114 additions and 61 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.cxx,v 1.5 2004-06-23 03:43:47 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.6 2004-06-27 22:43:49 stephena Exp $
//============================================================================
#include <SDL.h>
@ -30,6 +30,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGL::FrameBufferGL()
: myTexture(0),
myScreenmode(0),
myScreenmodeCount(0),
myFilterParam(GL_NEAREST)
{
}
@ -53,30 +55,13 @@ bool FrameBufferGL::createScreen()
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
uInt32 screenWidth = 0;
uInt32 screenHeight = 0;
uInt32 screenWidth = 0;
uInt32 screenHeight = 0;
GLdouble orthoWidth = 0.0;
GLdouble orthoHeight = 0.0;
myDimensions.w = (Uint16) (myWidth * theZoomLevel * theAspectRatio);
myDimensions.h = (Uint16) myHeight * theZoomLevel;
// Determine if we're in fullscreen or windowed mode
// In fullscreen mode, we clip the SDL screen to known resolutions
// In windowed mode, we use the actual image resolution for the SDL screen
if(mySDLFlags & SDL_FULLSCREEN)
{
SDL_Rect rect = viewport(myDimensions.w, myDimensions.h);
myDimensions.x = rect.x;
myDimensions.y = rect.y;
screenWidth = rect.w;
screenHeight = rect.h;
}
else
{
myDimensions.x = myDimensions.y = 0;
screenWidth = myDimensions.w;
screenHeight = myDimensions.h;
}
// Get the screen coordinates
viewport(&screenWidth, &screenHeight, &orthoWidth, &orthoHeight);
myScreen = SDL_SetVideoMode(screenWidth, screenHeight, 0, mySDLFlags);
if(myScreen == NULL)
@ -94,8 +79,7 @@ bool FrameBufferGL::createScreen()
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (GLdouble) myDimensions.w/(theZoomLevel * theAspectRatio),
(GLdouble) myDimensions.h/theZoomLevel, 0.0, 0.0, 1.0);
glOrtho(0.0, orthoWidth, orthoHeight, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
@ -201,6 +185,12 @@ bool FrameBufferGL::init()
break;
}
// Get the valid OpenGL screenmodes
myScreenmode = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_OPENGL);
if((myScreenmode != (SDL_Rect**) -1) && (myScreenmode != (SDL_Rect**) 0))
for(uInt32 i = 0; myScreenmode[i]; ++i)
myScreenmodeCount++;
// Create the screen
if(!createScreen())
return false;
@ -512,42 +502,93 @@ void FrameBufferGL::toggleFilter()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SDL_Rect FrameBufferGL::viewport(uInt32 width, uInt32 height)
void FrameBufferGL::viewport(uInt32* screenWidth, uInt32* screenHeight,
GLdouble* orthoWidth, GLdouble* orthoHeight)
{
SDL_Rect rect;
rect.x = rect.y = 0;
rect.w = width; rect.h = height;
struct Screenmode
// Determine if we're in fullscreen or windowed mode
// In fullscreen mode, we clip the SDL screen to known resolutions
// In windowed mode, we use the actual image resolution for the SDL screen
if(mySDLFlags & SDL_FULLSCREEN)
{
uInt32 w;
uInt32 h;
};
Uint16 iwidth = (Uint16) (myWidth * theZoomLevel * theAspectRatio);
Uint16 iheight = (Uint16) (myHeight * theZoomLevel);
Uint16 swidth = 0;
Uint16 sheight = 0;
float scaleX = 0.0f;
float scaleY = 0.0f;
float scale = 1.0f;
// List of valid fullscreen OpenGL modes
Screenmode myScreenmode[6] = {
{320, 240 },
{640, 480 },
{800, 600 },
{1024, 768 },
{1280, 1024},
{1600, 1200}
};
/* cerr << "original image width = " << iwidth << endl
<< "original image height = " << iheight << endl
<< endl; */
for(uInt32 i = 0; i < 6; i++)
{
if(width <= myScreenmode[i].w && height <= myScreenmode[i].h)
if(myConsole->settings().getBool("gl_fsmax") &&
myScreenmode != (SDL_Rect**) -1)
{
rect.x = (myScreenmode[i].w - width) / 2;
rect.y = (myScreenmode[i].h - height) / 2;
rect.w = myScreenmode[i].w;
rect.h = myScreenmode[i].h;
// Use the largest available screen size
swidth = myScreenmode[0]->w;
sheight = myScreenmode[0]->h;
return rect;
scaleX = float(iwidth) / swidth;
scaleY = float(iheight) / sheight;
// Figure out which dimension is closest to the 10% mark,
// and calculate the scaling required to bring it to exactly 10%
if(scaleX > scaleY)
scale = (swidth * 0.9) / iwidth;
else
scale = (sheight * 0.9) / iheight;
iwidth = (Uint16) (scale * iwidth);
iheight = (Uint16) (scale * iheight);
}
else if(myScreenmode == (SDL_Rect**) -1)
{
// All modes are available, so use the exact image resolution
swidth = iwidth;
sheight = iheight;
}
else // otherwise, search for a valid screenmode
{
for(uInt32 i = myScreenmodeCount-1; i >= 0; i--)
{
if(iwidth <= myScreenmode[i]->w && iheight <= myScreenmode[i]->h)
{
swidth = myScreenmode[i]->w;
sheight = myScreenmode[i]->h;
break;
}
}
}
}
// If we get here, it probably indicates an error
// But we have to return something ...
return rect;
/* cerr << "image width = " << iwidth << endl
<< "image height = " << iheight << endl
<< "screen width = " << swidth << endl
<< "screen height = " << sheight << endl
<< "scale factor = " << scale << endl
<< endl; */
// Now calculate the OpenGL coordinates
myDimensions.x = (swidth - iwidth) / 2;
myDimensions.y = (sheight - iheight) / 2;
myDimensions.w = iwidth;
myDimensions.h = iheight;
*screenWidth = swidth;
*screenHeight = sheight;
*orthoWidth = (GLdouble) (myDimensions.w / (theZoomLevel * theAspectRatio * scale));
*orthoHeight = (GLdouble) (myDimensions.h / (theZoomLevel * scale));
}
else
{
myDimensions.x = 0;
myDimensions.y = 0;
myDimensions.w = (Uint16) (myWidth * theZoomLevel * theAspectRatio);
myDimensions.h = (Uint16) myHeight * theZoomLevel;
*screenWidth = myDimensions.w;
*screenHeight = myDimensions.h;
*orthoWidth = (GLdouble) (myDimensions.w / (theZoomLevel * theAspectRatio));
*orthoHeight = (GLdouble) (myDimensions.h / theZoomLevel);
}
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.hxx,v 1.3 2004-06-23 00:15:32 stephena Exp $
// $Id: FrameBufferGL.hxx,v 1.4 2004-06-27 22:44:04 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GL_HXX
@ -34,7 +34,7 @@ class MediaSource;
This class implements an SDL OpenGL framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.3 2004-06-23 00:15:32 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.4 2004-06-27 22:44:04 stephena Exp $
*/
class FrameBufferGL : public FrameBufferSDL
{
@ -141,7 +141,8 @@ class FrameBufferGL : public FrameBufferSDL
bool createTextures();
SDL_Rect viewport(uInt32 width, uInt32 height);
void viewport(uInt32* screenWidth, uInt32* screenHeight,
GLdouble* orthoWidth, GLdouble* orthoHeight);
uInt32 power_of_two(uInt32 input)
{
@ -155,6 +156,12 @@ class FrameBufferGL : public FrameBufferSDL
// The main texture buffer
SDL_Surface* myTexture;
// The possible OpenGL screenmodes to use
SDL_Rect** myScreenmode;
// The number of usable OpenGL screenmodes
uInt32 myScreenmodeCount;
// The depth of the texture buffer
uInt32 myDepth;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBuffer.cxx,v 1.9 2004-06-23 03:43:47 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.10 2004-06-27 22:44:04 stephena Exp $
//============================================================================
#include <sstream>
@ -355,6 +355,10 @@ void FrameBuffer::sendKeyEvent(StellaEvent::KeyCode key, Int32 state)
moveCursorUp(1);
else if(key == StellaEvent::KCODE_DOWN)
moveCursorDown(1);
else if(key == StellaEvent::KCODE_PAGEUP)
moveCursorUp(4);
else if(key == StellaEvent::KCODE_PAGEDOWN)
moveCursorDown(4);
break; // MAIN_MENU

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Settings.cxx,v 1.21 2004-06-13 16:51:15 stephena Exp $
// $Id: Settings.cxx,v 1.22 2004-06-27 22:44:04 stephena Exp $
//============================================================================
#include <cassert>
@ -41,6 +41,7 @@ Settings::Settings()
#ifdef DISPLAY_OPENGL
set("gl_filter", "nearest");
set("gl_aspect", "2");
set("gl_fsmax", "false");
#endif
set("sound", "true");
set("fragsize", "512");