diff options
author | Yotam Barnoy | 2010-12-17 10:58:34 +0000 |
---|---|---|
committer | Yotam Barnoy | 2010-12-17 10:58:34 +0000 |
commit | 8d1f3f00adce5c755907f45cc5c304354ccea4e1 (patch) | |
tree | 94a6971d04f52597b34cb81d6d9ff129d6c781eb /backends | |
parent | 151d180e55782955fafce72477a808309af8ab27 (diff) | |
download | scummvm-rg350-8d1f3f00adce5c755907f45cc5c304354ccea4e1.tar.gz scummvm-rg350-8d1f3f00adce5c755907f45cc5c304354ccea4e1.tar.bz2 scummvm-rg350-8d1f3f00adce5c755907f45cc5c304354ccea4e1.zip |
PSP: fixed bug exhibited in Gob engine with blacked out video frames
The problem was that I was allowing changes to the palette (in this case) even before the separate display thread, which is synchronized to vsync, was done drawing. This caused the palette to change mid-render.
The fix is a semaphore synchronizing the threads.
svn-id: r54942
Diffstat (limited to 'backends')
-rw-r--r-- | backends/platform/psp/display_manager.cpp | 22 | ||||
-rw-r--r-- | backends/platform/psp/display_manager.h | 6 | ||||
-rw-r--r-- | backends/platform/psp/osys_psp.cpp | 12 |
3 files changed, 39 insertions, 1 deletions
diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index 9e479de938..471303796b 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -149,6 +149,17 @@ void MasterGuRenderer::threadFunction() { sceKernelSleepThreadCB(); // sleep until we get a callback } +// Sleep on the render mutex if the rendering thread hasn't finished its work +// +void MasterGuRenderer::sleepUntilRenderFinished() { + if (!isRenderFinished()) { + _renderSema.take(); // sleep on the semaphore + _renderSema.give(); + PSP_DEBUG_PRINT("slept on the rendering semaphore\n"); + } +} + + // This callback is called when the render is finished. It swaps the buffers int MasterGuRenderer::guCallback(int, int, void *__this) { @@ -160,6 +171,7 @@ int MasterGuRenderer::guCallback(int, int, void *__this) { _this->_renderFinished = true; // Only this thread can set the variable to true + _this->_renderSema.give(); // Release render semaphore return 0; } @@ -214,7 +226,11 @@ void MasterGuRenderer::guProgramDisplayBufferSizes() { inline void MasterGuRenderer::guPreRender() { DEBUG_ENTER_FUNC(); +#ifdef USE_DISPLAY_CALLBACK + _renderSema.take(); // Take the semaphore to prevent writes + // to the palette/screen before we're done _renderFinished = false; // set to synchronize with callback thread +#endif #ifdef ENABLE_RENDER_MEASURE _lastRenderTime = g_system->getMillis(); @@ -374,6 +390,12 @@ void DisplayManager::calculateScaleParams() { } +void DisplayManager::waitUntilRenderFinished() { +#ifdef USE_DISPLAY_CALLBACK + _masterGuRenderer.sleepUntilRenderFinished(); +#endif /* USE_DISPLAY_CALLBACK */ +} + // return true if we really rendered or no dirty. False otherwise bool DisplayManager::renderAll() { DEBUG_ENTER_FUNC(); diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h index 5c7d4c799a..4ebd98b524 100644 --- a/backends/platform/psp/display_manager.h +++ b/backends/platform/psp/display_manager.h @@ -75,12 +75,14 @@ private: */ class MasterGuRenderer : public PspThreadable { public: - MasterGuRenderer() : _lastRenderTime(0), _renderFinished(true), _callbackId(-1) {} + MasterGuRenderer() : _lastRenderTime(0), _renderFinished(true), + _renderSema(1, 1), _callbackId(-1) {} void guInit(); void guPreRender(); void guPostRender(); void guShutDown(); bool isRenderFinished() { return _renderFinished; } + void sleepUntilRenderFinished(); void setupCallbackThread(); private: virtual void threadFunction(); // for the display callback thread @@ -89,6 +91,7 @@ private: void guProgramDisplayBufferSizes(); static int guCallback(int, int, void *__this); // for the display callback bool _renderFinished; // for sync with render callback + PspSemaphore _renderSema; // semaphore for syncing int _callbackId; // to keep track of render callback }; @@ -114,6 +117,7 @@ public: void init(); bool renderAll(); // return true if rendered or nothing dirty. False otherwise + void waitUntilRenderFinished(); bool setGraphicsMode(int mode); bool setGraphicsMode(const char *name); int getGraphicsMode() const { return _graphicsMode; } diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index df330b0b00..025edeb684 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -131,12 +131,14 @@ int OSystem_PSP::getDefaultGraphicsMode() const { bool OSystem_PSP::setGraphicsMode(int mode) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; return _displayManager.setGraphicsMode(mode); } bool OSystem_PSP::setGraphicsMode(const char *name) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; return _displayManager.setGraphicsMode(name); } @@ -160,6 +162,7 @@ Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() const { void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _displayManager.setSizeAndPixelFormat(width, height, format); @@ -179,6 +182,7 @@ int16 OSystem_PSP::getHeight() { void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _screen.setPartialPalette(colors, start, num); _cursor.setScreenPalette(colors, start, num); @@ -187,6 +191,7 @@ void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _cursor.setCursorPalette(colors, start, num); _cursor.enableCursorPalette(true); @@ -201,12 +206,14 @@ void OSystem_PSP::disableCursorPalette(bool disable) { void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _screen.copyFromRect(buf, pitch, x, y, w, h); } Graphics::Surface *OSystem_PSP::lockScreen() { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; return _screen.lockAndGetForEditing(); } @@ -225,6 +232,7 @@ void OSystem_PSP::updateScreen() { void OSystem_PSP::setShakePos(int shakeOffset) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _screen.setShakePos(shakeOffset); } @@ -247,6 +255,7 @@ void OSystem_PSP::hideOverlay() { void OSystem_PSP::clearOverlay() { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _overlay.clearBuffer(); } @@ -258,6 +267,7 @@ void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) { void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _overlay.copyFromRect(buf, pitch, x, y, w, h); } @@ -288,12 +298,14 @@ bool OSystem_PSP::showMouse(bool v) { void OSystem_PSP::warpMouse(int x, int y) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; _cursor.setXY(x, y); } void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); + _displayManager.waitUntilRenderFinished(); _pendingUpdate = false; PSP_DEBUG_PRINT("pbuf[%p], w[%u], h[%u], hotspot:X[%d], Y[%d], keycolor[%d], scale[%d], pformat[%p]\n", buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format); |