OK, SDL2 is in the building! This is the first pass at porting the code

to SDL2.  For now, there are many things broken, namely keyboard handling
and fullscreen modes.  But the launcher does show up, allows to start a
game and enter/exit the debugger, etc.

The code will only compile on Linux for now, and sometimes maybe not even
then.  Expect breakage on a regular basis over the next month or so.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2854 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-02-19 15:34:22 +00:00
parent 46733e32c0
commit a1ea1b0c96
15 changed files with 285 additions and 603 deletions

18
configure vendored
View File

@ -6,7 +6,7 @@
# * command line options to...
# - override the host settings (for cross compiles
# - whether to do a debug build (with -g) or an optimized build (-O3 etc.)
# * detect whether the chosen backend is available (e.g. call sdl-config)
# * detect whether the chosen backend is available (e.g. call sdl2-config)
# * ....
@ -42,10 +42,9 @@ _zip="zip -q"
_cp=cp
_windowspath=""
_windres=windres
_sdlconfig=sdl-config
_sdlconfig=sdl2-config
_sdlpath="$PATH"
_prefix=/usr/local
X_LIBS="/usr/X11R6/lib"
_srcdir=`dirname $0`
@ -124,13 +123,13 @@ add_line_to_config_mk() {
#
# Determine sdl-config
# Determine sdl2-config
#
# TODO: small bit of code to test sdl useability
find_sdlconfig()
{
echo_n "Looking for sdl-config... "
sdlconfigs="$_sdlconfig:sdl-config:sdl11-config:sdl12-config"
echo_n "Looking for sdl2-config... "
sdlconfigs="$_sdlconfig"
_sdlconfig=
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="$SEPARATOR"
@ -220,10 +219,9 @@ Optional Features:
--force-builtin-zlib force use of built-in zlib library [auto]
Optional Libraries:
--with-sdl-prefix=DIR Prefix where the sdl-config script is installed (optional)
--with-sdl-prefix=DIR Prefix where the sdl2-config script is installed (optional)
--with-libpng-prefix=DIR Prefix where libpng is installed (optional)
--with-zlib-prefix=DIR Prefix where zlib is installed (optional)
--x-libraries Path to X11 libraries [${X_LIBS}]
Some influential environment variables:
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
@ -273,10 +271,6 @@ for ac_option in $@; do
ZLIB_CFLAGS="-I$_prefix/include"
ZLIB_LIBS="-L$_prefix/lib"
;;
--x-libraries=*)
arg=`echo $ac_option | cut -d '=' -f 2`
X_LIBS="$arg"
;;
--host=*)
_host=`echo $ac_option | cut -d '=' -f 2`
;;

View File

@ -62,7 +62,8 @@ void EventHandlerSDL2::pollEvent()
{
handleKeyEvent((StellaKey)event.key.keysym.sym,
(StellaMod)event.key.keysym.mod,
event.key.keysym.unicode & 0x7f,
//FIXSDL event.key.keysym.unicode & 0x7f,
event.key.keysym.scancode,
event.key.type == SDL_KEYDOWN);
break;
}
@ -88,17 +89,16 @@ void EventHandlerSDL2::pollEvent()
handleMouseButtonEvent(pressed ? EVENT_RBUTTONDOWN : EVENT_RBUTTONUP,
event.button.x, event.button.y);
break;
case SDL_BUTTON_WHEELDOWN:
if(pressed)
handleMouseButtonEvent(EVENT_WHEELDOWN, event.button.x,
event.button.y);
break;
case SDL_BUTTON_WHEELUP:
if(pressed)
handleMouseButtonEvent(EVENT_WHEELUP, event.button.x,
event.button.y);
}
break;
}
case SDL_MOUSEWHEEL:
{
if(event.wheel.y < 0)
handleMouseButtonEvent(EVENT_WHEELDOWN, 0, event.wheel.y);
else if(event.wheel.y > 0)
handleMouseButtonEvent(EVENT_WHEELUP, 0, event.wheel.y);
break;
}
@ -151,26 +151,24 @@ void EventHandlerSDL2::pollEvent()
}
}
#ifdef JOYSTICK_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
: stick(NULL)
{
#ifdef JOYSTICK_SUPPORT
stick = SDL_JoystickOpen(idx);
if(stick)
{
initialize(SDL_JoystickName(idx), SDL_JoystickNumAxes(stick),
SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick));
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL2::JoystickSDL2::~JoystickSDL2()
{
#ifdef JOYSTICK_SUPPORT
if(stick)
SDL_JoystickClose(stick);
stick = NULL;
#endif
}
#endif

View File

@ -58,6 +58,7 @@ class EventHandlerSDL2 : public EventHandler
private:
SDL_Event event;
#ifdef JOYSTICK_SUPPORT
// A thin wrapper around a basic StellaJoystick, holding the pointer to
// the underlying SDL stick.
class JoystickSDL2 : public StellaJoystick
@ -69,6 +70,7 @@ class EventHandlerSDL2 : public EventHandler
private:
SDL_Joystick* stick;
};
#endif
};
#endif

View File

