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 | |
| 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
| -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);  | 
