From c6caff61bf495f0fb78d769c6803f280bc342437 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 10 Feb 2014 15:14:45 +0100 Subject: [PATCH] Update native with buildfix. Fix some resizing issues. --- Core/Core.cpp | 13 +- Core/Core.h | 2 +- UI/EmuScreen.cpp | 12 +- UI/NativeApp.cpp | 7 +- Windows/EmuThread.cpp | 2 +- Windows/WndMainWindow.cpp | 2 +- headless/Headless.cpp | 1 + headless/Headless.cpp~RFfc3622a.TMP | 412 ++++++++++++++++++++++++++++ native | 2 +- 9 files changed, 433 insertions(+), 20 deletions(-) create mode 100644 headless/Headless.cpp~RFfc3622a.TMP diff --git a/Core/Core.cpp b/Core/Core.cpp index 29f66145e2..002d0d8d65 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -102,11 +102,11 @@ void Core_WaitInactive(int milliseconds) { } } -void UpdateScreenScale() { - dp_xres = PSP_CoreParameter().pixelWidth; - dp_yres = PSP_CoreParameter().pixelHeight; - pixel_xres = PSP_CoreParameter().pixelWidth; - pixel_yres = PSP_CoreParameter().pixelHeight; +void UpdateScreenScale(int width, int height) { + dp_xres = width; + dp_yres = height; + pixel_xres = width; + pixel_yres = height; g_dpi = 72; g_dpi_scale = 1.0f; #ifdef _WIN32 @@ -118,10 +118,11 @@ void UpdateScreenScale() { else #endif pixel_in_dps = (float)pixel_xres / dp_xres; + NativeResized(); } static inline void UpdateRunLoop() { - UpdateScreenScale(); + UpdateScreenScale(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); { { #ifdef _WIN32 diff --git a/Core/Core.h b/Core/Core.h index 7c2760f365..d96601e983 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -41,4 +41,4 @@ bool Core_IsInactive(); void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); -void UpdateScreenScale(); +void UpdateScreenScale(int width, int height); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index b2df4eb506..c99f515833 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -105,11 +105,6 @@ void EmuScreen::bootGame(const std::string &filename) { coreParam.renderHeight = 272 * g_Config.iInternalResolution; } - // If bounds is set to be smaller than the actual pixel resolution of the display, respect that. - // TODO: Should be able to use g_dpi_scale here instead. Might want to store the dpi scale in the UI context too. - coreParam.pixelWidth = pixel_xres * bounds.w / dp_xres; - coreParam.pixelHeight = pixel_yres * bounds.h / dp_yres; - std::string error_string; if (!PSP_InitStart(coreParam, &error_string)) { booted_ = true; @@ -477,8 +472,11 @@ void EmuScreen::update(InputState &input) { UIScreen::update(input); // Simply forcibily update to the current screen size every frame. Doesn't cost much. - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + // If bounds is set to be smaller than the actual pixel resolution of the display, respect that. + // TODO: Should be able to use g_dpi_scale here instead. Might want to store the dpi scale in the UI context too. + const Bounds &bounds = screenManager()->getUIContext()->GetBounds(); + PSP_CoreParameter().pixelWidth = pixel_xres * bounds.w / dp_xres; + PSP_CoreParameter().pixelHeight = pixel_yres * bounds.h / dp_yres; UpdateUIState(UISTATE_INGAME); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index d2dc5c7c8e..514dbbb512 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -496,7 +496,7 @@ void NativeInitGraphics() { uiContext->Init(UIShader_Get(), UIShader_GetPlain(), uiTexture, &ui_draw2d, &ui_draw2d_front); if (uiContext->Text()) uiContext->Text()->SetFont("Tahoma", 20, 0); - uiContext->SetBounds(Bounds(0, 0, dp_xres, dp_yres)); + screenManager->setUIContext(uiContext); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); @@ -618,8 +618,9 @@ void NativeRender() { glstate.viewport.set(0, 0, pixel_xres, pixel_yres); glstate.Restore(); - float xres = uiContext->GetBounds().w; - float yres = uiContext->GetBounds().h; + float xres = dp_xres; + float yres = dp_yres; + // Apply the UIContext bounds as a 2D transformation matrix. Matrix4x4 ortho; ortho.setOrtho(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index ed7c7fc505..8df85d968a 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -87,7 +87,6 @@ unsigned int WINAPI TheThread(void *) // Native overwrites host. Can't allow that. Host *oldHost = host; - UpdateScreenScale(); NativeInit(__argc, (const char **)__argv, "1234", "1234", "1234"); Host *nativeHost = host; @@ -116,6 +115,7 @@ unsigned int WINAPI TheThread(void *) } NativeInitGraphics(); + NativeResized(); INFO_LOG(BOOT, "Done."); _dbg_update_(); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index ea550297cb..9575ba68a4 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -334,7 +334,7 @@ namespace MainWindow ResizeDisplay(showOSM, true); ShowOwnedPopups(hwndMain, FALSE); - UpdateScreenScale(); + UpdateScreenScale(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); } RECT DetermineWindowRectangle() { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 1a265c6e00..94eb7bbdc1 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -68,6 +68,7 @@ struct InputState; void GL_SwapBuffers() { } void NativeUpdate(InputState &input_state) { } void NativeRender() { } +void NativeResized() { } std::string System_GetProperty(SystemProperty prop) { return ""; } void System_SendMessage(const char *command, const char *parameter) {} diff --git a/headless/Headless.cpp~RFfc3622a.TMP b/headless/Headless.cpp~RFfc3622a.TMP new file mode 100644 index 0000000000..0835a07661 --- /dev/null +++ b/headless/Headless.cpp~RFfc3622a.TMP @@ -0,0 +1,412 @@ +// Headless version of PPSSPP, for testing using http://code.google.com/p/pspautotests/ . +// See headless.txt. +// To build on non-windows systems, just run CMake in the SDL directory, it will build both a normal ppsspp and the headless version. + +#include +#include +#include + +#include "Common/FileUtil.h" +#include "Core/Config.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/System.h" +#include "Core/HLE/sceUtility.h" +#include "Core/Host.h" +#include "Log.h" +#include "LogManager.h" +#include "base/NativeApp.h" +#include "input/input_state.h" +#include "base/timeutil.h" + +#include "Compare.h" +#include "StubHost.h" +#ifdef _WIN32 +#include "Windows/OpenGLBase.h" +#include "WindowsHeadlessHost.h" +#include "WindowsHeadlessHostDx9.h" +#endif + +// https://github.com/richq/android-ndk-profiler +#ifdef ANDROID_NDK_PROFILER +#include +#include "android/android-ndk-profiler/prof.h" +#endif + +class PrintfLogger : public LogListener +{ +public: + void Log(LogTypes::LOG_LEVELS level, const char *msg) + { + switch (level) + { + case LogTypes::LVERBOSE: + fprintf(stderr, "V %s", msg); + break; + case LogTypes::LDEBUG: + fprintf(stderr, "D %s", msg); + break; + case LogTypes::LINFO: + fprintf(stderr, "I %s", msg); + break; + case LogTypes::LERROR: + fprintf(stderr, "E %s", msg); + break; + case LogTypes::LWARNING: + fprintf(stderr, "W %s", msg); + break; + case LogTypes::LNOTICE: + default: + fprintf(stderr, "N %s", msg); + break; + } + } +}; + +struct InputState; +// Temporary hack around annoying linking error. +void GL_SwapBuffers() { } +void NativeUpdate(InputState &input_state) { } +void NativeRender() { } + +std::string System_GetProperty(SystemProperty prop) { return ""; } +void System_SendMessage(const char *command, const char *parameter) {} +bool System_InputBoxGetWString(const wchar_t *title, const std::wstring &defaultvalue, std::wstring &outvalue) { return false; } + +#ifndef _WIN32 +InputState input_state; +#endif + +void printUsage(const char *progname, const char *reason) +{ + if (reason != NULL) + fprintf(stderr, "Error: %s\n\n", reason); + fprintf(stderr, "PPSSPP Headless\n"); + fprintf(stderr, "This is primarily meant as a non-interactive test tool.\n\n"); + fprintf(stderr, "Usage: %s file.elf... [options]\n\n", progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -m, --mount umd.cso mount iso on umd:\n"); + fprintf(stderr, " -l, --log full log output, not just emulated printfs\n"); + +#if HEADLESSHOST_CLASS != HeadlessHost + { + fprintf(stderr, " --graphics=BACKEND use the full gpu backend (slower)\n"); + fprintf(stderr, " options: gles, software, directx9\n"); + fprintf(stderr, " --screenshot=FILE compare against a screenshot\n"); + } +#endif + fprintf(stderr, " --timeout=SECONDS abort test it if takes longer than SECONDS\n"); + + fprintf(stderr, " -v, --verbose show the full passed/failed result\n"); + fprintf(stderr, " -i use the interpreter\n"); + fprintf(stderr, " -j use jit (default)\n"); + fprintf(stderr, " -c, --compare compare with output in file.expected\n"); + fprintf(stderr, "\nSee headless.txt for details.\n"); +} + +static HeadlessHost * getHost(GPUCore gpuCore) { + switch(gpuCore) { + case GPU_NULL: + return new HeadlessHost(); +#ifdef _WIN32 + case GPU_DIRECTX9: + return new WindowsHeadlessHostDx9(); +#endif + default: + return new HEADLESSHOST_CLASS(); + } +} + +bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool autoCompare, bool verbose, double timeout) +{ + if (teamCityMode) { + // Kinda ugly, trying to guesstimate the test name from filename... + teamCityName = GetTestName(coreParameter.fileToStart); + } + + std::string output; + if (autoCompare) + coreParameter.collectEmuLog = &output; + + std::string error_string; + if (!PSP_Init(coreParameter, &error_string)) { + fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); + printf("TESTERROR\n"); + TeamCityPrint("##teamcity[testIgnored name='%s' message='PRX/ELF missing']\n", teamCityName.c_str()); + return false; + } + + TeamCityPrint("##teamcity[testStarted name='%s' captureStandardOutput='true']\n", teamCityName.c_str()); + + host->BootDone(); + + if (autoCompare) + headlessHost->SetComparisonScreenshot(ExpectedScreenshotFromFilename(coreParameter.fileToStart)); + + time_update(); + bool passed = true; + // TODO: We must have some kind of stack overflow or we're not following the ABI right. + // This gets trashed if it's not static. + static double deadline; + deadline = time_now() + timeout; + + coreState = CORE_RUNNING; + while (coreState == CORE_RUNNING) + { + int blockTicks = usToCycles(1000000 / 10); + PSP_RunLoopFor(blockTicks); + + // If we were rendering, this might be a nice time to do something about it. + if (coreState == CORE_NEXTFRAME) { + coreState = CORE_RUNNING; + headlessHost->SwapBuffers(); + } + time_update(); + if (time_now_d() > deadline) { + // Don't compare, print the output at least up to this point, and bail. + printf("%s", output.c_str()); + passed = false; + + host->SendDebugOutput("TIMEOUT\n"); + TeamCityPrint("##teamcity[testFailed name='%s' message='Test timeout']\n", teamCityName.c_str()); + Core_Stop(); + } + } + + PSP_Shutdown(); + + headlessHost->FlushDebugOutput(); + + if (autoCompare && passed) + passed = CompareOutput(coreParameter.fileToStart, output, verbose); + + TeamCityPrint("##teamcity[testFinished name='%s']\n", teamCityName.c_str()); + + return passed; +} + +int main(int argc, const char* argv[]) +{ +#ifdef ANDROID_NDK_PROFILER + setenv("CPUPROFILE_FREQUENCY", "500", 1); + setenv("CPUPROFILE", "/sdcard/gmon.out", 1); + monstartup("ppsspp_headless"); +#endif + + bool fullLog = false; + bool useJit = true; + bool autoCompare = false; + bool verbose = false; + GPUCore gpuCore = GPU_NULL; + + std::vector testFilenames; + const char *mountIso = 0; + const char *screenshotFilename = 0; + bool readMount = false; + float timeout = std::numeric_limits::infinity(); + + for (int i = 1; i < argc; i++) + { + if (readMount) + { + mountIso = argv[i]; + readMount = false; + continue; + } + if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) + readMount = true; + else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) + fullLog = true; + else if (!strcmp(argv[i], "-i")) + useJit = false; + else if (!strcmp(argv[i], "-j")) + useJit = true; + else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) + autoCompare = true; + else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) + verbose = true; + else if (!strncmp(argv[i], "--graphics=", strlen("--graphics=")) && strlen(argv[i]) > strlen("--graphics=")) + { + const char *gpuName = argv[i] + strlen("--graphics="); + if (!strcasecmp(gpuName, "gles")) + gpuCore = GPU_GLES; + else if (!strcasecmp(gpuName, "software")) + gpuCore = GPU_SOFTWARE; + else if (!strcasecmp(gpuName, "directx9")) + gpuCore = GPU_DIRECTX9; + else if (!strcasecmp(gpuName, "null")) + gpuCore = GPU_NULL; + else + { + printUsage(argv[0], "Unknown gpu backend specified after --graphics="); + return 1; + } + } + // Default to GLES if no value selected. + else if (!strcmp(argv[i], "--graphics")) + gpuCore = GPU_GLES; + else if (!strncmp(argv[i], "--screenshot=", strlen("--screenshot=")) && strlen(argv[i]) > strlen("--screenshot=")) + screenshotFilename = argv[i] + strlen("--screenshot="); + else if (!strncmp(argv[i], "--timeout=", strlen("--timeout=")) && strlen(argv[i]) > strlen("--timeout=")) + timeout = strtod(argv[i] + strlen("--timeout="), NULL); + else if (!strcmp(argv[i], "--teamcity")) + teamCityMode = true; + else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) + { + printUsage(argv[0], NULL); + return 1; + } + else + testFilenames.push_back(argv[i]); + } + + // TODO: Allow a filename here? + if (testFilenames.size() == 1 && testFilenames[0] == "@-") + { + testFilenames.clear(); + char temp[2048]; + temp[2047] = '\0'; + + while (scanf("%2047s", temp) == 1) + testFilenames.push_back(temp); + } + + if (readMount) + { + printUsage(argv[0], "Missing argument after -m"); + return 1; + } + if (testFilenames.empty()) + { + printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); + return 1; + } + + HeadlessHost *headlessHost = getHost(gpuCore); + host = headlessHost; + + std::string error_string; + bool glWorking = host->InitGL(&error_string); + + LogManager::Init(); + LogManager *logman = LogManager::GetInstance(); + + PrintfLogger *printfLogger = new PrintfLogger(); + + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) + { + LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; + logman->SetEnable(type, fullLog); + logman->SetLogLevel(type, LogTypes::LDEBUG); + logman->AddListener(type, printfLogger); + } + + CoreParameter coreParameter; + coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; + coreParameter.gpuCore = glWorking ? gpuCore : GPU_NULL; + coreParameter.enableSound = false; + coreParameter.mountIso = mountIso ? mountIso : ""; + coreParameter.startPaused = false; + coreParameter.printfEmuLog = !autoCompare; + coreParameter.headLess = true; + coreParameter.renderWidth = 480; + coreParameter.renderHeight = 272; + coreParameter.pixelWidth = 480; + coreParameter.pixelHeight = 272; + coreParameter.unthrottle = true; + + g_Config.bEnableSound = false; + g_Config.bFirstRun = false; + g_Config.bIgnoreBadMemAccess = true; + // Never report from tests. + g_Config.sReportHost = ""; + g_Config.bAutoSaveSymbolMap = false; + g_Config.iRenderingMode = 0; + g_Config.bHardwareTransform = true; +#ifdef USING_GLES2 + g_Config.iAnisotropyLevel = 0; +#else + g_Config.iAnisotropyLevel = 8; +#endif + g_Config.bVertexCache = true; + g_Config.bTrueColor = true; + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; + g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; + g_Config.bEncryptSave = true; + g_Config.sNickName = "shadow"; + g_Config.iTimeZone = 60; + g_Config.iDateFormat = PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY; + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS; + g_Config.iLockParentalLevel = 9; + g_Config.iInternalResolution = 1; + g_Config.bFrameSkipUnthrottle = false; + g_Config.bEnableLogging = fullLog; + g_Config.iNumWorkerThreads = 1; + +#ifdef _WIN32 + InitSysDirectories(); +#endif + +#if defined(ANDROID) +#elif defined(BLACKBERRY) || defined(__SYMBIAN32__) +#elif !defined(_WIN32) + g_Config.memCardDirectory = std::string(getenv("HOME")) + "/.ppsspp/"; +#endif + + // Try to find the flash0 directory. Often this is from a subdirectory. + for (int i = 0; i < 3; ++i) + { + if (!File::Exists(g_Config.flash0Directory)) + g_Config.flash0Directory += "../../flash0/"; + } + // Or else, maybe in the executable's dir. + if (!File::Exists(g_Config.flash0Directory)) + g_Config.flash0Directory = File::GetExeDirectory() + "flash0/"; + + if (screenshotFilename != 0) + headlessHost->SetComparisonScreenshot(screenshotFilename); + + std::vector failedTests; + std::vector passedTests; + for (size_t i = 0; i < testFilenames.size(); ++i) + { + coreParameter.fileToStart = testFilenames[i]; + if (autoCompare) + printf("%s:\n", coreParameter.fileToStart.c_str()); + bool passed = RunAutoTest(headlessHost, coreParameter, autoCompare, verbose, timeout); + if (autoCompare) + { + std::string testName = GetTestName(coreParameter.fileToStart); + if (passed) + { + passedTests.push_back(testName); + printf(" %s - passed!\n", testName.c_str()); + } + else + failedTests.push_back(testName); + } + } + + if (autoCompare) + { + printf("%d tests passed, %d tests failed.\n", (int)passedTests.size(), (int)failedTests.size()); + if (!failedTests.empty()) + { + printf("Failed tests:\n"); + for (size_t i = 0; i < failedTests.size(); ++i) { + printf(" %s\n", failedTests[i].c_str()); + } + } + } + + host->ShutdownGL(); + delete host; + host = NULL; + headlessHost = NULL; + +#ifdef ANDROID_NDK_PROFILER + moncleanup(); +#endif + + return 0; +} diff --git a/native b/native index f73890f0b2..52a7af1ed3 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit f73890f0b2f74b852e86a5b8f33056fe1790ec5d +Subproject commit 52a7af1ed33af7f1244d4c09de8e3da6a7b47dc5