mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
3e973bc4c6
It allows us to use texture views and it reduces the overhead within the GPU driver. But it disallows us to reallocate the texture, but we don't do so anyways. In the end, it is the new way to allocate textures, so there is no need to use the old way.
246 lines
8.1 KiB
C++
246 lines
8.1 KiB
C++
// Copyright 2016 Citra Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <string>
|
|
#define SDL_MAIN_HANDLED
|
|
#include <SDL.h>
|
|
#include <fmt/format.h>
|
|
#include <glad/glad.h>
|
|
#include "common/logging/log.h"
|
|
#include "common/scm_rev.h"
|
|
#include "common/string_util.h"
|
|
#include "core/settings.h"
|
|
#include "input_common/keyboard.h"
|
|
#include "input_common/main.h"
|
|
#include "input_common/motion_emu.h"
|
|
#include "input_common/sdl/sdl.h"
|
|
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
|
|
|
|
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
|
|
TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
|
|
InputCommon::GetMotionEmu()->Tilt(x, y);
|
|
}
|
|
|
|
void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
|
|
if (button == SDL_BUTTON_LEFT) {
|
|
if (state == SDL_PRESSED) {
|
|
TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0));
|
|
} else {
|
|
TouchReleased();
|
|
}
|
|
} else if (button == SDL_BUTTON_RIGHT) {
|
|
if (state == SDL_PRESSED) {
|
|
InputCommon::GetMotionEmu()->BeginTilt(x, y);
|
|
} else {
|
|
InputCommon::GetMotionEmu()->EndTilt();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
|
|
if (state == SDL_PRESSED) {
|
|
InputCommon::GetKeyboard()->PressKey(key);
|
|
} else if (state == SDL_RELEASED) {
|
|
InputCommon::GetKeyboard()->ReleaseKey(key);
|
|
}
|
|
}
|
|
|
|
bool EmuWindow_SDL2::IsOpen() const {
|
|
return is_open;
|
|
}
|
|
|
|
void EmuWindow_SDL2::OnResize() {
|
|
int width, height;
|
|
SDL_GetWindowSize(render_window, &width, &height);
|
|
UpdateCurrentFramebufferLayout(width, height);
|
|
}
|
|
|
|
void EmuWindow_SDL2::Fullscreen() {
|
|
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN) == 0) {
|
|
return;
|
|
}
|
|
|
|
LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError());
|
|
|
|
// Try a different fullscreening method
|
|
LOG_INFO(Frontend, "Attempting to use borderless fullscreen...");
|
|
if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) {
|
|
return;
|
|
}
|
|
|
|
LOG_ERROR(Frontend, "Borderless fullscreening failed: {}", SDL_GetError());
|
|
|
|
// Fallback algorithm: Maximise window.
|
|
// Works on all systems (unless something is seriously wrong), so no fallback for this one.
|
|
LOG_INFO(Frontend, "Falling back on a maximised window...");
|
|
SDL_MaximizeWindow(render_window);
|
|
}
|
|
|
|
bool EmuWindow_SDL2::SupportsRequiredGLExtensions() {
|
|
std::vector<std::string> unsupported_ext;
|
|
|
|
if (!GLAD_GL_ARB_program_interface_query)
|
|
unsupported_ext.push_back("ARB_program_interface_query");
|
|
if (!GLAD_GL_ARB_separate_shader_objects)
|
|
unsupported_ext.push_back("ARB_separate_shader_objects");
|
|
if (!GLAD_GL_ARB_vertex_attrib_binding)
|
|
unsupported_ext.push_back("ARB_vertex_attrib_binding");
|
|
if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
|
|
unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev");
|
|
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
|
|
unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
|
|
if (!GLAD_GL_ARB_base_instance)
|
|
unsupported_ext.push_back("ARB_base_instance");
|
|
if (!GLAD_GL_ARB_texture_storage)
|
|
unsupported_ext.push_back("ARB_texture_storage");
|
|
|
|
// Extensions required to support some texture formats.
|
|
if (!GLAD_GL_EXT_texture_compression_s3tc)
|
|
unsupported_ext.push_back("EXT_texture_compression_s3tc");
|
|
if (!GLAD_GL_ARB_texture_compression_rgtc)
|
|
unsupported_ext.push_back("ARB_texture_compression_rgtc");
|
|
if (!GLAD_GL_ARB_texture_compression_bptc)
|
|
unsupported_ext.push_back("ARB_texture_compression_bptc");
|
|
if (!GLAD_GL_ARB_depth_buffer_float)
|
|
unsupported_ext.push_back("ARB_depth_buffer_float");
|
|
|
|
for (const std::string& ext : unsupported_ext)
|
|
LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext);
|
|
|
|
return unsupported_ext.empty();
|
|
}
|
|
|
|
EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
|
|
InputCommon::Init();
|
|
|
|
SDL_SetMainReady();
|
|
|
|
// Initialize the window
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
|
LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
|
|
exit(1);
|
|
}
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
|
|
|
|
std::string window_title = fmt::format("yuzu {} | {}-{}", Common::g_build_fullname,
|
|
Common::g_scm_branch, Common::g_scm_desc);
|
|
render_window =
|
|
SDL_CreateWindow(window_title.c_str(),
|
|
SDL_WINDOWPOS_UNDEFINED, // x position
|
|
SDL_WINDOWPOS_UNDEFINED, // y position
|
|
Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height,
|
|
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
|
|
|
if (render_window == nullptr) {
|
|
LOG_CRITICAL(Frontend, "Failed to create SDL2 window! {}", SDL_GetError());
|
|
exit(1);
|
|
}
|
|
|
|
if (fullscreen) {
|
|
Fullscreen();
|
|
}
|
|
|
|
gl_context = SDL_GL_CreateContext(render_window);
|
|
|
|
if (gl_context == nullptr) {
|
|
LOG_CRITICAL(Frontend, "Failed to create SDL2 GL context! {}", SDL_GetError());
|
|
exit(1);
|
|
}
|
|
|
|
if (!gladLoadGLLoader(static_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
|
|
LOG_CRITICAL(Frontend, "Failed to initialize GL functions! {}", SDL_GetError());
|
|
exit(1);
|
|
}
|
|
|
|
if (!SupportsRequiredGLExtensions()) {
|
|
LOG_CRITICAL(Frontend, "GPU does not support all required OpenGL extensions! Exiting...");
|
|
exit(1);
|
|
}
|
|
|
|
OnResize();
|
|
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
|
|
SDL_PumpEvents();
|
|
SDL_GL_SetSwapInterval(false);
|
|
LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch,
|
|
Common::g_scm_desc);
|
|
|
|
DoneCurrent();
|
|
}
|
|
|
|
EmuWindow_SDL2::~EmuWindow_SDL2() {
|
|
InputCommon::SDL::CloseSDLJoysticks();
|
|
SDL_GL_DeleteContext(gl_context);
|
|
SDL_Quit();
|
|
|
|
InputCommon::Shutdown();
|
|
}
|
|
|
|
void EmuWindow_SDL2::SwapBuffers() {
|
|
SDL_GL_SwapWindow(render_window);
|
|
}
|
|
|
|
void EmuWindow_SDL2::PollEvents() {
|
|
SDL_Event event;
|
|
|
|
// SDL_PollEvent returns 0 when there are no more events in the event queue
|
|
while (SDL_PollEvent(&event)) {
|
|
switch (event.type) {
|
|
case SDL_WINDOWEVENT:
|
|
switch (event.window.event) {
|
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
case SDL_WINDOWEVENT_RESIZED:
|
|
case SDL_WINDOWEVENT_MAXIMIZED:
|
|
case SDL_WINDOWEVENT_RESTORED:
|
|
case SDL_WINDOWEVENT_MINIMIZED:
|
|
OnResize();
|
|
break;
|
|
case SDL_WINDOWEVENT_CLOSE:
|
|
is_open = false;
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_KEYDOWN:
|
|
case SDL_KEYUP:
|
|
OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
OnMouseMotion(event.motion.x, event.motion.y);
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
case SDL_MOUSEBUTTONUP:
|
|
OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y);
|
|
break;
|
|
case SDL_QUIT:
|
|
is_open = false;
|
|
break;
|
|
default:
|
|
InputCommon::SDL::HandleGameControllerEvent(event);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EmuWindow_SDL2::MakeCurrent() {
|
|
SDL_GL_MakeCurrent(render_window, gl_context);
|
|
}
|
|
|
|
void EmuWindow_SDL2::DoneCurrent() {
|
|
SDL_GL_MakeCurrent(render_window, nullptr);
|
|
}
|
|
|
|
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(
|
|
const std::pair<unsigned, unsigned>& minimal_size) {
|
|
|
|
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
|
|
}
|