@ -29,35 +29,38 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
: myFB(buffer),
myGL(myFB.p_gl),
mySurface(NULL),
myTexture(NULL),
myVBOID(0),
myBaseW(0),
myBaseH(0),
myScanlinesEnabled(false),
myScanlineIntensityI(50),
myScanlineIntensityF(0.5)
myScanlinesEnabled(false)
// myScanlineIntensityI(50),
// myScanlineIntensityF(0.5)
{
myTexID[0] = myTexID[1] = 0;
// Texture width is set to contain all possible sizes for a TIA image,
// including Blargg filtering
myTexWidth = FrameBufferSDL2::power_of_two(ATARI_NTSC_OUT_WIDTH(160));
myTexHeight = FrameBufferSDL2::power_of_two(320);
int width = ATARI_NTSC_OUT_WIDTH(160);
int height = 320;
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat& pf = myFB.myPixelFormat;
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, myTexWidth, myTexHeight,
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
myPitch = myTexture->pitch / pf.BytesPerPixel;
mySrc.x = mySrc.y = myDst.x = myDst.y = 0;
mySrc.w = myDst.w = width;
mySrc.h = myDst.h = height;
myPitch = mySurface->pitch / pf.BytesPerPixel;
// To generate texture
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceTIA::~FBSurfaceTIA()
{
if(myTexture)
SDL_FreeSurface(myTexture);
if(mySurface)
SDL_FreeSurface(mySurface);
free();
}
@ -65,29 +68,29 @@ FBSurfaceTIA::~FBSurfaceTIA()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
{
x = myImageX;
y = myImageY;
x = mySrc.x;
y = mySrc.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
{
x -= myImageX;
y -= myImageY;
x = mySrc.x;
y = mySrc.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::update()
{
// Copy the mediasource framebuffer to the RGB texture
// In OpenGL mode, it's faster to just assume that the screen is dirty
// and always do an update
// In hardware rendering mode, it's faster to just assume that the screen
// is dirty and always do an update
uInt8* currentFrame = myTIA->currentFrameBuffer();
uInt8* previousFrame = myTIA->previousFrameBuffer();
uInt32 width = myTIA->width();
uInt32 height = myTIA->height();
uInt32* buffer = (uInt32*) myTexture->pixels;
uInt32* buffer = (uInt32*) mySurface->pixels;
// TODO - Eventually 'phosphor' won't be a separate mode, and will become
// a post-processing filter by blending several frames.
@ -129,17 +132,25 @@ void FBSurfaceTIA::update()
case FrameBufferSDL2::kBlarggNormal:
{
myFB.myNTSCFilter.blit_single(currentFrame, width, height,
buffer, myTexture->pitch);
buffer, mySurface->pitch);
break;
}
case FrameBufferSDL2::kBlarggPhosphor:
{
myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
buffer, myTexture->pitch);
buffer, mySurface->pitch);
break;
}
}
SDL_Rect tmp;
tmp.x = tmp.y = 0;
tmp.w = 160; tmp.h = 210;
SDL_UpdateTexture(myTexture, NULL, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
#if 0
myGL.EnableClientState(GL_VERTEX_ARRAY);
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -150,7 +161,7 @@ void FBSurfaceTIA::update()
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
myTexture->pixels);
mySurface->pixels);
if(myFB.myVBOAvailable)
{
@ -192,6 +203,7 @@ void FBSurfaceTIA::update()
myGL.DisableClientState(GL_VERTEX_ARRAY);
myGL.DisableClientState(GL_TEXTURE_COORD_ARRAY);
#endif
// Let postFrameUpdate() know that a change has been made
myFB.myDirtyFlag = true;
@ -200,20 +212,27 @@ void FBSurfaceTIA::update()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::invalidate()
{
SDL_FillRect(myTexture, NULL, 0);
SDL_FillRect(mySurface, NULL, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::free()
{
myGL.DeleteTextures(2, myTexID);
if(myFB.myVBOAvailable)
myGL.DeleteBuffers(1, &myVBOID);
if(myTexture)
{
SDL_DestroyTexture(myTexture);
myTexture = NULL;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::reload()
{
// Re-create texture; the underlying SDL_Surface is fine as-is
myTexture = SDL_CreateTexture(myFB.myRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
mySurface->w, mySurface->h);
#if 0
// This does a 'soft' reset of the surface
// It seems that on some system (notably, OSX), creating a new SDL window
// destroys the GL context, requiring a reload of all textures
@ -241,7 +260,7 @@ void FBSurfaceTIA::reload()
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
myTexture->pixels);
mySurface->pixels);
// Scanline texture (@ index 1)
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
@ -264,51 +283,72 @@ void FBSurfaceTIA::reload()
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
{
#if 0
myScanlineIntensityI = (GLuint)intensity;
myScanlineIntensityF = (GLfloat)intensity / 100;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setTexInterpolation(bool enable)
{
#if 0
myTexFilter[0] = enable ? GL_LINEAR : GL_NEAREST;
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setScanInterpolation(bool enable)
{
#if 0
myTexFilter[1] = enable ? GL_LINEAR : GL_NEAREST;
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::updateCoords(uInt32 baseH,
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
{
//cerr << "baseH=" << baseH << ", x=" << imgX << ", y=" << imgY << ", w=" << imgW << ", h=" << imgH << endl;
mySrc.w = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
mySrc.h = baseH;
myDst.w = imgW;
myDst.h = imgH;
//cerr << "src: x=" << mySrc.x << ", y=" << mySrc.y << ", w=" << mySrc.w << ", h=" << mySrc.h << endl;
//cerr << "dst: x=" << myDst.x << ", y=" << myDst.y << ", w=" << myDst.w << ", h=" << myDst.h << endl;
#if 0
myBaseH = baseH;
myImageX = imgX; myImageY = imgY;
myImageW = imgW; myImageH = imgH;
updateCoords();
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::updateCoords()
{
#if 0
// Normal TIA rendering and TV effects use different widths
// We use the same buffer, and only pick the width we need
myBaseW = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
@ -382,6 +422,7 @@ void FBSurfaceTIA::updateCoords()
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -25,10 +25,9 @@
#include "FrameBufferSDL2.hxx"
/**
A surface suitable for OpenGL rendering mode, but specifically for
rendering from a TIA source. It doesn't implement most of the
drawing primitives, since it's concerned with TIA images only.
This class extends FrameBuffer::FBSurface.
A surface suitable for SDL Render2D API and rendering from a TIA source.
It doesn't implement most of the drawing primitives, since it's concerned
with TIA images only. This class extends FrameBuffer::FBSurface.
@author Stephen Anthony
*/
@ -44,8 +43,8 @@ class FBSurfaceTIA : public FBSurface
// only the methods absolutely necessary for dealing with drawing
// a TIA image
void getPos(uInt32& x, uInt32& y) const;
uInt32 getWidth() const { return myImageW; }
uInt32 getHeight() const { return myImageH; }
uInt32 getWidth() const { return mySrc.w; }
uInt32 getHeight() const { return mySrc.h; }
void translateCoords(Int32& x, Int32& y) const;
void update();
void invalidate();
@ -64,23 +63,14 @@ class FBSurfaceTIA : public FBSurface
private:
FrameBufferSDL2& myFB;
const FrameBufferSDL2::GLpointers& myGL;
const TIA* myTIA;
SDL_Surface* myTexture;
SDL_Surface* mySurface;
SDL_Texture* myTexture;
SDL_Rect mySrc, myDst;
uInt32 myPitch;
GLuint myTexID[2], myVBOID;
GLsizei myTexWidth;
GLsizei myTexHeight;
GLuint myBaseW, myBaseH;
GLuint myImageX, myImageY, myImageW, myImageH;
GLfloat myTexCoordW, myTexCoordH;
GLfloat myCoord[32];
GLint myTexFilter[2];
bool myScanlinesEnabled;
GLuint myScanlineIntensityI;
GLfloat myScanlineIntensityF;
};
#endif

View File

@ -23,38 +23,31 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceUI::FBSurfaceUI(FrameBufferSDL2& buffer, uInt32 width, uInt32 height)
: myFB(buffer),
myGL(myFB.p_gl),
mySurface(NULL),
myTexture(NULL),
myTexID(0),
myVBOID(0),
myImageX(0),
myImageY(0),
myImageW(width),
myImageH(height)
mySurfaceIsDirty(true)
{
// Fill buffer struct with valid data
myTexWidth = FrameBufferSDL2::power_of_two(myImageW);
myTexHeight = FrameBufferSDL2::power_of_two(myImageH);
myTexCoordW = (GLfloat) myImageW / myTexWidth;
myTexCoordH = (GLfloat) myImageH / myTexHeight;
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat& pf = myFB.myPixelFormat;
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, myTexWidth, myTexHeight,
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
myPitch = myTexture->pitch / pf.BytesPerPixel;
mySrc.x = mySrc.y = myDst.x = myDst.y = 0;
mySrc.w = myDst.w = width;
mySrc.h = myDst.h = height;
// Associate the SDL surface with a GL texture object
updateCoords();
myPitch = mySurface->pitch / pf.BytesPerPixel;
// To generate texture
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBSurfaceUI::~FBSurfaceUI()
{
if(myTexture)
SDL_FreeSurface(myTexture);
if(mySurface)
SDL_FreeSurface(mySurface);
free();
}
@ -62,7 +55,7 @@ FBSurfaceUI::~FBSurfaceUI()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color)
{
uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x;
uInt32* buffer = (uInt32*) mySurface->pixels + y * myPitch + x;
while(x++ <= x2)
*buffer++ = (uInt32) myFB.myDefPalette[color];
}
@ -70,7 +63,7 @@ void FBSurfaceUI::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::vLine(uInt32 x, uInt32 y, uInt32 y2, uInt32 color)
{
uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x;
uInt32* buffer = (uInt32*) mySurface->pixels + y * myPitch + x;
while(y++ <= y2)
{
*buffer = (uInt32) myFB.myDefPalette[color];
@ -87,7 +80,7 @@ void FBSurfaceUI::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 color)
tmp.y = y;
tmp.w = w;
tmp.h = h;
SDL_FillRect(myTexture, &tmp, myFB.myDefPalette[color]);
SDL_FillRect(mySurface, &tmp, myFB.myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -122,7 +115,7 @@ void FBSurfaceUI::drawChar(const GUI::Font& font, uInt8 chr,
}
const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * desc.fbbh));
uInt32* buffer = (uInt32*) myTexture->pixels +
uInt32* buffer = (uInt32*) mySurface->pixels +
(ty + desc.ascent - bby - bbh) * myPitch +
tx + bbx;
@ -143,7 +136,7 @@ void FBSurfaceUI::drawChar(const GUI::Font& font, uInt8 chr,
void FBSurfaceUI::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
uInt32 color, uInt32 h)
{
uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx;
uInt32* buffer = (uInt32*) mySurface->pixels + ty * myPitch + tx;
for(uInt32 y = 0; y < h; ++y)
{
@ -159,7 +152,7 @@ void FBSurfaceUI::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::drawPixels(uInt32* data, uInt32 tx, uInt32 ty, uInt32 numpixels)
{
uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx;
uInt32* buffer = (uInt32*) mySurface->pixels + ty * myPitch + tx;
for(uInt32 i = 0; i < numpixels; ++i)
*buffer++ = (uInt32) data[i];
@ -170,42 +163,34 @@ void FBSurfaceUI::drawSurface(const FBSurface* surface, uInt32 tx, uInt32 ty)
{
const FBSurfaceUI* s = (const FBSurfaceUI*) surface;
SDL_Rect dstrect;
dstrect.x = tx;
dstrect.y = ty;
SDL_Rect srcrect;
srcrect.x = 0;
srcrect.y = 0;
srcrect.w = s->myImageW;
srcrect.h = s->myImageH;
SDL_Rect dst;
dst.x = tx;
dst.y = ty;
dst.w = s->mySrc.w;
dst.h = s->mySrc.h;
SDL_BlitSurface(s->myTexture, &srcrect, myTexture, &dstrect);
SDL_BlitSurface(s->mySurface, &(s->mySrc), mySurface, &dst);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
// OpenGL mode doesn't make use of dirty rectangles
// It's faster to just update the entire surface
// It's faster to just update the entire (hardware) surface
mySurfaceIsDirty = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::getPos(uInt32& x, uInt32& y) const
{
x = myImageX;
y = myImageY;
x = myDst.x;
y = myDst.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::setPos(uInt32 x, uInt32 y)
{
if(myImageX != x || myImageY != y)
{
myImageX = x;
myImageY = y;
updateCoords();
}
myDst.x = x;
myDst.y = y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -214,12 +199,8 @@ void FBSurfaceUI::setWidth(uInt32 w)
// This method can't be used with 'scaled' surface (aka TIA surfaces)
// That shouldn't really matter, though, as all the UI stuff isn't scaled,
// and it's the only thing that uses it
if(myImageW != w)
{
myImageW = BSPF_min(w, (uInt32)myTexWidth);
myTexCoordW = (GLfloat) myImageW / myTexWidth;
updateCoords();
}
mySrc.w = w;
myDst.w = w;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -228,19 +209,15 @@ void FBSurfaceUI::setHeight(uInt32 h)
// This method can't be used with 'scaled' surface (aka TIA surfaces)
// That shouldn't really matter, though, as all the UI stuff isn't scaled,
// and it's the only thing that uses it
if(myImageH != h)
{
myImageH = BSPF_min(h, (uInt32)myTexHeight);
myTexCoordH = (GLfloat) myImageH / myTexHeight;
updateCoords();
}
mySrc.h = h;
myDst.h = h;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::translateCoords(Int32& x, Int32& y) const
{
x -= myImageX;
y -= myImageY;
x -= myDst.x;
y -= myDst.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -248,32 +225,11 @@ void FBSurfaceUI::update()
{
if(mySurfaceIsDirty)
{
// Texturemap complete texture to surface so we have free scaling
// and antialiasing
myGL.ActiveTexture(GL_TEXTURE0);
myGL.BindTexture(GL_TEXTURE_2D, myTexID);
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myImageW, myImageH,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
myTexture->pixels);
//cerr << "src: x=" << mySrc.x << ", y=" << mySrc.y << ", w=" << mySrc.w << ", h=" << mySrc.h << endl;
//cerr << "dst: x=" << myDst.x << ", y=" << myDst.y << ", w=" << myDst.w << ", h=" << myDst.h << endl;
myGL.EnableClientState(GL_VERTEX_ARRAY);
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
if(myFB.myVBOAvailable)
{
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
myGL.VertexPointer(2, GL_FLOAT, 0, (const GLvoid*)0);
myGL.TexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*)(8*sizeof(GLfloat)));
}
else
{
myGL.VertexPointer(2, GL_FLOAT, 0, myCoord);
myGL.TexCoordPointer(2, GL_FLOAT, 0, myCoord+8);
}
myGL.DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
myGL.DisableClientState(GL_VERTEX_ARRAY);
myGL.DisableClientState(GL_TEXTURE_COORD_ARRAY);
SDL_UpdateTexture(myTexture, NULL, mySurface->pixels, mySurface->pitch);
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
mySurfaceIsDirty = false;
@ -282,85 +238,27 @@ void FBSurfaceUI::update()
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::invalidate()
{
SDL_FillRect(mySurface, NULL, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::free()
{
myGL.DeleteTextures(1, &myTexID);
if(myFB.myVBOAvailable)
myGL.DeleteBuffers(1, &myVBOID);
if(myTexture)
{
SDL_DestroyTexture(myTexture);
myTexture = NULL;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::reload()
{
// This does a 'soft' reset of the surface
// It seems that on some system (notably, OSX), creating a new SDL window
// destroys the GL context, requiring a reload of all textures
// However, destroying the entire FBSurfaceUI object is wasteful, since
// it will also regenerate SDL software surfaces (which are not required
// to be regenerated)
// Basically, all that needs to be done is to re-call glTexImage2D with a
// new texture ID, so that's what we do here
myGL.ActiveTexture(GL_TEXTURE0);
myGL.Enable(GL_TEXTURE_2D);
myGL.GenTextures(1, &myTexID);
myGL.BindTexture(GL_TEXTURE_2D, myTexID);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Create the texture in the most optimal format
myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
myTexture->pixels);
// Cache vertex and texture coordinates using vertex buffer object
if(myFB.myVBOAvailable)
{
myGL.GenBuffers(1, &myVBOID);
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
myGL.BufferData(GL_ARRAY_BUFFER, 16*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceUI::updateCoords()
{
// Vertex coordinates for texture
// Upper left (x,y)
myCoord[0] = (GLfloat)myImageX;
myCoord[1] = (GLfloat)myImageY;
// Upper right (x+w,y)
myCoord[2] = (GLfloat)(myImageX + myImageW);
myCoord[3] = (GLfloat)myImageY;
// Lower left (x,y+h)
myCoord[4] = (GLfloat)myImageX;
myCoord[5] = (GLfloat)(myImageY + myImageH);
// Lower right (x+w,y+h)
myCoord[6] = (GLfloat)(myImageX + myImageW);
myCoord[7] = (GLfloat)(myImageY + myImageH);
// Texture coordinates for texture
// Upper left (x,y)
myCoord[8] = 0.0f;
myCoord[9] = 0.0f;
// Upper right (x+w,y)
myCoord[10] = myTexCoordW;
myCoord[11] = 0.0f;
// Lower left (x,y+h)
myCoord[12] = 0.0f;
myCoord[13] = myTexCoordH;
// Lower right (x+w,y+h)
myCoord[14] = myTexCoordW;
myCoord[15] = myTexCoordH;
// Cache vertex and texture coordinates using vertex buffer object
if(myFB.myVBOAvailable)
{
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
myGL.BufferData(GL_ARRAY_BUFFER, 16*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
}
// Re-create texture; the underlying SDL_Surface is fine as-is
myTexture = SDL_CreateTexture(myFB.myRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
mySurface->w, mySurface->h);
}

View File

@ -24,7 +24,7 @@
#include "FrameBufferSDL2.hxx"
/**
A surface suitable for OpenGL rendering mode, used for various UI dialogs.
A surface suitable for SDL Render2D API, used for various UI dialogs.
This class extends FrameBuffer::FBSurface.
@author Stephen Anthony
@ -48,29 +48,22 @@ class FBSurfaceUI : public FBSurface
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
void getPos(uInt32& x, uInt32& y) const;
void setPos(uInt32 x, uInt32 y);
uInt32 getWidth() const { return myImageW; }
uInt32 getHeight() const { return myImageH; }
uInt32 getWidth() const { return mySrc.w; }
uInt32 getHeight() const { return mySrc.h; }
void setWidth(uInt32 w);
void setHeight(uInt32 h);
void translateCoords(Int32& x, Int32& y) const;
void update();
void invalidate();
void free();
void reload();
private:
void updateCoords();
private:
FrameBufferSDL2& myFB;
const FrameBufferSDL2::GLpointers& myGL;
SDL_Surface* myTexture;
GLuint myTexID, myVBOID;
GLsizei myTexWidth;
GLsizei myTexHeight;
GLuint myImageX, myImageY, myImageW, myImageH;
GLfloat myTexCoordW, myTexCoordH;
GLfloat myCoord[16];
SDL_Surface* mySurface;
SDL_Texture* myTexture;
SDL_Rect mySrc, myDst;
bool mySurfaceIsDirty;
uInt32 myPitch;

View File

@ -39,19 +39,20 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
: FrameBuffer(osystem),
myFilterType(kNormal),
myScreen(0),
mySDLFlags(0),
myWindow(NULL),
myRenderer(NULL),
myWindowFlags(0),
myTiaSurface(NULL),
myDirtyFlag(true)
{
// Initialize SDL2 context
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
{
ostringstream buf;
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
return;
// Load OpenGL function pointers
loadLibrary(osystem->settings().getString("gl_lib"));
if(loadFuncs(kGL_BASIC))
myVBOAvailable = myOSystem->settings().getBool("gl_vbo") && loadFuncs(kGL_VBO);
}
// We need a pixel format for palette value calculations
// It's done this way (vs directly accessing a FBSurfaceUI object)
@ -59,7 +60,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
// been created
// Note: alpha disabled for now, since it's not used
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
myPixelFormat = *(s->format);
SDL_FreeSurface(s);
@ -68,85 +69,13 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferSDL2::~FrameBufferSDL2()
{
// if(myWindow)
// SDL_DestroyWindow(myWindow);
// We're taking responsibility for this surface
delete myTiaSurface;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::loadLibrary(const string& library)
{
if(myLibraryLoaded)
return true;
// Try both the specified library and auto-detection
bool libLoaded = (library != "" && SDL_GL_LoadLibrary(library.c_str()) >= 0);
bool autoLoaded = false;
if(!libLoaded) autoLoaded = (SDL_GL_LoadLibrary(0) >= 0);
if(!libLoaded && !autoLoaded)
return false;
return myLibraryLoaded = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::loadFuncs(GLFunctionality functionality)
{
#define OGL_INIT(NAME,RET,FUNC,PARAMS) \
p_gl.NAME = (RET(APIENTRY*)PARAMS) SDL_GL_GetProcAddress(#FUNC); if(!p_gl.NAME) return false
if(myLibraryLoaded)
{
// Fill the function pointers for GL functions
// If anything fails, we'll know it immediately, and return false
switch(functionality)
{
case kGL_BASIC:
OGL_INIT(Clear,void,glClear,(GLbitfield));
OGL_INIT(Enable,void,glEnable,(GLenum));
OGL_INIT(Disable,void,glDisable,(GLenum));
OGL_INIT(PushAttrib,void,glPushAttrib,(GLbitfield));
OGL_INIT(GetString,const GLubyte*,glGetString,(GLenum));
OGL_INIT(Hint,void,glHint,(GLenum, GLenum));
OGL_INIT(ShadeModel,void,glShadeModel,(GLenum));
OGL_INIT(MatrixMode,void,glMatrixMode,(GLenum));
OGL_INIT(Ortho,void,glOrtho,(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
OGL_INIT(Viewport,void,glViewport,(GLint, GLint, GLsizei, GLsizei));
OGL_INIT(LoadIdentity,void,glLoadIdentity,(void));
OGL_INIT(Translatef,void,glTranslatef,(GLfloat,GLfloat,GLfloat));
OGL_INIT(EnableClientState,void,glEnableClientState,(GLenum));
OGL_INIT(DisableClientState,void,glDisableClientState,(GLenum));
OGL_INIT(VertexPointer,void,glVertexPointer,(GLint,GLenum,GLsizei,const GLvoid*));
OGL_INIT(TexCoordPointer,void,glTexCoordPointer,(GLint,GLenum,GLsizei,const GLvoid*));
OGL_INIT(DrawArrays,void,glDrawArrays,(GLenum,GLint,GLsizei));
OGL_INIT(ReadPixels,void,glReadPixels,(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*));
OGL_INIT(PixelStorei,void,glPixelStorei,(GLenum, GLint));
OGL_INIT(TexEnvf,void,glTexEnvf,(GLenum, GLenum, GLfloat));
OGL_INIT(GenTextures,void,glGenTextures,(GLsizei, GLuint*));
OGL_INIT(DeleteTextures,void,glDeleteTextures,(GLsizei, const GLuint*));
OGL_INIT(ActiveTexture,void,glActiveTexture,(GLenum));
OGL_INIT(BindTexture,void,glBindTexture,(GLenum, GLuint));
OGL_INIT(TexImage2D,void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
OGL_INIT(TexSubImage2D,void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
OGL_INIT(TexParameteri,void,glTexParameteri,(GLenum, GLenum, GLint));
OGL_INIT(GetError,GLenum,glGetError,(void));
OGL_INIT(Color4f,void,glColor4f,(GLfloat,GLfloat,GLfloat,GLfloat));
OGL_INIT(BlendFunc,void,glBlendFunc,(GLenum,GLenum));
break; // kGL_Full
case kGL_VBO:
OGL_INIT(GenBuffers,void,glGenBuffers,(GLsizei,GLuint*));
OGL_INIT(BindBuffer,void,glBindBuffer,(GLenum,GLuint));
OGL_INIT(BufferData,void,glBufferData,(GLenum,GLsizei,const void*,GLenum));
OGL_INIT(DeleteBuffers,void,glDeleteBuffers,(GLsizei, const GLuint*));
break; // kGL_VBO
}
}
else
return false;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res)
{
@ -157,9 +86,10 @@ bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res)
const GUI::Size& s = myOSystem->settings().getSize("maxres");
if(s.w <= 0 || s.h <= 0)
{
const SDL_VideoInfo* info = SDL_GetVideoInfo();
w = info->current_w;
h = info->current_h;
SDL_DisplayMode desktop;
SDL_GetDesktopDisplayMode(0, &desktop);
w = desktop.w;
h = desktop.h;
}
#if 0
@ -223,73 +153,45 @@ bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::initSubsystem(VideoMode& mode, bool full)
bool FrameBufferSDL2::setVideoMode(const string& title, VideoMode& mode, bool full)
{
// Now (re)initialize the SDL video system
// These things only have to be done one per FrameBuffer creation
// If not initialized by this point, then immediately fail
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
{
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
{
ostringstream buf;
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
return false;
}
}
mySDLFlags |= SDL_OPENGL;
setHint(kFullScreen, full);
// Set up the OpenGL attributes
myDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
switch(myDepth)
{
case 15:
case 16:
myRGB[0] = 5; myRGB[1] = 5; myRGB[2] = 5; myRGB[3] = 0;
break;
case 24:
case 32:
myRGB[0] = 8; myRGB[1] = 8; myRGB[2] = 8; myRGB[3] = 0;
break;
default: // This should never happen
return false;
break;
}
// Create the screen
if(!setVidMode(mode))
return false;
// Now check to see what color components were actually created
SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &myRGB[0] );
SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &myRGB[1] );
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &myRGB[2] );
SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, &myRGB[3] );
return true;
// (Re)create window and renderer
if(myRenderer)
{
SDL_DestroyRenderer(myRenderer);
myRenderer = NULL;
}
if(myWindow)
{
SDL_DestroyWindow(myWindow);
myWindow = NULL;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string FrameBufferSDL2::about() const
myWindow = SDL_CreateWindow(title.c_str(),
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
mode.image_w, mode.image_h,
0);
if(myWindow == NULL)
{
ostringstream out;
out << "Video rendering: OpenGL mode" << endl
<< " Vendor: " << p_gl.GetString(GL_VENDOR) << endl
<< " Renderer: " << p_gl.GetString(GL_RENDERER) << endl
<< " Version: " << p_gl.GetString(GL_VERSION) << endl
<< " Color: " << myDepth << " bit, " << myRGB[0] << "-"
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3] << ", "
<< "GL_BGRA" << endl
<< " Extensions: VBO " << (myVBOAvailable ? "enabled" : "disabled")
<< endl;
return out.str();
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
myOSystem->logMessage(msg, 0);
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::setVidMode(VideoMode& mode)
myRenderer = SDL_CreateRenderer(myWindow, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(myWindow == NULL)
{
string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError());
myOSystem->logMessage(msg, 0);
return false;
}
bool inTIAMode =
myOSystem->eventHandler().state() != EventHandler::S_LAUNCHER &&
myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER;
@ -298,6 +200,7 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
// We need it for the creating the TIA surface
uInt32 baseHeight = mode.image_h / mode.gfxmode.zoom;
#if 0
// Aspect ratio and fullscreen stretching only applies to the TIA
if(inTIAMode)
{
@ -362,18 +265,12 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
// We leave it to the user to test and decide
int vsync = myOSystem->settings().getBool("gl_vsync") ? 1 : 0;
SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, vsync );
#endif
// Create screen containing GL context
myScreen = SDL_SetVideoMode(mode.screen_w, mode.screen_h, 0, mySDLFlags);
if(myScreen == NULL)
{
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
myOSystem->logMessage(msg, 0);
return false;
}
// Make sure the flags represent the current screen state
mySDLFlags = myScreen->flags;
// myWindowFlags = myScreen->flags;
#if 0
// Optimization hints
p_gl.ShadeModel(GL_FLAT);
p_gl.Disable(GL_CULL_FACE);
@ -390,7 +287,7 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
p_gl.MatrixMode(GL_MODELVIEW);
p_gl.LoadIdentity();
p_gl.Translatef(0.375, 0.375, 0.0); // fix scanline mis-draw issues
#endif
//cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl << mode << endl;
// The framebuffer only takes responsibility for TIA surfaces
@ -422,25 +319,28 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setHint(FBHint hint, bool enabled)
string FrameBufferSDL2::about() const
{
int flag = 0;
switch(hint)
{
case kFullScreen:
flag = SDL_FULLSCREEN;
break;
}
if(enabled)
mySDLFlags |= flag;
else
mySDLFlags &= ~flag;
#if 0
ostringstream out;
out << "Video rendering: OpenGL mode" << endl
<< " Vendor: " << p_gl.GetString(GL_VENDOR) << endl
<< " Renderer: " << p_gl.GetString(GL_RENDERER) << endl
<< " Version: " << p_gl.GetString(GL_VERSION) << endl
<< " Color: " << myDepth << " bit, " << myRGB[0] << "-"
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3] << ", "
<< "GL_BGRA" << endl
<< " Extensions: VBO " << (myVBOAvailable ? "enabled" : "disabled")
<< endl;
return out.str();
#endif
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::invalidate()
{
p_gl.Clear(GL_COLOR_BUFFER_BIT);
SDL_RenderClear(myRenderer);
if(myTiaSurface)
myTiaSurface->invalidate();
}
@ -448,34 +348,32 @@ void FrameBufferSDL2::invalidate()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::showCursor(bool show)
{
SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
//FIXSDL SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::grabMouse(bool grab)
{
SDL_WM_GrabInput(grab ? SDL_GRAB_ON : SDL_GRAB_OFF);
//FIXSDL SDL_WM_GrabInput(grab ? SDL_GRAB_ON : SDL_GRAB_OFF);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::fullScreen() const
{
#if 0//FIXSDL
#ifdef WINDOWED_SUPPORT
return mySDLFlags & SDL_FULLSCREEN;
return myWindowFlags & SDL_FULLSCREEN;
#else
return true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setWindowTitle(const string& title)
{
SDL_WM_SetCaption(title.c_str(), "stella");
#endif
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::setWindowIcon()
{
#if 0 //FIXSDL
#if !defined(BSPF_MAC_OSX) && !defined(BSPF_UNIX)
#include "stella.xpm" // The Stella icon
@ -532,6 +430,7 @@ void FrameBufferSDL2::setWindowIcon()
SDL_WM_SetIcon(surface, (unsigned char *) mask);
SDL_FreeSurface(surface);
#endif
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -547,7 +446,7 @@ void FrameBufferSDL2::postFrameUpdate()
if(myDirtyFlag)
{
// Now show all changes made to the texture(s)
SDL_GL_SwapBuffers();
SDL_RenderPresent(myRenderer);
myDirtyFlag = false;
}
}
@ -570,7 +469,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
if(myTiaSurface)
{
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
myTiaSurface->updateCoords();
//FIXSDL myTiaSurface->updateCoords();
myTiaSurface->enableScanlines(ntscEnabled());
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
@ -584,6 +483,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
{
#if 0//FIXSDL
int intensity = myTiaSurface->myScanlineIntensityI;
if(myTiaSurface)
{
@ -596,6 +496,8 @@ uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
myRedrawEntireFrame = true;
}
return intensity;
#endif
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -627,6 +529,7 @@ FBSurface* FrameBufferSDL2::createSurface(int w, int h, bool isBase) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
{
#if 0
// Invert the row, since OpenGL rows start at the bottom
// of the framebuffer
const GUI::Rect& image = imageRect();
@ -634,6 +537,7 @@ void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
p_gl.PixelStorei(GL_PACK_ALIGNMENT, 1);
p_gl.ReadPixels(image.x(), row, image.width(), 1, GL_RGB, GL_UNSIGNED_BYTE, data);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -650,20 +554,20 @@ string FrameBufferSDL2::effectsInfo() const
break;
case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines="
#if 0
<< myTiaSurface->myScanlineIntensityI << "/"
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif
;
break;
case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
#if 0
<< myTiaSurface->myScanlineIntensityI << "/"
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
#endif
;
break;
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::myLibraryLoaded = false;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSDL2::myVBOAvailable = false;

View File

@ -54,15 +54,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
virtual ~FrameBufferSDL2();
/**
Check if OpenGL is available on this system, and then opens it.
If any errors occur, we shouldn't attempt to instantiate a
FrameBufferSDL2 object.
@param library The filename of the OpenGL library
*/
static bool loadLibrary(const string& library);
//////////////////////////////////////////////////////////////////////
// The following are derived from public methods in FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
@ -82,11 +73,6 @@ class FrameBufferSDL2 : public FrameBuffer
*/
bool fullScreen() const;
/**
Set the title for the main window.
*/
void setWindowTitle(const string& title);
/**
Enable/disable phosphor effect.
*/
@ -157,34 +143,16 @@ class FrameBufferSDL2 : public FrameBuffer
bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res);
/**
This method is called to initialize the video subsystem
with the given video mode. Normally, it will also call setVidMode().
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param title The title for the created window
@param mode The video mode to use
@param full Whether this is a fullscreen or windowed mode
@return False on any errors, else true
*/
bool initSubsystem(VideoMode& mode, bool full);
/**
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param mode The video mode to use
@return False on any errors (in which case 'mode' is invalid), else true
*/
bool setVidMode(VideoMode& mode);
/**
Sets a hint that the underlying renderer may use; it is also free
to ignore it completely.
@param hint The hint to set
@param enabled Whether the hint should be turned on or off
*/
void setHint(FBHint hint, bool enabled);
bool setVideoMode(const string& title, VideoMode& mode, bool full);
/**
This method is called to invalidate the contents of the entire
@ -240,11 +208,6 @@ class FrameBufferSDL2 : public FrameBuffer
void enableScanlineInterpolation(bool enable);
private:
enum GLFunctionality {
kGL_BASIC, kGL_VBO
};
bool loadFuncs(GLFunctionality functionality);
// Enumeration created such that phosphor off/on is in LSB,
// and Blargg off/on is in MSB
enum FilterType {
@ -255,23 +218,17 @@ class FrameBufferSDL2 : public FrameBuffer
};
FilterType myFilterType;
static uInt32 power_of_two(uInt32 input)
{
uInt32 value = 1;
while( value < input )
value <<= 1;
return value;
}
private:
// The SDL video buffer
SDL_Surface* myScreen;
SDL_Window* myWindow;
SDL_Renderer* myRenderer;
// SDL initialization flags
// This is set by the base FrameBuffer class, and read by the derived classes
// If a FrameBuffer is successfully created, the derived classes must modify
// it to point to the actual flags used by the SDL_Surface
uInt32 mySDLFlags;
uInt32 myWindowFlags;
// The lower-most base surface (will always be a TIA surface,
// since Dialog surfaces are allocated by the Dialog class directly).
@ -283,57 +240,8 @@ class FrameBufferSDL2 : public FrameBuffer
// The depth of the texture buffer
uInt32 myDepth;
// The size of color components for OpenGL
Int32 myRGB[4];
// Indicates that the texture has been modified, and should be redrawn
bool myDirtyFlag;
// Indicates if the OpenGL library has been properly loaded
static bool myLibraryLoaded;
// Indicates whether Vertex Buffer Objects (VBO) are available
static bool myVBOAvailable;
// Structure containing dynamically-loaded OpenGL function pointers
#define OGL_DECLARE(NAME,RET,FUNC,PARAMS) RET (APIENTRY* NAME) PARAMS
typedef struct {
OGL_DECLARE(Clear,void,glClear,(GLbitfield));
OGL_DECLARE(Enable,void,glEnable,(GLenum));
OGL_DECLARE(Disable,void,glDisable,(GLenum));
OGL_DECLARE(PushAttrib,void,glPushAttrib,(GLbitfield));
OGL_DECLARE(GetString,const GLubyte*,glGetString,(GLenum));
OGL_DECLARE(Hint,void,glHint,(GLenum, GLenum));
OGL_DECLARE(ShadeModel,void,glShadeModel,(GLenum));
OGL_DECLARE(MatrixMode,void,glMatrixMode,(GLenum));
OGL_DECLARE(Ortho,void,glOrtho,(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble));
OGL_DECLARE(Viewport,void,glViewport,(GLint, GLint, GLsizei, GLsizei));
OGL_DECLARE(LoadIdentity,void,glLoadIdentity,(void));
OGL_DECLARE(Translatef,void,glTranslatef,(GLfloat,GLfloat,GLfloat));
OGL_DECLARE(EnableClientState,void,glEnableClientState,(GLenum));
OGL_DECLARE(DisableClientState,void,glDisableClientState,(GLenum));
OGL_DECLARE(VertexPointer,void,glVertexPointer,(GLint,GLenum,GLsizei,const GLvoid*));
OGL_DECLARE(TexCoordPointer,void,glTexCoordPointer,(GLint,GLenum,GLsizei,const GLvoid*));
OGL_DECLARE(DrawArrays,void,glDrawArrays,(GLenum,GLint,GLsizei));
OGL_DECLARE(ReadPixels,void,glReadPixels,(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*));
OGL_DECLARE(PixelStorei,void,glPixelStorei,(GLenum, GLint));
OGL_DECLARE(TexEnvf,void,glTexEnvf,(GLenum, GLenum, GLfloat));
OGL_DECLARE(GenTextures,void,glGenTextures,(GLsizei, GLuint*));
OGL_DECLARE(DeleteTextures,void,glDeleteTextures,(GLsizei, const GLuint*));
OGL_DECLARE(ActiveTexture,void,glActiveTexture,(GLenum));
OGL_DECLARE(BindTexture,void,glBindTexture,(GLenum, GLuint));
OGL_DECLARE(TexImage2D,void,glTexImage2D,(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*));
OGL_DECLARE(TexSubImage2D,void,glTexSubImage2D,(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*));
OGL_DECLARE(TexParameteri,void,glTexParameteri,(GLenum, GLenum, GLint));
OGL_DECLARE(GetError,GLenum,glGetError,(void));
OGL_DECLARE(Color4f,void,glColor4f,(GLfloat,GLfloat,GLfloat,GLfloat));
OGL_DECLARE(BlendFunc,void,glBlendFunc,(GLenum,GLenum));
OGL_DECLARE(GenBuffers,void,glGenBuffers,(GLsizei,GLuint*));
OGL_DECLARE(BindBuffer,void,glBindBuffer,(GLenum,GLuint));
OGL_DECLARE(BufferData,void,glBufferData,(GLenum,GLsizei,const void*,GLenum));
OGL_DECLARE(DeleteBuffers,void,glDeleteBuffers,(GLsizei, const GLuint*));
} GLpointers;
GLpointers p_gl;
};
#endif

View File

@ -310,6 +310,6 @@ typedef enum {
// Just pass SDLMod directly as int (placeholder for now)
// The underlying code doesn't need to know how it's implemented
typedef int StellaMod;
typedef SDL_Keymod StellaMod;
#endif /* StellaKeys */

View File

@ -2041,7 +2041,7 @@ void EventHandler::setEventState(State state)
case S_EMULATE:
myOverlay = NULL;
myOSystem->sound().mute(false);
SDL_EnableUNICODE(0);
//FIXME SDL_EnableUNICODE(0);
if(myOSystem->console().controller(Controller::Left).type() ==
Controller::CompuMate)
myUseCtrlKeyFlag = false;
@ -2050,28 +2050,28 @@ void EventHandler::setEventState(State state)
case S_PAUSE:
myOverlay = NULL;
myOSystem->sound().mute(true);
SDL_EnableUNICODE(0);
//FIXME SDL_EnableUNICODE(0);
break;
case S_MENU:
myOverlay = &myOSystem->menu();
SDL_EnableUNICODE(1);
//FIXME SDL_EnableUNICODE(1);
break;
case S_CMDMENU:
myOverlay = &myOSystem->commandMenu();
SDL_EnableUNICODE(1);
//FIXME SDL_EnableUNICODE(1);
break;
case S_LAUNCHER:
myOverlay = &myOSystem->launcher();
SDL_EnableUNICODE(1);
//FIXME SDL_EnableUNICODE(1);
break;
#ifdef DEBUGGER_SUPPORT
case S_DEBUGGER:
myOverlay = &myOSystem->debugger();
SDL_EnableUNICODE(1);
//FIXME SDL_EnableUNICODE(1);
break;
#endif

View File

@ -186,11 +186,8 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
VideoMode mode = getSavedVidMode();
if(width <= mode.screen_w && height <= mode.screen_h)
{
setWindowTitle(title);
if(initSubsystem(mode, useFullscreen))
if(setVideoMode(title, mode, useFullscreen))
{
centerAppWindow(mode);
myImageRect.setWidth(mode.image_w);
myImageRect.setHeight(mode.image_h);
myImageRect.moveTo(mode.image_x, mode.image_y);
@ -498,7 +495,7 @@ void FrameBuffer::refresh()
// This method is in essence a FULL refresh, putting all rendering
// buffers in a known, fully redrawn state
bool doubleBuffered = (type() == kDoubleBuffer);
bool doubleBuffered = false;//FIXSDL(type() == kDoubleBuffer);
switch(myOSystem->eventHandler().state())
{
case EventHandler::S_EMULATE:
@ -756,6 +753,7 @@ void FrameBuffer::toggleFullscreen()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setFullscreen(bool enable)
{
#if 0 //FIXSDL
#ifdef WINDOWED_SUPPORT
// '-1' means fullscreen mode is completely disabled
bool full = enable && myOSystem->settings().getString("fullscreen") != "-1";
@ -769,11 +767,13 @@ void FrameBuffer::setFullscreen(bool enable)
// to changeVidMode()
changeVidMode(0);
#endif
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::changeVidMode(int direction)
{
#if 0 //FIXSDL
EventHandler::State state = myOSystem->eventHandler().state();
bool inUIMode = (state == EventHandler::S_DEBUGGER ||
state == EventHandler::S_LAUNCHER);
@ -793,8 +793,6 @@ bool FrameBuffer::changeVidMode(int direction)
VideoMode vidmode = myCurrentModeList->current(myOSystem->settings(), fullScreen());
if(setVidMode(vidmode))
{
centerAppWindow(vidmode);
myImageRect.setWidth(vidmode.image_w);
myImageRect.setHeight(vidmode.image_h);
myImageRect.moveTo(vidmode.image_x, vidmode.image_y);
@ -820,7 +818,7 @@ bool FrameBuffer::changeVidMode(int direction)
}
else
return false;
#endif
return true;
/*
cerr << "New mode:" << endl
@ -1025,22 +1023,6 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode()
return myCurrentModeList->current(myOSystem->settings(), fullScreen());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::centerAppWindow(const VideoMode& mode)
{
// FIXSDL
#if 0
// Attempt to center the application window in non-fullscreen mode
if(!fullScreen() && myOSystem->settings().getBool("center"))
{
int x = mode.screen_w >= myOSystem->desktopWidth() ? 0 :
((myOSystem->desktopWidth() - mode.screen_w) >> 1);
int y = mode.screen_h >= myOSystem->desktopHeight() ? 0 :
((myOSystem->desktopHeight() - mode.screen_h) >> 1);
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::VideoModeList::VideoModeList()
: myIdx(-1)

View File

@ -348,11 +348,6 @@ class FrameBuffer
*/
virtual bool fullScreen() const = 0;
/**
Set the title for the main window.
*/
virtual void setWindowTitle(const string& title) = 0;
/**
Enable/disable/query NTSC filtering effects.
*/
@ -454,35 +449,16 @@ class FrameBuffer
virtual bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res) = 0;
/**
This method is called to initialize the video subsystem
with the given video mode. Normally, it will also call setVidMode().
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param title The title for
@param title The title for the created window
@param mode The video mode to use
@param full Whether this is a fullscreen or windowed mode
@return False on any errors, else true
*/
virtual bool initSubsystem(VideoMode& mode, bool full) = 0;
/**
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param mode The video mode to use
@return False on any errors (in which case 'mode' is invalid), else true
*/
virtual bool setVidMode(VideoMode& mode) = 0;
/**
Sets a hint that the underlying renderer may use; it is also free
to ignore it completely.
@param hint The hint to set
@param enabled Whether the hint should be turned on or off
*/
virtual void setHint(FBHint hint, bool enabled) = 0;
virtual bool setVideoMode(const string& title, VideoMode& mode, bool full) = 0;
/**
This method is called to invalidate the contents of the entire
@ -600,11 +576,6 @@ class FrameBuffer
*/
VideoMode getSavedVidMode();
/**
Attempt to center the application window in windowed mode.
*/
void centerAppWindow(const VideoMode& mode);
/**
Set up the user interface palette for a screen of any depth > 8.
*/

View File

@ -107,10 +107,11 @@ OSystem::OSystem()
// Get build info
ostringstream info;
const SDL_version* ver = SDL_Linked_Version();
SDL_version ver;
SDL_GetVersion(&ver);
info << "Build " << STELLA_BUILD << ", using SDL " << (int)ver->major
<< "." << (int)ver->minor << "."<< (int)ver->patch
info << "Build " << STELLA_BUILD << ", using SDL " << (int)ver.major
<< "." << (int)ver.minor << "."<< (int)ver.patch
<< " [" << BSPF_ARCH << "]";
myBuildInfo = info.str();

View File

@ -165,8 +165,8 @@ class DialogContainer
// For continuous 'key down' events
struct {
StellaKey keycode;
StellaMod flags;
char ascii;
int flags;
} myCurrentKeyDown;
uInt64 myKeyRepeatTime;