mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
Merge branch 'master' into extdata
This commit is contained in:
commit
a9c2b05604
20 changed files with 208 additions and 96 deletions
22
.github/gles.patch
vendored
22
.github/gles.patch
vendored
|
@ -1,25 +1,3 @@
|
||||||
diff --git a/src/host_shaders/opengl_display.frag b/src/host_shaders/opengl_display.frag
|
|
||||||
index 612671c8..1937f711 100644
|
|
||||||
--- a/src/host_shaders/opengl_display.frag
|
|
||||||
+++ b/src/host_shaders/opengl_display.frag
|
|
||||||
@@ -1,4 +1,5 @@
|
|
||||||
-#version 410 core
|
|
||||||
+#version 300 es
|
|
||||||
+precision mediump float;
|
|
||||||
in vec2 UV;
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
diff --git a/src/host_shaders/opengl_display.vert b/src/host_shaders/opengl_display.vert
|
|
||||||
index 990e2f80..2e7842ac 100644
|
|
||||||
--- a/src/host_shaders/opengl_display.vert
|
|
||||||
+++ b/src/host_shaders/opengl_display.vert
|
|
||||||
@@ -1,4 +1,5 @@
|
|
||||||
-#version 410 core
|
|
||||||
+#version 300 es
|
|
||||||
+precision mediump float;
|
|
||||||
out vec2 UV;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag
|
diff --git a/src/host_shaders/opengl_fragment_shader.frag b/src/host_shaders/opengl_fragment_shader.frag
|
||||||
index 9f07df0b..96a35afa 100644
|
index 9f07df0b..96a35afa 100644
|
||||||
--- a/src/host_shaders/opengl_fragment_shader.frag
|
--- a/src/host_shaders/opengl_fragment_shader.frag
|
||||||
|
|
|
@ -50,6 +50,7 @@ option(GPU_DEBUG_INFO "Enable additional GPU debugging info" OFF)
|
||||||
option(ENABLE_OPENGL "Enable OpenGL rendering backend" ON)
|
option(ENABLE_OPENGL "Enable OpenGL rendering backend" ON)
|
||||||
option(ENABLE_VULKAN "Enable Vulkan rendering backend" ON)
|
option(ENABLE_VULKAN "Enable Vulkan rendering backend" ON)
|
||||||
option(ENABLE_METAL "Enable Metal rendering backend (if available)" ON)
|
option(ENABLE_METAL "Enable Metal rendering backend (if available)" ON)
|
||||||
|
option(ENABLE_WAYLAND "Enable Wayland support on Linux platforms" ON)
|
||||||
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
option(ENABLE_LTO "Enable link-time optimization" OFF)
|
||||||
option(ENABLE_TESTS "Compile unit-tests" OFF)
|
option(ENABLE_TESTS "Compile unit-tests" OFF)
|
||||||
option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF)
|
option(ENABLE_USER_BUILD "Make a user-facing build. These builds have various assertions disabled, LTO, and more" OFF)
|
||||||
|
@ -88,7 +89,7 @@ endif()
|
||||||
|
|
||||||
# Generate versioning files
|
# Generate versioning files
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
set(PANDA3DS_VERSION "0.8")
|
set(PANDA3DS_VERSION "0.9")
|
||||||
|
|
||||||
if(NOT EXISTS ${CMAKE_BINARY_DIR}/include/version.hpp.in)
|
if(NOT EXISTS ${CMAKE_BINARY_DIR}/include/version.hpp.in)
|
||||||
file(WRITE ${CMAKE_BINARY_DIR}/include/version.hpp.in "#define PANDA3DS_VERSION \"\${PANDA3DS_VERSION}\"")
|
file(WRITE ${CMAKE_BINARY_DIR}/include/version.hpp.in "#define PANDA3DS_VERSION \"\${PANDA3DS_VERSION}\"")
|
||||||
|
@ -97,22 +98,29 @@ endif()
|
||||||
if(GIT_FOUND AND ENABLE_GIT_VERSIONING)
|
if(GIT_FOUND AND ENABLE_GIT_VERSIONING)
|
||||||
execute_process(
|
execute_process(
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
|
||||||
OUTPUT_VARIABLE PANDA3DS_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
execute_process(
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
|
|
||||||
OUTPUT_VARIABLE git_version_tag OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_VARIABLE git_version_tag OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
if(NOT PANDA3DS_VERSION STREQUAL git_version_tag)
|
execute_process(
|
||||||
execute_process(
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --always --abbrev=7
|
OUTPUT_VARIABLE git_version_rev OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
OUTPUT_VARIABLE git_version_rev OUTPUT_STRIP_TRAILING_WHITESPACE
|
)
|
||||||
)
|
if(NOT git_version_tag STREQUAL "")
|
||||||
set(PANDA3DS_VERSION "${PANDA3DS_VERSION}.${git_version_rev}")
|
set(PANDA3DS_VERSION "${git_version_tag}")
|
||||||
unset(git_version_rev)
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} describe --tags
|
||||||
|
OUTPUT_VARIABLE git_version_desc OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if(git_version_tag STREQUAL git_version_desc)
|
||||||
|
set(git_version_rev "")
|
||||||
|
endif()
|
||||||
|
unset(git_version_desc)
|
||||||
|
endif()
|
||||||
|
if(NOT git_version_rev STREQUAL "")
|
||||||
|
set(PANDA3DS_VERSION "${PANDA3DS_VERSION}.${git_version_rev}")
|
||||||
endif()
|
endif()
|
||||||
string(REGEX REPLACE "^v" "" PANDA3DS_VERSION "${PANDA3DS_VERSION}")
|
string(REGEX REPLACE "^v" "" PANDA3DS_VERSION "${PANDA3DS_VERSION}")
|
||||||
unset(git_version_tag)
|
unset(git_version_tag)
|
||||||
|
unset(git_version_rev)
|
||||||
endif()
|
endif()
|
||||||
configure_file(${CMAKE_BINARY_DIR}/include/version.hpp.in ${CMAKE_BINARY_DIR}/include/version.hpp)
|
configure_file(${CMAKE_BINARY_DIR}/include/version.hpp.in ${CMAKE_BINARY_DIR}/include/version.hpp)
|
||||||
include_directories(${CMAKE_BINARY_DIR}/include/)
|
include_directories(${CMAKE_BINARY_DIR}/include/)
|
||||||
|
@ -140,6 +148,10 @@ add_compile_definitions(NOMINMAX) # Make windows.h not define min/ma
|
||||||
add_compile_definitions(WIN32_LEAN_AND_MEAN) # Make windows.h not include literally everything
|
add_compile_definitions(WIN32_LEAN_AND_MEAN) # Make windows.h not include literally everything
|
||||||
add_compile_definitions(SDL_MAIN_HANDLED)
|
add_compile_definitions(SDL_MAIN_HANDLED)
|
||||||
|
|
||||||
|
if(ENABLE_WAYLAND)
|
||||||
|
add_compile_definitions(WAYLAND_ENABLED)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_DISCORD_RPC AND NOT ANDROID)
|
if(ENABLE_DISCORD_RPC AND NOT ANDROID)
|
||||||
add_subdirectory(third_party/discord-rpc)
|
add_subdirectory(third_party/discord-rpc)
|
||||||
include_directories(third_party/discord-rpc/include)
|
include_directories(third_party/discord-rpc/include)
|
||||||
|
@ -422,16 +434,22 @@ if(ENABLE_LUAJIT AND NOT ANDROID)
|
||||||
target_link_libraries(AlberCore PRIVATE uv_a)
|
target_link_libraries(AlberCore PRIVATE uv_a)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(GL_CONTEXT_SOURCE_FILES "")
|
||||||
|
|
||||||
if(ENABLE_QT_GUI)
|
if(ENABLE_QT_GUI)
|
||||||
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
|
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
|
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
|
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
|
||||||
else()
|
else()
|
||||||
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_egl.cpp third_party/duckstation/gl/context_egl_wayland.cpp
|
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_egl.cpp third_party/duckstation/gl/context_egl_x11.cpp
|
||||||
third_party/duckstation/gl/context_egl_x11.cpp third_party/duckstation/gl/context_glx.cpp third_party/duckstation/gl/x11_window.cpp)
|
third_party/duckstation/gl/context_glx.cpp third_party/duckstation/gl/x11_window.cpp)
|
||||||
|
|
||||||
|
if(ENABLE_WAYLAND)
|
||||||
|
set(GL_CONTEXT_SOURCE_FILES ${GL_CONTEXT_SOURCE_FILES} third_party/duckstation/gl/context_egl_wayland.cpp)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -445,7 +463,7 @@ source_group("Source Files\\Core\\Applets" FILES ${APPLET_SOURCE_FILES})
|
||||||
source_group("Source Files\\Core\\PICA" FILES ${PICA_SOURCE_FILES})
|
source_group("Source Files\\Core\\PICA" FILES ${PICA_SOURCE_FILES})
|
||||||
source_group("Source Files\\Core\\Audio" FILES ${AUDIO_SOURCE_FILES})
|
source_group("Source Files\\Core\\Audio" FILES ${AUDIO_SOURCE_FILES})
|
||||||
source_group("Source Files\\Core\\Software Renderer" FILES ${RENDERER_SW_SOURCE_FILES})
|
source_group("Source Files\\Core\\Software Renderer" FILES ${RENDERER_SW_SOURCE_FILES})
|
||||||
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES})
|
source_group("Source Files\\Third Party" FILES ${THIRD_PARTY_SOURCE_FILES} ${GL_CONTEXT_SOURCE_FILES})
|
||||||
|
|
||||||
set(RENDERER_GL_SOURCE_FILES "") # Empty by default unless we are compiling with the GL renderer
|
set(RENDERER_GL_SOURCE_FILES "") # Empty by default unless we are compiling with the GL renderer
|
||||||
set(RENDERER_VK_SOURCE_FILES "") # Empty by default unless we are compiling with the VK renderer
|
set(RENDERER_VK_SOURCE_FILES "") # Empty by default unless we are compiling with the VK renderer
|
||||||
|
@ -460,8 +478,9 @@ if(ENABLE_OPENGL)
|
||||||
|
|
||||||
set(RENDERER_GL_SOURCE_FILES src/core/renderer_gl/renderer_gl.cpp
|
set(RENDERER_GL_SOURCE_FILES src/core/renderer_gl/renderer_gl.cpp
|
||||||
src/core/renderer_gl/textures.cpp src/core/renderer_gl/etc1.cpp
|
src/core/renderer_gl/textures.cpp src/core/renderer_gl/etc1.cpp
|
||||||
src/core/renderer_gl/gl_state.cpp src/host_shaders/opengl_display.frag
|
src/core/renderer_gl/gl_state.cpp src/host_shaders/opengl_display.vert
|
||||||
src/host_shaders/opengl_display.vert src/host_shaders/opengl_vertex_shader.vert
|
src/host_shaders/opengl_display.frag src/host_shaders/opengl_es_display.vert
|
||||||
|
src/host_shaders/opengl_es_display.frag src/host_shaders/opengl_vertex_shader.vert
|
||||||
src/host_shaders/opengl_fragment_shader.frag
|
src/host_shaders/opengl_fragment_shader.frag
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -474,8 +493,10 @@ if(ENABLE_OPENGL)
|
||||||
resources_renderer_gl
|
resources_renderer_gl
|
||||||
NAMESPACE RendererGL
|
NAMESPACE RendererGL
|
||||||
WHENCE "src/host_shaders/"
|
WHENCE "src/host_shaders/"
|
||||||
"src/host_shaders/opengl_display.frag"
|
|
||||||
"src/host_shaders/opengl_display.vert"
|
"src/host_shaders/opengl_display.vert"
|
||||||
|
"src/host_shaders/opengl_display.frag"
|
||||||
|
"src/host_shaders/opengl_es_display.vert"
|
||||||
|
"src/host_shaders/opengl_es_display.frag"
|
||||||
"src/host_shaders/opengl_vertex_shader.vert"
|
"src/host_shaders/opengl_vertex_shader.vert"
|
||||||
"src/host_shaders/opengl_fragment_shader.frag"
|
"src/host_shaders/opengl_fragment_shader.frag"
|
||||||
)
|
)
|
||||||
|
@ -751,7 +772,7 @@ if(NOT BUILD_HYDRA_CORE AND NOT BUILD_LIBRETRO_CORE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(Alber PRIVATE AlberCore)
|
target_link_libraries(Alber PRIVATE AlberCore)
|
||||||
target_sources(Alber PRIVATE ${FRONTEND_SOURCE_FILES} ${FRONTEND_HEADER_FILES} ${APP_RESOURCES})
|
target_sources(Alber PRIVATE ${FRONTEND_SOURCE_FILES} ${FRONTEND_HEADER_FILES} ${GL_CONTEXT_SOURCE_FILES} ${APP_RESOURCES})
|
||||||
elseif(BUILD_HYDRA_CORE)
|
elseif(BUILD_HYDRA_CORE)
|
||||||
target_compile_definitions(AlberCore PRIVATE PANDA3DS_HYDRA_CORE=1)
|
target_compile_definitions(AlberCore PRIVATE PANDA3DS_HYDRA_CORE=1)
|
||||||
include_directories(third_party/hydra_core/include)
|
include_directories(third_party/hydra_core/include)
|
||||||
|
|
|
@ -49,6 +49,12 @@ struct EmulatorConfig {
|
||||||
#endif
|
#endif
|
||||||
static constexpr bool accelerateShadersDefault = true;
|
static constexpr bool accelerateShadersDefault = true;
|
||||||
|
|
||||||
|
#if defined(__LIBRETRO__)
|
||||||
|
static constexpr bool audioEnabledDefault = true;
|
||||||
|
#else
|
||||||
|
static constexpr bool audioEnabledDefault = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool shaderJitEnabled = shaderJitDefault;
|
bool shaderJitEnabled = shaderJitDefault;
|
||||||
bool useUbershaders = ubershaderDefault;
|
bool useUbershaders = ubershaderDefault;
|
||||||
bool accelerateShaders = accelerateShadersDefault;
|
bool accelerateShaders = accelerateShadersDefault;
|
||||||
|
@ -66,7 +72,7 @@ struct EmulatorConfig {
|
||||||
bool sdWriteProtected = false;
|
bool sdWriteProtected = false;
|
||||||
bool usePortableBuild = false;
|
bool usePortableBuild = false;
|
||||||
|
|
||||||
bool audioEnabled = false;
|
bool audioEnabled = audioEnabledDefault;
|
||||||
bool vsyncEnabled = true;
|
bool vsyncEnabled = true;
|
||||||
bool aacEnabled = true; // Enable AAC audio?
|
bool aacEnabled = true; // Enable AAC audio?
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ class Emulator {
|
||||||
~Emulator();
|
~Emulator();
|
||||||
|
|
||||||
void step();
|
void step();
|
||||||
void render();
|
|
||||||
void reset(ReloadOption reload);
|
void reset(ReloadOption reload);
|
||||||
void runFrame();
|
void runFrame();
|
||||||
// Poll the scheduler for events
|
// Poll the scheduler for events
|
||||||
|
|
|
@ -81,6 +81,10 @@ class Renderer {
|
||||||
virtual std::string getUbershader() { return ""; }
|
virtual std::string getUbershader() { return ""; }
|
||||||
virtual void setUbershader(const std::string& shader) {}
|
virtual void setUbershader(const std::string& shader) {}
|
||||||
|
|
||||||
|
// Only relevant for OpenGL renderer and other OpenGL-based backends (eg software)
|
||||||
|
// Called to notify the core to use OpenGL ES and not desktop GL
|
||||||
|
virtual void setupGLES() {}
|
||||||
|
|
||||||
// This function is called on every draw call before parsing vertex data.
|
// This function is called on every draw call before parsing vertex data.
|
||||||
// It is responsible for things like looking up which vertex/fragment shaders to use, recompiling them if they don't exist, choosing between
|
// It is responsible for things like looking up which vertex/fragment shaders to use, recompiling them if they don't exist, choosing between
|
||||||
// ubershaders and shadergen, and so on.
|
// ubershaders and shadergen, and so on.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// Stuff like whether specific extensions are supported, and potentially things like OpenGL context information
|
// Stuff like whether specific extensions are supported, and potentially things like OpenGL context information
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
struct Driver {
|
struct Driver {
|
||||||
|
bool usingGLES = false;
|
||||||
bool supportsExtFbFetch = false;
|
bool supportsExtFbFetch = false;
|
||||||
bool supportsArmFbFetch = false;
|
bool supportsArmFbFetch = false;
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class RendererGL final : public Renderer {
|
||||||
OpenGL::VertexArray hwShaderVAO;
|
OpenGL::VertexArray hwShaderVAO;
|
||||||
OpenGL::VertexBuffer vbo;
|
OpenGL::VertexBuffer vbo;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
struct {
|
struct {
|
||||||
// TEV configuration uniform locations
|
// TEV configuration uniform locations
|
||||||
GLint textureEnvSourceLoc = -1;
|
GLint textureEnvSourceLoc = -1;
|
||||||
|
@ -157,6 +157,7 @@ class RendererGL final : public Renderer {
|
||||||
void initGraphicsContextInternal();
|
void initGraphicsContextInternal();
|
||||||
|
|
||||||
void accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel);
|
void accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel);
|
||||||
|
void compileDisplayShader();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RendererGL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs)
|
RendererGL(GPU& gpu, const std::array<u32, regNum>& internalRegs, const std::array<u32, extRegNum>& externalRegs)
|
||||||
|
@ -169,14 +170,15 @@ class RendererGL final : public Renderer {
|
||||||
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override; // Clear a GPU buffer in VRAM
|
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override; // Clear a GPU buffer in VRAM
|
||||||
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override; // Perform display transfer
|
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override; // Perform display transfer
|
||||||
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
|
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
|
||||||
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override; // Draw the given vertices
|
void drawVertices(PICA::PrimType primType, std::span<const PICA::Vertex> vertices) override; // Draw the given vertices
|
||||||
void deinitGraphicsContext() override;
|
void deinitGraphicsContext() override;
|
||||||
|
|
||||||
virtual bool supportsShaderReload() override { return true; }
|
virtual bool supportsShaderReload() override { return true; }
|
||||||
virtual std::string getUbershader() override;
|
virtual std::string getUbershader() override;
|
||||||
virtual void setUbershader(const std::string& shader) override;
|
virtual void setUbershader(const std::string& shader) override;
|
||||||
virtual bool prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) override;
|
virtual bool prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) override;
|
||||||
|
virtual void setupGLES() override;
|
||||||
|
|
||||||
std::optional<ColourBuffer> getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
|
std::optional<ColourBuffer> getColourBuffer(u32 addr, PICA::ColorFmt format, u32 width, u32 height, bool createIfnotFound = true);
|
||||||
|
|
||||||
// Note: The caller is responsible for deleting the currently bound FBO before calling this
|
// Note: The caller is responsible for deleting the currently bound FBO before calling this
|
||||||
|
|
|
@ -27,6 +27,7 @@ void EmulatorConfig::load() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Loading existing configuration file %s\n", path.string().c_str());
|
||||||
toml::value data;
|
toml::value data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -101,7 +102,7 @@ void EmulatorConfig::load() {
|
||||||
auto dspCoreName = toml::find_or<std::string>(audio, "DSPEmulation", "HLE");
|
auto dspCoreName = toml::find_or<std::string>(audio, "DSPEmulation", "HLE");
|
||||||
dspType = Audio::DSPCore::typeFromString(dspCoreName);
|
dspType = Audio::DSPCore::typeFromString(dspCoreName);
|
||||||
|
|
||||||
audioEnabled = toml::find_or<toml::boolean>(audio, "EnableAudio", false);
|
audioEnabled = toml::find_or<toml::boolean>(audio, "EnableAudio", audioEnabledDefault);
|
||||||
aacEnabled = toml::find_or<toml::boolean>(audio, "EnableAACAudio", true);
|
aacEnabled = toml::find_or<toml::boolean>(audio, "EnableAACAudio", true);
|
||||||
printDSPFirmware = toml::find_or<toml::boolean>(audio, "PrintDSPFirmware", false);
|
printDSPFirmware = toml::find_or<toml::boolean>(audio, "PrintDSPFirmware", false);
|
||||||
|
|
||||||
|
|
|
@ -51,17 +51,12 @@ void RendererGL::reset() {
|
||||||
|
|
||||||
gl.useProgram(oldProgram); // Switch to old GL program
|
gl.useProgram(oldProgram); // Switch to old GL program
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USING_GLES
|
|
||||||
fragShaderGen.setTarget(PICA::ShaderGen::API::GLES, PICA::ShaderGen::Language::GLSL);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererGL::initGraphicsContextInternal() {
|
void RendererGL::initGraphicsContextInternal() {
|
||||||
gl.reset();
|
gl.reset();
|
||||||
|
|
||||||
auto gl_resources = cmrc::RendererGL::get_filesystem();
|
auto gl_resources = cmrc::RendererGL::get_filesystem();
|
||||||
|
|
||||||
auto vertexShaderSource = gl_resources.open("opengl_vertex_shader.vert");
|
auto vertexShaderSource = gl_resources.open("opengl_vertex_shader.vert");
|
||||||
auto fragmentShaderSource = gl_resources.open("opengl_fragment_shader.frag");
|
auto fragmentShaderSource = gl_resources.open("opengl_fragment_shader.frag");
|
||||||
|
|
||||||
|
@ -70,16 +65,7 @@ void RendererGL::initGraphicsContextInternal() {
|
||||||
triangleProgram.create({vert, frag});
|
triangleProgram.create({vert, frag});
|
||||||
initUbershader(triangleProgram);
|
initUbershader(triangleProgram);
|
||||||
|
|
||||||
auto displayVertexShaderSource = gl_resources.open("opengl_display.vert");
|
compileDisplayShader();
|
||||||
auto displayFragmentShaderSource = gl_resources.open("opengl_display.frag");
|
|
||||||
|
|
||||||
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
|
|
||||||
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
|
|
||||||
displayProgram.create({vertDisplay, fragDisplay});
|
|
||||||
|
|
||||||
gl.useProgram(displayProgram);
|
|
||||||
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
|
||||||
|
|
||||||
// Create stream buffers for vertex, index and uniform buffers
|
// Create stream buffers for vertex, index and uniform buffers
|
||||||
static constexpr usize hwIndexBufferSize = 2_MB;
|
static constexpr usize hwIndexBufferSize = 2_MB;
|
||||||
static constexpr usize hwVertexBufferSize = 16_MB;
|
static constexpr usize hwVertexBufferSize = 16_MB;
|
||||||
|
@ -191,6 +177,7 @@ void RendererGL::initGraphicsContextInternal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
fragShaderGen.setTarget(driverInfo.usingGLES ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL);
|
||||||
|
|
||||||
// Populate our driver info structure
|
// Populate our driver info structure
|
||||||
driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0);
|
driverInfo.supportsExtFbFetch = (GLAD_GL_EXT_shader_framebuffer_fetch != 0);
|
||||||
|
@ -850,9 +837,9 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
|
||||||
|
|
||||||
PICA::FragmentConfig fsConfig(regs);
|
PICA::FragmentConfig fsConfig(regs);
|
||||||
// If we're not on GLES, ignore the logic op configuration and don't generate redundant shaders for it, since we use hw logic ops
|
// If we're not on GLES, ignore the logic op configuration and don't generate redundant shaders for it, since we use hw logic ops
|
||||||
#ifndef USING_GLES
|
if (!driverInfo.usingGLES) {
|
||||||
fsConfig.outConfig.logicOpMode = PICA::LogicOpMode(0);
|
fsConfig.outConfig.logicOpMode = PICA::LogicOpMode(0);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
OpenGL::Shader& fragShader = shaderCache.fragmentShaderCache[fsConfig];
|
OpenGL::Shader& fragShader = shaderCache.fragmentShaderCache[fsConfig];
|
||||||
if (!fragShader.exists()) {
|
if (!fragShader.exists()) {
|
||||||
|
@ -1010,7 +997,7 @@ bool RendererGL::prepareForDraw(ShaderUnit& shaderUnit, PICA::DrawAcceleration*
|
||||||
|
|
||||||
std::string picaShaderSource = PICA::ShaderGen::decompileShader(
|
std::string picaShaderSource = PICA::ShaderGen::decompileShader(
|
||||||
shaderUnit.vs, *emulatorConfig, shaderUnit.vs.entrypoint,
|
shaderUnit.vs, *emulatorConfig, shaderUnit.vs.entrypoint,
|
||||||
Helpers::isAndroid() ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL
|
driverInfo.usingGLES ? PICA::ShaderGen::API::GLES : PICA::ShaderGen::API::GL, PICA::ShaderGen::Language::GLSL
|
||||||
);
|
);
|
||||||
|
|
||||||
// Empty source means compilation error, if the source is not empty then we convert the recompiled PICA code into a valid shader and upload
|
// Empty source means compilation error, if the source is not empty then we convert the recompiled PICA code into a valid shader and upload
|
||||||
|
@ -1156,6 +1143,19 @@ void RendererGL::initUbershader(OpenGL::Program& program) {
|
||||||
glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3);
|
glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererGL::compileDisplayShader() {
|
||||||
|
auto gl_resources = cmrc::RendererGL::get_filesystem();
|
||||||
|
auto displayVertexShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.vert") : gl_resources.open("opengl_display.vert");
|
||||||
|
auto displayFragmentShaderSource = driverInfo.usingGLES ? gl_resources.open("opengl_es_display.frag") : gl_resources.open("opengl_display.frag");
|
||||||
|
|
||||||
|
OpenGL::Shader vertDisplay({displayVertexShaderSource.begin(), displayVertexShaderSource.size()}, OpenGL::Vertex);
|
||||||
|
OpenGL::Shader fragDisplay({displayFragmentShaderSource.begin(), displayFragmentShaderSource.size()}, OpenGL::Fragment);
|
||||||
|
displayProgram.create({vertDisplay, fragDisplay});
|
||||||
|
|
||||||
|
gl.useProgram(displayProgram);
|
||||||
|
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
||||||
|
}
|
||||||
|
|
||||||
void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) {
|
void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAcceleration* accel) {
|
||||||
u32 buffer = 0; // Vertex buffer index for non-fixed attributes
|
u32 buffer = 0; // Vertex buffer index for non-fixed attributes
|
||||||
u32 attrCount = 0;
|
u32 attrCount = 0;
|
||||||
|
@ -1250,4 +1250,20 @@ void RendererGL::accelerateVertexUpload(ShaderUnit& shaderUnit, PICA::DrawAccele
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererGL::setupGLES() {
|
||||||
|
driverInfo.usingGLES = true;
|
||||||
|
|
||||||
|
// OpenGL ES hardware is typically way too slow to use the ubershader (eg RPi, mobile phones, handhelds) or has other issues with it.
|
||||||
|
// So, display a warning and turn them off on OpenGL ES.
|
||||||
|
if (emulatorConfig->useUbershaders) {
|
||||||
|
emulatorConfig->useUbershaders = false;
|
||||||
|
Helpers::warn("Ubershaders enabled on OpenGL ES. This usually results in a worse experience, turning it off...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stub out logic operations so that calling them doesn't crash the emulator
|
||||||
|
if (!glLogicOp) {
|
||||||
|
glLogicOp = [](GLenum) {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -105,13 +105,18 @@ std::filesystem::path Emulator::getConfigPath() {
|
||||||
if constexpr (Helpers::isAndroid()) {
|
if constexpr (Helpers::isAndroid()) {
|
||||||
return getAndroidAppPath() / "config.toml";
|
return getAndroidAppPath() / "config.toml";
|
||||||
} else {
|
} else {
|
||||||
return std::filesystem::current_path() / "config.toml";
|
std::filesystem::path localPath = std::filesystem::current_path() / "config.toml";
|
||||||
|
|
||||||
|
if (std::filesystem::exists(localPath)) {
|
||||||
|
return localPath;
|
||||||
|
} else {
|
||||||
|
return getAppDataRoot() / "config.toml";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Emulator::step() {}
|
void Emulator::step() {}
|
||||||
void Emulator::render() {}
|
|
||||||
|
|
||||||
// Only resume if a ROM is properly loaded
|
// Only resume if a ROM is properly loaded
|
||||||
void Emulator::resume() {
|
void Emulator::resume() {
|
||||||
|
@ -468,4 +473,4 @@ void Emulator::reloadSettings() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
10
src/host_shaders/opengl_es_display.frag
Normal file
10
src/host_shaders/opengl_es_display.frag
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
in vec2 UV;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
void main() {
|
||||||
|
FragColor = texture(u_texture, UV);
|
||||||
|
}
|
25
src/host_shaders/opengl_es_display.vert
Normal file
25
src/host_shaders/opengl_es_display.vert
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
out vec2 UV;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
const vec4 positions[4] = vec4[](
|
||||||
|
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
|
||||||
|
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
|
||||||
|
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
|
||||||
|
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
|
||||||
|
);
|
||||||
|
|
||||||
|
// The 3DS displays both screens' framebuffer rotated 90 deg counter clockwise
|
||||||
|
// So we adjust our texcoords accordingly
|
||||||
|
const vec2 texcoords[4] = vec2[](
|
||||||
|
vec2(1.0, 1.0), // Top-right
|
||||||
|
vec2(1.0, 0.0), // Bottom-right
|
||||||
|
vec2(0.0, 1.0), // Top-left
|
||||||
|
vec2(0.0, 0.0) // Bottom-left
|
||||||
|
);
|
||||||
|
|
||||||
|
gl_Position = positions[gl_VertexID];
|
||||||
|
UV = texcoords[gl_VertexID];
|
||||||
|
}
|
|
@ -118,6 +118,7 @@ void HydraCore::resetContext() {
|
||||||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
||||||
Helpers::panic("OpenGL ES init failed");
|
Helpers::panic("OpenGL ES init failed");
|
||||||
}
|
}
|
||||||
|
emulator->getRenderer()->setupGLES();
|
||||||
#else
|
#else
|
||||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getProcAddress))) {
|
||||||
Helpers::panic("OpenGL init failed");
|
Helpers::panic("OpenGL init failed");
|
||||||
|
|
|
@ -78,6 +78,7 @@ AlberFunction(void, Initialize)(JNIEnv* env, jobject obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
__android_log_print(ANDROID_LOG_INFO, "AlberDriver", "OpenGL ES %d.%d", GLVersion.major, GLVersion.minor);
|
__android_log_print(ANDROID_LOG_INFO, "AlberDriver", "OpenGL ES %d.%d", GLVersion.major, GLVersion.minor);
|
||||||
|
emulator->getRenderer()->setupGLES();
|
||||||
emulator->initGraphicsContext(nullptr);
|
emulator->initGraphicsContext(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +154,6 @@ int AndroidUtils::openDocument(const char* path, const char* perms) {
|
||||||
|
|
||||||
jstring uri = env->NewStringUTF(path);
|
jstring uri = env->NewStringUTF(path);
|
||||||
jstring jmode = env->NewStringUTF(perms);
|
jstring jmode = env->NewStringUTF(perms);
|
||||||
|
|
||||||
jint result = env->CallStaticIntMethod(alberClass, alberClassOpenDocument, uri, jmode);
|
jint result = env->CallStaticIntMethod(alberClass, alberClassOpenDocument, uri, jmode);
|
||||||
|
|
||||||
env->DeleteLocalRef(uri);
|
env->DeleteLocalRef(uri);
|
||||||
|
|
|
@ -17,7 +17,8 @@ static retro_input_state_t inputStateCallback;
|
||||||
static retro_hw_render_callback hwRender;
|
static retro_hw_render_callback hwRender;
|
||||||
static std::filesystem::path savePath;
|
static std::filesystem::path savePath;
|
||||||
|
|
||||||
static bool screenTouched;
|
static bool screenTouched = false;
|
||||||
|
static bool usingGLES = false;
|
||||||
|
|
||||||
std::unique_ptr<Emulator> emulator;
|
std::unique_ptr<Emulator> emulator;
|
||||||
RendererGL* renderer;
|
RendererGL* renderer;
|
||||||
|
@ -35,15 +36,19 @@ static void* getGLProcAddress(const char* name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void videoResetContext() {
|
static void videoResetContext() {
|
||||||
#ifdef USING_GLES
|
if (usingGLES) {
|
||||||
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||||
Helpers::panic("OpenGL ES init failed");
|
Helpers::panic("OpenGL ES init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
emulator->getRenderer()->setupGLES();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
else {
|
||||||
Helpers::panic("OpenGL init failed");
|
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getGLProcAddress))) {
|
||||||
|
Helpers::panic("OpenGL init failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
emulator->initGraphicsContext(nullptr);
|
emulator->initGraphicsContext(nullptr);
|
||||||
}
|
}
|
||||||
|
@ -73,6 +78,7 @@ static bool setHWRender(retro_hw_context_type type) {
|
||||||
hwRender.version_minor = 1;
|
hwRender.version_minor = 1;
|
||||||
|
|
||||||
if (envCallback(RETRO_ENVIRONMENT_SET_HW_RENDER, &hwRender)) {
|
if (envCallback(RETRO_ENVIRONMENT_SET_HW_RENDER, &hwRender)) {
|
||||||
|
usingGLES = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -170,8 +176,9 @@ static void configInit() {
|
||||||
{"panda3ds_use_ubershader", EmulatorConfig::ubershaderDefault ? "Use ubershaders (No stutter, maybe slower); enabled|disabled"
|
{"panda3ds_use_ubershader", EmulatorConfig::ubershaderDefault ? "Use ubershaders (No stutter, maybe slower); enabled|disabled"
|
||||||
: "Use ubershaders (No stutter, maybe slower); disabled|enabled"},
|
: "Use ubershaders (No stutter, maybe slower); disabled|enabled"},
|
||||||
{"panda3ds_use_vsync", "Enable VSync; enabled|disabled"},
|
{"panda3ds_use_vsync", "Enable VSync; enabled|disabled"},
|
||||||
|
{"panda3ds_system_language", "System language; En|Fr|Es|De|It|Pt|Nl|Ru|Ja|Zh|Ko|Tw"},
|
||||||
{"panda3ds_dsp_emulation", "DSP emulation; HLE|LLE|Null"},
|
{"panda3ds_dsp_emulation", "DSP emulation; HLE|LLE|Null"},
|
||||||
{"panda3ds_use_audio", "Enable audio; disabled|enabled"},
|
{"panda3ds_use_audio", EmulatorConfig::audioEnabledDefault ? "Enable audio; enabled|disabled" : "Enable audio; disabled|enabled"},
|
||||||
{"panda3ds_audio_volume", "Audio volume; 100|0|10|20|40|60|80|90|100|120|140|150|180|200"},
|
{"panda3ds_audio_volume", "Audio volume; 100|0|10|20|40|60|80|90|100|120|140|150|180|200"},
|
||||||
{"panda3ds_mute_audio", "Mute audio; disabled|enabled"},
|
{"panda3ds_mute_audio", "Mute audio; disabled|enabled"},
|
||||||
{"panda3ds_enable_aac", "Enable AAC audio; enabled|disabled"},
|
{"panda3ds_enable_aac", "Enable AAC audio; enabled|disabled"},
|
||||||
|
@ -196,6 +203,8 @@ static void configUpdate() {
|
||||||
config.shaderJitEnabled = fetchVariableBool("panda3ds_use_shader_jit", EmulatorConfig::shaderJitDefault);
|
config.shaderJitEnabled = fetchVariableBool("panda3ds_use_shader_jit", EmulatorConfig::shaderJitDefault);
|
||||||
config.chargerPlugged = fetchVariableBool("panda3ds_use_charger", true);
|
config.chargerPlugged = fetchVariableBool("panda3ds_use_charger", true);
|
||||||
config.batteryPercentage = fetchVariableRange("panda3ds_battery_level", 5, 100);
|
config.batteryPercentage = fetchVariableRange("panda3ds_battery_level", 5, 100);
|
||||||
|
config.systemLanguage = EmulatorConfig::languageCodeFromString(fetchVariable("panda3ds_system_language", "en"));
|
||||||
|
|
||||||
config.dspType = Audio::DSPCore::typeFromString(fetchVariable("panda3ds_dsp_emulation", "null"));
|
config.dspType = Audio::DSPCore::typeFromString(fetchVariable("panda3ds_dsp_emulation", "null"));
|
||||||
config.audioEnabled = fetchVariableBool("panda3ds_use_audio", false);
|
config.audioEnabled = fetchVariableBool("panda3ds_use_audio", false);
|
||||||
config.aacEnabled = fetchVariableBool("panda3ds_enable_aac", true);
|
config.aacEnabled = fetchVariableBool("panda3ds_enable_aac", true);
|
||||||
|
|
|
@ -190,8 +190,18 @@ ConfigWindow::ConfigWindow(ConfigCallback configCallback, MainWindowCallback win
|
||||||
rendererType->addItem(tr("Vulkan"));
|
rendererType->addItem(tr("Vulkan"));
|
||||||
rendererType->setCurrentIndex(static_cast<int>(config.rendererType));
|
rendererType->setCurrentIndex(static_cast<int>(config.rendererType));
|
||||||
connect(rendererType, &QComboBox::currentIndexChanged, this, [&](int index) {
|
connect(rendererType, &QComboBox::currentIndexChanged, this, [&](int index) {
|
||||||
config.rendererType = static_cast<RendererType>(index);
|
auto type = static_cast<RendererType>(index);
|
||||||
updateConfig();
|
|
||||||
|
if (type == RendererType::Vulkan) {
|
||||||
|
QMessageBox messageBox(
|
||||||
|
QMessageBox::Icon::Critical, tr("Vulkan renderer unavailable"),
|
||||||
|
tr("Qt UI doesn't currently support Vulkan, try again at a later time")
|
||||||
|
);
|
||||||
|
messageBox.exec();
|
||||||
|
} else {
|
||||||
|
config.rendererType = type;
|
||||||
|
updateConfig();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
gpuLayout->addRow(tr("GPU renderer"), rendererType);
|
gpuLayout->addRow(tr("GPU renderer"), rendererType);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,5 @@ int main(int argc, char *argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
MainWindow window(&app);
|
MainWindow window(&app);
|
||||||
|
|
||||||
window.show();
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,13 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
||||||
// Enable drop events for loading ROMs
|
// Enable drop events for loading ROMs
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
resize(800, 240 * 4);
|
resize(800, 240 * 4);
|
||||||
|
show();
|
||||||
|
|
||||||
// We pass a callback to the screen widget that will be triggered every time we resize the screen
|
// We pass a callback to the screen widget that will be triggered every time we resize the screen
|
||||||
screen = new ScreenWidget([this](u32 width, u32 height) { handleScreenResize(width, height); }, this);
|
screen = new ScreenWidget([this](u32 width, u32 height) { handleScreenResize(width, height); }, this);
|
||||||
setCentralWidget(screen);
|
setCentralWidget(screen);
|
||||||
|
|
||||||
screen->show();
|
|
||||||
appRunning = true;
|
appRunning = true;
|
||||||
|
|
||||||
// Set our menu bar up
|
// Set our menu bar up
|
||||||
menuBar = new QMenuBar(nullptr);
|
menuBar = new QMenuBar(nullptr);
|
||||||
|
|
||||||
|
@ -140,6 +139,10 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
||||||
glContext->MakeCurrent();
|
glContext->MakeCurrent();
|
||||||
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
|
glContext->SetSwapInterval(emu->getConfig().vsyncEnabled ? 1 : 0);
|
||||||
|
|
||||||
|
if (glContext->IsGLES()) {
|
||||||
|
emu->getRenderer()->setupGLES();
|
||||||
|
}
|
||||||
|
|
||||||
emu->initGraphicsContext(glContext);
|
emu->initGraphicsContext(glContext);
|
||||||
} else if (usingVk) {
|
} else if (usingVk) {
|
||||||
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
|
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
|
||||||
|
@ -695,4 +698,4 @@ void MainWindow::setupControllerSensors(SDL_GameController* controller) {
|
||||||
if (haveAccelerometer) {
|
if (haveAccelerometer) {
|
||||||
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
|
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ ScreenWidget::ScreenWidget(ResizeCallback resizeCallback, QWidget* parent) : QWi
|
||||||
setAttribute(Qt::WA_KeyCompression, false);
|
setAttribute(Qt::WA_KeyCompression, false);
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
show();
|
||||||
|
|
||||||
if (!createGLContext()) {
|
if (!createGLContext()) {
|
||||||
Helpers::panic("Failed to create GL context for display");
|
Helpers::panic("Failed to create GL context for display");
|
||||||
|
@ -60,11 +61,12 @@ void ScreenWidget::resizeSurface(u32 width, u32 height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenWidget::createGLContext() {
|
bool ScreenWidget::createGLContext() {
|
||||||
// List of GL context versions we will try. Anything 4.1+ is good
|
// List of GL context versions we will try. Anything 4.1+ is good for desktop OpenGL, and 3.1+ for OpenGL ES
|
||||||
static constexpr std::array<GL::Context::Version, 6> versionsToTry = {
|
static constexpr std::array<GL::Context::Version, 8> versionsToTry = {
|
||||||
GL::Context::Version{GL::Context::Profile::Core, 4, 6}, GL::Context::Version{GL::Context::Profile::Core, 4, 5},
|
GL::Context::Version{GL::Context::Profile::Core, 4, 6}, GL::Context::Version{GL::Context::Profile::Core, 4, 5},
|
||||||
GL::Context::Version{GL::Context::Profile::Core, 4, 4}, GL::Context::Version{GL::Context::Profile::Core, 4, 3},
|
GL::Context::Version{GL::Context::Profile::Core, 4, 4}, GL::Context::Version{GL::Context::Profile::Core, 4, 3},
|
||||||
GL::Context::Version{GL::Context::Profile::Core, 4, 2}, GL::Context::Version{GL::Context::Profile::Core, 4, 1},
|
GL::Context::Version{GL::Context::Profile::Core, 4, 2}, GL::Context::Version{GL::Context::Profile::Core, 4, 1},
|
||||||
|
GL::Context::Version{GL::Context::Profile::ES, 3, 2}, GL::Context::Version{GL::Context::Profile::ES, 3, 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
||||||
|
@ -72,6 +74,10 @@ bool ScreenWidget::createGLContext() {
|
||||||
this->windowInfo = *windowInfo;
|
this->windowInfo = *windowInfo;
|
||||||
|
|
||||||
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
|
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
|
||||||
|
if (glContext == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
glContext->DoneCurrent();
|
glContext->DoneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +85,7 @@ bool ScreenWidget::createGLContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal ScreenWidget::devicePixelRatioFromScreen() const {
|
qreal ScreenWidget::devicePixelRatioFromScreen() const {
|
||||||
const QScreen* screenForRatio = window()->windowHandle()->screen();
|
const QScreen* screenForRatio = windowHandle()->screen();
|
||||||
if (!screenForRatio) {
|
if (!screenForRatio) {
|
||||||
screenForRatio = QGuiApplication::primaryScreen();
|
screenForRatio = QGuiApplication::primaryScreen();
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,11 +71,27 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
|
||||||
|
|
||||||
glContext = SDL_GL_CreateContext(window);
|
glContext = SDL_GL_CreateContext(window);
|
||||||
if (glContext == nullptr) {
|
if (glContext == nullptr) {
|
||||||
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
Helpers::warn("OpenGL context creation failed: %s\nTrying again with OpenGL ES.", SDL_GetError());
|
||||||
}
|
|
||||||
|
|
||||||
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
// Some low end devices (eg RPi, emulation handhelds) don't support desktop GL, but only OpenGL ES, so fall back to that if GL context
|
||||||
Helpers::panic("OpenGL init failed");
|
// creation failed
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||||
|
glContext = SDL_GL_CreateContext(window);
|
||||||
|
if (glContext == nullptr) {
|
||||||
|
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gladLoadGLES2Loader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||||
|
Helpers::panic("OpenGL init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
emu.getRenderer()->setupGLES();
|
||||||
|
} else {
|
||||||
|
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
||||||
|
Helpers::panic("OpenGL init failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SetSwapInterval(config.vsyncEnabled ? 1 : 0);
|
SDL_GL_SetSwapInterval(config.vsyncEnabled ? 1 : 0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue