diff options
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; } |