summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt5
-rw-r--r--src/common/bit_field.h65
-rw-r--r--src/common/break_points.cpp1
-rw-r--r--src/common/common_funcs.h2
-rw-r--r--src/common/framebuffer_layout.cpp157
-rw-r--r--src/common/framebuffer_layout.h55
-rw-r--r--src/common/hash.cpp6
-rw-r--r--src/common/x64/cpu_detect.cpp2
8 files changed, 49 insertions, 244 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 6905d2d50..7e83e64b0 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -27,7 +27,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU
27set(SRCS 27set(SRCS
28 break_points.cpp 28 break_points.cpp
29 file_util.cpp 29 file_util.cpp
30 framebuffer_layout.cpp
31 hash.cpp 30 hash.cpp
32 logging/filter.cpp 31 logging/filter.cpp
33 logging/text_formatter.cpp 32 logging/text_formatter.cpp
@@ -56,7 +55,6 @@ set(HEADERS
56 common_paths.h 55 common_paths.h
57 common_types.h 56 common_types.h
58 file_util.h 57 file_util.h
59 framebuffer_layout.h
60 hash.h 58 hash.h
61 linear_disk_cache.h 59 linear_disk_cache.h
62 logging/text_formatter.h 60 logging/text_formatter.h
@@ -97,6 +95,7 @@ endif()
97create_directory_groups(${SRCS} ${HEADERS}) 95create_directory_groups(${SRCS} ${HEADERS})
98 96
99add_library(common STATIC ${SRCS} ${HEADERS}) 97add_library(common STATIC ${SRCS} ${HEADERS})
98target_link_libraries(common PUBLIC Boost::boost microprofile)
100if (ARCHITECTURE_x86_64) 99if (ARCHITECTURE_x86_64)
101 target_link_libraries(common xbyak) 100 target_link_libraries(common PRIVATE xbyak)
102endif() 101endif()
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 030f7caeb..0cc0a1be0 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -108,7 +108,7 @@
108 * symptoms. 108 * symptoms.
109 */ 109 */
110#pragma pack(1) 110#pragma pack(1)
111template <std::size_t position, std::size_t bits, typename T> 111template <std::size_t Position, std::size_t Bits, typename T>
112struct BitField { 112struct BitField {
113private: 113private:
114 // We hide the copy assigment operator here, because the default copy 114 // We hide the copy assigment operator here, because the default copy
@@ -117,7 +117,45 @@ private:
117 // We don't delete it because we want BitField to be trivially copyable. 117 // We don't delete it because we want BitField to be trivially copyable.
118 BitField& operator=(const BitField&) = default; 118 BitField& operator=(const BitField&) = default;
119 119
120 // StorageType is T for non-enum types and the underlying type of T if
121 // T is an enumeration. Note that T is wrapped within an enable_if in the
122 // former case to workaround compile errors which arise when using
123 // std::underlying_type<T>::type directly.
124 using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>,
125 std::enable_if<true, T>>::type;
126
127 // Unsigned version of StorageType
128 using StorageTypeU = std::make_unsigned_t<StorageType>;
129
120public: 130public:
131 /// Constants to allow limited introspection of fields if needed
132 static constexpr size_t position = Position;
133 static constexpr size_t bits = Bits;
134 static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position;
135
136 /**
137 * Formats a value by masking and shifting it according to the field parameters. A value
138 * containing several bitfields can be assembled by formatting each of their values and ORing
139 * the results together.
140 */
141 static constexpr FORCE_INLINE StorageType FormatValue(const T& value) {
142 return ((StorageType)value << position) & mask;
143 }
144
145 /**
146 * Extracts a value from the passed storage. In most situations prefer use the member functions
147 * (such as Value() or operator T), but this can be used to extract a value from a bitfield
148 * union in a constexpr context.
149 */
150 static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) {
151 if (std::numeric_limits<T>::is_signed) {
152 std::size_t shift = 8 * sizeof(T) - bits;
153 return (T)((storage << (shift - position)) >> shift);
154 } else {
155 return (T)((storage & mask) >> position);
156 }
157 }
158
121 // This constructor and assignment operator might be considered ambiguous: 159 // This constructor and assignment operator might be considered ambiguous:
122 // Would they initialize the storage or just the bitfield? 160 // Would they initialize the storage or just the bitfield?
123 // Hence, delete them. Use the Assign method to set bitfield values! 161 // Hence, delete them. Use the Assign method to set bitfield values!
@@ -126,23 +164,18 @@ public:
126 164
127 // Force default constructor to be created 165 // Force default constructor to be created
128 // so that we can use this within unions 166 // so that we can use this within unions
129 BitField() = default; 167 constexpr BitField() = default;
130 168
131 FORCE_INLINE operator T() const { 169 FORCE_INLINE operator T() const {
132 return Value(); 170 return Value();
133 } 171 }
134 172
135 FORCE_INLINE void Assign(const T& value) { 173 FORCE_INLINE void Assign(const T& value) {
136 storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask()); 174 storage = (storage & ~mask) | FormatValue(value);
137 } 175 }
138 176
139 FORCE_INLINE T Value() const { 177 FORCE_INLINE T Value() const {
140 if (std::numeric_limits<T>::is_signed) { 178 return ExtractValue(storage);
141 std::size_t shift = 8 * sizeof(T) - bits;
142 return (T)((storage << (shift - position)) >> shift);
143 } else {
144 return (T)((storage & GetMask()) >> position);
145 }
146 } 179 }
147 180
148 // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015 181 // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
@@ -151,20 +184,6 @@ public:
151 } 184 }
152 185
153private: 186private:
154 // StorageType is T for non-enum types and the underlying type of T if
155 // T is an enumeration. Note that T is wrapped within an enable_if in the
156 // former case to workaround compile errors which arise when using
157 // std::underlying_type<T>::type directly.
158 typedef typename std::conditional<std::is_enum<T>::value, std::underlying_type<T>,
159 std::enable_if<true, T>>::type::type StorageType;
160
161 // Unsigned version of StorageType
162 typedef typename std::make_unsigned<StorageType>::type StorageTypeU;
163
164 FORCE_INLINE StorageType GetMask() const {
165 return (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position;
166 }
167
168 StorageType storage; 187 StorageType storage;
169 188
170 static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); 189 static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range");
diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp
index 03a19acba..fa367a4ca 100644
--- a/src/common/break_points.cpp
+++ b/src/common/break_points.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <sstream> 6#include <sstream>
7#include "common/break_points.h" 7#include "common/break_points.h"
8#include "common/logging/log.h"
9 8
10bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const { 9bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const {
11 auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; }; 10 auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; };
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index b141e79ed..2e7877500 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -7,7 +7,7 @@
7#if !defined(ARCHITECTURE_x86_64) && !defined(_M_ARM) 7#if !defined(ARCHITECTURE_x86_64) && !defined(_M_ARM)
8#include <cstdlib> // for exit 8#include <cstdlib> // for exit
9#endif 9#endif
10#include "common_types.h" 10#include "common/common_types.h"
11 11
12#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 12#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
13 13
diff --git a/src/common/framebuffer_layout.cpp b/src/common/framebuffer_layout.cpp
deleted file mode 100644
index a2a0e7dad..000000000
--- a/src/common/framebuffer_layout.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cmath>
6
7#include "common/assert.h"
8#include "common/framebuffer_layout.h"
9#include "core/settings.h"
10#include "video_core/video_core.h"
11
12namespace Layout {
13
14static const float TOP_SCREEN_ASPECT_RATIO =
15 static_cast<float>(VideoCore::kScreenTopHeight) / VideoCore::kScreenTopWidth;
16static const float BOT_SCREEN_ASPECT_RATIO =
17 static_cast<float>(VideoCore::kScreenBottomHeight) / VideoCore::kScreenBottomWidth;
18
19// Finds the largest size subrectangle contained in window area that is confined to the aspect ratio
20template <class T>
21static MathUtil::Rectangle<T> maxRectangle(MathUtil::Rectangle<T> window_area,
22 float screen_aspect_ratio) {
23 float scale = std::min(static_cast<float>(window_area.GetWidth()),
24 window_area.GetHeight() / screen_aspect_ratio);
25 return MathUtil::Rectangle<T>{0, 0, static_cast<T>(std::round(scale)),
26 static_cast<T>(std::round(scale * screen_aspect_ratio))};
27}
28
29FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height, bool swapped) {
30 ASSERT(width > 0);
31 ASSERT(height > 0);
32
33 FramebufferLayout res{width, height, true, true, {}, {}};
34 // Default layout gives equal screen sizes to the top and bottom screen
35 MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height / 2};
36 MathUtil::Rectangle<unsigned> top_screen =
37 maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
38 MathUtil::Rectangle<unsigned> bot_screen =
39 maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
40
41 float window_aspect_ratio = static_cast<float>(height) / width;
42 // both screens height are taken into account by multiplying by 2
43 float emulation_aspect_ratio = TOP_SCREEN_ASPECT_RATIO * 2;
44
45 if (window_aspect_ratio < emulation_aspect_ratio) {
46 // Apply borders to the left and right sides of the window.
47 top_screen =
48 top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2);
49 bot_screen =
50 bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2);
51 } else {
52 // Window is narrower than the emulation content => apply borders to the top and bottom
53 // Recalculate the bottom screen to account for the width difference between top and bottom
54 screen_window_area = {0, 0, width, top_screen.GetHeight()};
55 bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
56 bot_screen = bot_screen.TranslateX((top_screen.GetWidth() - bot_screen.GetWidth()) / 2);
57 if (swapped) {
58 bot_screen = bot_screen.TranslateY(height / 2 - bot_screen.GetHeight());
59 } else {
60 top_screen = top_screen.TranslateY(height / 2 - top_screen.GetHeight());
61 }
62 }
63 // Move the top screen to the bottom if we are swapped.
64 res.top_screen = swapped ? top_screen.TranslateY(height / 2) : top_screen;
65 res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateY(height / 2);
66 return res;
67}
68
69FramebufferLayout SingleFrameLayout(unsigned width, unsigned height, bool swapped) {
70 ASSERT(width > 0);
71 ASSERT(height > 0);
72 // The drawing code needs at least somewhat valid values for both screens
73 // so just calculate them both even if the other isn't showing.
74 FramebufferLayout res{width, height, !swapped, swapped, {}, {}};
75
76 MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height};
77 MathUtil::Rectangle<unsigned> top_screen =
78 maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO);
79 MathUtil::Rectangle<unsigned> bot_screen =
80 maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO);
81
82 float window_aspect_ratio = static_cast<float>(height) / width;
83 float emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
84
85 if (window_aspect_ratio < emulation_aspect_ratio) {
86 top_screen =
87 top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2);
88 bot_screen =
89 bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2);
90 } else {
91 top_screen = top_screen.TranslateY((height - top_screen.GetHeight()) / 2);
92 bot_screen = bot_screen.TranslateY((height - bot_screen.GetHeight()) / 2);
93 }
94 res.top_screen = top_screen;
95 res.bottom_screen = bot_screen;
96 return res;
97}
98
99FramebufferLayout LargeFrameLayout(unsigned width, unsigned height, bool swapped) {
100 ASSERT(width > 0);
101 ASSERT(height > 0);
102
103 FramebufferLayout res{width, height, true, true, {}, {}};
104 // Split the window into two parts. Give 4x width to the main screen and 1x width to the small
105 // To do that, find the total emulation box and maximize that based on window size
106 float window_aspect_ratio = static_cast<float>(height) / width;
107 float emulation_aspect_ratio =
108 swapped
109 ? VideoCore::kScreenBottomHeight * 4 /
110 (VideoCore::kScreenBottomWidth * 4.0f + VideoCore::kScreenTopWidth)
111 : VideoCore::kScreenTopHeight * 4 /
112 (VideoCore::kScreenTopWidth * 4.0f + VideoCore::kScreenBottomWidth);
113 float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
114 float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO;
115
116 MathUtil::Rectangle<unsigned> screen_window_area{0, 0, width, height};
117 MathUtil::Rectangle<unsigned> total_rect =
118 maxRectangle(screen_window_area, emulation_aspect_ratio);
119 MathUtil::Rectangle<unsigned> large_screen =
120 maxRectangle(total_rect, large_screen_aspect_ratio);
121 MathUtil::Rectangle<unsigned> fourth_size_rect = total_rect.Scale(.25f);
122 MathUtil::Rectangle<unsigned> small_screen =
123 maxRectangle(fourth_size_rect, small_screen_aspect_ratio);
124
125 if (window_aspect_ratio < emulation_aspect_ratio) {
126 large_screen =
127 large_screen.TranslateX((screen_window_area.GetWidth() - total_rect.GetWidth()) / 2);
128 } else {
129 large_screen = large_screen.TranslateY((height - total_rect.GetHeight()) / 2);
130 }
131 // Shift the small screen to the bottom right corner
132 small_screen =
133 small_screen.TranslateX(large_screen.right)
134 .TranslateY(large_screen.GetHeight() + large_screen.top - small_screen.GetHeight());
135 res.top_screen = swapped ? small_screen : large_screen;
136 res.bottom_screen = swapped ? large_screen : small_screen;
137 return res;
138}
139
140FramebufferLayout CustomFrameLayout(unsigned width, unsigned height) {
141 ASSERT(width > 0);
142 ASSERT(height > 0);
143
144 FramebufferLayout res{width, height, true, true, {}, {}};
145
146 MathUtil::Rectangle<unsigned> top_screen{
147 Settings::values.custom_top_left, Settings::values.custom_top_top,
148 Settings::values.custom_top_right, Settings::values.custom_top_bottom};
149 MathUtil::Rectangle<unsigned> bot_screen{
150 Settings::values.custom_bottom_left, Settings::values.custom_bottom_top,
151 Settings::values.custom_bottom_right, Settings::values.custom_bottom_bottom};
152
153 res.top_screen = top_screen;
154 res.bottom_screen = bot_screen;
155 return res;
156}
157}
diff --git a/src/common/framebuffer_layout.h b/src/common/framebuffer_layout.h
deleted file mode 100644
index f1df5c55a..000000000
--- a/src/common/framebuffer_layout.h
+++ /dev/null
@@ -1,55 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/math_util.h"
8namespace Layout {
9/// Describes the layout of the window framebuffer (size and top/bottom screen positions)
10struct FramebufferLayout {
11 unsigned width;
12 unsigned height;
13 bool top_screen_enabled;
14 bool bottom_screen_enabled;
15 MathUtil::Rectangle<unsigned> top_screen;
16 MathUtil::Rectangle<unsigned> bottom_screen;
17};
18
19/**
20 * Factory method for constructing a default FramebufferLayout
21 * @param width Window framebuffer width in pixels
22 * @param height Window framebuffer height in pixels
23 * @param is_swapped if true, the bottom screen will be displayed above the top screen
24 * @return Newly created FramebufferLayout object with default screen regions initialized
25 */
26FramebufferLayout DefaultFrameLayout(unsigned width, unsigned height, bool is_swapped);
27
28/**
29 * Factory method for constructing a FramebufferLayout with only the top or bottom screen
30 * @param width Window framebuffer width in pixels
31 * @param height Window framebuffer height in pixels
32 * @param is_swapped if true, the bottom screen will be displayed (and the top won't be displayed)
33 * @return Newly created FramebufferLayout object with default screen regions initialized
34 */
35FramebufferLayout SingleFrameLayout(unsigned width, unsigned height, bool is_swapped);
36
37/**
38 * Factory method for constructing a Frame with the a 4x size Top screen with a 1x size bottom
39 * screen on the right
40 * This is useful in particular because it matches well with a 1920x1080 resolution monitor
41 * @param width Window framebuffer width in pixels
42 * @param height Window framebuffer height in pixels
43 * @param is_swapped if true, the bottom screen will be the large display
44 * @return Newly created FramebufferLayout object with default screen regions initialized
45 */
46FramebufferLayout LargeFrameLayout(unsigned width, unsigned height, bool is_swapped);
47
48/**
49 * Factory method for constructing a custom FramebufferLayout
50 * @param width Window framebuffer width in pixels
51 * @param height Window framebuffer height in pixels
52 * @return Newly created FramebufferLayout object with default screen regions initialized
53 */
54FramebufferLayout CustomFrameLayout(unsigned width, unsigned height);
55}
diff --git a/src/common/hash.cpp b/src/common/hash.cpp
index f3d390dc5..a02e9e5b9 100644
--- a/src/common/hash.cpp
+++ b/src/common/hash.cpp
@@ -5,9 +5,9 @@
5#if defined(_MSC_VER) 5#if defined(_MSC_VER)
6#include <stdlib.h> 6#include <stdlib.h>
7#endif 7#endif
8#include "common_funcs.h" 8#include "common/common_funcs.h"
9#include "common_types.h" 9#include "common/common_types.h"
10#include "hash.h" 10#include "common/hash.h"
11 11
12namespace Common { 12namespace Common {
13 13
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp
index 2cb3ab9cc..62f17fbb5 100644
--- a/src/common/x64/cpu_detect.cpp
+++ b/src/common/x64/cpu_detect.cpp
@@ -6,7 +6,7 @@
6#include <string> 6#include <string>
7#include <thread> 7#include <thread>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "cpu_detect.h" 9#include "common/x64/cpu_detect.h"
10 10
11#ifdef _MSC_VER 11#ifdef _MSC_VER
12#include <intrin.h> 12#include <intrin.h>