mirror of https://github.com/stella-emu/stella.git
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:
parent
46733e32c0
commit
a1ea1b0c96
|
@ -6,7 +6,7 @@
|
||||||
# * command line options to...
|
# * command line options to...
|
||||||
# - override the host settings (for cross compiles
|
# - override the host settings (for cross compiles
|
||||||
# - whether to do a debug build (with -g) or an optimized build (-O3 etc.)
|
# - 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
|
_cp=cp
|
||||||
_windowspath=""
|
_windowspath=""
|
||||||
_windres=windres
|
_windres=windres
|
||||||
_sdlconfig=sdl-config
|
_sdlconfig=sdl2-config
|
||||||
_sdlpath="$PATH"
|
_sdlpath="$PATH"
|
||||||
_prefix=/usr/local
|
_prefix=/usr/local
|
||||||
X_LIBS="/usr/X11R6/lib"
|
|
||||||
|
|
||||||
_srcdir=`dirname $0`
|
_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
|
# TODO: small bit of code to test sdl useability
|
||||||
find_sdlconfig()
|
find_sdlconfig()
|
||||||
{
|
{
|
||||||
echo_n "Looking for sdl-config... "
|
echo_n "Looking for sdl2-config... "
|
||||||
sdlconfigs="$_sdlconfig:sdl-config:sdl11-config:sdl12-config"
|
sdlconfigs="$_sdlconfig"
|
||||||
_sdlconfig=
|
_sdlconfig=
|
||||||
|
|
||||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="$SEPARATOR"
|
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]
|
--force-builtin-zlib force use of built-in zlib library [auto]
|
||||||
|
|
||||||
Optional Libraries:
|
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-libpng-prefix=DIR Prefix where libpng is installed (optional)
|
||||||
--with-zlib-prefix=DIR Prefix where zlib 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:
|
Some influential environment variables:
|
||||||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
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_CFLAGS="-I$_prefix/include"
|
||||||
ZLIB_LIBS="-L$_prefix/lib"
|
ZLIB_LIBS="-L$_prefix/lib"
|
||||||
;;
|
;;
|
||||||
--x-libraries=*)
|
|
||||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
|
||||||
X_LIBS="$arg"
|
|
||||||
;;
|
|
||||||
--host=*)
|
--host=*)
|
||||||
_host=`echo $ac_option | cut -d '=' -f 2`
|
_host=`echo $ac_option | cut -d '=' -f 2`
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -62,7 +62,8 @@ void EventHandlerSDL2::pollEvent()
|
||||||
{
|
{
|
||||||
handleKeyEvent((StellaKey)event.key.keysym.sym,
|
handleKeyEvent((StellaKey)event.key.keysym.sym,
|
||||||
(StellaMod)event.key.keysym.mod,
|
(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);
|
event.key.type == SDL_KEYDOWN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -88,17 +89,16 @@ void EventHandlerSDL2::pollEvent()
|
||||||
handleMouseButtonEvent(pressed ? EVENT_RBUTTONDOWN : EVENT_RBUTTONUP,
|
handleMouseButtonEvent(pressed ? EVENT_RBUTTONDOWN : EVENT_RBUTTONUP,
|
||||||
event.button.x, event.button.y);
|
event.button.x, event.button.y);
|
||||||
break;
|
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;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,26 +151,24 @@ void EventHandlerSDL2::pollEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JOYSTICK_SUPPORT
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
||||||
: stick(NULL)
|
: stick(NULL)
|
||||||
{
|
{
|
||||||
#ifdef JOYSTICK_SUPPORT
|
|
||||||
stick = SDL_JoystickOpen(idx);
|
stick = SDL_JoystickOpen(idx);
|
||||||
if(stick)
|
if(stick)
|
||||||
{
|
{
|
||||||
initialize(SDL_JoystickName(idx), SDL_JoystickNumAxes(stick),
|
initialize(SDL_JoystickName(idx), SDL_JoystickNumAxes(stick),
|
||||||
SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick));
|
SDL_JoystickNumButtons(stick), SDL_JoystickNumHats(stick));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
EventHandlerSDL2::JoystickSDL2::~JoystickSDL2()
|
EventHandlerSDL2::JoystickSDL2::~JoystickSDL2()
|
||||||
{
|
{
|
||||||
#ifdef JOYSTICK_SUPPORT
|
|
||||||
if(stick)
|
if(stick)
|
||||||
SDL_JoystickClose(stick);
|
SDL_JoystickClose(stick);
|
||||||
stick = NULL;
|
stick = NULL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -58,6 +58,7 @@ class EventHandlerSDL2 : public EventHandler
|
||||||
private:
|
private:
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
|
#ifdef JOYSTICK_SUPPORT
|
||||||
// A thin wrapper around a basic StellaJoystick, holding the pointer to
|
// A thin wrapper around a basic StellaJoystick, holding the pointer to
|
||||||
// the underlying SDL stick.
|
// the underlying SDL stick.
|
||||||
class JoystickSDL2 : public StellaJoystick
|
class JoystickSDL2 : public StellaJoystick
|
||||||
|
@ -69,6 +70,7 @@ class EventHandlerSDL2 : public EventHandler
|
||||||
private:
|
private:
|
||||||
SDL_Joystick* stick;
|
SDL_Joystick* stick;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,35 +29,38 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
|
FBSurfaceTIA::FBSurfaceTIA(FrameBufferSDL2& buffer)
|
||||||
: myFB(buffer),
|
: myFB(buffer),
|
||||||
myGL(myFB.p_gl),
|
mySurface(NULL),
|
||||||
myTexture(NULL),
|
myTexture(NULL),
|
||||||
myVBOID(0),
|
myScanlinesEnabled(false)
|
||||||
myBaseW(0),
|
// myScanlineIntensityI(50),
|
||||||
myBaseH(0),
|
// 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,
|
// Texture width is set to contain all possible sizes for a TIA image,
|
||||||
// including Blargg filtering
|
// including Blargg filtering
|
||||||
myTexWidth = FrameBufferSDL2::power_of_two(ATARI_NTSC_OUT_WIDTH(160));
|
int width = ATARI_NTSC_OUT_WIDTH(160);
|
||||||
myTexHeight = FrameBufferSDL2::power_of_two(320);
|
int height = 320;
|
||||||
|
|
||||||
// Create a surface in the same format as the parent GL class
|
// Create a surface in the same format as the parent GL class
|
||||||
const SDL_PixelFormat& pf = myFB.myPixelFormat;
|
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);
|
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()
|
FBSurfaceTIA::~FBSurfaceTIA()
|
||||||
{
|
{
|
||||||
if(myTexture)
|
if(mySurface)
|
||||||
SDL_FreeSurface(myTexture);
|
SDL_FreeSurface(mySurface);
|
||||||
|
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
@ -65,29 +68,29 @@ FBSurfaceTIA::~FBSurfaceTIA()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
|
void FBSurfaceTIA::getPos(uInt32& x, uInt32& y) const
|
||||||
{
|
{
|
||||||
x = myImageX;
|
x = mySrc.x;
|
||||||
y = myImageY;
|
y = mySrc.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
|
void FBSurfaceTIA::translateCoords(Int32& x, Int32& y) const
|
||||||
{
|
{
|
||||||
x -= myImageX;
|
x = mySrc.x;
|
||||||
y -= myImageY;
|
y = mySrc.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::update()
|
void FBSurfaceTIA::update()
|
||||||
{
|
{
|
||||||
// Copy the mediasource framebuffer to the RGB texture
|
// Copy the mediasource framebuffer to the RGB texture
|
||||||
// In OpenGL mode, it's faster to just assume that the screen is dirty
|
// In hardware rendering mode, it's faster to just assume that the screen
|
||||||
// and always do an update
|
// is dirty and always do an update
|
||||||
|
|
||||||
uInt8* currentFrame = myTIA->currentFrameBuffer();
|
uInt8* currentFrame = myTIA->currentFrameBuffer();
|
||||||
uInt8* previousFrame = myTIA->previousFrameBuffer();
|
uInt8* previousFrame = myTIA->previousFrameBuffer();
|
||||||
uInt32 width = myTIA->width();
|
uInt32 width = myTIA->width();
|
||||||
uInt32 height = myTIA->height();
|
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
|
// TODO - Eventually 'phosphor' won't be a separate mode, and will become
|
||||||
// a post-processing filter by blending several frames.
|
// a post-processing filter by blending several frames.
|
||||||
|
@ -129,17 +132,25 @@ void FBSurfaceTIA::update()
|
||||||
case FrameBufferSDL2::kBlarggNormal:
|
case FrameBufferSDL2::kBlarggNormal:
|
||||||
{
|
{
|
||||||
myFB.myNTSCFilter.blit_single(currentFrame, width, height,
|
myFB.myNTSCFilter.blit_single(currentFrame, width, height,
|
||||||
buffer, myTexture->pitch);
|
buffer, mySurface->pitch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FrameBufferSDL2::kBlarggPhosphor:
|
case FrameBufferSDL2::kBlarggPhosphor:
|
||||||
{
|
{
|
||||||
myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
|
myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
|
||||||
buffer, myTexture->pitch);
|
buffer, mySurface->pitch);
|
||||||
break;
|
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_VERTEX_ARRAY);
|
||||||
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
|
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
@ -150,7 +161,7 @@ void FBSurfaceTIA::update()
|
||||||
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||||
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH,
|
myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH,
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||||
myTexture->pixels);
|
mySurface->pixels);
|
||||||
|
|
||||||
if(myFB.myVBOAvailable)
|
if(myFB.myVBOAvailable)
|
||||||
{
|
{
|
||||||
|
@ -192,6 +203,7 @@ void FBSurfaceTIA::update()
|
||||||
|
|
||||||
myGL.DisableClientState(GL_VERTEX_ARRAY);
|
myGL.DisableClientState(GL_VERTEX_ARRAY);
|
||||||
myGL.DisableClientState(GL_TEXTURE_COORD_ARRAY);
|
myGL.DisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Let postFrameUpdate() know that a change has been made
|
// Let postFrameUpdate() know that a change has been made
|
||||||
myFB.myDirtyFlag = true;
|
myFB.myDirtyFlag = true;
|
||||||
|
@ -200,20 +212,27 @@ void FBSurfaceTIA::update()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::invalidate()
|
void FBSurfaceTIA::invalidate()
|
||||||
{
|
{
|
||||||
SDL_FillRect(myTexture, NULL, 0);
|
SDL_FillRect(mySurface, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::free()
|
void FBSurfaceTIA::free()
|
||||||
{
|
{
|
||||||
myGL.DeleteTextures(2, myTexID);
|
if(myTexture)
|
||||||
if(myFB.myVBOAvailable)
|
{
|
||||||
myGL.DeleteBuffers(1, &myVBOID);
|
SDL_DestroyTexture(myTexture);
|
||||||
|
myTexture = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::reload()
|
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
|
// This does a 'soft' reset of the surface
|
||||||
// It seems that on some system (notably, OSX), creating a new SDL window
|
// It seems that on some system (notably, OSX), creating a new SDL window
|
||||||
// destroys the GL context, requiring a reload of all textures
|
// 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.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch);
|
||||||
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
|
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0,
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||||
myTexture->pixels);
|
mySurface->pixels);
|
||||||
|
|
||||||
// Scanline texture (@ index 1)
|
// Scanline texture (@ index 1)
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
||||||
|
@ -264,51 +283,72 @@ void FBSurfaceTIA::reload()
|
||||||
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
||||||
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
|
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
|
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
myScanlineIntensityI = (GLuint)intensity;
|
myScanlineIntensityI = (GLuint)intensity;
|
||||||
myScanlineIntensityF = (GLfloat)intensity / 100;
|
myScanlineIntensityF = (GLfloat)intensity / 100;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::setTexInterpolation(bool enable)
|
void FBSurfaceTIA::setTexInterpolation(bool enable)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
myTexFilter[0] = enable ? GL_LINEAR : GL_NEAREST;
|
myTexFilter[0] = enable ? GL_LINEAR : GL_NEAREST;
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
|
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_MIN_FILTER, myTexFilter[0]);
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_S, GL_CLAMP_TO_EDGE);
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::setScanInterpolation(bool enable)
|
void FBSurfaceTIA::setScanInterpolation(bool enable)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
myTexFilter[1] = enable ? GL_LINEAR : GL_NEAREST;
|
myTexFilter[1] = enable ? GL_LINEAR : GL_NEAREST;
|
||||||
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
|
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_MIN_FILTER, myTexFilter[1]);
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_S, GL_REPEAT);
|
||||||
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::updateCoords(uInt32 baseH,
|
void FBSurfaceTIA::updateCoords(uInt32 baseH,
|
||||||
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)
|
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;
|
myBaseH = baseH;
|
||||||
myImageX = imgX; myImageY = imgY;
|
myImageX = imgX; myImageY = imgY;
|
||||||
myImageW = imgW; myImageH = imgH;
|
myImageW = imgW; myImageH = imgH;
|
||||||
|
|
||||||
updateCoords();
|
updateCoords();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceTIA::updateCoords()
|
void FBSurfaceTIA::updateCoords()
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
// Normal TIA rendering and TV effects use different widths
|
// Normal TIA rendering and TV effects use different widths
|
||||||
// We use the same buffer, and only pick the width we need
|
// We use the same buffer, and only pick the width we need
|
||||||
myBaseW = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
|
myBaseW = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160;
|
||||||
|
@ -382,6 +422,7 @@ void FBSurfaceTIA::updateCoords()
|
||||||
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
myGL.BindBuffer(GL_ARRAY_BUFFER, myVBOID);
|
||||||
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
|
myGL.BufferData(GL_ARRAY_BUFFER, 32*sizeof(GLfloat), myCoord, GL_STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -25,10 +25,9 @@
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FrameBufferSDL2.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A surface suitable for OpenGL rendering mode, but specifically for
|
A surface suitable for SDL Render2D API and rendering from a TIA source.
|
||||||
rendering from a TIA source. It doesn't implement most of the
|
It doesn't implement most of the drawing primitives, since it's concerned
|
||||||
drawing primitives, since it's concerned with TIA images only.
|
with TIA images only. This class extends FrameBuffer::FBSurface.
|
||||||
This class extends FrameBuffer::FBSurface.
|
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
*/
|
*/
|
||||||
|
@ -44,8 +43,8 @@ class FBSurfaceTIA : public FBSurface
|
||||||
// only the methods absolutely necessary for dealing with drawing
|
// only the methods absolutely necessary for dealing with drawing
|
||||||
// a TIA image
|
// a TIA image
|
||||||
void getPos(uInt32& x, uInt32& y) const;
|
void getPos(uInt32& x, uInt32& y) const;
|
||||||
uInt32 getWidth() const { return myImageW; }
|
uInt32 getWidth() const { return mySrc.w; }
|
||||||
uInt32 getHeight() const { return myImageH; }
|
uInt32 getHeight() const { return mySrc.h; }
|
||||||
void translateCoords(Int32& x, Int32& y) const;
|
void translateCoords(Int32& x, Int32& y) const;
|
||||||
void update();
|
void update();
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
@ -64,23 +63,14 @@ class FBSurfaceTIA : public FBSurface
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FrameBufferSDL2& myFB;
|
||||||
const FrameBufferSDL2::GLpointers& myGL;
|
|
||||||
const TIA* myTIA;
|
const TIA* myTIA;
|
||||||
SDL_Surface* myTexture;
|
|
||||||
|
SDL_Surface* mySurface;
|
||||||
|
SDL_Texture* myTexture;
|
||||||
|
SDL_Rect mySrc, myDst;
|
||||||
uInt32 myPitch;
|
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;
|
bool myScanlinesEnabled;
|
||||||
GLuint myScanlineIntensityI;
|
|
||||||
GLfloat myScanlineIntensityF;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,38 +23,31 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceUI::FBSurfaceUI(FrameBufferSDL2& buffer, uInt32 width, uInt32 height)
|
FBSurfaceUI::FBSurfaceUI(FrameBufferSDL2& buffer, uInt32 width, uInt32 height)
|
||||||
: myFB(buffer),
|
: myFB(buffer),
|
||||||
myGL(myFB.p_gl),
|
mySurface(NULL),
|
||||||
myTexture(NULL),
|
myTexture(NULL),
|
||||||
myTexID(0),
|
mySurfaceIsDirty(true)
|
||||||
myVBOID(0),
|
|
||||||
myImageX(0),
|
|
||||||
myImageY(0),
|
|
||||||
myImageW(width),
|
|
||||||
myImageH(height)
|
|
||||||
{
|
{
|
||||||
// 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
|
// Create a surface in the same format as the parent GL class
|
||||||
const SDL_PixelFormat& pf = myFB.myPixelFormat;
|
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);
|
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
|
myPitch = mySurface->pitch / pf.BytesPerPixel;
|
||||||
updateCoords();
|
|
||||||
|
// To generate texture
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceUI::~FBSurfaceUI()
|
FBSurfaceUI::~FBSurfaceUI()
|
||||||
{
|
{
|
||||||
if(myTexture)
|
if(mySurface)
|
||||||
SDL_FreeSurface(myTexture);
|
SDL_FreeSurface(mySurface);
|
||||||
|
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
@ -62,7 +55,7 @@ FBSurfaceUI::~FBSurfaceUI()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color)
|
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)
|
while(x++ <= x2)
|
||||||
*buffer++ = (uInt32) myFB.myDefPalette[color];
|
*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)
|
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)
|
while(y++ <= y2)
|
||||||
{
|
{
|
||||||
*buffer = (uInt32) myFB.myDefPalette[color];
|
*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.y = y;
|
||||||
tmp.w = w;
|
tmp.w = w;
|
||||||
tmp.h = h;
|
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));
|
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 +
|
(ty + desc.ascent - bby - bbh) * myPitch +
|
||||||
tx + bbx;
|
tx + bbx;
|
||||||
|
|
||||||
|
@ -143,7 +136,7 @@ void FBSurfaceUI::drawChar(const GUI::Font& font, uInt8 chr,
|
||||||
void FBSurfaceUI::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
|
void FBSurfaceUI::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty,
|
||||||
uInt32 color, uInt32 h)
|
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)
|
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)
|
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)
|
for(uInt32 i = 0; i < numpixels; ++i)
|
||||||
*buffer++ = (uInt32) data[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;
|
const FBSurfaceUI* s = (const FBSurfaceUI*) surface;
|
||||||
|
|
||||||
SDL_Rect dstrect;
|
SDL_Rect dst;
|
||||||
dstrect.x = tx;
|
dst.x = tx;
|
||||||
dstrect.y = ty;
|
dst.y = ty;
|
||||||
SDL_Rect srcrect;
|
dst.w = s->mySrc.w;
|
||||||
srcrect.x = 0;
|
dst.h = s->mySrc.h;
|
||||||
srcrect.y = 0;
|
|
||||||
srcrect.w = s->myImageW;
|
|
||||||
srcrect.h = s->myImageH;
|
|
||||||
|
|
||||||
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)
|
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 (hardware) surface
|
||||||
// It's faster to just update the entire surface
|
|
||||||
mySurfaceIsDirty = true;
|
mySurfaceIsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::getPos(uInt32& x, uInt32& y) const
|
void FBSurfaceUI::getPos(uInt32& x, uInt32& y) const
|
||||||
{
|
{
|
||||||
x = myImageX;
|
x = myDst.x;
|
||||||
y = myImageY;
|
y = myDst.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::setPos(uInt32 x, uInt32 y)
|
void FBSurfaceUI::setPos(uInt32 x, uInt32 y)
|
||||||
{
|
{
|
||||||
if(myImageX != x || myImageY != y)
|
myDst.x = x;
|
||||||
{
|
myDst.y = y;
|
||||||
myImageX = x;
|
|
||||||
myImageY = y;
|
|
||||||
updateCoords();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -214,12 +199,8 @@ void FBSurfaceUI::setWidth(uInt32 w)
|
||||||
// This method can't be used with 'scaled' surface (aka TIA surfaces)
|
// 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,
|
// That shouldn't really matter, though, as all the UI stuff isn't scaled,
|
||||||
// and it's the only thing that uses it
|
// and it's the only thing that uses it
|
||||||
if(myImageW != w)
|
mySrc.w = w;
|
||||||
{
|
myDst.w = w;
|
||||||
myImageW = BSPF_min(w, (uInt32)myTexWidth);
|
|
||||||
myTexCoordW = (GLfloat) myImageW / myTexWidth;
|
|
||||||
updateCoords();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -228,19 +209,15 @@ void FBSurfaceUI::setHeight(uInt32 h)
|
||||||
// This method can't be used with 'scaled' surface (aka TIA surfaces)
|
// 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,
|
// That shouldn't really matter, though, as all the UI stuff isn't scaled,
|
||||||
// and it's the only thing that uses it
|
// and it's the only thing that uses it
|
||||||
if(myImageH != h)
|
mySrc.h = h;
|
||||||
{
|
myDst.h = h;
|
||||||
myImageH = BSPF_min(h, (uInt32)myTexHeight);
|
|
||||||
myTexCoordH = (GLfloat) myImageH / myTexHeight;
|
|
||||||
updateCoords();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::translateCoords(Int32& x, Int32& y) const
|
void FBSurfaceUI::translateCoords(Int32& x, Int32& y) const
|
||||||
{
|
{
|
||||||
x -= myImageX;
|
x -= myDst.x;
|
||||||
y -= myImageY;
|
y -= myDst.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -248,32 +225,11 @@ void FBSurfaceUI::update()
|
||||||
{
|
{
|
||||||
if(mySurfaceIsDirty)
|
if(mySurfaceIsDirty)
|
||||||
{
|
{
|
||||||
// Texturemap complete texture to surface so we have free scaling
|
//cerr << "src: x=" << mySrc.x << ", y=" << mySrc.y << ", w=" << mySrc.w << ", h=" << mySrc.h << endl;
|
||||||
// and antialiasing
|
//cerr << "dst: x=" << myDst.x << ", y=" << myDst.y << ", w=" << myDst.w << ", h=" << myDst.h << endl;
|
||||||
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);
|
|
||||||
|
|
||||||
myGL.EnableClientState(GL_VERTEX_ARRAY);
|
SDL_UpdateTexture(myTexture, NULL, mySurface->pixels, mySurface->pitch);
|
||||||
myGL.EnableClientState(GL_TEXTURE_COORD_ARRAY);
|
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrc, &myDst);
|
||||||
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);
|
|
||||||
|
|
||||||
mySurfaceIsDirty = false;
|
mySurfaceIsDirty = false;
|
||||||
|
|
||||||
|
@ -282,85 +238,27 @@ void FBSurfaceUI::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FBSurfaceUI::invalidate()
|
||||||
|
{
|
||||||
|
SDL_FillRect(mySurface, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::free()
|
void FBSurfaceUI::free()
|
||||||
{
|
{
|
||||||
myGL.DeleteTextures(1, &myTexID);
|
if(myTexture)
|
||||||
if(myFB.myVBOAvailable)
|
{
|
||||||
myGL.DeleteBuffers(1, &myVBOID);
|
SDL_DestroyTexture(myTexture);
|
||||||
|
myTexture = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceUI::reload()
|
void FBSurfaceUI::reload()
|
||||||
{
|
{
|
||||||
// This does a 'soft' reset of the surface
|
// Re-create texture; the underlying SDL_Surface is fine as-is
|
||||||
// It seems that on some system (notably, OSX), creating a new SDL window
|
myTexture = SDL_CreateTexture(myFB.myRenderer,
|
||||||
// destroys the GL context, requiring a reload of all textures
|
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
|
||||||
// However, destroying the entire FBSurfaceUI object is wasteful, since
|
mySurface->w, mySurface->h);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "FrameBufferSDL2.hxx"
|
#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.
|
This class extends FrameBuffer::FBSurface.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
|
@ -48,29 +48,22 @@ class FBSurfaceUI : public FBSurface
|
||||||
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
|
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
|
||||||
void getPos(uInt32& x, uInt32& y) const;
|
void getPos(uInt32& x, uInt32& y) const;
|
||||||
void setPos(uInt32 x, uInt32 y);
|
void setPos(uInt32 x, uInt32 y);
|
||||||
uInt32 getWidth() const { return myImageW; }
|
uInt32 getWidth() const { return mySrc.w; }
|
||||||
uInt32 getHeight() const { return myImageH; }
|
uInt32 getHeight() const { return mySrc.h; }
|
||||||
void setWidth(uInt32 w);
|
void setWidth(uInt32 w);
|
||||||
void setHeight(uInt32 h);
|
void setHeight(uInt32 h);
|
||||||
void translateCoords(Int32& x, Int32& y) const;
|
void translateCoords(Int32& x, Int32& y) const;
|
||||||
void update();
|
void update();
|
||||||
|
void invalidate();
|
||||||
void free();
|
void free();
|
||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
private:
|
|
||||||
void updateCoords();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FrameBufferSDL2& myFB;
|
||||||
const FrameBufferSDL2::GLpointers& myGL;
|
|
||||||
SDL_Surface* myTexture;
|
|
||||||
|
|
||||||
GLuint myTexID, myVBOID;
|
SDL_Surface* mySurface;
|
||||||
GLsizei myTexWidth;
|
SDL_Texture* myTexture;
|
||||||
GLsizei myTexHeight;
|
SDL_Rect mySrc, myDst;
|
||||||
GLuint myImageX, myImageY, myImageW, myImageH;
|
|
||||||
GLfloat myTexCoordW, myTexCoordH;
|
|
||||||
GLfloat myCoord[16];
|
|
||||||
|
|
||||||
bool mySurfaceIsDirty;
|
bool mySurfaceIsDirty;
|
||||||
uInt32 myPitch;
|
uInt32 myPitch;
|
||||||
|
|
|
@ -39,19 +39,20 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
|
||||||
: FrameBuffer(osystem),
|
: FrameBuffer(osystem),
|
||||||
myFilterType(kNormal),
|
myFilterType(kNormal),
|
||||||
myScreen(0),
|
myScreen(0),
|
||||||
mySDLFlags(0),
|
myWindow(NULL),
|
||||||
|
myRenderer(NULL),
|
||||||
|
myWindowFlags(0),
|
||||||
myTiaSurface(NULL),
|
myTiaSurface(NULL),
|
||||||
myDirtyFlag(true)
|
myDirtyFlag(true)
|
||||||
{
|
{
|
||||||
// Initialize SDL2 context
|
// Initialize SDL2 context
|
||||||
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
|
||||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 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;
|
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
|
// We need a pixel format for palette value calculations
|
||||||
// It's done this way (vs directly accessing a FBSurfaceUI object)
|
// It's done this way (vs directly accessing a FBSurfaceUI object)
|
||||||
|
@ -59,7 +60,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
|
||||||
// been created
|
// been created
|
||||||
// Note: alpha disabled for now, since it's not used
|
// Note: alpha disabled for now, since it's not used
|
||||||
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32,
|
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32,
|
||||||
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);
|
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
|
||||||
|
|
||||||
myPixelFormat = *(s->format);
|
myPixelFormat = *(s->format);
|
||||||
SDL_FreeSurface(s);
|
SDL_FreeSurface(s);
|
||||||
|
@ -68,85 +69,13 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferSDL2::~FrameBufferSDL2()
|
FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
{
|
{
|
||||||
|
// if(myWindow)
|
||||||
|
// SDL_DestroyWindow(myWindow);
|
||||||
|
|
||||||
// We're taking responsibility for this surface
|
// We're taking responsibility for this surface
|
||||||
delete myTiaSurface;
|
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)
|
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");
|
const GUI::Size& s = myOSystem->settings().getSize("maxres");
|
||||||
if(s.w <= 0 || s.h <= 0)
|
if(s.w <= 0 || s.h <= 0)
|
||||||
{
|
{
|
||||||
const SDL_VideoInfo* info = SDL_GetVideoInfo();
|
SDL_DisplayMode desktop;
|
||||||
w = info->current_w;
|
SDL_GetDesktopDisplayMode(0, &desktop);
|
||||||
h = info->current_h;
|
w = desktop.w;
|
||||||
|
h = desktop.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#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
|
// If not initialized by this point, then immediately fail
|
||||||
// These things only have to be done one per FrameBuffer creation
|
|
||||||
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
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;
|
return false;
|
||||||
|
|
||||||
// Now check to see what color components were actually created
|
// (Re)create window and renderer
|
||||||
SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &myRGB[0] );
|
if(myRenderer)
|
||||||
SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &myRGB[1] );
|
{
|
||||||
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &myRGB[2] );
|
SDL_DestroyRenderer(myRenderer);
|
||||||
SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, &myRGB[3] );
|
myRenderer = NULL;
|
||||||
|
}
|
||||||
return true;
|
if(myWindow)
|
||||||
|
{
|
||||||
|
SDL_DestroyWindow(myWindow);
|
||||||
|
myWindow = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
myWindow = SDL_CreateWindow(title.c_str(),
|
||||||
string FrameBufferSDL2::about() const
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
mode.image_w, mode.image_h,
|
||||||
|
0);
|
||||||
|
if(myWindow == NULL)
|
||||||
{
|
{
|
||||||
ostringstream out;
|
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
|
||||||
out << "Video rendering: OpenGL mode" << endl
|
myOSystem->logMessage(msg, 0);
|
||||||
<< " Vendor: " << p_gl.GetString(GL_VENDOR) << endl
|
return false;
|
||||||
<< " 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
myRenderer = SDL_CreateRenderer(myWindow, -1,
|
||||||
bool FrameBufferSDL2::setVidMode(VideoMode& mode)
|
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 =
|
bool inTIAMode =
|
||||||
myOSystem->eventHandler().state() != EventHandler::S_LAUNCHER &&
|
myOSystem->eventHandler().state() != EventHandler::S_LAUNCHER &&
|
||||||
myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER;
|
myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER;
|
||||||
|
@ -298,6 +200,7 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
|
||||||
// We need it for the creating the TIA surface
|
// We need it for the creating the TIA surface
|
||||||
uInt32 baseHeight = mode.image_h / mode.gfxmode.zoom;
|
uInt32 baseHeight = mode.image_h / mode.gfxmode.zoom;
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Aspect ratio and fullscreen stretching only applies to the TIA
|
// Aspect ratio and fullscreen stretching only applies to the TIA
|
||||||
if(inTIAMode)
|
if(inTIAMode)
|
||||||
{
|
{
|
||||||
|
@ -362,18 +265,12 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
|
||||||
// We leave it to the user to test and decide
|
// We leave it to the user to test and decide
|
||||||
int vsync = myOSystem->settings().getBool("gl_vsync") ? 1 : 0;
|
int vsync = myOSystem->settings().getBool("gl_vsync") ? 1 : 0;
|
||||||
SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, vsync );
|
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
|
// Make sure the flags represent the current screen state
|
||||||
mySDLFlags = myScreen->flags;
|
// myWindowFlags = myScreen->flags;
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Optimization hints
|
// Optimization hints
|
||||||
p_gl.ShadeModel(GL_FLAT);
|
p_gl.ShadeModel(GL_FLAT);
|
||||||
p_gl.Disable(GL_CULL_FACE);
|
p_gl.Disable(GL_CULL_FACE);
|
||||||
|
@ -390,7 +287,7 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode)
|
||||||
p_gl.MatrixMode(GL_MODELVIEW);
|
p_gl.MatrixMode(GL_MODELVIEW);
|
||||||
p_gl.LoadIdentity();
|
p_gl.LoadIdentity();
|
||||||
p_gl.Translatef(0.375, 0.375, 0.0); // fix scanline mis-draw issues
|
p_gl.Translatef(0.375, 0.375, 0.0); // fix scanline mis-draw issues
|
||||||
|
#endif
|
||||||
//cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl << mode << endl;
|
//cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl << mode << endl;
|
||||||
|
|
||||||
// The framebuffer only takes responsibility for TIA surfaces
|
// 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;
|
#if 0
|
||||||
switch(hint)
|
ostringstream out;
|
||||||
{
|
out << "Video rendering: OpenGL mode" << endl
|
||||||
case kFullScreen:
|
<< " Vendor: " << p_gl.GetString(GL_VENDOR) << endl
|
||||||
flag = SDL_FULLSCREEN;
|
<< " Renderer: " << p_gl.GetString(GL_RENDERER) << endl
|
||||||
break;
|
<< " Version: " << p_gl.GetString(GL_VERSION) << endl
|
||||||
}
|
<< " Color: " << myDepth << " bit, " << myRGB[0] << "-"
|
||||||
if(enabled)
|
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3] << ", "
|
||||||
mySDLFlags |= flag;
|
<< "GL_BGRA" << endl
|
||||||
else
|
<< " Extensions: VBO " << (myVBOAvailable ? "enabled" : "disabled")
|
||||||
mySDLFlags &= ~flag;
|
<< endl;
|
||||||
|
return out.str();
|
||||||
|
#endif
|
||||||
|
return EmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::invalidate()
|
void FrameBufferSDL2::invalidate()
|
||||||
{
|
{
|
||||||
p_gl.Clear(GL_COLOR_BUFFER_BIT);
|
SDL_RenderClear(myRenderer);
|
||||||
if(myTiaSurface)
|
if(myTiaSurface)
|
||||||
myTiaSurface->invalidate();
|
myTiaSurface->invalidate();
|
||||||
}
|
}
|
||||||
|
@ -448,34 +348,32 @@ void FrameBufferSDL2::invalidate()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::showCursor(bool show)
|
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)
|
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
|
bool FrameBufferSDL2::fullScreen() const
|
||||||
{
|
{
|
||||||
|
#if 0//FIXSDL
|
||||||
#ifdef WINDOWED_SUPPORT
|
#ifdef WINDOWED_SUPPORT
|
||||||
return mySDLFlags & SDL_FULLSCREEN;
|
return myWindowFlags & SDL_FULLSCREEN;
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
#endif
|
||||||
|
return false;
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferSDL2::setWindowTitle(const string& title)
|
|
||||||
{
|
|
||||||
SDL_WM_SetCaption(title.c_str(), "stella");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::setWindowIcon()
|
void FrameBufferSDL2::setWindowIcon()
|
||||||
{
|
{
|
||||||
|
#if 0 //FIXSDL
|
||||||
#if !defined(BSPF_MAC_OSX) && !defined(BSPF_UNIX)
|
#if !defined(BSPF_MAC_OSX) && !defined(BSPF_UNIX)
|
||||||
#include "stella.xpm" // The Stella icon
|
#include "stella.xpm" // The Stella icon
|
||||||
|
|
||||||
|
@ -532,6 +430,7 @@ void FrameBufferSDL2::setWindowIcon()
|
||||||
SDL_WM_SetIcon(surface, (unsigned char *) mask);
|
SDL_WM_SetIcon(surface, (unsigned char *) mask);
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -547,7 +446,7 @@ void FrameBufferSDL2::postFrameUpdate()
|
||||||
if(myDirtyFlag)
|
if(myDirtyFlag)
|
||||||
{
|
{
|
||||||
// Now show all changes made to the texture(s)
|
// Now show all changes made to the texture(s)
|
||||||
SDL_GL_SwapBuffers();
|
SDL_RenderPresent(myRenderer);
|
||||||
myDirtyFlag = false;
|
myDirtyFlag = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,7 +469,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
|
||||||
if(myTiaSurface)
|
if(myTiaSurface)
|
||||||
{
|
{
|
||||||
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
|
myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01);
|
||||||
myTiaSurface->updateCoords();
|
//FIXSDL myTiaSurface->updateCoords();
|
||||||
|
|
||||||
myTiaSurface->enableScanlines(ntscEnabled());
|
myTiaSurface->enableScanlines(ntscEnabled());
|
||||||
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
|
||||||
|
@ -584,6 +483,7 @@ void FrameBufferSDL2::enableNTSC(bool enable)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
||||||
{
|
{
|
||||||
|
#if 0//FIXSDL
|
||||||
int intensity = myTiaSurface->myScanlineIntensityI;
|
int intensity = myTiaSurface->myScanlineIntensityI;
|
||||||
if(myTiaSurface)
|
if(myTiaSurface)
|
||||||
{
|
{
|
||||||
|
@ -596,6 +496,8 @@ uInt32 FrameBufferSDL2::enableScanlines(int relative, int absolute)
|
||||||
myRedrawEntireFrame = true;
|
myRedrawEntireFrame = true;
|
||||||
}
|
}
|
||||||
return intensity;
|
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
|
void FrameBufferSDL2::scanline(uInt32 row, uInt8* data) const
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
// Invert the row, since OpenGL rows start at the bottom
|
// Invert the row, since OpenGL rows start at the bottom
|
||||||
// of the framebuffer
|
// of the framebuffer
|
||||||
const GUI::Rect& image = imageRect();
|
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.PixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
p_gl.ReadPixels(image.x(), row, image.width(), 1, GL_RGB, GL_UNSIGNED_BYTE, data);
|
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;
|
break;
|
||||||
case kBlarggNormal:
|
case kBlarggNormal:
|
||||||
buf << myNTSCFilter.getPreset() << ", scanlines="
|
buf << myNTSCFilter.getPreset() << ", scanlines="
|
||||||
|
#if 0
|
||||||
<< myTiaSurface->myScanlineIntensityI << "/"
|
<< myTiaSurface->myScanlineIntensityI << "/"
|
||||||
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
||||||
|
#endif
|
||||||
|
;
|
||||||
break;
|
break;
|
||||||
case kBlarggPhosphor:
|
case kBlarggPhosphor:
|
||||||
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
|
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
|
||||||
|
#if 0
|
||||||
<< myTiaSurface->myScanlineIntensityI << "/"
|
<< myTiaSurface->myScanlineIntensityI << "/"
|
||||||
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
<< (myTiaSurface->myTexFilter[1] == GL_LINEAR ? "inter" : "nointer");
|
||||||
|
#endif
|
||||||
|
;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameBufferSDL2::myLibraryLoaded = false;
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameBufferSDL2::myVBOAvailable = false;
|
|
||||||
|
|
|
@ -54,15 +54,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
*/
|
*/
|
||||||
virtual ~FrameBufferSDL2();
|
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
|
// The following are derived from public methods in FrameBuffer.hxx
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
@ -82,11 +73,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
*/
|
*/
|
||||||
bool fullScreen() const;
|
bool fullScreen() const;
|
||||||
|
|
||||||
/**
|
|
||||||
Set the title for the main window.
|
|
||||||
*/
|
|
||||||
void setWindowTitle(const string& title);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable/disable phosphor effect.
|
Enable/disable phosphor effect.
|
||||||
*/
|
*/
|
||||||
|
@ -157,34 +143,16 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res);
|
bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to initialize the video subsystem
|
This method is called to change to the given video mode. If the mode
|
||||||
with the given video mode. Normally, it will also call setVidMode().
|
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 mode The video mode to use
|
||||||
@param full Whether this is a fullscreen or windowed mode
|
@param full Whether this is a fullscreen or windowed mode
|
||||||
|
|
||||||
@return False on any errors, else true
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
bool initSubsystem(VideoMode& mode, bool full);
|
bool setVideoMode(const string& title, 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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to invalidate the contents of the entire
|
This method is called to invalidate the contents of the entire
|
||||||
|
@ -240,11 +208,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
void enableScanlineInterpolation(bool enable);
|
void enableScanlineInterpolation(bool enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum GLFunctionality {
|
|
||||||
kGL_BASIC, kGL_VBO
|
|
||||||
};
|
|
||||||
bool loadFuncs(GLFunctionality functionality);
|
|
||||||
|
|
||||||
// Enumeration created such that phosphor off/on is in LSB,
|
// Enumeration created such that phosphor off/on is in LSB,
|
||||||
// and Blargg off/on is in MSB
|
// and Blargg off/on is in MSB
|
||||||
enum FilterType {
|
enum FilterType {
|
||||||
|
@ -255,23 +218,17 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
};
|
};
|
||||||
FilterType myFilterType;
|
FilterType myFilterType;
|
||||||
|
|
||||||
static uInt32 power_of_two(uInt32 input)
|
|
||||||
{
|
|
||||||
uInt32 value = 1;
|
|
||||||
while( value < input )
|
|
||||||
value <<= 1;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The SDL video buffer
|
// The SDL video buffer
|
||||||
SDL_Surface* myScreen;
|
SDL_Surface* myScreen;
|
||||||
|
SDL_Window* myWindow;
|
||||||
|
SDL_Renderer* myRenderer;
|
||||||
|
|
||||||
// SDL initialization flags
|
// SDL initialization flags
|
||||||
// This is set by the base FrameBuffer class, and read by the derived classes
|
// 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
|
// If a FrameBuffer is successfully created, the derived classes must modify
|
||||||
// it to point to the actual flags used by the SDL_Surface
|
// 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,
|
// The lower-most base surface (will always be a TIA surface,
|
||||||
// since Dialog surfaces are allocated by the Dialog class directly).
|
// since Dialog surfaces are allocated by the Dialog class directly).
|
||||||
|
@ -283,57 +240,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
// The depth of the texture buffer
|
// The depth of the texture buffer
|
||||||
uInt32 myDepth;
|
uInt32 myDepth;
|
||||||
|
|
||||||
// The size of color components for OpenGL
|
|
||||||
Int32 myRGB[4];
|
|
||||||
|
|
||||||
// Indicates that the texture has been modified, and should be redrawn
|
// Indicates that the texture has been modified, and should be redrawn
|
||||||
bool myDirtyFlag;
|
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
|
#endif
|
||||||
|
|
|
@ -310,6 +310,6 @@ typedef enum {
|
||||||
|
|
||||||
// Just pass SDLMod directly as int (placeholder for now)
|
// Just pass SDLMod directly as int (placeholder for now)
|
||||||
// The underlying code doesn't need to know how it's implemented
|
// The underlying code doesn't need to know how it's implemented
|
||||||
typedef int StellaMod;
|
typedef SDL_Keymod StellaMod;
|
||||||
|
|
||||||
#endif /* StellaKeys */
|
#endif /* StellaKeys */
|
||||||
|
|
|
@ -2041,7 +2041,7 @@ void EventHandler::setEventState(State state)
|
||||||
case S_EMULATE:
|
case S_EMULATE:
|
||||||
myOverlay = NULL;
|
myOverlay = NULL;
|
||||||
myOSystem->sound().mute(false);
|
myOSystem->sound().mute(false);
|
||||||
SDL_EnableUNICODE(0);
|
//FIXME SDL_EnableUNICODE(0);
|
||||||
if(myOSystem->console().controller(Controller::Left).type() ==
|
if(myOSystem->console().controller(Controller::Left).type() ==
|
||||||
Controller::CompuMate)
|
Controller::CompuMate)
|
||||||
myUseCtrlKeyFlag = false;
|
myUseCtrlKeyFlag = false;
|
||||||
|
@ -2050,28 +2050,28 @@ void EventHandler::setEventState(State state)
|
||||||
case S_PAUSE:
|
case S_PAUSE:
|
||||||
myOverlay = NULL;
|
myOverlay = NULL;
|
||||||
myOSystem->sound().mute(true);
|
myOSystem->sound().mute(true);
|
||||||
SDL_EnableUNICODE(0);
|
//FIXME SDL_EnableUNICODE(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_MENU:
|
case S_MENU:
|
||||||
myOverlay = &myOSystem->menu();
|
myOverlay = &myOSystem->menu();
|
||||||
SDL_EnableUNICODE(1);
|
//FIXME SDL_EnableUNICODE(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_CMDMENU:
|
case S_CMDMENU:
|
||||||
myOverlay = &myOSystem->commandMenu();
|
myOverlay = &myOSystem->commandMenu();
|
||||||
SDL_EnableUNICODE(1);
|
//FIXME SDL_EnableUNICODE(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_LAUNCHER:
|
case S_LAUNCHER:
|
||||||
myOverlay = &myOSystem->launcher();
|
myOverlay = &myOSystem->launcher();
|
||||||
SDL_EnableUNICODE(1);
|
//FIXME SDL_EnableUNICODE(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
case S_DEBUGGER:
|
case S_DEBUGGER:
|
||||||
myOverlay = &myOSystem->debugger();
|
myOverlay = &myOSystem->debugger();
|
||||||
SDL_EnableUNICODE(1);
|
//FIXME SDL_EnableUNICODE(1);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -186,11 +186,8 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
|
||||||
VideoMode mode = getSavedVidMode();
|
VideoMode mode = getSavedVidMode();
|
||||||
if(width <= mode.screen_w && height <= mode.screen_h)
|
if(width <= mode.screen_w && height <= mode.screen_h)
|
||||||
{
|
{
|
||||||
setWindowTitle(title);
|
if(setVideoMode(title, mode, useFullscreen))
|
||||||
if(initSubsystem(mode, useFullscreen))
|
|
||||||
{
|
{
|
||||||
centerAppWindow(mode);
|
|
||||||
|
|
||||||
myImageRect.setWidth(mode.image_w);
|
myImageRect.setWidth(mode.image_w);
|
||||||
myImageRect.setHeight(mode.image_h);
|
myImageRect.setHeight(mode.image_h);
|
||||||
myImageRect.moveTo(mode.image_x, mode.image_y);
|
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
|
// This method is in essence a FULL refresh, putting all rendering
|
||||||
// buffers in a known, fully redrawn state
|
// buffers in a known, fully redrawn state
|
||||||
|
|
||||||
bool doubleBuffered = (type() == kDoubleBuffer);
|
bool doubleBuffered = false;//FIXSDL(type() == kDoubleBuffer);
|
||||||
switch(myOSystem->eventHandler().state())
|
switch(myOSystem->eventHandler().state())
|
||||||
{
|
{
|
||||||
case EventHandler::S_EMULATE:
|
case EventHandler::S_EMULATE:
|
||||||
|
@ -756,6 +753,7 @@ void FrameBuffer::toggleFullscreen()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBuffer::setFullscreen(bool enable)
|
void FrameBuffer::setFullscreen(bool enable)
|
||||||
{
|
{
|
||||||
|
#if 0 //FIXSDL
|
||||||
#ifdef WINDOWED_SUPPORT
|
#ifdef WINDOWED_SUPPORT
|
||||||
// '-1' means fullscreen mode is completely disabled
|
// '-1' means fullscreen mode is completely disabled
|
||||||
bool full = enable && myOSystem->settings().getString("fullscreen") != "-1";
|
bool full = enable && myOSystem->settings().getString("fullscreen") != "-1";
|
||||||
|
@ -769,11 +767,13 @@ void FrameBuffer::setFullscreen(bool enable)
|
||||||
// to changeVidMode()
|
// to changeVidMode()
|
||||||
changeVidMode(0);
|
changeVidMode(0);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBuffer::changeVidMode(int direction)
|
bool FrameBuffer::changeVidMode(int direction)
|
||||||
{
|
{
|
||||||
|
#if 0 //FIXSDL
|
||||||
EventHandler::State state = myOSystem->eventHandler().state();
|
EventHandler::State state = myOSystem->eventHandler().state();
|
||||||
bool inUIMode = (state == EventHandler::S_DEBUGGER ||
|
bool inUIMode = (state == EventHandler::S_DEBUGGER ||
|
||||||
state == EventHandler::S_LAUNCHER);
|
state == EventHandler::S_LAUNCHER);
|
||||||
|
@ -793,8 +793,6 @@ bool FrameBuffer::changeVidMode(int direction)
|
||||||
VideoMode vidmode = myCurrentModeList->current(myOSystem->settings(), fullScreen());
|
VideoMode vidmode = myCurrentModeList->current(myOSystem->settings(), fullScreen());
|
||||||
if(setVidMode(vidmode))
|
if(setVidMode(vidmode))
|
||||||
{
|
{
|
||||||
centerAppWindow(vidmode);
|
|
||||||
|
|
||||||
myImageRect.setWidth(vidmode.image_w);
|
myImageRect.setWidth(vidmode.image_w);
|
||||||
myImageRect.setHeight(vidmode.image_h);
|
myImageRect.setHeight(vidmode.image_h);
|
||||||
myImageRect.moveTo(vidmode.image_x, vidmode.image_y);
|
myImageRect.moveTo(vidmode.image_x, vidmode.image_y);
|
||||||
|
@ -820,7 +818,7 @@ bool FrameBuffer::changeVidMode(int direction)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
/*
|
/*
|
||||||
cerr << "New mode:" << endl
|
cerr << "New mode:" << endl
|
||||||
|
@ -1025,22 +1023,6 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode()
|
||||||
return myCurrentModeList->current(myOSystem->settings(), fullScreen());
|
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()
|
FrameBuffer::VideoModeList::VideoModeList()
|
||||||
: myIdx(-1)
|
: myIdx(-1)
|
||||||
|
|
|
@ -348,11 +348,6 @@ class FrameBuffer
|
||||||
*/
|
*/
|
||||||
virtual bool fullScreen() const = 0;
|
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.
|
Enable/disable/query NTSC filtering effects.
|
||||||
*/
|
*/
|
||||||
|
@ -454,35 +449,16 @@ class FrameBuffer
|
||||||
virtual bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res) = 0;
|
virtual bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to initialize the video subsystem
|
This method is called to change to the given video mode. If the mode
|
||||||
with the given video mode. Normally, it will also call setVidMode().
|
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 mode The video mode to use
|
||||||
@param full Whether this is a fullscreen or windowed mode
|
@param full Whether this is a fullscreen or windowed mode
|
||||||
|
|
||||||
@return False on any errors, else true
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
virtual bool initSubsystem(VideoMode& mode, bool full) = 0;
|
virtual bool setVideoMode(const string& title, 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to invalidate the contents of the entire
|
This method is called to invalidate the contents of the entire
|
||||||
|
@ -600,11 +576,6 @@ class FrameBuffer
|
||||||
*/
|
*/
|
||||||
VideoMode getSavedVidMode();
|
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.
|
Set up the user interface palette for a screen of any depth > 8.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -107,10 +107,11 @@ OSystem::OSystem()
|
||||||
|
|
||||||
// Get build info
|
// Get build info
|
||||||
ostringstream 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
|
info << "Build " << STELLA_BUILD << ", using SDL " << (int)ver.major
|
||||||
<< "." << (int)ver->minor << "."<< (int)ver->patch
|
<< "." << (int)ver.minor << "."<< (int)ver.patch
|
||||||
<< " [" << BSPF_ARCH << "]";
|
<< " [" << BSPF_ARCH << "]";
|
||||||
myBuildInfo = info.str();
|
myBuildInfo = info.str();
|
||||||
|
|
||||||
|
|
|
@ -165,8 +165,8 @@ class DialogContainer
|
||||||
// For continuous 'key down' events
|
// For continuous 'key down' events
|
||||||
struct {
|
struct {
|
||||||
StellaKey keycode;
|
StellaKey keycode;
|
||||||
|
StellaMod flags;
|
||||||
char ascii;
|
char ascii;
|
||||||
int flags;
|
|
||||||
} myCurrentKeyDown;
|
} myCurrentKeyDown;
|
||||||
uInt64 myKeyRepeatTime;
|
uInt64 myKeyRepeatTime;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue