aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYotam Barnoy2010-12-17 10:58:34 +0000
committerYotam Barnoy2010-12-17 10:58:34 +0000
commit8d1f3f00adce5c755907f45cc5c304354ccea4e1 (patch)
tree94a6971d04f52597b34cb81d6d9ff129d6c781eb
parent151d180e55782955fafce72477a808309af8ab27 (diff)
downloadscummvm-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
-rw-r--r--backends/platform/psp/display_manager.cpp22
-rw-r--r--backends/platform/psp/display_manager.h6
-rw-r--r--backends/platform/psp/osys_psp.cpp12
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);