diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/assert.h | 31 | ||||
-rw-r--r-- | src/common/emu_window.cpp | 50 | ||||
-rw-r--r-- | src/common/emu_window.h | 32 | ||||
-rw-r--r-- | src/common/logging/backend.cpp | 9 | ||||
-rw-r--r-- | src/common/logging/backend.h | 3 | ||||
-rw-r--r-- | src/common/logging/filter.h | 2 | ||||
-rw-r--r-- | src/common/logging/text_formatter.cpp | 7 | ||||
-rw-r--r-- | src/common/logging/text_formatter.h | 3 |
8 files changed, 117 insertions, 20 deletions
diff --git a/src/common/assert.h b/src/common/assert.h index 3b2232a7e..9ca7adb15 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -4,24 +4,43 @@ #pragma once +#include <cstdlib> + #include "common/common_funcs.h" +// For asserts we'd like to keep all the junk executed when an assert happens away from the +// important code in the function. One way of doing this is to put all the relevant code inside a +// lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to +// specify __declspec on lambda functions, so what we do instead is define a noinline wrapper +// template that calls the lambda. This seems to generate an extra instruction at the call-site +// compared to the ideal implementation (which wouldn't support ASSERT_MSG parameters), but is good +// enough for our purposes. +template <typename Fn> +#if defined(_MSC_VER) + __declspec(noinline, noreturn) +#elif defined(__GNUC__) + __attribute__((noinline, noreturn, cold)) +#endif +static void assert_noinline_call(const Fn& fn) { + fn(); + Crash(); + exit(1); // Keeps GCC's mouth shut about this actually returning +} + // TODO (yuriks) allow synchronous logging so we don't need printf #define ASSERT(_a_) \ - do if (!(_a_)) {\ + do if (!(_a_)) { assert_noinline_call([] { \ fprintf(stderr, "Assertion Failed!\n\n Line: %d\n File: %s\n Time: %s\n", \ __LINE__, __FILE__, __TIME__); \ - Crash(); \ - } while (0) + }); } while (0) #define ASSERT_MSG(_a_, ...) \ - do if (!(_a_)) {\ + do if (!(_a_)) { assert_noinline_call([&] { \ fprintf(stderr, "Assertion Failed!\n\n Line: %d\n File: %s\n Time: %s\n", \ __LINE__, __FILE__, __TIME__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ - Crash(); \ - } while (0) + }); } while (0) #define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!") diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 48bb35db5..6459d2f32 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "emu_window.h" +#include "video_core/video_core.h" void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); @@ -15,3 +16,52 @@ void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { Service::HID::PadButtonRelease(mapped_key); } + +EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, unsigned height) { + ASSERT(width > 0); + ASSERT(height > 0); + + EmuWindow::FramebufferLayout res = { width, height, {}, {} }; + + float window_aspect_ratio = static_cast<float>(height) / width; + float emulation_aspect_ratio = static_cast<float>(VideoCore::kScreenTopHeight * 2) / + VideoCore::kScreenTopWidth; + + if (window_aspect_ratio > emulation_aspect_ratio) { + // Window is narrower than the emulation content => apply borders to the top and bottom + int viewport_height = static_cast<int>(std::round(emulation_aspect_ratio * width)); + + res.top_screen.left = 0; + res.top_screen.right = res.top_screen.left + width; + res.top_screen.top = (height - viewport_height) / 2; + res.top_screen.bottom = res.top_screen.top + viewport_height / 2; + + int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) / + VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left)); + int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2; + + res.bottom_screen.left = bottom_border; + res.bottom_screen.right = res.bottom_screen.left + bottom_width; + res.bottom_screen.top = res.top_screen.bottom; + res.bottom_screen.bottom = res.bottom_screen.top + viewport_height / 2; + } else { + // Otherwise, apply borders to the left and right sides of the window. + int viewport_width = static_cast<int>(std::round(height / emulation_aspect_ratio)); + + res.top_screen.left = (width - viewport_width) / 2; + res.top_screen.right = res.top_screen.left + viewport_width; + res.top_screen.top = 0; + res.top_screen.bottom = res.top_screen.top + height / 2; + + int bottom_width = static_cast<int>((static_cast<float>(VideoCore::kScreenBottomWidth) / + VideoCore::kScreenTopWidth) * (res.top_screen.right - res.top_screen.left)); + int bottom_border = ((res.top_screen.right - res.top_screen.left) - bottom_width) / 2; + + res.bottom_screen.left = res.top_screen.left + bottom_border; + res.bottom_screen.right = res.bottom_screen.left + bottom_width; + res.bottom_screen.top = res.top_screen.bottom; + res.bottom_screen.bottom = res.bottom_screen.top + height / 2; + } + + return res; +} diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 1ad4b82a3..f6099fdb6 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -8,6 +8,7 @@ #include "common/scm_rev.h" #include "common/string_util.h" #include "common/key_map.h" +#include "common/math_util.h" /** * Abstraction class used to provide an interface between emulation code and the frontend @@ -38,6 +39,23 @@ public: std::pair<unsigned,unsigned> min_client_area_size; }; + /// Describes the layout of the window framebuffer (size and top/bottom screen positions) + struct FramebufferLayout { + + /** + * Factory method for constructing a default FramebufferLayout + * @param width Window framebuffer width in pixels + * @param height Window framebuffer height in pixels + * @return Newly created FramebufferLayout object with default screen regions initialized + */ + static FramebufferLayout DefaultScreenLayout(unsigned width, unsigned height); + + unsigned width; + unsigned height; + MathUtil::Rectangle<unsigned> top_screen; + MathUtil::Rectangle<unsigned> bottom_screen; + }; + /// Swap buffers to display the next frame virtual void SwapBuffers() = 0; @@ -75,11 +93,11 @@ public: } /** - * Gets the framebuffer size in pixels. + * Gets the framebuffer layout (width, height, and screen regions) * @note This method is thread-safe */ - const std::pair<unsigned,unsigned> GetFramebufferSize() const { - return framebuffer_size; + const FramebufferLayout& GetFramebufferLayout() const { + return framebuffer_layout; } /** @@ -118,11 +136,11 @@ protected: } /** - * Update internal framebuffer size with the given parameter. + * Update framebuffer layout with the given parameter. * @note EmuWindow implementations will usually use this in window resize event handlers. */ - void NotifyFramebufferSizeChanged(const std::pair<unsigned,unsigned>& size) { - framebuffer_size = size; + void NotifyFramebufferLayoutChanged(const FramebufferLayout& layout) { + framebuffer_layout = layout; } /** @@ -143,7 +161,7 @@ private: // By default, ignore this request and do nothing. } - std::pair<unsigned,unsigned> framebuffer_size; + FramebufferLayout framebuffer_layout; ///< Current framebuffer layout unsigned client_area_width; ///< Current client width, should be set by window impl. unsigned client_area_height; ///< Current client height, should be set by window impl. diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 7c1010b22..7b479b569 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -135,9 +135,18 @@ Entry CreateEntry(Class log_class, Level log_level, return std::move(entry); } +static Filter* filter; + +void SetFilter(Filter* new_filter) { + filter = new_filter; +} + void LogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_nr, const char* function, const char* format, ...) { + if (!filter->CheckMessage(log_class, log_level)) + return; + va_list args; va_start(args, format); Entry entry = CreateEntry(log_class, log_level, diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 1c44c929e..3114f864c 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -10,6 +10,7 @@ #include "common/concurrent_ring_buffer.h" +#include "common/logging/filter.h" #include "common/logging/log.h" namespace Log { @@ -131,4 +132,6 @@ Entry CreateEntry(Class log_class, Level log_level, /// Initializes the default Logger. std::shared_ptr<Logger> InitGlobalLogger(); +void SetFilter(Filter* filter); + } diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h index c3da9989f..b53e4e633 100644 --- a/src/common/logging/filter.h +++ b/src/common/logging/filter.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include <array> #include <string> diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp index ef5739d84..36c91c4f6 100644 --- a/src/common/logging/text_formatter.cpp +++ b/src/common/logging/text_formatter.cpp @@ -11,7 +11,6 @@ #endif #include "common/logging/backend.h" -#include "common/logging/filter.h" #include "common/logging/log.h" #include "common/logging/text_formatter.h" @@ -116,7 +115,7 @@ void PrintColoredMessage(const Entry& entry) { #endif } -void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) { +void TextLoggingLoop(std::shared_ptr<Logger> logger) { std::array<Entry, 256> entry_buffer; while (true) { @@ -126,9 +125,7 @@ void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) { } for (size_t i = 0; i < num_entries; ++i) { const Entry& entry = entry_buffer[i]; - if (filter->CheckMessage(entry.log_class, entry.log_level)) { - PrintColoredMessage(entry); - } + PrintColoredMessage(entry); } } } diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h index 2f05794f0..8474a1904 100644 --- a/src/common/logging/text_formatter.h +++ b/src/common/logging/text_formatter.h @@ -11,7 +11,6 @@ namespace Log { class Logger; struct Entry; -class Filter; /** * Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's @@ -36,6 +35,6 @@ void PrintColoredMessage(const Entry& entry); * Logging loop that repeatedly reads messages from the provided logger and prints them to the * console. It is the baseline barebones log outputter. */ -void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter); +void TextLoggingLoop(std::shared_ptr<Logger> logger); } |