qt: More error handling and tweaking to opengl 3 renderer
This commit is contained in:
@@ -172,7 +172,7 @@ OpenGLOptions::addShader(const QString &path)
|
||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % "\n#extension GL_ARB_shading_language_420pack : enable\n" % "\n#define VERTEX\n" % shader_text))
|
||||
throw_shader_error(tr("Error compiling vertex shader in file \"%1\""));
|
||||
|
||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % "\n#extension GL_ARB_shading_language_420pack : enable\n" "\n#define FRAGMENT\n" % shader_text))
|
||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % "\n#extension GL_ARB_shading_language_420pack : enable\n" % "\n#define FRAGMENT\n" % shader_text))
|
||||
throw_shader_error(tr("Error compiling fragment shader in file \"%1\""));
|
||||
|
||||
if (!shader->link())
|
||||
|
@@ -18,8 +18,8 @@
|
||||
#include <QMessageBox>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLTexture>
|
||||
#include <QStringBuilder>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QOpenGLTexture>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -44,18 +44,13 @@ OpenGLRenderer::OpenGLRenderer(QWidget *parent)
|
||||
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
format.setMajorVersion(3);
|
||||
format.setMinorVersion(0);
|
||||
format.setMinorVersion(2);
|
||||
|
||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
|
||||
setFormat(format);
|
||||
|
||||
context = new QOpenGLContext(this);
|
||||
|
||||
context->setFormat(format);
|
||||
|
||||
context->create();
|
||||
|
||||
parentWidget = parent;
|
||||
|
||||
source.setRect(0, 0, INIT_WIDTH, INIT_HEIGHT);
|
||||
@@ -108,21 +103,22 @@ OpenGLRenderer::event(QEvent *event)
|
||||
void
|
||||
OpenGLRenderer::initialize()
|
||||
{
|
||||
if (!context->makeCurrent(this)) {
|
||||
/* TODO: This could be done much better */
|
||||
QMessageBox::critical((QWidget *) qApp->findChild<QWindow *>(), tr("Error initializing OpenGL"), tr("Error setting OpenGL context. Falling back to software rendering."));
|
||||
context->doneCurrent();
|
||||
isFinalized = true;
|
||||
isInitialized = true;
|
||||
emit errorInitializing();
|
||||
return;
|
||||
}
|
||||
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."));
|
||||
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
setupExtensions();
|
||||
initializeExtensions();
|
||||
|
||||
setupBuffers();
|
||||
initializeBuffers();
|
||||
|
||||
/* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */
|
||||
const GLfloat surface[] = {
|
||||
@@ -160,12 +156,30 @@ OpenGLRenderer::initialize()
|
||||
glViewport(
|
||||
destination.x(),
|
||||
destination.y(),
|
||||
destination.width(),
|
||||
destination.height());
|
||||
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();
|
||||
|
||||
} 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<QWindow *>(), tr("Error initializing OpenGL"), e.what() % tr("\nFalling back to software rendering."));
|
||||
|
||||
context->doneCurrent();
|
||||
isFinalized = true;
|
||||
isInitialized = true;
|
||||
|
||||
emit errorInitializing();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -174,6 +188,8 @@ OpenGLRenderer::finalize()
|
||||
if (isFinalized)
|
||||
return;
|
||||
|
||||
renderTimer->stop();
|
||||
|
||||
context->makeCurrent(this);
|
||||
|
||||
if (hasBufferStorage)
|
||||
@@ -203,7 +219,7 @@ OpenGLRenderer::getOptions(QWidget *parent)
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLRenderer::setupExtensions()
|
||||
OpenGLRenderer::initializeExtensions()
|
||||
{
|
||||
#ifndef NO_BUFFER_STORAGE
|
||||
if (context->hasExtension("GL_ARB_buffer_storage")) {
|
||||
@@ -215,7 +231,7 @@ OpenGLRenderer::setupExtensions()
|
||||
}
|
||||
|
||||
void
|
||||
OpenGLRenderer::setupBuffers()
|
||||
OpenGLRenderer::initializeBuffers()
|
||||
{
|
||||
glGenBuffers(1, &unpackBufferID);
|
||||
|
||||
@@ -232,6 +248,9 @@ OpenGLRenderer::setupBuffers()
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
@@ -90,8 +91,8 @@ private:
|
||||
void *unpackBuffer = nullptr;
|
||||
|
||||
void initialize();
|
||||
void setupExtensions();
|
||||
void setupBuffers();
|
||||
void initializeExtensions();
|
||||
void initializeBuffers();
|
||||
void applyOptions();
|
||||
void applyShader(const OpenGLShaderPass &shader);
|
||||
bool notReady() const { return !isInitialized || isFinalized; }
|
||||
@@ -107,4 +108,12 @@ private slots:
|
||||
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
|
||||
|
@@ -272,6 +272,7 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
});
|
||||
connect(hw, &OpenGLRenderer::errorInitializing, [=]() {
|
||||
/* Renderer could initialize, fallback to software. */
|
||||
imagebufs = {};
|
||||
endblit();
|
||||
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
||||
});
|
||||
@@ -299,7 +300,7 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
void
|
||||
RendererStack::blit(int x, int y, int w, int h)
|
||||
{
|
||||
if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
|
||||
if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
|
||||
video_blit_complete();
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user