aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2007-06-19 22:39:59 +0000
committerMax Horn2007-06-19 22:39:59 +0000
commitb51f2f3212ae8a5abbdce4d947ec2d1cad1a0b6f (patch)
tree45a838924ce55038021cd3c3d8760e80ff630f38
parentab9b9a1bf362e68f5f6a69462ef2b7c146e6e08f (diff)
downloadscummvm-rg350-b51f2f3212ae8a5abbdce4d947ec2d1cad1a0b6f.tar.gz
scummvm-rg350-b51f2f3212ae8a5abbdce4d947ec2d1cad1a0b6f.tar.bz2
scummvm-rg350-b51f2f3212ae8a5abbdce4d947ec2d1cad1a0b6f.zip
Implemented the OSystem framebuffer API, as discussed on scummvm-devel. All changes are just fine, and won't cause any compile problems or regressions, despite the fact that I can't test most of the non-SDL backend changes, at an improbability level of two to the power of two hundred and seventy-six thousand to one against - possibly much higher. Anything you still can't cope with is therefore your own problem. Please relax.
svn-id: r27548
-rw-r--r--backends/platform/PalmOS/Src/be_os5.h5
-rw-r--r--backends/platform/PalmOS/Src/os5_gfx.cpp17
-rw-r--r--backends/platform/dc/dc.h6
-rw-r--r--backends/platform/dc/display.cpp27
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp21
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h5
-rw-r--r--backends/platform/gp2x/gp2x-common.h7
-rw-r--r--backends/platform/gp2x/graphics.cpp34
-rw-r--r--backends/platform/gp32/gp32_osys.cpp16
-rw-r--r--backends/platform/gp32/gp32_osys.h5
-rw-r--r--backends/platform/null/null.cpp10
-rw-r--r--backends/platform/ps2/Gs2dScreen.cpp24
-rw-r--r--backends/platform/ps2/Gs2dScreen.h6
-rw-r--r--backends/platform/ps2/systemps2.cpp11
-rw-r--r--backends/platform/ps2/systemps2.h3
-rw-r--r--backends/platform/psp/osys_psp.cpp17
-rw-r--r--backends/platform/psp/osys_psp.h4
-rw-r--r--backends/platform/sdl/graphics.cpp50
-rw-r--r--backends/platform/sdl/sdl-common.h12
-rw-r--r--backends/platform/sdl/sdl.cpp1
-rw-r--r--backends/platform/wince/wince-sdl.cpp10
-rw-r--r--backends/platform/wince/wince-sdl.h3
-rw-r--r--common/system.cpp5
-rw-r--r--common/system.h29
-rw-r--r--engines/scumm/gfx.cpp11
-rw-r--r--graphics/scaler/thumbnail.cpp22
26 files changed, 217 insertions, 144 deletions
diff --git a/backends/platform/PalmOS/Src/be_os5.h b/backends/platform/PalmOS/Src/be_os5.h
index 13e8b4ff20..bb38c51ca6 100644
--- a/backends/platform/PalmOS/Src/be_os5.h
+++ b/backends/platform/PalmOS/Src/be_os5.h
@@ -110,6 +110,8 @@ private:
typedef void (OSystem_PalmOS5::*RendererProc)(RectangleType &r, PointType &p);
RendererProc _render;
+ Graphics::Surface _framebuffer;
+
OverlayColor *_overlayP;
WinHandle _overlayH, _workScreenH;
int16 *_workScreenP;
@@ -168,7 +170,8 @@ public:
void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
void clearScreen();
- bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
void setCursorPalette(const byte *colors, uint start, uint num);
void disableCursorPalette(bool disable);
diff --git a/backends/platform/PalmOS/Src/os5_gfx.cpp b/backends/platform/PalmOS/Src/os5_gfx.cpp
index cff9e79abe..be5d28bc56 100644
--- a/backends/platform/PalmOS/Src/os5_gfx.cpp
+++ b/backends/platform/PalmOS/Src/os5_gfx.cpp
@@ -219,13 +219,18 @@ void OSystem_PalmOS5::copyRectToScreen(const byte *buf, int pitch, int x, int y,
}
}
-bool OSystem_PalmOS5::grabRawScreen(Graphics::Surface *surf) {
- assert(surf);
+Graphics::Surface *OSystem_PalmOS5::lockScreen() {
+ _framebuffer.pixels = _offScreenP;
+ _framebuffer.w = _screenWidth;
+ _framebuffer.h = _screenHeight;
+ _framebuffer.pitch = _screenWidth;
+ _framebuffer.bytesPerPixel = 1;
+
+ return &_framebuffer;
+}
- surf->create(_screenWidth, _screenHeight, 1);
- MemMove(surf->pixels, _offScreenP, _screenWidth * _screenHeight);
-
- return true;
+void OSystem_PalmOS5::unlockScreen() {
+ // The screen is always completely update anyway, so we don't have to force a full update here.
}
void OSystem_PalmOS5::int_updateScreen() {
diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h
index 01e86a561b..fa47ed21f5 100644
--- a/backends/platform/dc/dc.h
+++ b/backends/platform/dc/dc.h
@@ -81,8 +81,8 @@ class OSystem_Dreamcast : public OSystem {
// The screen will not be updated to reflect the new bitmap
void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
- // Copies the current screen contents to a new surface.
- bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
// Clear the screen to black.
void clearScreen();
@@ -213,6 +213,8 @@ class OSystem_Dreamcast : public OSystem {
void *ovl_tx[NUM_BUFFERS];
unsigned short palette[256], cursor_palette[256];
+ Graphics::Surface _framebuffer;
+
int temp_sound_buffer[RING_BUFFER_SAMPLES>>SOUND_BUFFER_SHIFT];
void checkSound();
diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp
index 73312cafed..da9f6e83ff 100644
--- a/backends/platform/dc/display.cpp
+++ b/backends/platform/dc/display.cpp
@@ -609,19 +609,24 @@ int OSystem_Dreamcast::getGraphicsMode() const
return 0;
}
-bool OSystem_Dreamcast::grabRawScreen(Graphics::Surface *surf)
+Graphics::Surface *OSystem_Dreamcast::lockScreen()
{
- if(!screen || !surf)
- return false;
+ if (!screen)
+ return 0;
- surf->create(_screen_w, _screen_h, 1);
- unsigned char *src = screen, *dst = (unsigned char *)surf->pixels;
- for(int h = _screen_h; h>0; --h) {
- memcpy(dst, src, _screen_w);
- src += SCREEN_W;
- dst += _screen_w;
- }
- return true;
+ _framebuffer.pixels = screen;
+ _framebuffer.w = _screen_w;
+ _framebuffer.h = _screen_h;
+ _framebuffer.pitch = SCREEN_W;
+ _framebuffer.bytesPerPixel = 1;
+
+ return &_framebuffer;
+}
+
+void OSystem_Dreamcast::unlockScreen()
+{
+ // Force screen update
+ _screen_dirty = true;
}
void OSystem_Dreamcast::clearScreen()
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index a804369b26..cad6ad6b78 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -474,8 +474,13 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager()
}
}
-bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
- surf->create(DS::getGameWidth(), DS::getGameHeight(), 1);
+Graphics::Surface *OSystem_DS::lockScreen() {
+ // For now, we create a full temporary screen surface, to which we copy the
+ // the screen content. Later unlockScreen will copy everything back.
+ // Not very nice nor efficient, but at least works, and is not worse
+ // than in the bad old times where we used grabRawScreen + copyRectToScreen.
+
+ _framebuffer.create(DS::getGameWidth(), DS::getGameHeight(), 1);
// Ensure we copy using 16 bit quantities due to limitation of VRAM addressing
@@ -486,11 +491,19 @@ bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
DC_FlushRange(image + (y << 8), DS::getGameWidth());
for (int x = 0; x < DS::getGameWidth() >> 1; x++)
{
- *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x];
+ *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x];
}
}
- return true;
+ return &_framebuffer;
+}
+
+void OSystem_DS::unlockScreen() {
+ // Copy temp framebuffer back to screen
+ copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h);
+
+ // Free memory
+ _framebuffer.free();
}
void OSystem_DS::setFocusRectangle(const Common::Rect& rect) {
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index 316f45bb6e..58b940af2c 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -53,6 +53,8 @@ public:
DSAudioMixer* _mixer;
DSTimerManager* _timer;
+ Graphics::Surface _framebuffer;
+
static OSystem_DS* _instance;
typedef void (*SoundProc)(void *param, byte *buf, int len);
@@ -127,7 +129,8 @@ public:
void addEvent(Common::Event& e);
bool isEventQueueEmpty() { return queuePos == 0; }
- virtual bool grabRawScreen(Graphics::Surface* surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
virtual void setFocusRectangle(const Common::Rect& rect);
diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h
index 4c91a00247..68f2fb997e 100644
--- a/backends/platform/gp2x/gp2x-common.h
+++ b/backends/platform/gp2x/gp2x-common.h
@@ -90,11 +90,8 @@ public:
// The screen will not be updated to reflect the new bitmap
void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h);
- // Copies the screen to a buffer
- bool grabRawScreen(Graphics::Surface *surf);
-
- // Clear the screen
- void clearScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
// Update the dirty areas of the screen
void updateScreen();
diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp
index a482689e43..c3ed5c627c 100644
--- a/backends/platform/gp2x/graphics.cpp
+++ b/backends/platform/gp2x/graphics.cpp
@@ -687,22 +687,6 @@ void OSystem_GP2X::setZoomOnMouse() {
}
}
-void OSystem_GP2X::clearScreen() {
- assert (_transactionMode == kTransactionNone);
-
- // Try to lock the screen surface
- if (SDL_LockSurface(_screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_screen->pixels;
-
- // Clear the screen
- memset(dst, 0, _screenWidth * _screenHeight);
-
- // Unlock the screen surface
- SDL_UnlockSurface(_screen);
-}
-
void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
assert (_transactionMode == kTransactionNone);
assert(src);
@@ -772,15 +756,19 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in
SDL_UnlockSurface(_screen);
}
-// TIDY: DIRTY HACK: Try a REALLY simple version of grabRawScreen to
-// debug why it will not work on the GP2X.
-bool OSystem_GP2X::grabRawScreen(Graphics::Surface *surf) {
- assert(surf);
+Graphics::Surface *OSystem_GP2X::lockScreen() {
+ _framebuffer.pixels = _screen->pixels;
+ _framebuffer.w = _screen->w;
+ _framebuffer.h = _screen->h;
+ _framebuffer.pitch = _screen->pitch;
+ _framebuffer.bytesPerPixel = 1;
- surf->create(_screenWidth, _screenHeight, 1);
- memcpy(surf->pixels, _screen->pixels, _screenWidth * _screenHeight);
+ return &_framebuffer;
+}
- return true;
+void OSystem_GP2X::unlockScreen() {
+ // Force screen update
+ _forceFull = true;
}
void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {
diff --git a/backends/platform/gp32/gp32_osys.cpp b/backends/platform/gp32/gp32_osys.cpp
index ab2ac1616b..1cb5eb2d9f 100644
--- a/backends/platform/gp32/gp32_osys.cpp
+++ b/backends/platform/gp32/gp32_osys.cpp
@@ -209,14 +209,18 @@ void OSystem_GP32::copyRectToScreen(const byte *src, int pitch, int x, int y, in
}
}
-bool OSystem_GP32::grabRawScreen(Graphics::Surface *surf) {
- assert(surf);
+Graphics::Surface *OSystem_GP32::lockScreen() {
+ _framebuffer.pixels = _gameScreen;
+ _framebuffer.w = _screenWidth;
+ _framebuffer.h = _screenHeight;
+ _framebuffer.pitch = _screenWidth;
+ _framebuffer.bytesPerPixel = 1;
- surf->create(_screenWidth, _screenHeight, 1);
-
- memcpy(surf->pixels, _gameScreen, _screenWidth * _screenHeight);
+ return &_framebuffer;
+}
- return true;
+void OSystem_GP32::unlockScreen() {
+ // The screen is always completely update anyway, so we don't have to force a full update here.
}
//TODO: Implement Dirty rect?
diff --git a/backends/platform/gp32/gp32_osys.h b/backends/platform/gp32/gp32_osys.h
index fa8a0903ad..94578e8e15 100644
--- a/backends/platform/gp32/gp32_osys.h
+++ b/backends/platform/gp32/gp32_osys.h
@@ -49,6 +49,8 @@ protected:
uint16 *_tmpScreen, *_hwScreen;
OverlayColor *_overlayBuffer;
+ Graphics::Surface _framebuffer;
+
int _overlayWidth, _overlayHeight;
bool _overlayVisible;
uint32 _shakePos;
@@ -111,7 +113,8 @@ public:
void grabOverlay(OverlayColor *buf, int pitch);
void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
- bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
int16 getOverlayHeight();
int16 getOverlayWidth();
diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp
index 963b3429f5..250ca0fb29 100644
--- a/backends/platform/null/null.cpp
+++ b/backends/platform/null/null.cpp
@@ -63,7 +63,8 @@ public:
virtual void grabPalette(byte *colors, uint start, uint num);
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
virtual void updateScreen();
- virtual bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
virtual void setShakePos(int shakeOffset);
virtual void showOverlay();
@@ -189,8 +190,11 @@ void OSystem_NULL::copyRectToScreen(const byte *buf, int pitch, int x, int y, in
void OSystem_NULL::updateScreen() {
}
-bool OSystem_NULL::grabRawScreen(Graphics::Surface *surf) {
- return false;
+Graphics::Surface *OSystem_NULL::lockScreen() {
+ return 0;
+}
+
+void OSystem_NULL::unlockScreen() {
}
void OSystem_NULL::setShakePos(int shakeOffset) {
diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp
index 4829027f15..1de3c5e8c8 100644
--- a/backends/platform/ps2/Gs2dScreen.cpp
+++ b/backends/platform/ps2/Gs2dScreen.cpp
@@ -364,13 +364,6 @@ void Gs2dScreen::copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w
}
}
-void Gs2dScreen::clearScreen(void) {
- WaitSema(g_DmacSema);
- memset(_screenBuf, 0, _width * _height);
- _screenChanged = true;
- SignalSema(g_DmacSema);
-}
-
void Gs2dScreen::setPalette(const uint32 *pal, uint8 start, uint16 num) {
assert(start + num <= 256);
@@ -393,11 +386,20 @@ void Gs2dScreen::grabPalette(uint32 *pal, uint8 start, uint16 num) {
}
}
-void Gs2dScreen::grabScreen(Graphics::Surface *surf) {
- assert(surf);
+Graphics::Surface *Gs2dScreen::lockScreen() {
WaitSema(g_DmacSema);
- surf->create(_width, _height, 1);
- memcpy(surf->pixels, _screenBuf, _width * _height);
+
+ _framebuffer.pixels = _screen->pixels;
+ _framebuffer.w = _screen->w;
+ _framebuffer.h = _screen->h;
+ _framebuffer.pitch = _screen->pitch;
+ _framebuffer.bytesPerPixel = 1;
+
+ return &_framebuffer;
+}
+
+void Gs2dScreen::unlockScreen() {
+ _screenChanged = true;
SignalSema(g_DmacSema);
}
diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h
index 353e577980..471ec87789 100644
--- a/backends/platform/ps2/Gs2dScreen.h
+++ b/backends/platform/ps2/Gs2dScreen.h
@@ -56,13 +56,13 @@ public:
void copyPrintfOverlay(const uint8* buf);
void clearPrintfOverlay(void);
- void clearScreen(void);
void copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h);
void setPalette(const uint32 *pal, uint8 start, uint16 num);
void updateScreen(void);
void grabPalette(uint32 *pal, uint8 start, uint16 num);
- void grabScreen(Graphics::Surface *surf);
+ Graphics::Surface *lockScreen();
+ void unlockScreen();
//- overlay routines
void copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
void grabOverlay(uint16 *buf, uint16 pitch);
@@ -99,6 +99,8 @@ private:
uint32 _mouseScaleX, _mouseScaleY;
uint8 _mTraCol;
+ Graphics::Surface _framebuffer;
+
int _shakePos;
bool _showMouse, _showOverlay, _screenChanged, _overlayChanged, _clutChanged;
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 80d5ab9c83..32290bddea 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -326,7 +326,7 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) {
}
_screen->wantAnim(false);
- _screen->clearScreen();
+ clearScreen();
}
OSystem_PS2::~OSystem_PS2(void) {
@@ -510,9 +510,12 @@ void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
_screen->copyScreenRect((const uint8*)buf, pitch, x, y, w, h);
}
-bool OSystem_PS2::grabRawScreen(Graphics::Surface *surf) {
- _screen->grabScreen(surf);
- return true;
+Graphics::Surface *OSystem_PS2::lockScreen() {
+ return _screen->lockScreen();
+}
+
+void OSystem_PS2::unlockScreen() {
+ _screen->unlockScreen();
}
void OSystem_PS2::updateScreen(void) {
diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h
index 4a3764666e..b5c84d3b95 100644
--- a/backends/platform/ps2/systemps2.h
+++ b/backends/platform/ps2/systemps2.h
@@ -56,7 +56,8 @@ public:
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
virtual void setShakePos(int shakeOffset);
virtual void grabPalette(byte *colors, uint start, uint num);
- virtual bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
virtual void updateScreen();
virtual void showOverlay();
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index bee422d36f..f7c18e5142 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -209,13 +209,18 @@ void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
}
}
-bool OSystem_PSP::grabRawScreen(Graphics::Surface *surf) {
- assert(surf);
+Graphics::Surface *OSystem_PSP::lockScreen() {
+ _framebuffer.pixels = _offscreen;
+ _framebuffer.w = _screenWidth;
+ _framebuffer.h = _screenHeight;
+ _framebuffer.pitch = _screenWidth;
+ _framebuffer.bytesPerPixel = 1;
- surf->create(_screenWidth, _screenHeight, 1);
- memcpy(surf->pixels, _offscreen, _screenWidth * _screenHeight);
-
- return true;
+ return &_framebuffer;
+}
+
+void OSystem_PSP::unlockScreen() {
+ // The screen is always completely update anyway, so we don't have to force a full update here.
}
void OSystem_PSP::updateScreen() {
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index b833f5e179..c7a5c06051 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -62,6 +62,7 @@ protected:
bool _overlayVisible;
uint32 _shakePos;
+ Graphics::Surface _framebuffer;
bool _mouseVisible;
int _mouseX, _mouseY;
@@ -101,7 +102,8 @@ public:
virtual int16 getHeight();
virtual void setPalette(const byte *colors, uint start, uint num);
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
- virtual bool grabRawScreen(Graphics::Surface *surf);
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
virtual void updateScreen();
virtual void setShakePos(int shakeOffset);
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index e0b7de28ab..f93c806aa8 100644
--- a/backends/platform/sdl/graphics.cpp
+++ b/backends/platform/sdl/graphics.cpp
@@ -761,22 +761,6 @@ void OSystem_SDL::setAspectRatioCorrection(bool enable) {
}
}
-void OSystem_SDL::clearScreen() {
- assert (_transactionMode == kTransactionNone);
-
- // Try to lock the screen surface
- if (SDL_LockSurface(_screen) == -1)
- error("SDL_LockSurface failed: %s", SDL_GetError());
-
- byte *dst = (byte *)_screen->pixels;
-
- // Clear the screen
- memset(dst, 0, _screenWidth * _screenHeight);
-
- // Unlock the screen surface
- SDL_UnlockSurface(_screen);
-}
-
void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
assert (_transactionMode == kTransactionNone);
assert(src);
@@ -848,24 +832,44 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
SDL_UnlockSurface(_screen);
}
-bool OSystem_SDL::grabRawScreen(Graphics::Surface *surf) {
- assert(_screen);
- assert(surf);
+Graphics::Surface *OSystem_SDL::lockScreen() {
+ assert (_transactionMode == kTransactionNone);
- Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+ // Lock the graphics mutex
+ lockMutex(_graphicsMutex);
- surf->create(_screenWidth, _screenHeight, _screen->format->BytesPerPixel);
+ // paranoia check
+ assert(!_screenIsLocked);
+ _screenIsLocked = true;
// Try to lock the screen surface
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- memcpy(surf->pixels, _screen->pixels, _screenWidth * _screenHeight * _screen->format->BytesPerPixel);
+ _framebuffer.pixels = _screen->pixels;
+ _framebuffer.w = _screen->w;
+ _framebuffer.h = _screen->h;
+ _framebuffer.pitch = _screen->pitch;
+ _framebuffer.bytesPerPixel = 1;
+
+ return &_framebuffer;
+}
+
+void OSystem_SDL::unlockScreen() {
+ assert (_transactionMode == kTransactionNone);
+
+ // paranoia check
+ assert(_screenIsLocked);
+ _screenIsLocked = false;
// Unlock the screen surface
SDL_UnlockSurface(_screen);
- return true;
+ // Trigger a full screen update
+ _forceFull = true;
+
+ // Finally unlock the graphics mutex
+ unlockMutex(_graphicsMutex);
}
void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {
diff --git a/backends/platform/sdl/sdl-common.h b/backends/platform/sdl/sdl-common.h
index e66ca71e7f..4795b22a53 100644
--- a/backends/platform/sdl/sdl-common.h
+++ b/backends/platform/sdl/sdl-common.h
@@ -92,11 +92,8 @@ public:
// The screen will not be updated to reflect the new bitmap
virtual void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
- // Copies the screen to a buffer
- bool grabRawScreen(Graphics::Surface *surf);
-
- // Clear the screen
- void clearScreen();
+ virtual Graphics::Surface *lockScreen();
+ virtual void unlockScreen();
// Update the dirty areas of the screen
void updateScreen();
@@ -218,6 +215,8 @@ protected:
// unseen game screen
SDL_Surface *_screen;
+
+ // TODO: We could get rid of the following two vars and just use _screen instead
int _screenWidth, _screenHeight;
// temporary screen (for scalers)
@@ -274,6 +273,9 @@ protected:
int _mode;
int _transactionMode;
bool _fullscreen;
+
+ bool _screenIsLocked;
+ Graphics::Surface _framebuffer;
/** Current video mode flags (see DF_* constants) */
uint32 _modeFlags;
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 0fe16e0520..fe78bd4236 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -243,6 +243,7 @@ OSystem_SDL::OSystem_SDL()
_savefile(0),
_mixer(0),
_timer(0),
+ _screenIsLocked(false),
_graphicsMutex(0), _transactionMode(kTransactionNone) {
// allocate palette storage
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index 0ee6f6e60d..92012c7159 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -1587,9 +1587,15 @@ void OSystem_WINCE3::internUpdateScreen() {
_forceFull = false;
}
-bool OSystem_WINCE3::grabRawScreen(Graphics::Surface *surf) {
+Graphics::Surface *OSystem_WINCE3::lockScreen() {
+ // FIXME: Fingolfing asks: Why is undrawMouse() needed here?
+ // Please document this.
undrawMouse();
- return OSystem_SDL::grabRawScreen(surf);
+ return OSystem_SDL::lockScreen();
+}
+
+void OSystem_WINCE3::unlockScreen() {
+ OSystem_SDL::unlockScreen();
}
bool OSystem_WINCE3::saveScreenshot(const char *filename) {
diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h
index 41b71bba02..e74c438807 100644
--- a/backends/platform/wince/wince-sdl.h
+++ b/backends/platform/wince/wince-sdl.h
@@ -97,7 +97,8 @@ public:
void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
void showOverlay();
void hideOverlay();
- bool grabRawScreen(Graphics::Surface *surf);
+ Graphics::Surface *lockScreen();
+ void unlockScreen();
// GUI and action stuff
void swap_panel_visibility();
diff --git a/common/system.cpp b/common/system.cpp
index 2720a19775..f8068d41f5 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -101,3 +101,8 @@ Common::EventManager *OSystem::getEventManager() {
return s_eventManager;
}
+void OSystem::clearScreen() {
+ Graphics::Surface *screen = lockScreen();
+ memset(screen->pixels, 0, screen->h * screen->pitch);
+ unlockScreen();
+}
diff --git a/common/system.h b/common/system.h
index 500056e695..a54546f233 100644
--- a/common/system.h
+++ b/common/system.h
@@ -452,21 +452,34 @@ public:
virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) = 0;
/**
- * Copies the current screen contents to a new surface, with the original
- * bit depth. This will allocate memory for the pixel data.
- * WARNING: surf->free() must be called by the user to avoid leaking.
+ * Lock the active screen framebuffer and return a Graphics::Surface
+ * representing it. The caller can then perform arbitrary graphics
+ * transformations on the framebuffer (blitting, scrolling, etc.).
+ * Must be followed by matching call to unlockScreen(). Calling code
+ * should make sure to only lock the framebuffer for the briefest
+ * periods of time possible, as the whole system is potentially stalled
+ * while the lock is active.
+ * Returns 0 if an error occurred. Otherwise an 8bit surface is returned.
*
- * @param surf the surfce to store the data in it
- * @return true if all went well, false if an error occured
+ * The returned surface must *not* be deleted by the client code.
*/
- virtual bool grabRawScreen(Graphics::Surface *surf) = 0;
+ virtual Graphics::Surface *lockScreen() = 0;
+
+ /**
+ * Unlock the screen framebuffer, and mark it as dirty (i.e. during the
+ * next updateScreen() call, the whole screen will be updated.
+ */
+ virtual void unlockScreen() = 0;
/**
* Clear the screen to black.
*/
- virtual void clearScreen() {}
+ virtual void clearScreen();
- /** Update the dirty areas of the screen. */
+ /**
+ * Flush the whole screen, that is render the current content of the screen
+ * framebuffer (resp. the dirty/changed parts of it) to the display.
+ */
virtual void updateScreen() = 0;
/**
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index dd7a23d0cf..3547986ce3 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -1146,12 +1146,11 @@ void ScummEngine::moveScreen(int dx, int dy, int height) {
if ((dx == 0 && dy == 0) || height <= 0)
return;
- Graphics::Surface screen;
- assert(_system->grabRawScreen(&screen));
-
- screen.move(dx, dy, height);
- _system->copyRectToScreen((byte *)screen.pixels, screen.pitch, 0, 0, screen.w, screen.h);
- screen.free();
+ Graphics::Surface *screen = _system->lockScreen();
+ if (!screen)
+ return;
+ screen->move(dx, dy, height);
+ _system->unlockScreen();
}
void ScummEngine_v5::clearFlashlight() {
diff --git a/graphics/scaler/thumbnail.cpp b/graphics/scaler/thumbnail.cpp
index a6575f3ea3..40d0cba156 100644
--- a/graphics/scaler/thumbnail.cpp
+++ b/graphics/scaler/thumbnail.cpp
@@ -97,32 +97,32 @@ void createThumbnail(const uint8* src, uint32 srcPitch, uint8* dstPtr, uint32 ds
* Copies the current screen contents to a new surface, using RGB565 format.
* WARNING: surf->free() must be called by the user to avoid leaking.
*
- * @param surf the surfce to store the data in it
+ * @param surf the surface to store the data in it
*/
static bool grabScreen565(Graphics::Surface *surf) {
- Graphics::Surface screen;
- if (!g_system->grabRawScreen(&screen))
+ Graphics::Surface *screen = g_system->lockScreen();
+ if (!screen)
return false;
- assert(screen.bytesPerPixel == 1 && screen.pixels != 0);
+ assert(screen->bytesPerPixel == 1 && screen->pixels != 0);
byte palette[256 * 4];
g_system->grabPalette(&palette[0], 0, 256);
- surf->create(screen.w, screen.h, 2);
+ surf->create(screen->w, screen->h, 2);
- for (uint y = 0; y < screen.h; ++y) {
- for (uint x = 0; x < screen.w; ++x) {
+ for (uint y = 0; y < screen->h; ++y) {
+ for (uint x = 0; x < screen->w; ++x) {
byte r, g, b;
- r = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4];
- g = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 1];
- b = palette[((uint8*)screen.pixels)[y * screen.pitch + x] * 4 + 2];
+ r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4];
+ g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 1];
+ b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 2];
((uint16*)surf->pixels)[y * surf->w + x] = (((r >> 3) & 0x1F) << 11) | (((g >> 2) & 0x3F) << 5) | ((b >> 3) & 0x1F);
}
}
- screen.free();
+ g_system->unlockScreen();
return true;
}