mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-17 19:21:30 +12:00
Add Qt screen widget
This commit is contained in:
parent
f98662e1bd
commit
b8032c8286
4 changed files with 143 additions and 10 deletions
|
@ -179,9 +179,14 @@ set(RENDERER_SW_SOURCE_FILES src/core/renderer_sw/renderer_sw.cpp)
|
||||||
|
|
||||||
# Frontend source files
|
# Frontend source files
|
||||||
if(ENABLE_QT_GUI)
|
if(ENABLE_QT_GUI)
|
||||||
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp)
|
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp)
|
||||||
|
set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp)
|
||||||
|
|
||||||
|
source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES})
|
||||||
|
source_group("Header Files\\Qt" FILES ${FRONTEND_HEADER_FILES})
|
||||||
else()
|
else()
|
||||||
set(FRONTEND_SOURCE_FILES src/panda_sdl/main.cpp)
|
set(FRONTEND_SOURCE_FILES src/panda_sdl/main.cpp)
|
||||||
|
set(FRONTEND_HEADER_FILES "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
|
set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
|
||||||
|
@ -353,7 +358,8 @@ endif()
|
||||||
|
|
||||||
source_group("Header Files\\Core" FILES ${HEADER_FILES})
|
source_group("Header Files\\Core" FILES ${HEADER_FILES})
|
||||||
set(ALL_SOURCES ${SOURCE_FILES} ${FRONTEND_SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES}
|
set(ALL_SOURCES ${SOURCE_FILES} ${FRONTEND_SOURCE_FILES} ${FS_SOURCE_FILES} ${CRYPTO_SOURCE_FILES} ${KERNEL_SOURCE_FILES}
|
||||||
${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES} ${APPLET_SOURCE_FILES} ${RENDERER_SW_SOURCE_FILES} ${PICA_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES} ${HEADER_FILES})
|
${LOADER_SOURCE_FILES} ${SERVICE_SOURCE_FILES} ${APPLET_SOURCE_FILES} ${RENDERER_SW_SOURCE_FILES} ${PICA_SOURCE_FILES} ${THIRD_PARTY_SOURCE_FILES}
|
||||||
|
${HEADER_FILES} ${FRONTEND_HEADER_FILES})
|
||||||
|
|
||||||
if(ENABLE_OPENGL)
|
if(ENABLE_OPENGL)
|
||||||
# Add the OpenGL source files to ALL_SOURCES
|
# Add the OpenGL source files to ALL_SOURCES
|
||||||
|
|
36
include/panda_qt/screen.hpp
Normal file
36
include/panda_qt/screen.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
#include <QWidget>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "gl/context.h"
|
||||||
|
#include "window_info.h"
|
||||||
|
|
||||||
|
// OpenGL widget for drawing the 3DS screen
|
||||||
|
class ScreenWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScreenWidget(QWidget* parent = nullptr) : QWidget(parent) {
|
||||||
|
// Create a native window for use with our graphics API of choice
|
||||||
|
setAutoFillBackground(false);
|
||||||
|
setAttribute(Qt::WA_NativeWindow, true);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||||
|
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||||
|
setAttribute(Qt::WA_KeyCompression, false);
|
||||||
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
setMouseTracking(true);
|
||||||
|
|
||||||
|
if (!createGLContext()) {
|
||||||
|
Helpers::panic("Failed to create GL context for display");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<GL::Context> glContext = nullptr;
|
||||||
|
bool createGLContext();
|
||||||
|
|
||||||
|
qreal devicePixelRatioFromScreen() const;
|
||||||
|
int scaledWindowWidth() const;
|
||||||
|
int scaledWindowHeight() const;
|
||||||
|
std::optional<WindowInfo> getWindowInfo();
|
||||||
|
};
|
|
@ -1,6 +1,8 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
|
|
||||||
|
#include "panda_qt/screen.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
QWidget window;
|
QWidget window;
|
||||||
|
@ -8,5 +10,8 @@ int main(int argc, char *argv[]) {
|
||||||
window.resize(320, 240);
|
window.resize(320, 240);
|
||||||
window.show();
|
window.show();
|
||||||
window.setWindowTitle("Alber");
|
window.setWindowTitle("Alber");
|
||||||
|
ScreenWidget screen(&window);
|
||||||
|
screen.show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
86
src/panda_qt/screen.cpp
Normal file
86
src/panda_qt/screen.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#include "panda_qt/screen.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
// OpenGL screen widget, based on https://github.com/melonDS-emu/melonDS/blob/master/src/frontend/qt_sdl/main.cpp
|
||||||
|
|
||||||
|
#ifdef PANDA3DS_ENABLE_OPENGL
|
||||||
|
bool ScreenWidget::createGLContext() {
|
||||||
|
// List of GL context versions we will try. Anything 4.1+ is good
|
||||||
|
static constexpr std::array<GL::Context::Version, 6> 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, 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},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<WindowInfo> windowInfo = getWindowInfo();
|
||||||
|
if (windowInfo.has_value()) {
|
||||||
|
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
|
||||||
|
glContext->DoneCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return glContext != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ScreenWidget::devicePixelRatioFromScreen() const {
|
||||||
|
const QScreen* screenForRatio = window()->windowHandle()->screen();
|
||||||
|
if (!screenForRatio) {
|
||||||
|
screenForRatio = QGuiApplication::primaryScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
return screenForRatio ? screenForRatio->devicePixelRatio() : static_cast<qreal>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScreenWidget::scaledWindowWidth() const {
|
||||||
|
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen())), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ScreenWidget::scaledWindowHeight() const {
|
||||||
|
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen())), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<WindowInfo> ScreenWidget::getWindowInfo() {
|
||||||
|
WindowInfo wi;
|
||||||
|
|
||||||
|
// Windows and Apple are easy here since there's no display connection.
|
||||||
|
#if defined(_WIN32)
|
||||||
|
wi.type = WindowInfo::Type::Win32;
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
wi.type = WindowInfo::Type::MacOS;
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
#else
|
||||||
|
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||||
|
const QString platform_name = QGuiApplication::platformName();
|
||||||
|
if (platform_name == QStringLiteral("xcb")) {
|
||||||
|
wi.type = WindowInfo::Type::X11;
|
||||||
|
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
|
||||||
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
||||||
|
} else if (platform_name == QStringLiteral("wayland")) {
|
||||||
|
wi.type = WindowInfo::Type::Wayland;
|
||||||
|
QWindow* handle = windowHandle();
|
||||||
|
if (handle == nullptr) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
wi.display_connection = pni->nativeResourceForWindow("display", handle);
|
||||||
|
wi.window_handle = pni->nativeResourceForWindow("surface", handle);
|
||||||
|
} else {
|
||||||
|
qCritical() << "Unknown PNI platform " << platform_name;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wi.surface_width = static_cast<u32>(scaledWindowWidth());
|
||||||
|
wi.surface_height = static_cast<u32>(scaledWindowHeight());
|
||||||
|
wi.surface_scale = static_cast<float>(devicePixelRatioFromScreen());
|
||||||
|
|
||||||
|
return wi;
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue