From 50390e9198ee2953e44ff2435b8c7627163bf990 Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Thu, 22 Feb 2024 19:06:19 +0500 Subject: [PATCH 1/6] Platform: Core: Replace GLEW with glad --- CMakeLists.txt | 2 +- src/platform/core/CMakeLists.txt | 16 ++++++++++++---- .../include/platform/device/ogl_video_device.hpp | 2 +- .../core/src/device/ogl_video_device.cpp | 2 -- src/platform/qt/src/widget/screen.cpp | 11 ++++++++--- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e26c039..98f4154f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.11...3.28) -project(NanoBoyAdvance LANGUAGES CXX) +project(NanoBoyAdvance LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/src/platform/core/CMakeLists.txt b/src/platform/core/CMakeLists.txt index 3a211153..2bc6d8c3 100644 --- a/src/platform/core/CMakeLists.txt +++ b/src/platform/core/CMakeLists.txt @@ -15,12 +15,21 @@ else() endif() find_package(OpenGL REQUIRED) -find_package(GLEW REQUIRED) + +include(FetchContent) +FetchContent_Declare(glad + GIT_REPOSITORY https://github.com/Dav1dde/glad.git + GIT_TAG adc3d7a1d704e099581ca25bc5bbdf728c2db67b # v2.0.5-2-gadc3d7a + SOURCE_SUBDIR cmake +) +FetchContent_MakeAvailable(glad) +glad_add_library(glad_gl_core_33 STATIC + LANGUAGE c REPRODUCIBLE API gl:core=3.3 EXTENSIONS NONE +) if(USE_SYSTEM_TOML11) find_package(toml11 3.7 REQUIRED) else() - include(FetchContent) FetchContent_Declare(toml11 GIT_REPOSITORY https://github.com/ToruNiina/toml11.git GIT_TAG dcfe39a783a94e8d52c885e5883a6fbb21529019 # v3.7.1 @@ -37,7 +46,6 @@ else() set(USE_SYSTEM_ZLIB OFF CACHE BOOL "" FORCE) set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) - include(FetchContent) FetchContent_Declare(unarr GIT_REPOSITORY https://github.com/selmf/unarr.git GIT_TAG b211040df83dee513362cdeb9bd87afa26fd5e38 # v1.1.1 @@ -104,5 +112,5 @@ endif() target_link_libraries(platform-core PRIVATE unarr::unarr - PUBLIC nba toml11::toml11 OpenGL::GL GLEW::GLEW + PUBLIC nba toml11::toml11 OpenGL::GL glad_gl_core_33 ) diff --git a/src/platform/core/include/platform/device/ogl_video_device.hpp b/src/platform/core/include/platform/device/ogl_video_device.hpp index 1b7f3d1b..ebcf1602 100644 --- a/src/platform/core/include/platform/device/ogl_video_device.hpp +++ b/src/platform/core/include/platform/device/ogl_video_device.hpp @@ -8,8 +8,8 @@ #pragma once #include +#include #include -#include #include #include #include diff --git a/src/platform/core/src/device/ogl_video_device.cpp b/src/platform/core/src/device/ogl_video_device.cpp index 3fb65e63..05e6dffa 100644 --- a/src/platform/core/src/device/ogl_video_device.cpp +++ b/src/platform/core/src/device/ogl_video_device.cpp @@ -47,8 +47,6 @@ OGLVideoDevice::~OGLVideoDevice() { } void OGLVideoDevice::Initialize() { - glewInit(); - // Create a fullscreen quad to render to the viewport. glGenVertexArrays(1, &quad_vao); glGenBuffers(1, &quad_vbo); diff --git a/src/platform/qt/src/widget/screen.cpp b/src/platform/qt/src/widget/screen.cpp index b8546474..cc827998 100644 --- a/src/platform/qt/src/widget/screen.cpp +++ b/src/platform/qt/src/widget/screen.cpp @@ -5,10 +5,11 @@ * Refer to the included LICENSE file. */ -#include - #include "widget/screen.hpp" +#include +#include // Has to go after glad. + Screen::Screen( QWidget* parent, std::shared_ptr config @@ -93,8 +94,12 @@ void Screen::UpdateViewport() { ogl_video_device.SetViewport(viewport_x, viewport_y, viewport_width, viewport_height); } +static auto get_proc_address(const char* proc_name) { + return QOpenGLContext::currentContext()->getProcAddress(proc_name); +} + void Screen::initializeGL() { - makeCurrent(); + gladLoadGL(get_proc_address); ogl_video_device.Initialize(); } From 0c037a06c6f93fa711253b01625a35d6321f6960 Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Sun, 10 Mar 2024 21:10:01 +0500 Subject: [PATCH 2/6] CI: Bump actions --- .github/workflows/build.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6a017a9a..9b7a9a6b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: msys2/setup-msys2@v2 with: install: make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-glew mingw-w64-x86_64-qt5-static @@ -31,7 +31,7 @@ jobs: mkdir upload cp -r build/bin/qt/{NanoBoyAdvance.exe,config.toml} upload - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: NanoBoyAdvance-win64 path: upload @@ -40,7 +40,7 @@ jobs: build-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies run: | sudo apt-get update -qq @@ -55,7 +55,7 @@ jobs: mkdir upload cp -r build/bin/qt/{NanoBoyAdvance,config.toml} upload - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: NanoBoyAdvance-linux path: upload @@ -64,7 +64,7 @@ jobs: build-macOS: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies env: HOMEBREW_NO_ANALYTICS: 1 @@ -94,7 +94,7 @@ jobs: -ov -format UDBZ \ NanoBoyAdvance.dmg - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: NanoBoyAdvance-${{ runner.os }}-x64 path: NanoBoyAdvance.dmg @@ -103,7 +103,7 @@ jobs: build-macOS-arm: runs-on: macos-14 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup dependencies env: HOMEBREW_NO_ANALYTICS: 1 @@ -133,7 +133,7 @@ jobs: -ov -format UDBZ \ NanoBoyAdvance.dmg - name: Upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: NanoBoyAdvance-${{ runner.os }}-arm64 path: NanoBoyAdvance.dmg From c2bf6defe62b5d5d70b5804b189d748461e603ae Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Tue, 27 Feb 2024 19:37:31 +0500 Subject: [PATCH 3/6] CI: Remove GLEW and add dependencies of glad --- .github/workflows/build.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b7a9a6b..17c739b7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v4 - uses: msys2/setup-msys2@v2 with: - install: make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-glew mingw-w64-x86_64-qt5-static + install: make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-python-jinja mingw-w64-x86_64-python-lxml mingw-w64-x86_64-SDL2 mingw-w64-x86_64-qt5-static - name: Build NanoBoyAdvance run: | cmake \ @@ -20,9 +20,9 @@ jobs: -G"Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_FLAGS="-s" \ + -DPython_EXECUTABLE="$(which python3)" \ -DPLATFORM_QT_STATIC=ON \ -DUSE_STATIC_SDL=ON \ - -DGLEW_USE_STATIC_LIBS=ON \ -DQT5_STATIC_DIR="/c/tools/msys64/mingw64/qt5-static" cd build make -j$NUMBER_OF_PROCESSORS @@ -44,7 +44,7 @@ jobs: - name: Setup dependencies run: | sudo apt-get update -qq - sudo apt-get install -y libsdl2-dev libglew-dev qtbase5-dev + sudo apt-get install -y python3-jinja2 python3-lxml libsdl2-dev qtbase5-dev - name: Build NanoBoyAdvance run: | cmake -Bbuild -DCMAKE_BUILD_TYPE=Release @@ -65,18 +65,22 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.x' - name: Setup dependencies env: HOMEBREW_NO_ANALYTICS: 1 - run: brew install sdl2 glew qt@5 + run: | + brew install sdl2 qt@5 + python3 -m pip install Jinja2 - name: Build NanoBoyAdvance run: | cmake -Bbuild \ -DCMAKE_CXX_FLAGS="-s" \ -DUSE_STATIC_SDL=ON \ - -DGLEW_USE_STATIC_LIBS=ON \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix glew)" \ + -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5)" \ -DMACOS_BUILD_APP_BUNDLE=ON \ -DMACOS_BUNDLE_QT=ON cd build @@ -104,18 +108,22 @@ jobs: runs-on: macos-14 steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.x' - name: Setup dependencies env: HOMEBREW_NO_ANALYTICS: 1 - run: brew install sdl2 glew qt@5 + run: | + brew install sdl2 qt@5 + python3 -m pip install Jinja2 - name: Build NanoBoyAdvance run: | cmake -Bbuild \ -DCMAKE_CXX_FLAGS="-s" \ -DUSE_STATIC_SDL=ON \ - -DGLEW_USE_STATIC_LIBS=ON \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix glew)" \ + -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5)" \ -DMACOS_BUILD_APP_BUNDLE=ON \ -DMACOS_BUNDLE_QT=ON cd build From 44523312e623d71fdd5335b4c10350aa0a1fd71b Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Sun, 10 Mar 2024 16:12:46 +0500 Subject: [PATCH 4/6] Docs: Update compiling instructions --- docs/COMPILING.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 36462cc5..2706d9b9 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -4,10 +4,10 @@ NanoBoyAdvance can be compiled on Windows, Linux, and macOS. - Clang or GCC with C++17 support - CMake 3.11 or higher +- Python modules Jinja and (optionally) lxml - OpenGL (usually provided by the operating system) -- SDL2 library -- GLEW library -- Qt5 library +- SDL 2 library +- Qt 5 library ### Source Code @@ -28,13 +28,13 @@ Here is a list of commands for popular distributions and macOS: ##### Arch Linux ```bash -pacman -S cmake sdl2 glew qt5-base +pacman -S cmake python-jinja python-lxml sdl2 qt5-base ``` ##### Ubuntu or other Debian-derived distribution ```bash -apt install cmake libsdl2-dev libglew-dev qtbase5-dev libqt5opengl5-dev +apt install cmake python3-jinja2 python3-lxml libsdl2-dev qtbase5-dev libqt5opengl5-dev ``` ##### macOS @@ -42,14 +42,15 @@ apt install cmake libsdl2-dev libglew-dev qtbase5-dev libqt5opengl5-dev Get [Brew](https://brew.sh/) and run: ``` bash -brew install cmake sdl2 glew qt@5 +brew install cmake python@3 sdl2 qt@5 +python3 -m pip install Jinja2 ``` ##### FreeBSD ```bash su -pkg install cmake git sdl2 glew qt5 qt5-opengl +pkg install cmake git py39-Jinja2 py39-lxml sdl2 qt5 qt5-opengl ``` #### 2. Setup CMake build directory @@ -67,7 +68,7 @@ NOTE: the location and name of the `build` directory is arbitrary. ``` cd /somewhere/on/your/system/NanoBoyAdvance -cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5);$(brew --prefix glew)" +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$(brew --prefix qt@5)" ``` NOTE: the location and name of the `build` directory is arbitrary. @@ -94,7 +95,7 @@ This guide uses [MSYS2](https://www.msys2.org/) to install Mingw-w64 and other d In your MSYS2 command line, run: ```bash -pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-glew mingw-w64-x86_64-qt5-static +pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-python-jinja mingw-w64-x86_64-python-lxml mingw-w64-x86_64-SDL2 mingw-w64-x86_64-qt5-static ``` #### 2. Setup CMake build directory From 64127069a5de9955a524811325f0578126b556c7 Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Mon, 26 Feb 2024 03:49:11 +0500 Subject: [PATCH 5/6] Qt: Replace QOpenGLWidget with QWidget --- .../core/src/device/ogl_video_device.cpp | 7 +- src/platform/qt/CMakeLists.txt | 4 +- src/platform/qt/src/widget/main_window.cpp | 22 ++--- src/platform/qt/src/widget/screen.cpp | 82 ++++++++++++------- src/platform/qt/src/widget/screen.hpp | 18 ++-- 5 files changed, 77 insertions(+), 56 deletions(-) diff --git a/src/platform/core/src/device/ogl_video_device.cpp b/src/platform/core/src/device/ogl_video_device.cpp index 05e6dffa..a4a68711 100644 --- a/src/platform/core/src/device/ogl_video_device.cpp +++ b/src/platform/core/src/device/ogl_video_device.cpp @@ -62,8 +62,7 @@ void OGLVideoDevice::Initialize() { glGenFramebuffers(1, &fbo); glGenTextures(textures.size(), textures.data()); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0, 0.0, 0.0, 1.0); ReloadConfig(); } @@ -352,14 +351,16 @@ void OGLVideoDevice::Draw(u32* buffer) { copy_area_y = view_y; copy_area_width = view_width; copy_area_height = view_height; + glBindFramebuffer(GL_READ_FRAMEBUFFER, default_fbo); + glReadBuffer(GL_BACK); } else { glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[output_index], 0); + glReadBuffer(GL_COLOR_ATTACHMENT0); } glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[history_index]); - glReadBuffer(GL_COLOR_ATTACHMENT0); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, copy_area_x, copy_area_y, copy_area_width, copy_area_height); } } diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 056419e4..a28a2833 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -47,8 +47,8 @@ option(USE_QT6 "Use Qt 6" OFF) option(PORTABLE_MODE "Portable Mode" ON) if(USE_QT6) - find_package(Qt6 COMPONENTS Core Gui Widgets OpenGL OpenGLWidgets REQUIRED) - set(QT_DEPS Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGL Qt6::OpenGLWidgets) + find_package(Qt6 COMPONENTS Core Gui Widgets OpenGL REQUIRED) + set(QT_DEPS Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGL) else() find_package(Qt5 COMPONENTS Core Gui Widgets OpenGL REQUIRED) set(QT_DEPS Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) diff --git a/src/platform/qt/src/widget/main_window.cpp b/src/platform/qt/src/widget/main_window.cpp index 9085f4b3..a13d9d92 100644 --- a/src/platform/qt/src/widget/main_window.cpp +++ b/src/platform/qt/src/widget/main_window.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "widget/main_window.hpp" @@ -40,10 +41,12 @@ MainWindow::MainWindow( setWindowTitle(base_window_title); setAcceptDrops(true); + config->Load(); + screen = std::make_shared(this, config); setCentralWidget(screen.get()); - - config->Load(); + screen->windowHandle()->create(); + screen->Initialize(); auto menu_bar = new QMenuBar(this); setMenuBar(menu_bar); @@ -694,10 +697,6 @@ void MainWindow::ApplyPauseState() { const bool window_inactive_and_should_pause = !isActiveWindow() && config->window.pause_emulator_when_inactive; const bool paused = pause_action->isChecked() || window_inactive_and_should_pause; - if(!paused) { - screen->SetForceClear(false); - } - emu_thread->SetPause(paused); config->audio_dev->SetPause(paused); } @@ -706,7 +705,9 @@ void MainWindow::Stop() { if(emu_thread->IsRunning()) { core = emu_thread->Stop(); config->audio_dev->Close(); - screen->SetForceClear(true); + + // Clear the screen. + screen->Draw(nullptr); // Clear the list of save state slots: game_loaded = false; @@ -832,13 +833,6 @@ void MainWindow::LoadROM(std::u16string const& path) { core->Reset(); emu_thread->Start(std::move(core)); - /** - * If the the emulator is paused we force-clear the screen to avoid - * presenting the last frame from before pausing, since that could be confusing. - * In the other case we explicitly disable force-clear, because it is currently enabled (due to the call to Stop() at the top). - */ - screen->SetForceClear(pause_action->isChecked()); - UpdateSolarSensorLevel(); UpdateMenuBarVisibility(); } diff --git a/src/platform/qt/src/widget/screen.cpp b/src/platform/qt/src/widget/screen.cpp index cc827998..867c3155 100644 --- a/src/platform/qt/src/widget/screen.cpp +++ b/src/platform/qt/src/widget/screen.cpp @@ -9,26 +9,42 @@ #include #include // Has to go after glad. +#include Screen::Screen( QWidget* parent, std::shared_ptr config -) : QOpenGLWidget(parent) +) : QWidget(parent) , ogl_video_device(config) , config(config) { connect(this, &Screen::RequestDraw, this, &Screen::OnRequestDraw); + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_OpaquePaintEvent); + setAttribute(Qt::WA_PaintOnScreen); + windowHandle()->setSurfaceType(QWindow::OpenGLSurface); } -void Screen::Draw(u32* buffer) { - emit RequestDraw(buffer); +static auto get_proc_address(const char* proc_name) { + return QOpenGLContext::currentContext()->getProcAddress(proc_name); } -void Screen::SetForceClear(bool force_clear) { - this->force_clear = force_clear; - update(); +void Screen::Initialize() { + context = new QOpenGLContext(); + context->create(); + context->makeCurrent(this->windowHandle()); + + gladLoadGL(get_proc_address); + ogl_video_device.Initialize(); + + context->doneCurrent(); +} + +void Screen::Draw(u32* buffer) { + emit RequestDraw(buffer); } void Screen::ReloadConfig() { + context->makeCurrent(this->windowHandle()); ogl_video_device.ReloadConfig(); UpdateViewport(); } @@ -38,7 +54,36 @@ void Screen::OnRequestDraw(u32* buffer) { update(); } +void Screen::paintEvent([[maybe_unused]] QPaintEvent* event) { + Render(); +} + +void Screen::resizeEvent([[maybe_unused]] QResizeEvent* event) { + UpdateViewport(); +} + +void Screen::Render() { + if(!context) { + return; + } + + context->makeCurrent(this->windowHandle()); + glClear(GL_COLOR_BUFFER_BIT); + + if(buffer) { + ogl_video_device.SetDefaultFBO(context->defaultFramebufferObject()); + ogl_video_device.Draw(buffer); + } + + context->swapBuffers(this->windowHandle()); + context->doneCurrent(); +} + void Screen::UpdateViewport() { + if(!context) { + return; + } + auto dpr = devicePixelRatio(); int width = size().width() * dpr; int height = size().height() * dpr; @@ -91,28 +136,7 @@ void Screen::UpdateViewport() { viewport_x = (width - viewport_width ) / 2; viewport_y = (height - viewport_height) / 2; + context->makeCurrent(this->windowHandle()); ogl_video_device.SetViewport(viewport_x, viewport_y, viewport_width, viewport_height); -} - -static auto get_proc_address(const char* proc_name) { - return QOpenGLContext::currentContext()->getProcAddress(proc_name); -} - -void Screen::initializeGL() { - gladLoadGL(get_proc_address); - ogl_video_device.Initialize(); -} - -void Screen::paintGL() { - if(force_clear) { - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - } else if(buffer != nullptr) { - ogl_video_device.SetDefaultFBO(defaultFramebufferObject()); - ogl_video_device.Draw(buffer); - } -} - -void Screen::resizeGL(int width, int height) { - UpdateViewport(); + context->doneCurrent(); } diff --git a/src/platform/qt/src/widget/screen.hpp b/src/platform/qt/src/widget/screen.hpp index 02c50ac5..ed16feaa 100644 --- a/src/platform/qt/src/widget/screen.hpp +++ b/src/platform/qt/src/widget/screen.hpp @@ -8,19 +8,21 @@ #pragma once #include -#include +#include +#include #include "config.hpp" -struct Screen : QOpenGLWidget, nba::VideoDevice { - Screen( +struct Screen : QWidget, nba::VideoDevice { + explicit Screen( QWidget* parent, std::shared_ptr config ); + void Initialize(); void Draw(u32* buffer) final; - void SetForceClear(bool force_clear); void ReloadConfig(); + QPaintEngine* paintEngine() const override { return nullptr; }; // Silence Qt. signals: void RequestDraw(u32* buffer); @@ -29,19 +31,19 @@ private slots: void OnRequestDraw(u32* buffer); protected: - void initializeGL() override; - void paintGL() override; - void resizeGL(int width, int height) override; + void paintEvent(QPaintEvent* event) override; + void resizeEvent(QResizeEvent* event) override; private: static constexpr int kGBANativeWidth = 240; static constexpr int kGBANativeHeight = 160; static constexpr float kGBANativeAR = static_cast(kGBANativeWidth) / static_cast(kGBANativeHeight); + void Render(); void UpdateViewport(); u32* buffer = nullptr; - bool force_clear = false; + QOpenGLContext* context = nullptr; nba::OGLVideoDevice ogl_video_device; std::shared_ptr config; From 0fb4517a398c8667319b0440225e01cc51c46bf9 Mon Sep 17 00:00:00 2001 From: GranMinigun <11149380+GranMinigun@users.noreply.github.com> Date: Thu, 14 Mar 2024 18:52:58 +0500 Subject: [PATCH 6/6] Qt: Check version of created OpenGL context --- src/platform/qt/src/main.cpp | 6 +++++ src/platform/qt/src/widget/main_window.cpp | 15 +++++++++-- src/platform/qt/src/widget/main_window.hpp | 1 + src/platform/qt/src/widget/screen.cpp | 31 +++++++++++++++++++--- src/platform/qt/src/widget/screen.hpp | 2 +- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/platform/qt/src/main.cpp b/src/platform/qt/src/main.cpp index 9a4a6b96..e85cc979 100644 --- a/src/platform/qt/src/main.cpp +++ b/src/platform/qt/src/main.cpp @@ -48,6 +48,9 @@ auto create_window(QApplication& app, int argc, char** argv) -> std::unique_ptr< } auto window = std::make_unique(&app); + if(!window->Initialize()) { + return nullptr; + } if(!rom.empty()) { window->LoadROM(rom.u16string()); @@ -104,6 +107,9 @@ int main(int argc, char** argv) { QGuiApplication::setDesktopFileName("io.github.nba_emuNanoBoyAdvance"); auto window = create_window(app, argc, argv); + if(!window) { + return EXIT_FAILURE; + } return app.exec(); } diff --git a/src/platform/qt/src/widget/main_window.cpp b/src/platform/qt/src/widget/main_window.cpp index a13d9d92..222e3c17 100644 --- a/src/platform/qt/src/widget/main_window.cpp +++ b/src/platform/qt/src/widget/main_window.cpp @@ -45,8 +45,6 @@ MainWindow::MainWindow( screen = std::make_shared(this, config); setCentralWidget(screen.get()); - screen->windowHandle()->create(); - screen->Initialize(); auto menu_bar = new QMenuBar(this); setMenuBar(menu_bar); @@ -93,6 +91,19 @@ MainWindow::~MainWindow() { delete controller_manager; } +bool MainWindow::Initialize() { + screen->windowHandle()->create(); + if(!screen->Initialize()) { + QMessageBox::critical(this, QApplication::instance()->applicationName(), + tr("Failed to initialize graphics subsystem.\n\n" + "Make sure that your hardware supports OpenGL 3.3 or later, " + "and you have the latest driver version installed.")); + return false; + } + + return true; +} + void MainWindow::CreateFileMenu() { auto file_menu = menuBar()->addMenu(tr("File")); diff --git a/src/platform/qt/src/widget/main_window.hpp b/src/platform/qt/src/widget/main_window.hpp index a5ddead8..32c0be86 100644 --- a/src/platform/qt/src/widget/main_window.hpp +++ b/src/platform/qt/src/widget/main_window.hpp @@ -39,6 +39,7 @@ struct MainWindow : QMainWindow { ~MainWindow(); + bool Initialize(); void LoadROM(std::u16string const& path); signals: diff --git a/src/platform/qt/src/widget/screen.cpp b/src/platform/qt/src/widget/screen.cpp index 867c3155..8c5a8b45 100644 --- a/src/platform/qt/src/widget/screen.cpp +++ b/src/platform/qt/src/widget/screen.cpp @@ -28,15 +28,38 @@ static auto get_proc_address(const char* proc_name) { return QOpenGLContext::currentContext()->getProcAddress(proc_name); } -void Screen::Initialize() { +bool Screen::Initialize() { context = new QOpenGLContext(); - context->create(); - context->makeCurrent(this->windowHandle()); + if(!context->create()) { + delete context; + context = nullptr; + return false; + } + if(context->format().majorVersion() < 3 || + context->format().majorVersion() == 3 && context->format().minorVersion() < 3) { + delete context; + context = nullptr; + return false; + } + + if(!context->makeCurrent(this->windowHandle())) { + delete context; + context = nullptr; + return false; + } + + if(!gladLoadGL(get_proc_address)) { + delete context; + context = nullptr; + return false; + } - gladLoadGL(get_proc_address); ogl_video_device.Initialize(); + UpdateViewport(); context->doneCurrent(); + + return true; } void Screen::Draw(u32* buffer) { diff --git a/src/platform/qt/src/widget/screen.hpp b/src/platform/qt/src/widget/screen.hpp index ed16feaa..b69bfb74 100644 --- a/src/platform/qt/src/widget/screen.hpp +++ b/src/platform/qt/src/widget/screen.hpp @@ -19,7 +19,7 @@ struct Screen : QWidget, nba::VideoDevice { std::shared_ptr config ); - void Initialize(); + bool Initialize(); void Draw(u32* buffer) final; void ReloadConfig(); QPaintEngine* paintEngine() const override { return nullptr; }; // Silence Qt.