diff --git a/src/86box.c b/src/86box.c index 13167b1bd..24f6f0deb 100644 --- a/src/86box.c +++ b/src/86box.c @@ -172,7 +172,6 @@ int force_43 = 0; /* (C) video * int video_filter_method = 1; /* (C) video */ int video_vsync = 0; /* (C) video */ int video_framerate = -1; /* (C) video */ -char video_shader[512] = { '\0' }; /* (C) video */ bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */ int bugger_enabled = 0; /* (C) enable ISAbugger */ diff --git a/src/config.c b/src/config.c index 20981885a..5ad804df6 100644 --- a/src/config.c +++ b/src/config.c @@ -200,7 +200,6 @@ load_general(void) video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1); video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0); - strncpy(video_shader, ini_section_get_string(cat, "video_gl_shader", ""), sizeof(video_shader) - 1); window_remember = ini_section_get_int(cat, "window_remember", 0); if (window_remember) { @@ -1733,7 +1732,19 @@ load_gl3_shaders(void) if (shaders > MAX_USER_SHADERS) shaders = MAX_USER_SHADERS; - for (int i = 0; i < shaders; i++) { + if (shaders == 0) { + ini_section_t general = ini_find_section(config, "General"); + if (general) { + p = ini_section_get_string(general, "video_gl_shader", NULL); + if (p) { + strncpy(gl3_shader_file[0], p, 512); + ini_delete_var(config, general, "video_gl_shader"); + return; + } + } + } + + for (i = 0; i < shaders; i++) { temp[0] = 0; snprintf(temp, 512, "shader%d", i); p = ini_section_get_string(cat, temp, ""); @@ -2035,10 +2046,6 @@ save_general(void) ini_section_set_int(cat, "video_gl_vsync", video_vsync); else ini_section_delete_var(cat, "video_gl_vsync"); - if (strlen(video_shader) > 0) - ini_section_set_string(cat, "video_gl_shader", video_shader); - else - ini_section_delete_var(cat, "video_gl_shader"); if (do_auto_pause) ini_section_set_int(cat, "do_auto_pause", do_auto_pause); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 30905741c..768ca6267 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -126,7 +126,6 @@ extern int video_filter_method; /* (C) video */ extern int video_vsync; /* (C) video */ extern int video_framerate; /* (C) video */ extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */ -extern char video_shader[512]; /* (C) video */ extern int bugger_enabled; /* (C) enable ISAbugger */ extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ extern int postcard_enabled; /* (C) enable POST card */ diff --git a/src/include/86box/ini.h b/src/include/86box/ini.h index 3139f410e..bb250e697 100644 --- a/src/include/86box/ini.h +++ b/src/include/86box/ini.h @@ -92,36 +92,6 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name); extern void ini_rename_section(ini_section_t section, const char *name); extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section); -static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } -static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); - if (size == 0) - return res; - if (str != NULL) - strncpy(dst, str, size - 1); - else - dst[0] = 0; - return res; -} -static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = ini_get_int((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = (float)ini_get_double((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) { - int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); - *dst = !!ini_get_int((ini_t)config, "", name, defVal); - return res; -} -static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); } -static inline void wx_config_free(void *config) { ini_close(config); }; - #ifdef __cplusplus } #endif diff --git a/src/ini.c b/src/ini.c index 7a54d5396..503b17ae3 100644 --- a/src/ini.c +++ b/src/ini.c @@ -162,7 +162,6 @@ ini_has_entry(ini_section_t self, const char *name) { section_t *section = (section_t *) self; const entry_t *entry; - int value = 0; if (section == NULL) return 0; @@ -546,6 +545,7 @@ ini_write(ini_t ini, const char *fn) (void) fclose(fp); } +/* Wide-character version of "trim" */ wchar_t * trim_w(wchar_t *str) { @@ -609,7 +609,6 @@ ini_strip_quotes(ini_t ini) ent = (entry_t *) sec->entry_head.next; while (ent != NULL) { if (ent->name[0] != '\0') { - int i = 0; int trailing_hash = strcspn(ent->data, "#"); int trailing_quote; ent->wdata[trailing_hash] = 0; diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 574aae7b7..8137be98e 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -87,16 +87,9 @@ add_library(ui STATIC qt_softwarerenderer.hpp qt_hardwarerenderer.cpp qt_hardwarerenderer.hpp - qt_openglrenderer.cpp - qt_openglrenderer.hpp qt_openglrenderer_pcem.cpp qt_openglrenderer_pcem.hpp qt_glsl_parser.cpp - qt_opengloptions.cpp - qt_opengloptions.hpp - qt_opengloptionsdialog.cpp - qt_opengloptionsdialog.hpp - qt_opengloptionsdialog.ui qt_settings.cpp qt_settings.hpp @@ -197,7 +190,10 @@ add_library(ui STATIC qt_openglshadermanagerdialog.hpp qt_openglshadermanagerdialog.cpp qt_openglshadermanagerdialog.ui - qt_openglshaderconfig.hpp qt_openglshaderconfig.cpp qt_openglshaderconfig.ui + + qt_openglshaderconfig.hpp + qt_openglshaderconfig.cpp + qt_openglshaderconfig.ui ) if(RTMIDI) diff --git a/src/qt/qt_glsl_parser.cpp b/src/qt/qt_glsl_parser.cpp index 2a4c4ddd1..bf02014db 100644 --- a/src/qt/qt_glsl_parser.cpp +++ b/src/qt/qt_glsl_parser.cpp @@ -28,6 +28,43 @@ extern void endblit(); (a)[(n)-1] = 0; \ } while (0) + + +static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; } + +static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + char* str = ini_get_string((ini_t)config, "", name, (char*)defVal); + if (size == 0) + return res; + if (str != NULL) + strncpy(dst, str, size - 1); + else + dst[0] = 0; + return res; +} + +static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = ini_get_int((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = (float)ini_get_double((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) { + int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); + *dst = !!ini_get_int((ini_t)config, "", name, defVal); + return res; +} + +static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); } +static inline void wx_config_free(void *config) { ini_close(config); }; + static int endswith(const char *str, const char *ext) { int i; const char *p; diff --git a/src/qt/qt_opengloptions.cpp b/src/qt/qt_opengloptions.cpp deleted file mode 100644 index 58030b467..000000000 --- a/src/qt/qt_opengloptions.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * OpenGL renderer options for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include -#include - -#include - -#include "qt_opengloptions.hpp" - -extern "C" { -#include <86box/86box.h> -} - -/* Default vertex shader. */ -static const GLchar *vertex_shader = "\ -in vec2 VertexCoord;\n\ -in vec2 TexCoord;\n\ -out vec2 tex;\n\ -void main(){\n\ - gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\ - tex = TexCoord;\n\ -}\n"; - -/* Default fragment shader. */ -static const GLchar *fragment_shader = "\ -in vec2 tex;\n\ -uniform sampler2D texsampler;\n\ -out vec4 color;\n\ -void main() {\n\ - color = texture(texsampler, tex);\n\ -}\n"; - -OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion) - : QObject(parent) - , m_glslVersion(glslVersion) -{ - m_filter = video_filter_method == 0 - ? FilterType::Nearest - : FilterType::Linear; - - if (!loadConfig) - return; - - /* Initialize with config. */ - m_vsync = video_vsync != 0; - m_framerate = video_framerate; - - m_renderBehavior = video_framerate == -1 - ? RenderBehaviorType::SyncWithVideo - : RenderBehaviorType::TargetFramerate; - - QString shaderPath(video_shader); - - if (shaderPath.isEmpty()) { - addDefaultShader(); - } else { - try { - addShader(shaderPath); - } catch (const std::runtime_error &) { - /* Fallback to default shader */ - addDefaultShader(); - } - } -} - -void -OpenGLOptions::save() const -{ - video_vsync = m_vsync ? 1 : 0; - video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate; - video_filter_method = m_filter == FilterType::Nearest ? 0 : 1; - - /* TODO: multiple shaders */ - auto path = m_shaders.first().path().toLocal8Bit(); - - if (!path.isEmpty()) - qstrncpy(video_shader, path.constData(), sizeof(video_shader)); - else - video_shader[0] = '\0'; -} - -OpenGLOptions::FilterType -OpenGLOptions::filter() const -{ - /* Filter method is controlled externally */ - return video_filter_method == 0 - ? FilterType::Nearest - : FilterType::Linear; -} - -void -OpenGLOptions::setRenderBehavior(RenderBehaviorType value) -{ - m_renderBehavior = value; -} - -void -OpenGLOptions::setFrameRate(int value) -{ - m_framerate = value; -} - -void -OpenGLOptions::setVSync(bool value) -{ - m_vsync = value; -} - -void -OpenGLOptions::setFilter(FilterType value) -{ - m_filter = value; -} - -void -OpenGLOptions::addShader(const QString &path) -{ - QFile shader_file(path); - - if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) { - throw std::runtime_error( - QString(tr("Error opening \"%1\": %2")) - .arg(path) - .arg(shader_file.errorString()) - .toStdString()); - } - - auto shader_text = QString(shader_file.readAll()); - - shader_file.close(); - - /* Remove parameter lines */ - shader_text.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption)); - - QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption); - - auto match = version.match(shader_text); - - QString version_line(m_glslVersion); - - if (match.hasMatch()) { - /* Extract existing version and remove it. */ - version_line = match.captured(1); - shader_text.remove(version); - } - - auto shader = new QOpenGLShaderProgram(this); - - auto throw_shader_error = [path, shader](const QString &what) { - throw std::runtime_error( - QString(what % ":\n\n %2") - .arg(path) - .arg(shader->log()) - .toStdString()); - }; - - static const char *extension = "\n#extension GL_ARB_shading_language_420pack : enable\n"; - - if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % extension % "\n#define VERTEX\n#line 1\n" % shader_text)) - throw_shader_error(tr("Error compiling vertex shader in file \"%1\"")); - - if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % extension % "\n#define FRAGMENT\n#line 1\n" % shader_text)) - throw_shader_error(tr("Error compiling fragment shader in file \"%1\"")); - - if (!shader->link()) - throw_shader_error(tr("Error linking shader program in file \"%1\"")); - - m_shaders << OpenGLShaderPass(shader, path); -} - -void -OpenGLOptions::addDefaultShader() -{ - auto shader = new QOpenGLShaderProgram(this); - shader->addShaderFromSourceCode(QOpenGLShader::Vertex, m_glslVersion % "\n" % vertex_shader); - shader->addShaderFromSourceCode(QOpenGLShader::Fragment, m_glslVersion % "\n" % fragment_shader); - shader->link(); - m_shaders << OpenGLShaderPass(shader, QString()); -} diff --git a/src/qt/qt_opengloptions.hpp b/src/qt/qt_opengloptions.hpp deleted file mode 100644 index 64f761670..000000000 --- a/src/qt/qt_opengloptions.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header for OpenGL renderer options - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLOPTIONS_HPP -#define QT_OPENGLOPTIONS_HPP - -#include -#include -#include -#include - -class OpenGLShaderPass { -public: - OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path) - : m_shader(shader) - , m_path(path) - , m_vertex_coord(shader->attributeLocation("VertexCoord")) - , m_tex_coord(shader->attributeLocation("TexCoord")) - , m_color(shader->attributeLocation("Color")) - , m_mvp_matrix(shader->uniformLocation("MVPMatrix")) - , m_input_size(shader->uniformLocation("InputSize")) - , m_output_size(shader->uniformLocation("OutputSize")) - , m_texture_size(shader->uniformLocation("TextureSize")) - , m_frame_count(shader->uniformLocation("FrameCount")) - { - } - - bool bind() const { return m_shader->bind(); } - const QString &path() const { return m_path; } - const GLint &vertex_coord() const { return m_vertex_coord; } - const GLint &tex_coord() const { return m_tex_coord; } - const GLint &color() const { return m_color; } - const GLint &mvp_matrix() const { return m_mvp_matrix; } - const GLint &input_size() const { return m_input_size; } - const GLint &output_size() const { return m_output_size; } - const GLint &texture_size() const { return m_texture_size; } - const GLint &frame_count() const { return m_frame_count; } - -private: - QOpenGLShaderProgram *m_shader; - QString m_path; - GLint m_vertex_coord; - GLint m_tex_coord; - GLint m_color; - GLint m_mvp_matrix; - GLint m_input_size; - GLint m_output_size; - GLint m_texture_size; - GLint m_frame_count; -}; - -class OpenGLOptions : public QObject { - Q_OBJECT - -public: - enum RenderBehaviorType { SyncWithVideo, - TargetFramerate }; - - enum FilterType { Nearest, - Linear }; - - OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion); - - RenderBehaviorType renderBehavior() const { return m_renderBehavior; } - int framerate() const { return m_framerate; } - bool vSync() const { return m_vsync; } - FilterType filter() const; - - const QList &shaders() const { return m_shaders; } - - void setRenderBehavior(RenderBehaviorType value); - void setFrameRate(int value); - void setVSync(bool value); - void setFilter(FilterType value); - void addShader(const QString &path); - void addDefaultShader(); - void save() const; - -private: - RenderBehaviorType m_renderBehavior = SyncWithVideo; - int m_framerate = -1; - bool m_vsync = false; - FilterType m_filter = Nearest; - QList m_shaders; - QString m_glslVersion; -}; - -#endif diff --git a/src/qt/qt_opengloptionsdialog.cpp b/src/qt/qt_opengloptionsdialog.cpp deleted file mode 100644 index acb2ce9f2..000000000 --- a/src/qt/qt_opengloptionsdialog.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * OpenGL renderer options dialog for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include - -#include - -#include "qt_opengloptionsdialog.hpp" -#include "qt_util.hpp" -#include "ui_qt_opengloptionsdialog.h" - -OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory) - : QDialog(parent) - , ui(new Ui::OpenGLOptionsDialog) - , createOptions(optionsFactory) -{ - ui->setupUi(this); - - if (options.renderBehavior() == OpenGLOptions::SyncWithVideo) - ui->syncWithVideo->setChecked(true); - else { - ui->syncToFramerate->setChecked(true); - ui->targetFps->setValue(options.framerate()); - } - - ui->vsync->setChecked(options.vSync()); - - if (!options.shaders().isEmpty()) { - auto path = options.shaders().first().path(); - if (!path.isEmpty()) - ui->shader->setPlainText(path); - } -} - -OpenGLOptionsDialog::~OpenGLOptionsDialog() -{ - delete ui; -} - -void -OpenGLOptionsDialog::accept() -{ - auto options = createOptions(); - - options->setRenderBehavior( - ui->syncWithVideo->isChecked() - ? OpenGLOptions::SyncWithVideo - : OpenGLOptions::TargetFramerate); - - options->setFrameRate(ui->targetFps->value()); - - options->setVSync(ui->vsync->isChecked()); - - auto shader = ui->shader->toPlainText(); - - try { - - if (!shader.isEmpty()) - options->addShader(shader); - else - options->addDefaultShader(); - - } catch (const std::runtime_error &e) { - delete options; - - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Shader error")); - msgBox.setText(tr("Could not load shaders.")); - msgBox.setInformativeText(tr("More information in details.")); - msgBox.setDetailedText(e.what()); - msgBox.setIcon(QMessageBox::Critical); - msgBox.setStandardButtons(QMessageBox::Close); - msgBox.setDefaultButton(QMessageBox::Close); - msgBox.setStyleSheet("QTextEdit { min-width: 45em; }"); - msgBox.exec(); - - return; - } - - options->save(); - - emit optionsChanged(options); - - QDialog::accept(); -} - -void -OpenGLOptionsDialog::on_addShader_clicked() -{ - auto shader = QFileDialog::getOpenFileName( - this, - QString(), - QString(), - tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true)); - - if (shader.isNull()) - return; - - ui->shader->setPlainText(shader); -} diff --git a/src/qt/qt_opengloptionsdialog.hpp b/src/qt/qt_opengloptionsdialog.hpp deleted file mode 100644 index f34d74d75..000000000 --- a/src/qt/qt_opengloptionsdialog.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header for OpenGL renderer options dialog - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLOPTIONSDIALOG_H -#define QT_OPENGLOPTIONSDIALOG_H - -#include - -#include - -#include "qt_opengloptions.hpp" - -namespace Ui { -class OpenGLOptionsDialog; -} - -class OpenGLOptionsDialog : public QDialog { - Q_OBJECT - -public: - explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function optionsFactory); - ~OpenGLOptionsDialog(); - -signals: - void optionsChanged(OpenGLOptions *options); - -public slots: - void accept() override; - -private: - Ui::OpenGLOptionsDialog *ui; - - std::function createOptions; - -private slots: - void on_addShader_clicked(); -}; - -#endif // QT_OPENGLOPTIONSDIALOG_H diff --git a/src/qt/qt_opengloptionsdialog.ui b/src/qt/qt_opengloptionsdialog.ui deleted file mode 100644 index a6f86b6c2..000000000 --- a/src/qt/qt_opengloptionsdialog.ui +++ /dev/null @@ -1,280 +0,0 @@ - - - OpenGLOptionsDialog - - - - 0 - 0 - 400 - 320 - - - - OpenGL 3.0 renderer options - - - - - - Render behavior - - - - - - Use target framerate: - - - - - - - false - - - fps - - - 15 - - - 240 - - - 60 - - - - - - - VSync - - - - - - - <html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html> - - - Synchronize with video - - - true - - - - - - - false - - - 15 - - - 240 - - - 60 - - - Qt::Horizontal - - - false - - - QSlider::NoTicks - - - - - - - - - - Shaders - - - - - - Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - true - - - No shader selected - - - - - - - Browse... - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - syncWithVideo - syncToFramerate - fpsSlider - targetFps - vsync - shader - addShader - removeShader - - - - - buttonBox - accepted() - OpenGLOptionsDialog - accept() - - - 257 - 310 - - - 157 - 274 - - - - - buttonBox - rejected() - OpenGLOptionsDialog - reject() - - - 325 - 310 - - - 286 - 274 - - - - - syncToFramerate - toggled(bool) - targetFps - setEnabled(bool) - - - 140 - 71 - - - 380 - 98 - - - - - syncToFramerate - toggled(bool) - fpsSlider - setEnabled(bool) - - - 158 - 66 - - - 168 - 87 - - - - - fpsSlider - valueChanged(int) - targetFps - setValue(int) - - - 252 - 90 - - - 308 - 89 - - - - - targetFps - valueChanged(int) - fpsSlider - setValue(int) - - - 364 - 93 - - - 134 - 93 - - - - - removeShader - clicked() - shader - clear() - - - 333 - 201 - - - 235 - 208 - - - - - diff --git a/src/qt/qt_openglrenderer.cpp b/src/qt/qt_openglrenderer.cpp deleted file mode 100644 index 60aa998a9..000000000 --- a/src/qt/qt_openglrenderer.cpp +++ /dev/null @@ -1,468 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * OpenGL renderer for Qt - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "qt_opengloptionsdialog.hpp" -#include "qt_openglrenderer.hpp" - -#ifndef GL_MAP_PERSISTENT_BIT -# define GL_MAP_PERSISTENT_BIT 0x0040 -#endif - -#ifndef GL_MAP_COHERENT_BIT -# define GL_MAP_COHERENT_BIT 0x0080 -#endif - -OpenGLRenderer::OpenGLRenderer(QWidget *parent) - : QWindow(parent->windowHandle()) - , renderTimer(new QTimer(this)) - , options(nullptr) -{ - renderTimer->setTimerType(Qt::PreciseTimer); - /* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */ - connect(renderTimer, &QTimer::timeout, this, &OpenGLRenderer::render); - - buf_usage = std::vector(BUFFERCOUNT); - for (auto &flag : buf_usage) - flag.clear(); - - setSurfaceType(QWindow::OpenGLSurface); - - QSurfaceFormat format; - -#ifdef Q_OS_MACOS - format.setVersion(4, 1); -#else - format.setVersion(3, 2); -#endif - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) - format.setRenderableType(QSurfaceFormat::OpenGLES); - - setFormat(format); - - parentWidget = parent; - - source.setRect(0, 0, INIT_WIDTH, INIT_HEIGHT); -} - -OpenGLRenderer::~OpenGLRenderer() -{ - finalize(); -} - -void -OpenGLRenderer::exposeEvent(QExposeEvent *event) -{ - Q_UNUSED(event); - - if (!isInitialized) - initialize(); - - onResize(size().width(), size().height()); -} - -void -OpenGLRenderer::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - onResize(event->size().width(), event->size().height()); - - if (notReady()) - return; - - context->makeCurrent(this); - - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); -} - -bool -OpenGLRenderer::event(QEvent *event) -{ - Q_UNUSED(event); - - bool res = false; - if (!eventDelegate(event, res)) - return QWindow::event(event); - return res; -} - -void -OpenGLRenderer::initialize() -{ - try { - context = new QOpenGLContext(this); - - context->setFormat(format()); - - if (!context->create()) - throw opengl_init_error(tr("Couldn't create OpenGL context.")); - - if (!context->makeCurrent(this)) - throw opengl_init_error(tr("Couldn't switch to OpenGL context.")); - - auto version = context->format().version(); - - if (version.first < 3) - throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); - - initializeOpenGLFunctions(); - - /* Prepare the shader version string */ - glslVersion = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); - glslVersion.truncate(4); - glslVersion.remove('.'); - glslVersion.prepend("#version "); - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) - glslVersion.append(" es"); - else if (context->format().profile() == QSurfaceFormat::CoreProfile) - glslVersion.append(" core"); - - initializeExtensions(); - - initializeBuffers(); - - /* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */ - const GLfloat surface[] = { - -1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f, - 1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f, - -1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f, - 1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f - }; - - glGenVertexArrays(1, &vertexArrayID); - - glBindVertexArray(vertexArrayID); - - glGenBuffers(1, &vertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW); - - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - - const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f }; - - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - - glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - - reloadOptions(); - - glClearColor(0.f, 0.f, 0.f, 1.f); - - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); - - GLenum error = glGetError(); - if (error != GL_NO_ERROR) - throw opengl_init_error(tr("OpenGL initialization failed. Error %1.").arg(error)); - - isInitialized = true; - - emit initialized(); - - glClear(GL_COLOR_BUFFER_BIT); - - context->swapBuffers(this); - } catch (const opengl_init_error &e) { - /* Mark all buffers as in use */ - for (auto &flag : buf_usage) - flag.test_and_set(); - - QMessageBox::critical((QWidget *) qApp->findChild(), tr("Error initializing OpenGL"), e.what() % tr("\nFalling back to software rendering.")); - - context->doneCurrent(); - isFinalized = true; - isInitialized = true; - - emit errorInitializing(); - } -} - -void -OpenGLRenderer::finalize() -{ - if (isFinalized) - return; - - renderTimer->stop(); - - context->makeCurrent(this); - - if (hasBufferStorage) - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - - glDeleteBuffers(1, &unpackBufferID); - glDeleteTextures(1, &textureID); - glDeleteBuffers(1, &vertexBufferID); - glDeleteVertexArrays(1, &vertexArrayID); - - if (!hasBufferStorage && unpackBuffer) - free(unpackBuffer); - - context->doneCurrent(); - - isFinalized = true; -} - -QDialog * -OpenGLRenderer::getOptions(QWidget *parent) -{ - auto dialog = new OpenGLOptionsDialog(parent, *options, [this]() { return new OpenGLOptions(this, false, glslVersion); }); - - connect(dialog, &OpenGLOptionsDialog::optionsChanged, this, &OpenGLRenderer::updateOptions); - - return dialog; -} - -void -OpenGLRenderer::initializeExtensions() -{ -#ifndef NO_BUFFER_STORAGE - if (context->hasExtension("GL_ARB_buffer_storage") || context->hasExtension("GL_EXT_buffer_storage")) { - hasBufferStorage = true; - - glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress(context->hasExtension("GL_EXT_buffer_storage") ? "glBufferStorageEXT" : "glBufferStorage"); - if (!glBufferStorage) - glBufferStorage = (PFNGLBUFFERSTORAGEEXTPROC_LOCAL) context->getProcAddress("glBufferStorage"); - } -#endif -} - -void -OpenGLRenderer::initializeBuffers() -{ - glGenBuffers(1, &unpackBufferID); - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); - - if (hasBufferStorage) { -#ifndef NO_BUFFER_STORAGE - /* Create persistent buffer for pixel transfer. */ - glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); - - unpackBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); -#endif - } else { - /* Fallback; create our own buffer. */ - unpackBuffer = malloc(BUFFERBYTES * BUFFERCOUNT); - - if (unpackBuffer == nullptr) - throw opengl_init_error(tr("Allocating memory for unpack buffer failed.")); - - glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW); - } -} - -void -OpenGLRenderer::applyOptions() -{ - /* TODO: change detection in options */ - - if (options->framerate() > 0) { - int interval = (int) ceilf(1000.f / (float) options->framerate()); - renderTimer->setInterval(std::chrono::milliseconds(interval)); - } - - if (options->renderBehavior() == OpenGLOptions::TargetFramerate) - renderTimer->start(); - else - renderTimer->stop(); - - auto format = this->format(); - int interval = options->vSync() ? 1 : 0; - - if (format.swapInterval() != interval) { - format.setSwapInterval(interval); - setFormat(format); - context->setFormat(format); - } - - GLint filter = options->filter() == OpenGLOptions::Linear ? GL_LINEAR : GL_NEAREST; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - - currentFilter = options->filter(); -} - -void -OpenGLRenderer::reloadOptions() -{ - if (options) { - delete options; - options = nullptr; - } - options = new OpenGLOptions(this, true, glslVersion); - - applyOptions(); -} - -void -OpenGLRenderer::applyShader(const OpenGLShaderPass &shader) -{ - if (!shader.bind()) - return; - - if (shader.vertex_coord() != -1) { - glEnableVertexAttribArray(shader.vertex_coord()); - glVertexAttribPointer(shader.vertex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0); - } - - if (shader.tex_coord() != -1) { - glEnableVertexAttribArray(shader.tex_coord()); - glVertexAttribPointer(shader.tex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat))); - } - - if (shader.color() != -1) { - glEnableVertexAttribArray(shader.color()); - glVertexAttribPointer(shader.color(), 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat))); - } - - if (shader.mvp_matrix() != -1) { - static const GLfloat mvp[] = { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }; - glUniformMatrix4fv(shader.mvp_matrix(), 1, GL_FALSE, mvp); - } - - if (shader.output_size() != -1) - glUniform2f(shader.output_size(), destination.width(), destination.height()); - - if (shader.input_size() != -1) - glUniform2f(shader.input_size(), source.width(), source.height()); - - if (shader.texture_size() != -1) - glUniform2f(shader.texture_size(), source.width(), source.height()); - - if (shader.frame_count() != -1) - glUniform1i(shader.frame_count(), frameCounter); -} - -void -OpenGLRenderer::render() -{ - context->makeCurrent(this); - - if (options->filter() != currentFilter) - applyOptions(); - - /* TODO: multiple shader passes */ - applyShader(options->shaders().first()); - - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - context->swapBuffers(this); - - frameCounter = (frameCounter + 1) & 1023; -} - -void -OpenGLRenderer::updateOptions(OpenGLOptions *newOptions) -{ - context->makeCurrent(this); - - glUseProgram(0); - - delete options; - - options = newOptions; - - options->setParent(this); - - applyOptions(); -} - -std::vector> -OpenGLRenderer::getBuffers() -{ - std::vector> buffers; - - if (notReady() || !unpackBuffer) - return buffers; - - /* Split the buffer area */ - for (int i = 0; i < BUFFERCOUNT; i++) { - buffers.push_back(std::make_tuple((uint8_t *) unpackBuffer + BUFFERBYTES * i, &buf_usage[i])); - } - - return buffers; -} - -void -OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) -{ - if (notReady()) - return; - - context->makeCurrent(this); - -#ifdef Q_OS_MACOS - glViewport( - destination.x() * devicePixelRatio(), - destination.y() * devicePixelRatio(), - destination.width() * devicePixelRatio(), - destination.height() * devicePixelRatio()); -#endif - - if (source.width() != w || source.height() != h) { - source.setRect(0, 0, w, h); - - /* Resize the texture */ - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D(GL_TEXTURE_2D, 0, (GLenum) QOpenGLTexture::RGBA8_UNorm, source.width(), source.height(), 0, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID); - } - - if (!hasBufferStorage) - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * buf_idx, h * ROW_LENGTH * sizeof(uint32_t) + (y * ROW_LENGTH * sizeof(uint32_t)), (uint8_t *) unpackBuffer + BUFFERBYTES * buf_idx); - - glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * buf_idx + y * ROW_LENGTH + x); - glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, (GLenum) QOpenGLTexture::BGRA, (GLenum) QOpenGLTexture::UInt32_RGBA8_Rev, NULL); - - /* TODO: check if fence sync is implementable here and still has any benefit. */ - glFinish(); - - buf_usage[buf_idx].clear(); - - if (options->renderBehavior() == OpenGLOptions::SyncWithVideo) - render(); -} diff --git a/src/qt/qt_openglrenderer.hpp b/src/qt/qt_openglrenderer.hpp deleted file mode 100644 index 27822600c..000000000 --- a/src/qt/qt_openglrenderer.hpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Header file for OpenGL renderer - * - * - * - * Authors: Teemu Korhonen - * - * Copyright 2022 Teemu Korhonen - */ - -#ifndef QT_OPENGLRENDERER_HPP -#define QT_OPENGLRENDERER_HPP - -#if defined Q_OS_MACOS || __arm__ -# define NO_BUFFER_STORAGE -#endif - -#include -#include -#include -#include -#include -#include -#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) -# include -#endif - -#include -#include -#include -#include - -#include "qt_opengloptions.hpp" -#include "qt_renderercommon.hpp" - -typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags); - -class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon { - Q_OBJECT - -public: - QOpenGLContext *context; - - OpenGLRenderer(QWidget *parent = nullptr); - ~OpenGLRenderer(); - - std::vector> getBuffers() override; - - void finalize() override final; - bool hasOptions() const override { return true; } - QDialog *getOptions(QWidget *parent) override; - void reloadOptions() override; - -signals: - void initialized(); - void errorInitializing(); - -public slots: - void onBlit(int buf_idx, int x, int y, int w, int h); - -protected: - void exposeEvent(QExposeEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - bool event(QEvent *event) override; - -private: - static constexpr int INIT_WIDTH = 640; - static constexpr int INIT_HEIGHT = 400; - static constexpr int ROW_LENGTH = 2048; - static constexpr int BUFFERPIXELS = 4194304; - static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */ - static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */ - - QTimer *renderTimer; - OpenGLOptions *options; - - QString glslVersion; - - bool isInitialized = false; - bool isFinalized = false; - - GLuint unpackBufferID = 0; - GLuint vertexArrayID = 0; - GLuint vertexBufferID = 0; - GLuint textureID = 0; - int frameCounter = 0; - - OpenGLOptions::FilterType currentFilter; - - void *unpackBuffer = nullptr; - - void initialize(); - void initializeExtensions(); - void initializeBuffers(); - void applyOptions(); - void applyShader(const OpenGLShaderPass &shader); - bool notReady() const { return !isInitialized || isFinalized; } - - /* GL_ARB_buffer_storage */ - bool hasBufferStorage = false; -#ifndef NO_BUFFER_STORAGE - PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr; -#endif - -private slots: - void render(); - void updateOptions(OpenGLOptions *newOptions); -}; - -class opengl_init_error : public std::runtime_error { -public: - opengl_init_error(const QString &what) - : std::runtime_error(what.toStdString()) - { - } -}; - -#endif diff --git a/src/qt/qt_openglrenderer_pcem.cpp b/src/qt/qt_openglrenderer_pcem.cpp index 79960323f..5b1c8518d 100644 --- a/src/qt/qt_openglrenderer_pcem.cpp +++ b/src/qt/qt_openglrenderer_pcem.cpp @@ -1,3 +1,26 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * OpenGL renderer for Qt, mostly ported over from PCem. + * + * + * + * Authors: Teemu Korhonen + * Cacodemon345 + * bit + * Sarah Walker + * + * Copyright 2022 Teemu Korhonen + * Copyright 2025 Cacodemon345 + * Copyright 2017 Bit + * Copyright 2017-2020 Sarah Walker + */ + #include "qt_renderercommon.hpp" #include "qt_mainwindow.hpp" @@ -114,7 +137,7 @@ next_pow2(unsigned int n) } int -OpenGLRendererPCem::create_program(struct shader_program *program) +OpenGLRenderer::create_program(struct shader_program *program) { GLint status; program->id = glw.glCreateProgram(); @@ -146,7 +169,7 @@ OpenGLRendererPCem::create_program(struct shader_program *program) } int -OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) +OpenGLRenderer::compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst) { const char *source[3]; char version[50]; @@ -197,19 +220,19 @@ OpenGLRendererPCem::compile_shader(GLenum shader_type, const char *prepend, cons } GLuint -OpenGLRendererPCem::get_uniform(GLuint program, const char *name) +OpenGLRenderer::get_uniform(GLuint program, const char *name) { return glw.glGetUniformLocation(program, name); } GLuint -OpenGLRendererPCem::get_attrib(GLuint program, const char *name) +OpenGLRenderer::get_attrib(GLuint program, const char *name) { return glw.glGetAttribLocation(program, name); } void -OpenGLRendererPCem::find_uniforms(struct glsl_shader *glsl, int num_pass) +OpenGLRenderer::find_uniforms(struct glsl_shader *glsl, int num_pass) { int i; char s[50]; @@ -294,7 +317,7 @@ setup_scale(struct shader *shader, struct shader_pass *pass) } void -OpenGLRendererPCem::create_texture(struct shader_texture *tex) +OpenGLRenderer::create_texture(struct shader_texture *tex) { if (tex->width > max_texture_size) tex->width = max_texture_size; @@ -314,7 +337,7 @@ OpenGLRendererPCem::create_texture(struct shader_texture *tex) } void -OpenGLRendererPCem::delete_texture(struct shader_texture *tex) +OpenGLRenderer::delete_texture(struct shader_texture *tex) { if (tex->id > 0) glw.glDeleteTextures(1, (GLuint *) &tex->id); @@ -322,7 +345,7 @@ OpenGLRendererPCem::delete_texture(struct shader_texture *tex) } void -OpenGLRendererPCem::delete_fbo(struct shader_fbo *fbo) +OpenGLRenderer::delete_fbo(struct shader_fbo *fbo) { if (fbo->id >= 0) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -331,7 +354,7 @@ OpenGLRendererPCem::delete_fbo(struct shader_fbo *fbo) } void -OpenGLRendererPCem::delete_program(struct shader_program *program) +OpenGLRenderer::delete_program(struct shader_program *program) { if (program->vertex_shader) glw.glDeleteShader(program->vertex_shader); @@ -341,7 +364,7 @@ OpenGLRendererPCem::delete_program(struct shader_program *program) } void -OpenGLRendererPCem::delete_vbo(struct shader_vbo *vbo) +OpenGLRenderer::delete_vbo(struct shader_vbo *vbo) { if (vbo->color >= 0) glw.glDeleteBuffers(1, (GLuint *) &vbo->color); @@ -350,7 +373,7 @@ OpenGLRendererPCem::delete_vbo(struct shader_vbo *vbo) } void -OpenGLRendererPCem::delete_pass(struct shader_pass *pass) +OpenGLRenderer::delete_pass(struct shader_pass *pass) { delete_fbo(&pass->fbo); delete_vbo(&pass->vbo); @@ -359,14 +382,14 @@ OpenGLRendererPCem::delete_pass(struct shader_pass *pass) } void -OpenGLRendererPCem::delete_prev(struct shader_prev *prev) +OpenGLRenderer::delete_prev(struct shader_prev *prev) { delete_fbo(&prev->fbo); delete_vbo(&prev->vbo); } void -OpenGLRendererPCem::delete_shader(struct glsl_shader *glsl) +OpenGLRenderer::delete_shader(struct glsl_shader *glsl) { int i; for (i = 0; i < glsl->num_passes; ++i) @@ -381,7 +404,7 @@ OpenGLRendererPCem::delete_shader(struct glsl_shader *glsl) } void -OpenGLRendererPCem::delete_glsl(glsl_t *glsl) +OpenGLRenderer::delete_glsl(glsl_t *glsl) { int i; for (i = 0; i < glsl->num_shaders; ++i) @@ -395,7 +418,7 @@ OpenGLRendererPCem::delete_glsl(glsl_t *glsl) } void -OpenGLRendererPCem::create_fbo(struct shader_fbo *fbo) +OpenGLRenderer::create_fbo(struct shader_fbo *fbo) { create_texture(&fbo->texture); @@ -410,7 +433,7 @@ OpenGLRendererPCem::create_fbo(struct shader_fbo *fbo) } void -OpenGLRendererPCem::setup_fbo(struct shader *shader, struct shader_fbo *fbo) +OpenGLRenderer::setup_fbo(struct shader *shader, struct shader_fbo *fbo) { fbo->texture.internal_format = GL_RGBA8; fbo->texture.format = GL_RGBA; @@ -442,7 +465,7 @@ OpenGLRendererPCem::setup_fbo(struct shader *shader, struct shader_fbo *fbo) } void -OpenGLRendererPCem::recreate_fbo(struct shader_fbo *fbo, int width, int height) +OpenGLRenderer::recreate_fbo(struct shader_fbo *fbo, int width, int height) { if (width != fbo->texture.width || height != fbo->texture.height) { glw.glDeleteFramebuffers(1, (GLuint *) &fbo->id); @@ -454,7 +477,7 @@ OpenGLRendererPCem::recreate_fbo(struct shader_fbo *fbo, int width, int height) } int -OpenGLRendererPCem::create_default_shader_tex(struct shader_pass *pass) +OpenGLRenderer::create_default_shader_tex(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_tex_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_tex_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -474,7 +497,7 @@ OpenGLRendererPCem::create_default_shader_tex(struct shader_pass *pass) } int -OpenGLRendererPCem::create_default_shader_color(struct shader_pass *pass) +OpenGLRenderer::create_default_shader_color(struct shader_pass *pass) { if (!compile_shader(GL_VERTEX_SHADER, 0, vertex_shader_default_color_src, &pass->program.vertex_shader) || !compile_shader(GL_FRAGMENT_SHADER, 0, fragment_shader_default_color_src, &pass->program.fragment_shader) || !create_program(&pass->program)) return 0; @@ -494,7 +517,7 @@ OpenGLRendererPCem::create_default_shader_color(struct shader_pass *pass) /* create the default scene shader */ void -OpenGLRendererPCem::create_scene_shader() +OpenGLRenderer::create_scene_shader() { struct shader scene_shader_conf; memset(&scene_shader_conf, 0, sizeof(struct shader)); @@ -554,7 +577,7 @@ load_texture(const char *f, struct shader_texture *tex) } glsl_t * -OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) +OpenGLRenderer::load_glslp(glsl_t *glsl, int num_shader, const char *f) { int i, j; glslp_t *p = glslp_parse(f); @@ -704,7 +727,7 @@ OpenGLRendererPCem::load_glslp(glsl_t *glsl, int num_shader, const char *f) } glsl_t * -OpenGLRendererPCem::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) +OpenGLRenderer::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) { int i; glsl_t *glsl; @@ -731,7 +754,7 @@ OpenGLRendererPCem::load_shaders(int num, char shaders[MAX_USER_SHADERS][512]) } void -OpenGLRendererPCem::read_shader_config() +OpenGLRenderer::read_shader_config() { char s[512]; int i, j; @@ -747,10 +770,9 @@ OpenGLRendererPCem::read_shader_config() } } -OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) +OpenGLRenderer::OpenGLRenderer(QWidget *parent) : QWindow(parent->windowHandle()) , renderTimer(new QTimer(this)) - , options(nullptr) { connect(renderTimer, &QTimer::timeout, this, [this]() { this->render(); } ); imagebufs[0] = std::unique_ptr(new uint8_t[2048 * 2048 * 4]); @@ -785,10 +807,10 @@ OpenGLRendererPCem::OpenGLRendererPCem(QWidget *parent) isFinalized = false; } -OpenGLRendererPCem::~OpenGLRendererPCem() { finalize(); } +OpenGLRenderer::~OpenGLRenderer() { finalize(); } void -OpenGLRendererPCem::initialize() +OpenGLRenderer::initialize() { try { context = new QOpenGLContext(this); @@ -796,15 +818,15 @@ OpenGLRendererPCem::initialize() context->setFormat(format()); if (!context->create()) - throw opengl_init_error_pcem(tr("Couldn't create OpenGL context.")); + throw opengl_init_error(tr("Couldn't create OpenGL context.")); if (!context->makeCurrent(this)) - throw opengl_init_error_pcem(tr("Couldn't switch to OpenGL context.")); + throw opengl_init_error(tr("Couldn't switch to OpenGL context.")); auto version = context->format().version(); if (version.first < 3) - throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); + throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current version is %1.%2").arg(version.first).arg(version.second)); glw.initializeOpenGLFunctions(); @@ -813,7 +835,7 @@ OpenGLRendererPCem::initialize() glw.glGetIntegerv(GL_MAJOR_VERSION, &glsl_version[0]); glw.glGetIntegerv(GL_MINOR_VERSION, &glsl_version[1]); if (glsl_version[0] < 3) { - throw opengl_init_error_pcem(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); + throw opengl_init_error(tr("OpenGL version 3.0 or greater is required. Current GLSL version is %1.%2").arg(glsl_version[0]).arg(glsl_version[1])); } pclog("Using OpenGL %s\n", glw.glGetString(GL_VERSION)); pclog("Using Shading Language %s\n", glw.glGetString(GL_SHADING_LANGUAGE_VERSION)); @@ -1035,7 +1057,7 @@ OpenGLRendererPCem::initialize() glw.glClear(GL_COLOR_BUFFER_BIT); context->swapBuffers(this); - } catch (const opengl_init_error_pcem &e) { + } catch (const opengl_init_error &e) { /* Mark all buffers as in use */ for (auto &flag : buf_usage) flag.test_and_set(); @@ -1051,7 +1073,7 @@ OpenGLRendererPCem::initialize() } void -OpenGLRendererPCem::finalize() +OpenGLRenderer::finalize() { if (isFinalized) return; @@ -1074,7 +1096,7 @@ OpenGLRendererPCem::finalize() } void -OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) +OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h) { if (notReady()) return; @@ -1112,7 +1134,7 @@ OpenGLRendererPCem::onBlit(int buf_idx, int x, int y, int w, int h) } std::vector> -OpenGLRendererPCem::getBuffers() +OpenGLRenderer::getBuffers() { std::vector> buffers; @@ -1123,7 +1145,7 @@ OpenGLRendererPCem::getBuffers() } void -OpenGLRendererPCem::exposeEvent(QExposeEvent *event) +OpenGLRenderer::exposeEvent(QExposeEvent *event) { Q_UNUSED(event); @@ -1134,7 +1156,7 @@ OpenGLRendererPCem::exposeEvent(QExposeEvent *event) } void -OpenGLRendererPCem::resizeEvent(QResizeEvent *event) +OpenGLRenderer::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); @@ -1153,7 +1175,7 @@ OpenGLRendererPCem::resizeEvent(QResizeEvent *event) } void -OpenGLRendererPCem::render_pass(struct render_data *data) +OpenGLRenderer::render_pass(struct render_data *data) { int i; GLuint texture_unit = 0; @@ -1298,7 +1320,7 @@ OpenGLRendererPCem::render_pass(struct render_data *data) } bool -OpenGLRendererPCem::event(QEvent *event) +OpenGLRenderer::event(QEvent *event) { Q_UNUSED(event); @@ -1309,13 +1331,13 @@ OpenGLRendererPCem::event(QEvent *event) } QDialog* -OpenGLRendererPCem::getOptions(QWidget *parent) +OpenGLRenderer::getOptions(QWidget *parent) { return new OpenGLShaderManagerDialog(parent); } void -OpenGLRendererPCem::render() +OpenGLRenderer::render() { if (!context) return; @@ -1353,17 +1375,12 @@ OpenGLRendererPCem::render() struct { uint32_t x, y, w, h; - } rect, video_rect; + } rect; rect.x = 0; rect.y = 0; rect.w = source.width(); rect.h = source.height(); - video_rect.x = source.x(); - video_rect.y = source.y(); - video_rect.w = source.width(); - video_rect.h = source.height(); - pass->state.input_size[0] = pass->state.output_size[0] = rect.w; pass->state.input_size[1] = pass->state.output_size[1] = rect.h; diff --git a/src/qt/qt_openglrenderer_pcem.hpp b/src/qt/qt_openglrenderer_pcem.hpp index 706a744fa..9db1e7307 100644 --- a/src/qt/qt_openglrenderer_pcem.hpp +++ b/src/qt/qt_openglrenderer_pcem.hpp @@ -11,12 +11,14 @@ * * * Authors: Teemu Korhonen + * Cacodemon345 * * Copyright 2022 Teemu Korhonen + * Copyright 2025 Cacodemon345 */ -#ifndef QT_OpenGLRendererPCem_HPP -#define QT_OpenGLRendererPCem_HPP +#ifndef QT_OpenGLRenderer_HPP +#define QT_OpenGLRenderer_HPP #if defined Q_OS_MACOS || __arm__ # define NO_BUFFER_STORAGE @@ -37,7 +39,6 @@ #include #include -#include "qt_opengloptions.hpp" #include "qt_renderercommon.hpp" extern "C" @@ -55,14 +56,14 @@ struct render_data { int frame_count; }; -class OpenGLRendererPCem : public QWindow, public RendererCommon { +class OpenGLRenderer : public QWindow, public RendererCommon { Q_OBJECT public: QOpenGLContext *context; - OpenGLRendererPCem(QWidget *parent = nullptr); - ~OpenGLRendererPCem(); + OpenGLRenderer(QWidget *parent = nullptr); + ~OpenGLRenderer(); std::vector> getBuffers() override; @@ -88,7 +89,6 @@ private: std::array, 2> imagebufs; QTimer *renderTimer; - OpenGLOptions *options; QString glslVersion = ""; @@ -98,7 +98,6 @@ private: int max_texture_size = 65536; int frameCounter = 0; - OpenGLOptions::FilterType currentFilter; QOpenGLExtraFunctions glw; struct shader_texture scene_texture; glsl_t *active_shader; @@ -144,12 +143,11 @@ private: private slots: void render(); - //void updateOptions(OpenGLOptions *newOptions); }; -class opengl_init_error_pcem : public std::runtime_error { +class opengl_init_error : public std::runtime_error { public: - opengl_init_error_pcem(const QString &what) + opengl_init_error(const QString &what) : std::runtime_error(what.toStdString()) { } diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 63d35e719..26ea2271f 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -22,7 +22,6 @@ #include "ui_qt_rendererstack.h" #include "qt_hardwarerenderer.hpp" -#include "qt_openglrenderer.hpp" #include "qt_openglrenderer_pcem.hpp" #include "qt_softwarerenderer.hpp" #include "qt_vulkanwindowrenderer.hpp" @@ -341,16 +340,16 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::OpenGL3PCem: { this->createWinId(); - auto hw = new OpenGLRendererPCem(this); + auto hw = new OpenGLRenderer(this); rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRendererPCem::initialized, [=]() { + connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); + connect(hw, &OpenGLRenderer::initialized, [=]() { /* Buffers are available only after initialization. */ imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); }); - connect(hw, &OpenGLRendererPCem::errorInitializing, [=]() { + connect(hw, &OpenGLRenderer::errorInitializing, [=]() { /* Renderer not could initialize, fallback to software. */ imagebufs = {}; QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); }); @@ -361,16 +360,16 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::OpenGL3: { this->createWinId(); - auto hw = new OpenGLRendererPCem(this); + auto hw = new OpenGLRenderer(this); rendererWindow = hw; - connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection); - connect(hw, &OpenGLRendererPCem::initialized, [=]() { + connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection); + connect(hw, &OpenGLRenderer::initialized, [=]() { /* Buffers are available only after initialization. */ imagebufs = rendererWindow->getBuffers(); endblit(); emit rendererChanged(); }); - connect(hw, &OpenGLRendererPCem::errorInitializing, [=]() { + connect(hw, &OpenGLRenderer::errorInitializing, [=]() { /* Renderer not could initialize, fallback to software. */ imagebufs = {}; QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });