aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--backends/sdl/sdl_gl.cpp369
2 files changed, 305 insertions, 66 deletions
diff --git a/README b/README
index 4019f530d5..876489ffb9 100644
--- a/README
+++ b/README
@@ -335,7 +335,7 @@ simon games.
Ctrl-Alt 1 - Switch beetwen bilinear and non-linear filtering [OpenGL backend]
Ctrl-Alt 2 - Don't fit the game in the whole screen (black borders) [OpenGL backend]
Ctrl-Alt 3 - Fit the game in the whole screen (no black borders) [OpenGL backend]
- Ctrl-Alt 4-7 - Zoom [OpenGL backend]
+ Ctrl-Alt 4-7 - Switch between graphics filters [OpenGL backend]
Scumm:
Ctrl 0-9 and Alt 0-9 - load and save game state
diff --git a/backends/sdl/sdl_gl.cpp b/backends/sdl/sdl_gl.cpp
index 13dcb90190..e1ff24d891 100644
--- a/backends/sdl/sdl_gl.cpp
+++ b/backends/sdl/sdl_gl.cpp
@@ -34,11 +34,7 @@ int glGetColorTable(int, int, int, void *) { return 0; }
class OSystem_SDL_OpenGL : public OSystem_SDL_Common {
public:
- OSystem_SDL_OpenGL() {
- _glScreenStart = 0;
- _glBilinearFilter = true;
- _glBottomOfTexture = 256; // height is always 256
- }
+ OSystem_SDL_OpenGL();
// Set colors of the palette
void set_palette(const byte *colors, uint start, uint num);
@@ -49,14 +45,24 @@ public:
// Set a parameter
uint32 property(int param, Property *value);
+ // Get the next event.
+ // Returns true if an event was retrieved.
+// bool poll_event(Event *event);
+
protected:
FB2GL fb2gl;
int _glFlags;
int _glScreenStart;
bool _glBilinearFilter;
+ bool _usingOpenGL;
SDL_Surface *tmpSurface; // Used for black rectangles blitting
- SDL_Rect tmpBlackRect; // Black rectangle at end of the GL screen
+ SDL_Rect tmpBlackRect; // Black rectangle at end of the GL screen
+ SDL_Rect _glWindow; // Only uses w and h (for window resizing)
int _glBottomOfTexture;
+
+ SDL_Surface *_hwscreen; // hardware screen (=> _usingOpenGL == false)
+
+ ScalerProc *_scaler_proc;
virtual void load_gfx_mode();
virtual void unload_gfx_mode();
@@ -67,6 +73,18 @@ OSystem_SDL_Common *OSystem_SDL_Common::create() {
return new OSystem_SDL_OpenGL();
}
+OSystem_SDL_OpenGL::OSystem_SDL_OpenGL()
+ : _hwscreen(0), _scaler_proc(0)
+{
+ _glScreenStart = 0;
+ _glBilinearFilter = true;
+ _usingOpenGL = true; // false => Switch to filters used in the sdl.cpp version
+ _glBottomOfTexture = 256; // height is always 256
+ // 640x480 resolution
+ _glWindow.w = 640;
+ _glWindow.h = 480;
+}
+
void OSystem_SDL_OpenGL::set_palette(const byte *colors, uint start, uint num) {
const byte *b = colors;
uint i;
@@ -93,13 +111,51 @@ void OSystem_SDL_OpenGL::load_gfx_mode() {
Gmask = 0x07E0; // 6
Bmask = 0x001F; // 5
Amask = 0;
-
+
_forceFull = true;
_mode_flags = DF_UPDATE_EXPAND_1_PIXEL;
- _scaleFactor = 2;
_tmpscreen = NULL;
_tmpScreenWidth = (_screenWidth + 3);
+
+ switch(_mode) {
+ case GFX_2XSAI:
+ _scaleFactor = 2;
+ _scaler_proc = _2xSaI;
+ break;
+ case GFX_SUPER2XSAI:
+ _scaleFactor = 2;
+ _scaler_proc = Super2xSaI;
+ break;
+ case GFX_SUPEREAGLE:
+ _scaleFactor = 2;
+ _scaler_proc = SuperEagle;
+ break;
+ case GFX_ADVMAME2X:
+ _scaleFactor = 2;
+ _scaler_proc = AdvMame2x;
+ break;
+ case GFX_TV2X:
+ _scaleFactor = 2;
+ _scaler_proc = TV2x;
+ break;
+ case GFX_DOTMATRIX:
+ _scaleFactor = 2;
+ _scaler_proc = DotMatrix;
+ break;
+ case GFX_NORMAL:
+ _scaleFactor = 1;
+ _scaler_proc = Normal1x;
+ break;
+ default:
+// error("unknown gfx mode");
+ _mode = GFX_NORMAL;
+ _scaleFactor = 1;
+ _scaler_proc = Normal1x;
+ }
+
+ if (_mode != GFX_NORMAL)
+ _usingOpenGL = false;
//
// Create the surface that contains the 8 bit game data
@@ -108,21 +164,37 @@ void OSystem_SDL_OpenGL::load_gfx_mode() {
if (_screen == NULL)
error("_screen failed");
-
//
// Create the surface that contains the scaled graphics in 16 bit mode
//
-
- _glFlags = FB2GL_320 | FB2GL_RGBA | FB2GL_16BIT;
- if (_full_screen) {
- _glFlags |= (FB2GL_FS);
- _glScreenStart = 0;
+ if (_usingOpenGL) {
+
+ _glFlags = FB2GL_320 | FB2GL_RGBA | FB2GL_16BIT;
+ if (_full_screen) {
+ _glFlags |= (FB2GL_FS);
+ _glScreenStart = 0;
+ }
+ // _glWindow defines the resolution
+ fb2gl.init(_glWindow.w, _glWindow.h, 0, _glScreenStart? 15: 70,
+ _glFlags);
+
+ }
+ else { // SDL backend
+
+ _hwscreen = SDL_SetVideoMode(_screenWidth * _scaleFactor, _screenHeight * _scaleFactor, 16,
+ _full_screen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
+ );
+ if (_hwscreen == NULL)
+ error("_hwscreen failed");
+
+ // Distinguish 555 and 565 mode
+ if (_hwscreen->format->Rmask == 0x7C00)
+ Init_2xSaI(555);
+ else
+ Init_2xSaI(565);
}
- // 640x480 screen resolution
- fb2gl.init(640, 480, 0,_glScreenStart? 15: 70,_glFlags);
SDL_SetGamma(1.25, 1.25, 1.25);
-
//
// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
@@ -130,12 +202,29 @@ void OSystem_SDL_OpenGL::load_gfx_mode() {
// Need some extra bytes around when using 2xSaI
uint16 *tmp_screen = (uint16 *)calloc(_tmpScreenWidth * (_screenHeight + 3),sizeof(uint16));
- _tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,
- _tmpScreenWidth, _screenHeight + 3, 16, _tmpScreenWidth * 2,
+
+ if (_usingOpenGL) {
+ _tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,
+ _tmpScreenWidth,
+ _screenHeight + 3,
+ 16,
+ _tmpScreenWidth * 2,
Rmask,
Gmask,
Bmask,
Amask);
+ }
+ else { // SDL backend
+ _tmpscreen = SDL_CreateRGBSurfaceFrom(tmp_screen,
+ _tmpScreenWidth,
+ _screenHeight + 3,
+ 16,
+ _tmpScreenWidth * 2,
+ _hwscreen->format->Rmask,
+ _hwscreen->format->Gmask,
+ _hwscreen->format->Bmask,
+ _hwscreen->format->Amask);
+ }
tmpSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth,
// 320x256 texture (black end)
@@ -162,12 +251,17 @@ void OSystem_SDL_OpenGL::load_gfx_mode() {
}
void OSystem_SDL_OpenGL::unload_gfx_mode() {
+
SDL_SetGamma(1.0, 1.0, 1.0);
+
if (_screen) {
SDL_FreeSurface(_screen);
_screen = NULL;
}
-
+ if (_hwscreen) {
+ SDL_FreeSurface(_hwscreen);
+ _hwscreen = NULL;
+ }
if (_tmpscreen) {
free((uint16 *)_tmpscreen->pixels);
SDL_FreeSurface(_tmpscreen);
@@ -185,8 +279,14 @@ void OSystem_SDL_OpenGL::hotswap_gfx_mode() {
SDL_Surface *old_tmpscreen = _tmpscreen;
// Release the HW screen surface
- SDL_FreeSurface(fb2gl.getScreen());
- fb2gl.setScreen(NULL);
+ if (fb2gl.getScreen()) { // _usingOpenGL was true
+ SDL_FreeSurface(fb2gl.getScreen());
+ fb2gl.setScreen(NULL);
+ }
+ if (_hwscreen) {
+ SDL_FreeSurface(_hwscreen);
+ _hwscreen = NULL;
+ }
// Setup the new GFX mode
load_gfx_mode();
@@ -210,10 +310,21 @@ void OSystem_SDL_OpenGL::hotswap_gfx_mode() {
void OSystem_SDL_OpenGL::update_screen() {
// If the shake position changed, fill the dirty area with blackness
if (_currentShakePos != _newShakePos) {
- SDL_Rect blackrect = {0, _glScreenStart, _screenWidth, _newShakePos+_glScreenStart};
+ if (_usingOpenGL) {
+ SDL_Rect blackrect = {
+ 0,
+ _glScreenStart,
+ _screenWidth,
+ _newShakePos + _glScreenStart
+ };
- SDL_FillRect(tmpSurface, &blackrect, 0);
- fb2gl.blit16(tmpSurface, 1, &blackrect, 0, 0);
+ SDL_FillRect(tmpSurface, &blackrect, 0);
+ fb2gl.blit16(tmpSurface, 1, &blackrect, 0, 0);
+ }
+ else { // SDL backend
+ SDL_Rect blackrect = {0, 0, _screenWidth * _scaleFactor, _newShakePos * _scaleFactor};
+ SDL_FillRect(_hwscreen, &blackrect, 0);
+ }
_currentShakePos = _newShakePos;
@@ -249,45 +360,141 @@ void OSystem_SDL_OpenGL::update_screen() {
if (_num_dirty_rects > 0) {
SDL_Rect *r;
+ uint32 srcPitch, dstPitch;
SDL_Rect *last_rect = _dirty_rect_list + _num_dirty_rects;
-
+
// Convert appropriate parts of the 8bpp image into 16bpp
+ SDL_Rect dst;
if (!_overlayVisible) {
- SDL_Rect dst;
for(r = _dirty_rect_list; r != last_rect; ++r) {
dst = *r;
-// dst.x++; // Shift rect by one since 2xSai needs to acces the data around
-// dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
- if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
+ dst.x++; // Shift rect by one since 2xSai needs to acces the data around
+ dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
+ if (_scaler_proc == Normal1x) {
+ if (_usingOpenGL) {
+ if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+ else { // SDL backend
+ if (SDL_BlitSurface(_screen, r, _hwscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+ } else { // _scaler_proc != Normal1x
+ if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+ }
+ } else {
+ if (!_usingOpenGL) {
+ for(r = _dirty_rect_list; r != last_rect; ++r) {
+ dst = *r;
+ if (SDL_BlitSurface(_tmpscreen, r, _hwscreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
}
+ }
}
- // Almost the same thing as SDL_UpdateRects
- fb2gl.blit16(_tmpscreen, _num_dirty_rects, _dirty_rect_list, 0,
- _currentShakePos+_glScreenStart);
-
- int _glBottomOfGameScreen = _screenHeight + _glScreenStart + _currentShakePos;
- // Bottom black border height
- tmpBlackRect.h = _glBottomOfTexture - _glBottomOfGameScreen;
- if (!(_full_screen) && (tmpBlackRect.h > 0)) {
- SDL_FillRect(tmpSurface, &tmpBlackRect, 0);
- fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0,
- _glBottomOfGameScreen);
+ if (_usingOpenGL) {
+ // Almost the same thing as SDL_UpdateRects
+ fb2gl.blit16(
+ _tmpscreen,
+ _num_dirty_rects,
+ _dirty_rect_list,
+ 0,
+ _currentShakePos + _glScreenStart
+ );
+
+ int _glBottomOfGameScreen = _screenHeight +
+ _glScreenStart + _currentShakePos;
+
+ // Bottom black border height
+ tmpBlackRect.h = _glBottomOfTexture - _glBottomOfGameScreen;
+ if (!(_full_screen) && (tmpBlackRect.h > 0)) {
+ SDL_FillRect(tmpSurface, &tmpBlackRect, 0);
+ fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0,
+ _glBottomOfGameScreen);
+ }
+
+ fb2gl.display();
}
+ else { // SDL backend
+
+ if (_scaler_proc != Normal1x) {
+ SDL_LockSurface(_tmpscreen);
+ SDL_LockSurface(_hwscreen);
- fb2gl.display();
- }
+ srcPitch = _tmpscreen->pitch;
+ dstPitch = _hwscreen->pitch;
+
+ for(r = _dirty_rect_list; r != last_rect; ++r) {
+ register int dst_y = r->y + _currentShakePos;
+ register int dst_h = 0;
+ if (dst_y < _screenHeight) {
+ dst_h = r->h;
+ if (dst_h > _screenHeight - dst_y)
+ dst_h = _screenHeight - dst_y;
+
+ dst_y *= _scaleFactor;
+
+ _scaler_proc((byte *)_tmpscreen->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, NULL,
+ (byte *)_hwscreen->pixels + r->x * 2 * _scaleFactor + dst_y * dstPitch, dstPitch, r->w, dst_h);
+ }
+
+ r->x *= _scaleFactor;
+ r->y = dst_y;
+ r->w *= _scaleFactor;
+ r->h = dst_h * _scaleFactor;
+ }
+
+ SDL_UnlockSurface(_tmpscreen);
+ SDL_UnlockSurface(_hwscreen);
+ }
+
+ // Readjust the dirty rect list in case we are doing a full update.
+ // This is necessary if shaking is active.
+ if (_forceFull) {
+ _dirty_rect_list[0].y = 0;
+ _dirty_rect_list[0].h = _screenHeight * _scaleFactor;
+ }
+
+ // Finally, blit all our changes to the screen
+ SDL_UpdateRects(_hwscreen, _num_dirty_rects, _dirty_rect_list);
+ } // END OF "SDL backend"
+ } // if (num_dirty_rects > 0) ...
_num_dirty_rects = 0;
_forceFull = false;
}
+/*
+bool OSystem_SDL_OpenGL::poll_event(Event *event) {
+ SDL_Event ev;
+ ev.type = 0;
+
+ SDL_PeepEvents(&ev, 1, SDL_GETEVENT, SDL_VIDEORESIZEMASK);
+
+ if (ev.type == SDL_VIDEORESIZE) {
+ int w = ev.resize.w;
+ int h = ev.resize.h;
+ glViewport(0, 0, (GLsizei)w, (GLsizei)h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
+ _glWindow.w = w;
+ _glWindow.h = h;
+ }
+
+ return OSystem_SDL_Common::poll_event(event);
+}
+*/
+
uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {
int i;
if (param == PROP_TOGGLE_FULLSCREEN) {
+ if (!_usingOpenGL)
+ assert(_hwscreen != 0);
_full_screen ^= true;
#ifdef MACOSX
// On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse,
@@ -295,7 +502,15 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {
// use hotswap_gfx_mode() directly to switch to fullscreen mode.
hotswap_gfx_mode();
#else
- if (!SDL_WM_ToggleFullScreen(fb2gl.getScreen())) {
+ SDL_Surface *_tmpScreen;
+ if (_usingOpenGL) {
+ _tmpScreen = fb2gl.getScreen();
+ }
+ else { // SDL backend
+ _tmpScreen = _hwscreen;
+ }
+
+ if (!SDL_WM_ToggleFullScreen(_tmpScreen)) {
// if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode
hotswap_gfx_mode();
}
@@ -305,23 +520,46 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {
}
else if (param == PROP_SET_GFX_MODE) {
SDL_Rect full = {0, 0, _screenWidth, _screenHeight};
- glPopMatrix();
+ if (value->gfx_mode < 3) { // OpenGL modes
+ if (!_usingOpenGL) {
+ _usingOpenGL = true;
+ _mode = GFX_NORMAL;
+ hotswap_gfx_mode();
+ }
+ }
+
switch(value->gfx_mode) {
case 0: // Bilinear Filtering (on/off)
_glBilinearFilter ^= true;
for (i = 0; i < 2; i++) {
glBindTexture(GL_TEXTURE_2D, i);
if (_glBilinearFilter) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(
+ GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR
+ );
+ glTexParameteri(
+ GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR
+ );
} else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(
+ GL_TEXTURE_2D,
+ GL_TEXTURE_MAG_FILTER,
+ GL_NEAREST
+ );
+ glTexParameteri(
+ GL_TEXTURE_2D,
+ GL_TEXTURE_MIN_FILTER,
+ GL_NEAREST
+ );
}
}
break;
- case 1: // Don't use the whole screen
+ case 1: // Don't use the whole screen (black borders)
fb2gl.init(0, 0, 0, 15, _glFlags);
_glScreenStart = 20;
SDL_FillRect(tmpSurface, &tmpBlackRect, 0);
@@ -331,25 +569,26 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) {
fb2gl.init(0, 0, 0, 70, _glFlags);
_glScreenStart = 0;
break;
- default: // Zooming
- glPushMatrix();
-/* SDL_FillRect(tmpSurface, &full, 0);
- fb2gl.blit16(tmpSurface, 1, &full,0, _glScreenStart);
- fb2gl.display();
- double x = (double)((_mouseCurState.x)
- - (_screenWidth / 2)) / (_screenWidth / 2);
- double y = (double)((_mouseCurState.y)
- - (_screenHeight / 2)) / (_screenHeight / 2);
- glTranslatef(-x, y, 0);
-*/
- glScalef(1.0 + (double)(value->gfx_mode - 1) / 10,
- 1.0 + (double)(value->gfx_mode - 1) / 10, 0);
+ default: // SDL backend
+ if (value->gfx_mode >= 9)
+ return 0;
+
+ _mode = value->gfx_mode;
+
+ if (_usingOpenGL)
+ _usingOpenGL = false;
+
+ hotswap_gfx_mode();
};
- fb2gl.blit16(_tmpscreen, 1, &full, 0, _glScreenStart);
- fb2gl.display();
+
+ if (_usingOpenGL) {
+ fb2gl.blit16(_tmpscreen, 1, &full, 0, _glScreenStart);
+ fb2gl.display();
+ }
return 1;
}
return OSystem_SDL_Common::property(param, value);
}
+