From f770156dccff6ed5f1211cbe7676652897582ee9 Mon Sep 17 00:00:00 2001 From: Yotam Barnoy Date: Wed, 9 Jun 2010 14:15:51 +0000 Subject: PSP: fixed missing frame issue with kyrandia and possibly other games by calling updateScreen() from pollEvent() once in a while svn-id: r49541 --- backends/platform/psp/display_manager.cpp | 11 +++++---- backends/platform/psp/display_manager.h | 8 +++---- backends/platform/psp/osys_psp.cpp | 37 +++++++++++++++++++++++++++++-- backends/platform/psp/osys_psp.h | 6 +++-- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index c2f21e084b..5c9f8f92f0 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -311,25 +311,26 @@ void DisplayManager::calculateScaleParams() { } } -void DisplayManager::renderAll() { +// return true if we really rendered or no dirty. False otherwise +bool DisplayManager::renderAll() { DEBUG_ENTER_FUNC(); #ifdef USE_DISPLAY_CALLBACK if (!_masterGuRenderer.isRenderFinished()) { PSP_DEBUG_PRINT("Callback render not finished.\n"); - return; + return false; // didn't render } #endif /* USE_DISPLAY_CALLBACK */ if (!isTimeToUpdate()) - return; + return false; // didn't render if (!_screen->isDirty() && (!_overlay->isDirty()) && (!_cursor->isDirty()) && (!_keyboard->isDirty())) { PSP_DEBUG_PRINT("Nothing dirty\n"); - return; + return true; // nothing to render } PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n", @@ -361,6 +362,8 @@ void DisplayManager::renderAll() { _keyboard->setClean(); _masterGuRenderer.guPostRender(); + + return true; // rendered successfully } inline bool DisplayManager::isTimeToUpdate() { diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h index 5864f39b36..bceb85703d 100644 --- a/backends/platform/psp/display_manager.h +++ b/backends/platform/psp/display_manager.h @@ -40,12 +40,12 @@ public: void setupCallbackThread(); private: static uint32 _displayList[]; - uint32 _lastRenderTime; // For measuring rendering + uint32 _lastRenderTime; // For measuring rendering time void guProgramDisplayBufferSizes(); static int guCallbackThread(SceSize, void *); // for the graphics callbacks static int guCallback(int, int, void *__this); - bool _renderFinished; - int _callbackId; + bool _renderFinished; // for sync with render callback + int _callbackId; // to keep track of render callback }; class Screen; @@ -68,7 +68,7 @@ public: ~DisplayManager(); void init(); - void renderAll(); + bool renderAll(); // return true if rendered or nothing dirty. False otherwise 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 2043a4bef2..48e9044535 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -127,11 +127,13 @@ int OSystem_PSP::getDefaultGraphicsMode() const { bool OSystem_PSP::setGraphicsMode(int mode) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _displayManager.setGraphicsMode(mode); } bool OSystem_PSP::setGraphicsMode(const char *name) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _displayManager.setGraphicsMode(name); } @@ -154,6 +156,7 @@ Common::List OSystem_PSP::getSupportedFormats() { void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _displayManager.setSizeAndPixelFormat(width, height, format); _cursor.setVisible(false); @@ -172,6 +175,7 @@ int16 OSystem_PSP::getHeight() { void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.setPartialPalette(colors, start, num); _cursor.setScreenPalette(colors, start, num); _cursor.clearKeyColor(); @@ -179,6 +183,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(); + _pendingUpdate = false; _cursor.setCursorPalette(colors, start, num); _cursor.enableCursorPalette(true); _cursor.clearKeyColor(); // Do we need this? @@ -186,37 +191,43 @@ void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { void OSystem_PSP::disableCursorPalette(bool disable) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _cursor.enableCursorPalette(!disable); } void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.copyFromRect(buf, pitch, x, y, w, h); } Graphics::Surface *OSystem_PSP::lockScreen() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _screen.lockAndGetForEditing(); } void OSystem_PSP::unlockScreen() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; // The screen is always completely updated anyway, so we don't have to force a full update here. _screen.unlock(); } void OSystem_PSP::updateScreen() { DEBUG_ENTER_FUNC(); - _displayManager.renderAll(); + _pendingUpdate = !_displayManager.renderAll(); // if we didn't update, we have a pending update } void OSystem_PSP::setShakePos(int shakeOffset) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.setShakePos(shakeOffset); } void OSystem_PSP::showOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.setVisible(true); _cursor.setLimits(_overlay.getWidth(), _overlay.getHeight()); _cursor.useGlobalScaler(false); // mouse with overlay is 1:1 @@ -224,6 +235,7 @@ void OSystem_PSP::showOverlay() { void OSystem_PSP::hideOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.setVisible(false); _cursor.setLimits(_screen.getWidth(), _screen.getHeight()); _cursor.useGlobalScaler(true); // mouse needs to be scaled with screen @@ -231,6 +243,7 @@ void OSystem_PSP::hideOverlay() { void OSystem_PSP::clearOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.clearBuffer(); } @@ -241,6 +254,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(); + _pendingUpdate = false; _overlay.copyFromRect(buf, pitch, x, y, w, h); } @@ -259,6 +273,8 @@ void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) { bool OSystem_PSP::showMouse(bool v) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; + PSP_DEBUG_PRINT("%s\n", v ? "true" : "false"); bool last = _cursor.isVisible(); _cursor.setVisible(v); @@ -268,11 +284,14 @@ bool OSystem_PSP::showMouse(bool v) { void OSystem_PSP::warpMouse(int x, int y) { DEBUG_ENTER_FUNC(); + _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(); + _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); if (format) { PSP_DEBUG_PRINT("format: bpp[%d], rLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d], rShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", format->bytesPerPixel, format->rLoss, format->gLoss, format->bLoss, format->aLoss, format->rShift, format->gShift, format->bShift, format->aShift); @@ -292,9 +311,23 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { // Pausing the engine is a necessary fix for games that use the timer for music synchronization // recovering many hours later causes the game to crash. We're polling without mutexes since it's not critical to // get it right now. - PowerMan.pollPauseEngine(); + // A hack: + // Check if we have a pending update that we missed for some reason (FPS throttling for example) + // Time between event polls is usually 5-10ms, so waiting for 4 calls before checking to update the screen should be fine + if (_pendingUpdate) { + _pendingUpdateCounter++; + + if (_pendingUpdateCounter >= 4) { + PSP_DEBUG_PRINT("servicing pending update\n"); + updateScreen(); + if (!_pendingUpdate) // we handled the update + _pendingUpdateCounter = 0; + } + } else + _pendingUpdateCounter = 0; // reset the counter, no pending + return _inputHandler.getAllInputs(event); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index a6c84ba39a..d8ec8fe824 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -50,6 +50,8 @@ private: Common::SaveFileManager *_savefile; Audio::MixerImpl *_mixer; Common::TimerManager *_timer; + bool _pendingUpdate; // save an update we couldn't perform + uint32 _pendingUpdateCounter; // prevent checking for pending update too often, in a cheap way // All needed sub-members Screen _screen; @@ -62,10 +64,10 @@ private: PspTimer _pspTimer; PspRtc _pspRtc; - void initSDL(); + void initSDL(); public: - OSystem_PSP() : _savefile(0), _mixer(0), _timer(0) {} + OSystem_PSP() : _savefile(0), _mixer(0), _timer(0), _pendingUpdate(false), _pendingUpdateCounter(0) {} ~OSystem_PSP(); static OSystem *instance(); -- cgit v1.2.3