Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt: Replace QOpenGLWidget with QWidget #366

Merged
merged 6 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ 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
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 \
-Bbuild \
-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
Expand All @@ -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
Expand All @@ -40,11 +40,11 @@ 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
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
Expand All @@ -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
Expand All @@ -64,19 +64,23 @@ jobs:
build-macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- 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
Expand All @@ -94,7 +98,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
Expand All @@ -103,19 +107,23 @@ jobs:
build-macOS-arm:
runs-on: macos-14
steps:
- uses: actions/checkout@v3
- 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
Expand All @@ -133,7 +141,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
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
19 changes: 10 additions & 9 deletions docs/COMPILING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -28,28 +28,29 @@ 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

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
Expand All @@ -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.
Expand All @@ -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
Expand Down
16 changes: 12 additions & 4 deletions src/platform/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#pragma once

#include <array>
#include <glad/gl.h>
#include <nba/device/video_device.hpp>
#include <GL/glew.h>
#include <platform/config.hpp>
#include <string>
#include <utility>
Expand Down
9 changes: 4 additions & 5 deletions src/platform/core/src/device/ogl_video_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -64,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();
}
Expand Down Expand Up @@ -354,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);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/platform/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/platform/qt/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ auto create_window(QApplication& app, int argc, char** argv) -> std::unique_ptr<
}

auto window = std::make_unique<MainWindow>(&app);
if(!window->Initialize()) {
return nullptr;
}

if(!rom.empty()) {
window->LoadROM(rom.u16string());
Expand Down Expand Up @@ -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();
}
33 changes: 19 additions & 14 deletions src/platform/qt/src/widget/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <QKeyEvent>
#include <QLocale>
#include <QStatusBar>
#include <QWindow>
#include <unordered_map>

#include "widget/main_window.hpp"
Expand All @@ -40,11 +41,11 @@ MainWindow::MainWindow(
setWindowTitle(base_window_title);
setAcceptDrops(true);

config->Load();

screen = std::make_shared<Screen>(this, config);
setCentralWidget(screen.get());

config->Load();

auto menu_bar = new QMenuBar(this);
setMenuBar(menu_bar);

Expand Down Expand Up @@ -90,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"));

Expand Down Expand Up @@ -694,10 +708,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);
}
Expand All @@ -706,7 +716,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;
Expand Down Expand Up @@ -832,13 +844,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();
}
Expand Down
Loading