diff --git a/src/qt/qt.c b/src/qt/qt.c index 7bbc91036..7207a67e2 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -79,6 +79,8 @@ plat_vidapi(char* api) { return 1; } else if (!strcasecmp(api, "qt_opengles")) { return 2; + } else if (!strcasecmp(api, "qt_opengl3")) { + return 3; } return 0; @@ -97,6 +99,9 @@ char* plat_vidapi_name(int api) { case 2: name = "qt_opengles"; break; + case 3: + name = "qt_opengl3"; + break; default: fatal("Unknown renderer: %i\n", api); break; diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index 64dcbdd50..ac0acb8b5 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -27,16 +27,36 @@ void HardwareRenderer::initializeGL() m_blt->create(); QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this); const char *vsrc = - "attribute highp vec4 vertex;\n" - "attribute mediump vec4 texCoord;\n" + "attribute highp vec4 VertexCoord;\n" + "attribute mediump vec4 TexCoord;\n" "varying mediump vec4 texc;\n" - "uniform mediump mat4 matrix;\n" + "uniform mediump mat4 MVPMatrix;\n" "void main(void)\n" "{\n" - " gl_Position = matrix * vertex;\n" - " texc = texCoord;\n" + " gl_Position = MVPMatrix * VertexCoord;\n" + " texc = TexCoord;\n" "}\n"; - vshader->compileSourceCode(vsrc); + QString vsrccore = + "in highp vec4 VertexCoord;\n" + "in mediump vec4 TexCoord;\n" + "out mediump vec4 texc;\n" + "uniform mediump mat4 MVPMatrix;\n" + "void main(void)\n" + "{\n" + " gl_Position = MVPMatrix * VertexCoord;\n" + " texc = TexCoord;\n" + "}\n"; + if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) + { + vsrccore.prepend("#version 300 es\n"); + vshader->compileSourceCode(vsrccore); + } + else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) + { + vsrccore.prepend("#version 130\n"); + vshader->compileSourceCode(vsrccore); + } + else vshader->compileSourceCode(vsrc); QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this); const char *fsrc = @@ -46,18 +66,47 @@ void HardwareRenderer::initializeGL() "{\n" " gl_FragColor = texture2D(texture, texc.st).bgra;\n" "}\n"; - fshader->compileSourceCode(fsrc); + QString fsrccore = + "uniform sampler2D texture;\n" + "in mediump vec4 texc;\n" + "out highp vec4 FragColor;\n" + "void main(void)\n" + "{\n" + " FragColor = texture2D(texture, texc.st).bgra;\n" + "}\n"; + if (m_context->isOpenGLES() && m_context->format().version() >= qMakePair(3, 0)) + { + fsrccore.prepend("#version 300 es\n"); + fshader->compileSourceCode(fsrccore); + } + else if (m_context->format().version() >= qMakePair(3, 0) && m_context->format().profile() == QSurfaceFormat::CoreProfile) + { + fsrccore.prepend("#version 130\n"); + fshader->compileSourceCode(fsrccore); + } + else fshader->compileSourceCode(fsrc); m_prog = new QOpenGLShaderProgram; m_prog->addShader(vshader); m_prog->addShader(fshader); - m_prog->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE); - m_prog->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE); + m_prog->bindAttributeLocation("VertexCoord", PROGRAM_VERTEX_ATTRIBUTE); + m_prog->bindAttributeLocation("TexCoord", PROGRAM_TEXCOORD_ATTRIBUTE); m_prog->link(); m_prog->bind(); m_prog->setUniformValue("texture", 0); + if (m_context->format().version() >= qMakePair(3, 0) && m_vao.create()) { + m_vao.bind(); + } + + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].create(); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].allocate(sizeof(QVector2D) * 4); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].create(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].allocate(sizeof(QVector2D) * 4); + pclog("OpenGL vendor: %s\n", glGetString(GL_VENDOR)); pclog("OpenGL renderer: %s\n", glGetString(GL_RENDERER)); pclog("OpenGL version: %s\n", glGetString(GL_VERSION)); @@ -78,12 +127,15 @@ void HardwareRenderer::paintGL() { texcoords.push_back(QVector2D((float)source.x() / 2048.f, (float)(source.y() + source.height()) / 2048.f)); texcoords.push_back(QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y() + source.height()) / 2048.f)); texcoords.push_back(QVector2D((float)(source.x() + source.width()) / 2048.f, (float)(source.y()) / 2048.f)); + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].write(0, verts.data(), sizeof(QVector2D) * 4); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].write(0, texcoords.data(), sizeof(QVector2D) * 4); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); - m_prog->setUniformValue("matrix", mat); + m_prog->setUniformValue("MVPMatrix", mat); m_prog->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); m_prog->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); - m_prog->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, verts.data()); - m_prog->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, texcoords.data()); + + m_vbo[PROGRAM_VERTEX_ATTRIBUTE].bind(); m_prog->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2, 0); m_vbo[PROGRAM_VERTEX_ATTRIBUTE].release(); + m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].bind(); m_prog->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 0, 2, 0); m_vbo[PROGRAM_TEXCOORD_ATTRIBUTE].release(); m_texture->bind(); m_texture->setMinMagFilters(video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest, video_filter_method ? QOpenGLTexture::Linear : QOpenGLTexture::Nearest); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -92,6 +144,9 @@ void HardwareRenderer::paintGL() { void HardwareRenderer::setRenderType(RenderType type) { QSurfaceFormat format; switch (type) { + case RenderType::OpenGL3: + format.setVersion(3, 0); + format.setProfile(QSurfaceFormat::CoreProfile); case RenderType::OpenGL: format.setRenderableType(QSurfaceFormat::OpenGL); break; @@ -107,6 +162,12 @@ void HardwareRenderer::onBlit(const std::unique_ptr* img, int x, int y, auto tval = this; void* nuldata = 0; if (memcmp(&tval, &nuldata, sizeof(void*)) == 0) return; + if (!m_texture || !img || !img->get() || (m_texture && !m_texture->isCreated())) + { + in_use->clear(); + source.setRect(x, y, w, h); + return; + } m_context->makeCurrent(this); m_texture->setData(QOpenGLTexture::PixelFormat::RGBA, QOpenGLTexture::PixelType::UInt8, (const void*)img->get()); in_use->clear(); diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index 296306f15..6e2103071 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include +#include #include #include #include @@ -29,13 +31,16 @@ private: bool wayland = false; QWidget* parentWidget{nullptr}; QOpenGLContext* m_context; - QOpenGLTexture* m_texture; - QOpenGLShaderProgram* m_prog; - QOpenGLTextureBlitter* m_blt; + QOpenGLTexture* m_texture{nullptr}; + QOpenGLShaderProgram* m_prog{nullptr}; + QOpenGLTextureBlitter* m_blt{nullptr}; + QOpenGLBuffer m_vbo[2]; + QOpenGLVertexArrayObject m_vao; public: enum class RenderType { OpenGL, OpenGLES, + OpenGL3, }; void resizeGL(int w, int h) override; void initializeGL() override; @@ -56,6 +61,11 @@ public: { m_context->makeCurrent(this); if (m_blt) m_blt->destroy(); + m_prog->release(); + delete m_prog; + m_prog = nullptr; + m_context->doneCurrent(); + delete m_context; } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 49394a06b..00128c187 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -4,6 +4,9 @@ #include "qt_specifydimensions.h" #include "qt_soundgain.hpp" +#include "qt_rendererstack.hpp" +#include "qt_renderercomon.hpp" + extern "C" { #include <86box/86box.h> #include <86box/config.h> @@ -36,6 +39,9 @@ extern "C" { #include "qt_mediamenu.hpp" #ifdef __unix__ +#ifdef WAYLAND +#include "wl_mouse.hpp" +#endif #include #include #undef KeyPress @@ -163,11 +169,16 @@ MainWindow::MainWindow(QWidget *parent) : ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES); ui->actionHardware_Renderer_OpenGL_ES->setChecked(true); break; + case 3: + ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3); + ui->actionOpenGL_3_0_Core->setChecked(true); + break; } actGroup = new QActionGroup(this); actGroup->addAction(ui->actionSoftware_Renderer); actGroup->addAction(ui->actionHardware_Renderer_OpenGL); actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES); + actGroup->addAction(ui->actionOpenGL_3_0_Core); switch (scale) { case 0: ui->action0_5x->setChecked(true); @@ -1028,6 +1039,7 @@ void MainWindow::on_actionSoftware_Renderer_triggered() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); ui->actionHardware_Renderer_OpenGL->setChecked(false); ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); + ui->actionOpenGL_3_0_Core->setChecked(false); vid_api = 0; } @@ -1035,6 +1047,7 @@ void MainWindow::on_actionHardware_Renderer_OpenGL_triggered() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL); ui->actionSoftware_Renderer->setChecked(false); ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); + ui->actionOpenGL_3_0_Core->setChecked(false); vid_api = 1; } @@ -1042,6 +1055,7 @@ void MainWindow::on_actionHardware_Renderer_OpenGL_ES_triggered() { ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES); ui->actionSoftware_Renderer->setChecked(false); ui->actionHardware_Renderer_OpenGL->setChecked(false); + ui->actionOpenGL_3_0_Core->setChecked(false); vid_api = 2; } @@ -1343,3 +1357,13 @@ void MainWindow::setSendKeyboardInput(bool enabled) { send_keyboard_input = enabled; } + +void MainWindow::on_actionOpenGL_3_0_Core_triggered() +{ + ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3); + ui->actionSoftware_Renderer->setChecked(false); + ui->actionHardware_Renderer_OpenGL->setChecked(false); + ui->actionHardware_Renderer_OpenGL_ES->setChecked(false); + ui->actionOpenGL_3_0_Core->setChecked(true); + vid_api = 3; +} diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 126ecaccd..559352df3 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -99,6 +99,8 @@ private slots: void on_actionSound_gain_triggered(); + void on_actionOpenGL_3_0_Core_triggered(); + protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 35471ddc3..6eff44fc6 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -37,7 +37,7 @@ 0 - + @@ -47,7 +47,7 @@ 0 0 724 - 19 + 22 @@ -87,6 +87,7 @@ + @@ -511,19 +512,16 @@ Sound gain... + + + true + + + OpenGL 3.0 Core + + - - HardwareRenderer - QOpenGLWidget -
qt_hardwarerenderer.hpp
-
- - SoftwareRenderer - QWidget -
qt_softwarerenderer.hpp
- 1 -
RendererStack QStackedWidget diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index bdbf3529c..d165c007b 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -196,6 +196,14 @@ void RendererStack::switchRenderer(Renderer renderer) { current.reset(this->createWindowContainer(hw, this)); break; } + case Renderer::OpenGL3: + { + this->createWinId(); + auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGL3); + connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection); + current.reset(this->createWindowContainer(hw, this)); + break; + } } current->setFocusPolicy(Qt::NoFocus); current->setFocusProxy(this); diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index a512fb7e1..5edd40f08 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -39,6 +39,7 @@ public: Software, OpenGL, OpenGLES, + OpenGL3 }; void switchRenderer(Renderer renderer);