mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 15:43:17 +02:00
Moving to custom context creation
This commit is contained in:
parent
c3e345150b
commit
617633b85c
31 changed files with 803 additions and 296 deletions
|
@ -778,8 +778,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
|
||||
// enable mouse tracking; otherwise, we only get drag events
|
||||
_glWidget->setMouseTracking(true);
|
||||
// Make sure the window is set to the correct size by processing the pending events
|
||||
QCoreApplication::processEvents();
|
||||
_glWidget->createContext();
|
||||
_glWidget->makeCurrent();
|
||||
_glWidget->initializeGL();
|
||||
|
||||
initializeGL();
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
|
@ -1484,7 +1486,7 @@ void Application::initializeGL() {
|
|||
_glWidget->makeCurrent();
|
||||
_chromiumShareContext = new OffscreenGLCanvas();
|
||||
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
||||
_chromiumShareContext->create(_glWidget->context()->contextHandle());
|
||||
_chromiumShareContext->create(_glWidget->qglContext());
|
||||
_chromiumShareContext->makeCurrent();
|
||||
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
||||
|
||||
|
@ -1531,7 +1533,7 @@ void Application::initializeGL() {
|
|||
|
||||
_offscreenContext = new OffscreenGLCanvas();
|
||||
_offscreenContext->setObjectName("MainThreadContext");
|
||||
_offscreenContext->create(_glWidget->context()->contextHandle());
|
||||
_offscreenContext->create(_glWidget->qglContext());
|
||||
_offscreenContext->makeCurrent();
|
||||
|
||||
// update before the first render
|
||||
|
@ -1553,7 +1555,7 @@ void Application::initializeUi() {
|
|||
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->create(_glWidget->context()->contextHandle());
|
||||
offscreenUi->create(_glWidget->qglContext());
|
||||
|
||||
auto rootContext = offscreenUi->getRootContext();
|
||||
|
||||
|
@ -5675,7 +5677,7 @@ MainWindow* Application::getPrimaryWindow() {
|
|||
}
|
||||
|
||||
QOpenGLContext* Application::getPrimaryContext() {
|
||||
return _glWidget->context()->contextHandle();
|
||||
return _glWidget->qglContext();
|
||||
}
|
||||
|
||||
bool Application::makeRenderingContextCurrent() {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <gl/GLWidget.h>
|
||||
#include <gl/Config.h>
|
||||
#include <gl/GLEscrow.h>
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
@ -108,7 +109,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void setContext(QGLContext * context) {
|
||||
void setContext(gl::Context* context) {
|
||||
// Move the OpenGL context to the present thread
|
||||
// Extra code because of the widget 'wrapper' context
|
||||
_context = context;
|
||||
|
@ -126,7 +127,6 @@ public:
|
|||
OpenGLDisplayPlugin* currentPlugin{ nullptr };
|
||||
Q_ASSERT(_context);
|
||||
_context->makeCurrent();
|
||||
Q_ASSERT(isCurrentContext(_context->contextHandle()));
|
||||
while (!_shutdown) {
|
||||
if (_pendingMainThreadOperation) {
|
||||
PROFILE_RANGE("MainThreadOp")
|
||||
|
@ -250,7 +250,7 @@ private:
|
|||
bool _finishedMainThreadOperation { false };
|
||||
QThread* _mainThread { nullptr };
|
||||
std::queue<OpenGLDisplayPlugin*> _newPluginQueue;
|
||||
QGLContext* _context { nullptr };
|
||||
gl::Context* _context { nullptr };
|
||||
};
|
||||
|
||||
bool OpenGLDisplayPlugin::activate() {
|
||||
|
@ -649,8 +649,8 @@ float OpenGLDisplayPlugin::presentRate() const {
|
|||
}
|
||||
|
||||
void OpenGLDisplayPlugin::swapBuffers() {
|
||||
static auto widget = _container->getPrimaryWidget();
|
||||
widget->swapBuffers();
|
||||
static auto context = _container->getPrimaryWidget()->context();
|
||||
context->swapBuffers();
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
|
||||
|
|
279
libraries/gl/src/gl/Context.cpp
Normal file
279
libraries/gl/src/gl/Context.cpp
Normal file
|
@ -0,0 +1,279 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/08/21
|
||||
// Copyright 2013-2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Context.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcessEnvironment>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool enableDebugLogger = true;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENGL");
|
||||
static bool enableDebugLogger = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "Config.h"
|
||||
#include "GLHelpers.h"
|
||||
|
||||
|
||||
using namespace gl;
|
||||
|
||||
Context* Context::PRIMARY = nullptr;
|
||||
|
||||
Context::Context() {}
|
||||
|
||||
Context::Context(QWindow* window) {
|
||||
setWindow(window);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void Context::destroyWin32Context(HGLRC hglrc) {
|
||||
wglDeleteContext(hglrc);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Context::release() {
|
||||
doneCurrent();
|
||||
#ifdef Q_OS_WIN
|
||||
if (_wrappedContext) {
|
||||
destroyContext(_wrappedContext);
|
||||
_wrappedContext = nullptr;
|
||||
}
|
||||
if (_hglrc) {
|
||||
destroyWin32Context(_hglrc);
|
||||
_hglrc = 0;
|
||||
}
|
||||
if (_hdc) {
|
||||
ReleaseDC(_hwnd, _hdc);
|
||||
_hdc = 0;
|
||||
}
|
||||
_hwnd = 0;
|
||||
#else
|
||||
destroyContext(_context);
|
||||
_context = nullptr;
|
||||
#endif
|
||||
_window = nullptr;
|
||||
if (PRIMARY == this) {
|
||||
PRIMARY = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context() {
|
||||
release();
|
||||
}
|
||||
|
||||
void Context::setWindow(QWindow* window) {
|
||||
release();
|
||||
_window = window;
|
||||
#ifdef Q_OS_WIN
|
||||
_hwnd = (HWND)window->winId();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static const char* PRIMARY_CONTEXT_PROPERTY_NAME = "com.highfidelity.gl.primaryContext";
|
||||
|
||||
bool Context::makeCurrent() {
|
||||
BOOL result = wglMakeCurrent(_hdc, _hglrc);
|
||||
assert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Context::swapBuffers() {
|
||||
SwapBuffers(_hdc);
|
||||
}
|
||||
|
||||
void Context::doneCurrent() {
|
||||
wglMakeCurrent(0, 0);
|
||||
}
|
||||
|
||||
void GLAPIENTRY debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
|
||||
if (GL_DEBUG_SEVERITY_NOTIFICATION == severity) {
|
||||
return;
|
||||
}
|
||||
qDebug() << "QQQ " << message;
|
||||
}
|
||||
|
||||
// FIXME build the PFD based on the
|
||||
static const PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
24, // Select Our Color Depth
|
||||
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
1, // Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
24, // 24 Bit Z-Buffer (Depth Buffer)
|
||||
8, // 8 Bit Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
|
||||
void setupPixelFormatSimple(HDC hdc) {
|
||||
auto pixelFormat = ChoosePixelFormat(hdc, &pfd);
|
||||
if (pixelFormat == 0) {
|
||||
throw std::runtime_error("Unable to create initial context");
|
||||
}
|
||||
|
||||
if (SetPixelFormat(hdc, pixelFormat, &pfd) == FALSE) {
|
||||
throw std::runtime_error("Unable to create initial context");
|
||||
}
|
||||
}
|
||||
|
||||
void Context::create() {
|
||||
if (!PRIMARY) {
|
||||
PRIMARY = static_cast<Context*>(qApp->property(PRIMARY_CONTEXT_PROPERTY_NAME).value<void*>());
|
||||
}
|
||||
|
||||
if (PRIMARY) {
|
||||
_version = PRIMARY->_version;
|
||||
}
|
||||
|
||||
assert(0 != _hwnd);
|
||||
assert(0 == _hdc);
|
||||
auto hwnd = _hwnd;
|
||||
// Create a temporary context to initialize glew
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
auto hdc = GetDC(hwnd);
|
||||
setupPixelFormatSimple(hdc);
|
||||
auto glrc = wglCreateContext(hdc);
|
||||
BOOL makeCurrentResult;
|
||||
makeCurrentResult = wglMakeCurrent(hdc, glrc);
|
||||
if (!makeCurrentResult) {
|
||||
throw std::runtime_error("Unable to create initial context");
|
||||
}
|
||||
glewExperimental = true;
|
||||
glewInit();
|
||||
if (glewIsSupported("GL_VERSION_4_5")) {
|
||||
_version = 0x0405;
|
||||
} else if (glewIsSupported("GL_VERSION_4_3")) {
|
||||
_version = 0x0403;
|
||||
}
|
||||
glGetError();
|
||||
wglMakeCurrent(0, 0);
|
||||
wglDeleteContext(glrc);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
});
|
||||
|
||||
_hdc = GetDC(_hwnd);
|
||||
static int pixelFormat = 0;
|
||||
static PIXELFORMATDESCRIPTOR pfd;
|
||||
if (!pixelFormat) {
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
std::vector<int> formatAttribs;
|
||||
formatAttribs.push_back(WGL_DRAW_TO_WINDOW_ARB);
|
||||
formatAttribs.push_back(GL_TRUE);
|
||||
formatAttribs.push_back(WGL_SUPPORT_OPENGL_ARB);
|
||||
formatAttribs.push_back(GL_TRUE);
|
||||
formatAttribs.push_back(WGL_DOUBLE_BUFFER_ARB);
|
||||
formatAttribs.push_back(GL_TRUE);
|
||||
formatAttribs.push_back(WGL_PIXEL_TYPE_ARB);
|
||||
formatAttribs.push_back(WGL_TYPE_RGBA_ARB);
|
||||
formatAttribs.push_back(WGL_COLOR_BITS_ARB);
|
||||
formatAttribs.push_back(32);
|
||||
formatAttribs.push_back(WGL_DEPTH_BITS_ARB);
|
||||
formatAttribs.push_back(24);
|
||||
formatAttribs.push_back(WGL_STENCIL_BITS_ARB);
|
||||
formatAttribs.push_back(8);
|
||||
formatAttribs.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||
formatAttribs.push_back(GL_TRUE);
|
||||
// terminate the list
|
||||
formatAttribs.push_back(0);
|
||||
UINT numFormats;
|
||||
wglChoosePixelFormatARB(_hdc, &formatAttribs[0], NULL, 1, &pixelFormat, &numFormats);
|
||||
DescribePixelFormat(_hdc, pixelFormat, sizeof(pfd), &pfd);
|
||||
}
|
||||
SetPixelFormat(_hdc, pixelFormat, &pfd);
|
||||
{
|
||||
std::vector<int> contextAttribs;
|
||||
uint32_t majorVersion = _version >> 8;
|
||||
uint32_t minorVersion = _version & 0xFF;
|
||||
contextAttribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
|
||||
contextAttribs.push_back(majorVersion);
|
||||
contextAttribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
|
||||
contextAttribs.push_back(minorVersion);
|
||||
contextAttribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
|
||||
contextAttribs.push_back(WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
|
||||
contextAttribs.push_back(WGL_CONTEXT_FLAGS_ARB);
|
||||
if (enableDebugLogger) {
|
||||
contextAttribs.push_back(WGL_CONTEXT_DEBUG_BIT_ARB);
|
||||
} else {
|
||||
contextAttribs.push_back(0);
|
||||
}
|
||||
contextAttribs.push_back(0);
|
||||
auto shareHglrc = PRIMARY ? PRIMARY->_hglrc : 0;
|
||||
_hglrc = wglCreateContextAttribsARB(_hdc, shareHglrc, &contextAttribs[0]);
|
||||
}
|
||||
|
||||
if (_hglrc == 0) {
|
||||
throw std::runtime_error("Could not create GL context");
|
||||
}
|
||||
|
||||
if (!PRIMARY) {
|
||||
PRIMARY = this;
|
||||
qApp->setProperty(PRIMARY_CONTEXT_PROPERTY_NAME, QVariant::fromValue((void*)PRIMARY));
|
||||
}
|
||||
|
||||
if (enableDebugLogger) {
|
||||
makeCurrent();
|
||||
glDebugMessageCallback(debugMessageCallback, NULL);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
doneCurrent();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Context::clear() {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
QSize windowSize = _window->size() * _window->devicePixelRatio();
|
||||
glViewport(0, 0, windowSize.width(), windowSize.height());
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
OffscreenContext::~OffscreenContext() {
|
||||
_window->deleteLater();
|
||||
}
|
||||
|
||||
void OffscreenContext::create() {
|
||||
if (!_window) {
|
||||
_window = new QWindow();
|
||||
_window->setFlags(Qt::MSWindowsOwnDC);
|
||||
_window->setSurfaceType(QSurface::OpenGLSurface);
|
||||
_window->create();
|
||||
setWindow(_window);
|
||||
QGuiApplication::processEvents();
|
||||
}
|
||||
Parent::create();
|
||||
}
|
72
libraries/gl/src/gl/Context.h
Normal file
72
libraries/gl/src/gl/Context.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/08/21
|
||||
// Copyright 2013-2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_gl_context_h
|
||||
#define hifi_gl_context_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
class QSurface;
|
||||
class QWindow;
|
||||
class QOpenGLContext;
|
||||
class QThread;
|
||||
|
||||
namespace gl {
|
||||
|
||||
class Context {
|
||||
protected:
|
||||
QWindow* _window { nullptr };
|
||||
static Context* PRIMARY;
|
||||
static void destroyContext(QOpenGLContext* context);
|
||||
#if defined(Q_OS_WIN)
|
||||
uint32_t _version { 0x0401 };
|
||||
HWND _hwnd { 0 };
|
||||
HDC _hdc { 0 };
|
||||
HGLRC _hglrc { 0 };
|
||||
static void destroyWin32Context(HGLRC hglrc);
|
||||
QOpenGLContext* _wrappedContext { nullptr };
|
||||
#else
|
||||
QOpenGLContext* _context { nullptr };
|
||||
#endif
|
||||
|
||||
private:
|
||||
Context(const Context& other);
|
||||
|
||||
public:
|
||||
Context();
|
||||
Context(QWindow* window);
|
||||
void release();
|
||||
virtual ~Context();
|
||||
|
||||
void clear();
|
||||
void setWindow(QWindow* window);
|
||||
bool makeCurrent();
|
||||
static void makeCurrent(QOpenGLContext* context, QSurface* surface);
|
||||
void swapBuffers();
|
||||
void doneCurrent();
|
||||
virtual void create();
|
||||
QOpenGLContext* qglContext();
|
||||
void moveToThread(QThread* thread);
|
||||
};
|
||||
|
||||
class OffscreenContext : public Context {
|
||||
using Parent = Context;
|
||||
protected:
|
||||
QWindow* _window { nullptr };
|
||||
public:
|
||||
virtual ~OffscreenContext();
|
||||
virtual void create();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // hifi_gpu_GPUConfig_h
|
75
libraries/gl/src/gl/ContextQt.cpp
Normal file
75
libraries/gl/src/gl/ContextQt.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/08/21
|
||||
// Copyright 2013-2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Context.h"
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtPlatformHeaders/QWGLNativeContext>
|
||||
#endif
|
||||
|
||||
using namespace gl;
|
||||
|
||||
void Context::destroyContext(QOpenGLContext* context) {
|
||||
delete context;
|
||||
}
|
||||
|
||||
void Context::makeCurrent(QOpenGLContext* context, QSurface* surface) {
|
||||
context->makeCurrent(surface);
|
||||
}
|
||||
|
||||
QOpenGLContext* Context::qglContext() {
|
||||
#ifdef Q_OS_WIN
|
||||
if (!_wrappedContext) {
|
||||
_wrappedContext = new QOpenGLContext();
|
||||
_wrappedContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd)));
|
||||
_wrappedContext->create();
|
||||
}
|
||||
return _wrappedContext;
|
||||
#else
|
||||
|
||||
return _context;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Context::moveToThread(QThread* thread) {
|
||||
qglContext()->moveToThread(thread);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
bool Context::makeCurrent() {
|
||||
return _context->makeCurrent(_window);
|
||||
}
|
||||
|
||||
void Context::swapBuffers() {
|
||||
_context->swapBuffers(_window);
|
||||
}
|
||||
|
||||
void Context::doneCurrent() {
|
||||
if (_context) {
|
||||
_context->doneCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
||||
|
||||
|
||||
void Context::create() {
|
||||
_context = new QOpenGLContext();
|
||||
if (PRIMARY) {
|
||||
_context->setShareContext(PRIMARY->qglContext());
|
||||
} else {
|
||||
PRIMARY = this;
|
||||
}
|
||||
_context->setFormat(getDefaultOpenGLSurfaceFormat());
|
||||
_context->create();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -21,44 +21,20 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
|||
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
||||
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
||||
setGLFormatVersion(format);
|
||||
if (GLDebug::enabled()) {
|
||||
qDebug() << "Enabling debug context";
|
||||
format.setOption(QSurfaceFormat::DebugContext);
|
||||
}
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
});
|
||||
return format;
|
||||
}
|
||||
|
||||
const QGLFormat& getDefaultGLFormat() {
|
||||
// Specify an OpenGL 3.3 format using the Core profile.
|
||||
// That is, no old-school fixed pipeline functionality
|
||||
static QGLFormat glFormat;
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
setGLFormatVersion(glFormat);
|
||||
glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0
|
||||
glFormat.setSampleBuffers(false);
|
||||
glFormat.setDepth(false);
|
||||
glFormat.setStencil(false);
|
||||
QGLFormat::setDefaultFormat(glFormat);
|
||||
});
|
||||
return glFormat;
|
||||
}
|
||||
|
||||
int glVersionToInteger(QString glVersion) {
|
||||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||
int majorNumber = versionParts[0].toInt();
|
||||
int minorNumber = versionParts[1].toInt();
|
||||
return majorNumber * 100 + minorNumber * 10;
|
||||
return (majorNumber << 16) | minorNumber;
|
||||
}
|
||||
|
||||
QJsonObject getGLContextData() {
|
||||
if (!QOpenGLContext::currentContext()) {
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
QString glVersion = QString((const char*)glGetString(GL_VERSION));
|
||||
QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
QString glVendor = QString((const char*) glGetString(GL_VENDOR));
|
||||
|
@ -77,31 +53,3 @@ QThread* RENDER_THREAD = nullptr;
|
|||
bool isRenderThread() {
|
||||
return QThread::currentThread() == RENDER_THREAD;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool enableDebugLogger = true;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENGL");
|
||||
static bool enableDebugLogger = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
#endif
|
||||
|
||||
bool GLDebug::enabled() {
|
||||
return enableDebugLogger;
|
||||
}
|
||||
|
||||
void GLDebug::log(const QOpenGLDebugMessage & debugMessage) {
|
||||
qDebug() << debugMessage;
|
||||
}
|
||||
|
||||
void GLDebug::setupLogger(QObject* window) {
|
||||
if (enabled()) {
|
||||
QOpenGLDebugLogger* logger = new QOpenGLDebugLogger(window);
|
||||
logger->initialize(); // initializes in the current context, i.e. ctx
|
||||
logger->enableMessages();
|
||||
QObject::connect(logger, &QOpenGLDebugLogger::messageLogged, window, [&](const QOpenGLDebugMessage & debugMessage) {
|
||||
GLDebug::log(debugMessage);
|
||||
});
|
||||
logger->startLogging(QOpenGLDebugLogger::SynchronousLogging);
|
||||
}
|
||||
}
|
|
@ -27,19 +27,9 @@ template<class F>
|
|||
void setGLFormatVersion(F& format, int major = 4, int minor = 5) { format.setVersion(major, minor); }
|
||||
|
||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
||||
const QGLFormat& getDefaultGLFormat();
|
||||
QJsonObject getGLContextData();
|
||||
int glVersionToInteger(QString glVersion);
|
||||
|
||||
bool isRenderThread();
|
||||
|
||||
|
||||
class GLDebug {
|
||||
public:
|
||||
static bool enabled();
|
||||
static void log(const QOpenGLDebugMessage& debugMessage);
|
||||
static void setupLogger(QObject* window = nullptr);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,30 +7,52 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "GLWidget.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QPaintEngine>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
|
||||
#include "Context.h"
|
||||
#include "GLHelpers.h"
|
||||
|
||||
class GLPaintEngine : public QPaintEngine {
|
||||
bool begin(QPaintDevice *pdev) override { return true; }
|
||||
bool end() override { return true; }
|
||||
void updateState(const QPaintEngineState &state) override { }
|
||||
void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override { }
|
||||
Type type() const override { return OpenGL2; }
|
||||
};
|
||||
|
||||
GLWidget::GLWidget() : QGLWidget(getDefaultGLFormat()) {
|
||||
GLWidget::GLWidget() {
|
||||
#ifdef Q_OS_LINUX
|
||||
// Cause GLWidget::eventFilter to be called.
|
||||
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
|
||||
qApp->installEventFilter(this);
|
||||
#endif
|
||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
setAttribute(Qt::WA_NativeWindow);
|
||||
setAttribute(Qt::WA_PaintOnScreen);
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAutoFillBackground(false);
|
||||
grabGesture(Qt::PinchGesture);
|
||||
setAcceptDrops(true);
|
||||
_paintEngine = new GLPaintEngine();
|
||||
}
|
||||
|
||||
GLWidget::~GLWidget() {
|
||||
delete _paintEngine;
|
||||
_paintEngine = nullptr;
|
||||
}
|
||||
|
||||
int GLWidget::getDeviceWidth() const {
|
||||
|
@ -41,31 +63,25 @@ int GLWidget::getDeviceHeight() const {
|
|||
return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
|
||||
}
|
||||
|
||||
void GLWidget::initializeGL() {
|
||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
grabGesture(Qt::PinchGesture);
|
||||
setAcceptDrops(true);
|
||||
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
|
||||
setAutoBufferSwap(false);
|
||||
|
||||
makeCurrent();
|
||||
if (isValid() && context() && context()->contextHandle()) {
|
||||
#if defined(Q_OS_WIN)
|
||||
_vsyncSupported = context()->contextHandle()->hasExtension("WGL_EXT_swap_control");
|
||||
#elif defined(Q_OS_MAC)
|
||||
_vsyncSupported = true;
|
||||
#else
|
||||
// TODO: write the proper code for linux
|
||||
#endif
|
||||
}
|
||||
void GLWidget::createContext() {
|
||||
_context = new gl::Context();
|
||||
_context->setWindow(windowHandle());
|
||||
_context->create();
|
||||
_context->clear();
|
||||
_context->makeCurrent();
|
||||
}
|
||||
|
||||
void GLWidget::paintEvent(QPaintEvent* event) {
|
||||
QWidget::paintEvent(event);
|
||||
bool GLWidget::makeCurrent() {
|
||||
gl::Context::makeCurrent(_context->qglContext(), windowHandle());
|
||||
return _context->makeCurrent();
|
||||
}
|
||||
|
||||
void GLWidget::resizeEvent(QResizeEvent* event) {
|
||||
QWidget::resizeEvent(event);
|
||||
QOpenGLContext* GLWidget::qglContext() {
|
||||
return _context->qglContext();
|
||||
}
|
||||
|
||||
void GLWidget::doneCurrent() {
|
||||
_context->doneCurrent();
|
||||
}
|
||||
|
||||
bool GLWidget::event(QEvent* event) {
|
||||
|
@ -94,10 +110,9 @@ bool GLWidget::event(QEvent* event) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return QGLWidget::event(event);
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
|
||||
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
||||
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
|
||||
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
|
||||
|
@ -119,7 +134,7 @@ bool GLWidget::eventFilter(QObject*, QEvent* event) {
|
|||
} else if (event->type() == QEvent::KeyRelease) {
|
||||
keyReleaseEvent(keyEvent);
|
||||
} else {
|
||||
QGLWidget::event(event);
|
||||
QWidget::event(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -130,7 +145,22 @@ bool GLWidget::eventFilter(QObject*, QEvent* event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool GLWidget::isVsyncSupported() const {
|
||||
return _vsyncSupported;
|
||||
|
||||
bool GLWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) {
|
||||
#ifdef Q_OS_WIN32
|
||||
MSG* win32message = static_cast<MSG*>(message);
|
||||
switch (win32message->message) {
|
||||
case WM_ERASEBKGND:
|
||||
*result = 1L;
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return QWidget::nativeEvent(eventType, message, result);
|
||||
}
|
||||
|
||||
QPaintEngine* GLWidget::paintEngine() const {
|
||||
return _paintEngine;
|
||||
}
|
||||
|
|
|
@ -10,31 +10,43 @@
|
|||
#ifndef hifi_GLWidget_h
|
||||
#define hifi_GLWidget_h
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
namespace gl {
|
||||
class Context;
|
||||
}
|
||||
|
||||
class QOpenGLContext;
|
||||
|
||||
/// customized canvas that simply forwards requests/events to the singleton application
|
||||
class GLWidget : public QGLWidget {
|
||||
class GLWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GLWidget();
|
||||
~GLWidget();
|
||||
int getDeviceWidth() const;
|
||||
int getDeviceHeight() const;
|
||||
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
|
||||
bool isVsyncSupported() const;
|
||||
virtual void initializeGL() override;
|
||||
QPaintEngine* paintEngine() const override;
|
||||
void createContext();
|
||||
bool makeCurrent();
|
||||
void doneCurrent();
|
||||
gl::Context* context() { return _context; }
|
||||
QOpenGLContext* qglContext();
|
||||
|
||||
|
||||
protected:
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||
virtual bool event(QEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
virtual void resizeEvent(QResizeEvent* event) override;
|
||||
gl::Context* _context { nullptr };
|
||||
|
||||
private slots:
|
||||
virtual bool eventFilter(QObject*, QEvent* event) override;
|
||||
|
||||
private:
|
||||
QPaintEngine* _paintEngine { nullptr };
|
||||
bool _vsyncSupported { false };
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_GLCanvas_h
|
||||
|
|
|
@ -60,7 +60,6 @@ bool OffscreenGLCanvas::makeCurrent() {
|
|||
qDebug() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
GLDebug::setupLogger(this);
|
||||
});
|
||||
|
||||
return result;
|
||||
|
|
|
@ -10,27 +10,46 @@
|
|||
//
|
||||
|
||||
#include "OpenGLVersionChecker.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QRegularExpression>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "Config.h"
|
||||
#include "GLWidget.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtOpenGL/QGLWidget>
|
||||
|
||||
#include "GLHelpers.h"
|
||||
|
||||
#define MINIMUM_GL_VERSION 410
|
||||
#define MINIMUM_GL_VERSION 0x0401
|
||||
|
||||
OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) :
|
||||
QApplication(argc, argv)
|
||||
{
|
||||
}
|
||||
|
||||
const QGLFormat& getDefaultGLFormat() {
|
||||
// Specify an OpenGL 3.3 format using the Core profile.
|
||||
// That is, no old-school fixed pipeline functionality
|
||||
static QGLFormat glFormat;
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
setGLFormatVersion(glFormat);
|
||||
glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0
|
||||
glFormat.setSampleBuffers(false);
|
||||
glFormat.setDepth(false);
|
||||
glFormat.setStencil(false);
|
||||
QGLFormat::setDefaultFormat(glFormat);
|
||||
});
|
||||
return glFormat;
|
||||
}
|
||||
|
||||
|
||||
QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||
valid = true;
|
||||
override = false;
|
||||
|
||||
GLWidget* glWidget = new GLWidget();
|
||||
QGLWidget* glWidget = new QGLWidget();
|
||||
valid = glWidget->isValid();
|
||||
// Inform user if no OpenGL support
|
||||
if (!valid) {
|
||||
|
@ -46,7 +65,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
|||
}
|
||||
|
||||
// Retrieve OpenGL version
|
||||
glWidget->initializeGL();
|
||||
// glWidget->initializeGL();
|
||||
glWidget->makeCurrent();
|
||||
QJsonObject glData = getGLContextData();
|
||||
delete glWidget;
|
||||
|
||||
|
@ -60,8 +80,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
|||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||
int majorNumber = versionParts[0].toInt();
|
||||
int minorNumber = versionParts[1].toInt();
|
||||
int minimumMajorNumber = MINIMUM_GL_VERSION / 100;
|
||||
int minimumMinorNumber = (MINIMUM_GL_VERSION - minimumMajorNumber * 100) / 10;
|
||||
int minimumMajorNumber = (MINIMUM_GL_VERSION >> 16);
|
||||
int minimumMinorNumber = (MINIMUM_GL_VERSION & 0xFF);
|
||||
valid = (majorNumber > minimumMajorNumber
|
||||
|| (majorNumber == minimumMajorNumber && minorNumber >= minimumMinorNumber));
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ float GLTexture::getMemoryPressure() {
|
|||
|
||||
// If no memory limit has been set, use a percentage of the total dedicated memory
|
||||
if (!availableTextureMemory) {
|
||||
auto totalGpuMemory = gpu::gl::getDedicatedMemory();
|
||||
auto totalGpuMemory = getDedicatedMemory();
|
||||
|
||||
// If no limit has been explicitly set, and the dedicated memory can't be determined,
|
||||
// just use a fallback fixed value of 256 MB
|
||||
|
@ -118,7 +118,7 @@ float GLTexture::getMemoryPressure() {
|
|||
return (float)consumedGpuMemory / (float)availableTextureMemory;
|
||||
}
|
||||
|
||||
GLTexture::DownsampleSource::DownsampleSource(const std::weak_ptr<gl::GLBackend>& backend, GLTexture* oldTexture) :
|
||||
GLTexture::DownsampleSource::DownsampleSource(const std::weak_ptr<GLBackend>& backend, GLTexture* oldTexture) :
|
||||
_backend(backend),
|
||||
_size(oldTexture ? oldTexture->_size : 0),
|
||||
_texture(oldTexture ? oldTexture->takeOwnership() : 0),
|
||||
|
@ -161,7 +161,7 @@ GLTexture::GLTexture(const std::weak_ptr<GLBackend>& backend, const gpu::Texture
|
|||
|
||||
|
||||
// Create the texture and allocate storage
|
||||
GLTexture::GLTexture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLuint id, bool transferrable) :
|
||||
GLTexture::GLTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLuint id, bool transferrable) :
|
||||
GLTexture(backend, texture, id, nullptr, transferrable)
|
||||
{
|
||||
// FIXME, do during allocation
|
||||
|
@ -170,7 +170,7 @@ GLTexture::GLTexture(const std::weak_ptr<gl::GLBackend>& backend, const Texture&
|
|||
}
|
||||
|
||||
// Create the texture and copy from the original higher resolution version
|
||||
GLTexture::GLTexture(const std::weak_ptr<gl::GLBackend>& backend, const gpu::Texture& texture, GLuint id, GLTexture* originalTexture) :
|
||||
GLTexture::GLTexture(const std::weak_ptr<GLBackend>& backend, const gpu::Texture& texture, GLuint id, GLTexture* originalTexture) :
|
||||
GLTexture(backend, texture, id, originalTexture, originalTexture->_transferrable)
|
||||
{
|
||||
Q_ASSERT(_minMip >= originalTexture->_minMip);
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
// If we just did a transfer, return the object after doing post-transfer work
|
||||
if (GLSyncState::Transferred == object->getSyncState()) {
|
||||
object->postTransfer();
|
||||
return object;
|
||||
}
|
||||
|
||||
if (object->isOutdated()) {
|
||||
|
|
|
@ -7,10 +7,8 @@
|
|||
//
|
||||
#include "GLTextureTransfer.h"
|
||||
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
#include <gl/OffscreenGLCanvas.h>
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#endif
|
||||
#include <gl/GLHelpers.h>
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include "GLShared.h"
|
||||
#include "GLTexture.h"
|
||||
|
@ -20,16 +18,9 @@ using namespace gpu::gl;
|
|||
|
||||
GLTextureTransferHelper::GLTextureTransferHelper() {
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
_canvas = QSharedPointer<OffscreenGLCanvas>(new OffscreenGLCanvas(), &QObject::deleteLater);
|
||||
_canvas->setObjectName("TextureTransferCanvas");
|
||||
_canvas->create(QOpenGLContextWrapper::currentContext());
|
||||
if (!_canvas->makeCurrent()) {
|
||||
qFatal("Unable to create texture transfer context");
|
||||
}
|
||||
_canvas->doneCurrent();
|
||||
setObjectName("TextureTransferThread");
|
||||
_context.create();
|
||||
initialize(true, QThread::LowPriority);
|
||||
_canvas->moveToThreadWithContext(_thread);
|
||||
|
||||
// Clean shutdown on UNIX, otherwise _canvas is freed early
|
||||
connect(qApp, &QCoreApplication::aboutToQuit, [&] { terminate(); });
|
||||
#endif
|
||||
|
@ -64,17 +55,9 @@ void GLTextureTransferHelper::transferTexture(const gpu::TexturePointer& texture
|
|||
}
|
||||
|
||||
void GLTextureTransferHelper::setup() {
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
_canvas->makeCurrent();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLTextureTransferHelper::shutdown() {
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
_canvas->doneCurrent();
|
||||
_canvas->moveToThreadWithContext(qApp->thread());
|
||||
_canvas.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLTextureTransferHelper::do_transfer(GLTexture& texture) {
|
||||
|
@ -85,6 +68,9 @@ void GLTextureTransferHelper::do_transfer(GLTexture& texture) {
|
|||
}
|
||||
|
||||
bool GLTextureTransferHelper::processQueueItems(const Queue& messages) {
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
_context.makeCurrent();
|
||||
#endif
|
||||
for (auto package : messages) {
|
||||
TexturePointer texturePointer = package.texture.lock();
|
||||
// Texture no longer exists, move on to the next
|
||||
|
@ -93,21 +79,39 @@ bool GLTextureTransferHelper::processQueueItems(const Queue& messages) {
|
|||
}
|
||||
|
||||
if (package.fence) {
|
||||
glClientWaitSync(package.fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
auto result = glClientWaitSync(package.fence, 0, 0);
|
||||
while (GL_TIMEOUT_EXPIRED == result || GL_WAIT_FAILED == result) {
|
||||
// Minimum sleep
|
||||
QThread::usleep(1);
|
||||
result = glClientWaitSync(package.fence, 0, 0);
|
||||
}
|
||||
assert(GL_CONDITION_SATISFIED == result || GL_ALREADY_SIGNALED == result);
|
||||
glDeleteSync(package.fence);
|
||||
package.fence = 0;
|
||||
}
|
||||
|
||||
GLTexture* object = Backend::getGPUObject<GLTexture>(*texturePointer);
|
||||
|
||||
do_transfer(*object);
|
||||
glBindTexture(object->_target, 0);
|
||||
|
||||
auto writeSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
glClientWaitSync(writeSync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(writeSync);
|
||||
{
|
||||
auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
assert(fence);
|
||||
auto result = glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
|
||||
while (GL_TIMEOUT_EXPIRED == result || GL_WAIT_FAILED == result) {
|
||||
// Minimum sleep
|
||||
QThread::usleep(1);
|
||||
result = glClientWaitSync(fence, 0, 0);
|
||||
}
|
||||
glDeleteSync(package.fence);
|
||||
}
|
||||
|
||||
object->_contentStamp = texturePointer->getDataStamp();
|
||||
object->setSyncState(GLSyncState::Transferred);
|
||||
}
|
||||
#ifdef THREADED_TEXTURE_TRANSFER
|
||||
_context.doneCurrent();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
#include <GenericQueueThread.h>
|
||||
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include "GLShared.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define THREADED_TEXTURE_TRANSFER
|
||||
#endif
|
||||
|
||||
class OffscreenGLCanvas;
|
||||
|
||||
namespace gpu { namespace gl {
|
||||
|
||||
struct TextureTransferPackage {
|
||||
|
@ -43,7 +43,7 @@ protected:
|
|||
void do_transfer(GLTexture& texturePointer);
|
||||
|
||||
private:
|
||||
QSharedPointer<OffscreenGLCanvas> _canvas;
|
||||
::gl::OffscreenContext _context;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
namespace gpu { namespace gl41 {
|
||||
|
||||
class GL41Backend : public gl::GLBackend {
|
||||
using Parent = gl::GLBackend;
|
||||
using namespace gpu::gl;
|
||||
|
||||
class GL41Backend : public GLBackend {
|
||||
using Parent = GLBackend;
|
||||
// Context Backend static interface required
|
||||
friend class Context;
|
||||
|
||||
|
@ -36,12 +38,12 @@ public:
|
|||
explicit GL41Backend(bool syncCache) : Parent(syncCache) {}
|
||||
GL41Backend() : Parent() {}
|
||||
|
||||
class GL41Texture : public gpu::gl::GLTexture {
|
||||
using Parent = gpu::gl::GLTexture;
|
||||
class GL41Texture : public GLTexture {
|
||||
using Parent = GLTexture;
|
||||
GLuint allocate();
|
||||
public:
|
||||
GL41Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& buffer, bool transferrable);
|
||||
GL41Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& buffer, GL41Texture* original);
|
||||
GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture& buffer, bool transferrable);
|
||||
GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture& buffer, GL41Texture* original);
|
||||
|
||||
protected:
|
||||
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
||||
|
@ -56,16 +58,16 @@ public:
|
|||
|
||||
protected:
|
||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||
gl::GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||
|
||||
GLuint getBufferID(const Buffer& buffer) override;
|
||||
gl::GLBuffer* syncGPUObject(const Buffer& buffer) override;
|
||||
GLBuffer* syncGPUObject(const Buffer& buffer) override;
|
||||
|
||||
GLuint getTextureID(const TexturePointer& texture, bool needTransfer = true) override;
|
||||
gl::GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) override;
|
||||
GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) override;
|
||||
|
||||
GLuint getQueryID(const QueryPointer& query) override;
|
||||
gl::GLQuery* syncGPUObject(const Query& query) override;
|
||||
GLQuery* syncGPUObject(const Query& query) override;
|
||||
|
||||
// Draw Stage
|
||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace gpu {
|
||||
namespace gl41 {
|
||||
class GL41Buffer : public gl::GLBuffer {
|
||||
class GL41Buffer : public gpu::gl::GLBuffer {
|
||||
using Parent = gpu::gl::GLBuffer;
|
||||
static GLuint allocate() {
|
||||
GLuint result;
|
||||
|
@ -55,6 +55,7 @@ namespace gpu {
|
|||
}
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl41;
|
||||
|
||||
|
||||
|
@ -62,6 +63,6 @@ GLuint GL41Backend::getBufferID(const Buffer& buffer) {
|
|||
return GL41Buffer::getId<GL41Buffer>(*this, buffer);
|
||||
}
|
||||
|
||||
gl::GLBuffer* GL41Backend::syncGPUObject(const Buffer& buffer) {
|
||||
GLBuffer* GL41Backend::syncGPUObject(const Buffer& buffer) {
|
||||
return GL41Buffer::sync<GL41Buffer>(*this, buffer);
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
#include "../gl/GLQuery.h"
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl41;
|
||||
|
||||
class GL41Query : public gpu::gl::GLQuery {
|
||||
using Parent = gpu::gl::GLQuery;
|
||||
class GL41Query : public GLQuery {
|
||||
using Parent = GLQuery;
|
||||
public:
|
||||
static GLuint allocateQuery() {
|
||||
GLuint result;
|
||||
|
@ -24,11 +25,11 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
GL41Query(const std::weak_ptr<gl::GLBackend>& backend, const Query& query)
|
||||
GL41Query(const std::weak_ptr<GLBackend>& backend, const Query& query)
|
||||
: Parent(backend, query, allocateQuery(), allocateQuery()) { }
|
||||
};
|
||||
|
||||
gl::GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
||||
GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
||||
return GL41Query::sync<GL41Query>(*this, query);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
#include "../gl/GLTexelFormat.h"
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl41;
|
||||
|
||||
using GL41TexelFormat = gl::GLTexelFormat;
|
||||
using GL41TexelFormat = GLTexelFormat;
|
||||
using GL41Texture = GL41Backend::GL41Texture;
|
||||
|
||||
GLuint GL41Texture::allocate() {
|
||||
|
@ -33,13 +34,13 @@ GLuint GL41Backend::getTextureID(const TexturePointer& texture, bool transfer) {
|
|||
return GL41Texture::getId<GL41Texture>(*this, texture, transfer);
|
||||
}
|
||||
|
||||
gl::GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texture, bool transfer) {
|
||||
GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texture, bool transfer) {
|
||||
return GL41Texture::sync<GL41Texture>(*this, texture, transfer);
|
||||
}
|
||||
|
||||
GL41Texture::GL41Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, bool transferrable) : gl::GLTexture(backend, texture, allocate(), transferrable) {}
|
||||
GL41Texture::GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, bool transferrable) : GLTexture(backend, texture, allocate(), transferrable) {}
|
||||
|
||||
GL41Texture::GL41Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GL41Texture* original) : gl::GLTexture(backend, texture, allocate(), original) {}
|
||||
GL41Texture::GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GL41Texture* original) : GLTexture(backend, texture, allocate(), original) {}
|
||||
|
||||
void GL41Backend::GL41Texture::withPreservedTexture(std::function<void()> f) const {
|
||||
GLint boundTex = -1;
|
||||
|
@ -71,7 +72,7 @@ void GL41Backend::GL41Texture::generateMips() const {
|
|||
}
|
||||
|
||||
void GL41Backend::GL41Texture::allocateStorage() const {
|
||||
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
(void)CHECK_GL_ERROR();
|
||||
glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||
|
@ -131,7 +132,7 @@ void GL41Backend::GL41Texture::updateSize() const {
|
|||
// Move content bits from the CPU to the GPU for a given mip / face
|
||||
void GL41Backend::GL41Texture::transferMip(uint16_t mipLevel, uint8_t face) const {
|
||||
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
||||
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||
//GLenum target = getFaceTargets()[face];
|
||||
GLenum target = _target == GL_TEXTURE_2D ? GL_TEXTURE_2D : CUBE_FACE_LAYOUT[face];
|
||||
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||
|
@ -216,7 +217,7 @@ void GL41Backend::GL41Texture::syncSampler() const {
|
|||
|
||||
if (sampler.doComparison()) {
|
||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_FUNC, gl::COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||
} else {
|
||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,9 @@ void GL41Backend::transferTransformState(const Batch& batch) const {
|
|||
#else
|
||||
glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _transform._objectBuffer);
|
||||
if (!batch._objects.empty()) {
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _transform._objectBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
#include "../gl/GLTexture.h"
|
||||
|
||||
namespace gpu { namespace gl45 {
|
||||
|
||||
using namespace gpu::gl;
|
||||
|
||||
class GL45Backend : public gl::GLBackend {
|
||||
using Parent = gl::GLBackend;
|
||||
class GL45Backend : public GLBackend {
|
||||
using Parent = GLBackend;
|
||||
// Context Backend static interface required
|
||||
friend class Context;
|
||||
|
||||
|
@ -25,12 +27,12 @@ public:
|
|||
explicit GL45Backend(bool syncCache) : Parent(syncCache) {}
|
||||
GL45Backend() : Parent() {}
|
||||
|
||||
class GL45Texture : public gpu::gl::GLTexture {
|
||||
using Parent = gpu::gl::GLTexture;
|
||||
class GL45Texture : public GLTexture {
|
||||
using Parent = GLTexture;
|
||||
GLuint allocate(const Texture& texture);
|
||||
public:
|
||||
GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, bool transferrable);
|
||||
GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLTexture* original);
|
||||
GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, bool transferrable);
|
||||
GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLTexture* original);
|
||||
|
||||
protected:
|
||||
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
||||
|
@ -45,16 +47,16 @@ public:
|
|||
|
||||
protected:
|
||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||
gl::GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||
|
||||
GLuint getBufferID(const Buffer& buffer) override;
|
||||
gl::GLBuffer* syncGPUObject(const Buffer& buffer) override;
|
||||
GLBuffer* syncGPUObject(const Buffer& buffer) override;
|
||||
|
||||
GLuint getTextureID(const TexturePointer& texture, bool needTransfer = true) override;
|
||||
gl::GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) override;
|
||||
GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) override;
|
||||
|
||||
GLuint getQueryID(const QueryPointer& query) override;
|
||||
gl::GLQuery* syncGPUObject(const Query& query) override;
|
||||
GLQuery* syncGPUObject(const Query& query) override;
|
||||
|
||||
// Draw Stage
|
||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||
|
|
|
@ -8,41 +8,42 @@
|
|||
#include "GL45Backend.h"
|
||||
#include "../gl/GLBuffer.h"
|
||||
|
||||
namespace gpu {
|
||||
namespace gl45 {
|
||||
class GL45Buffer : public gl::GLBuffer {
|
||||
using Parent = gpu::gl::GLBuffer;
|
||||
static GLuint allocate() {
|
||||
GLuint result;
|
||||
glCreateBuffers(1, &result);
|
||||
return result;
|
||||
}
|
||||
namespace gpu { namespace gl45 {
|
||||
using namespace gpu::gl;
|
||||
|
||||
public:
|
||||
GL45Buffer(const std::weak_ptr<gl::GLBackend>& backend, const Buffer& buffer, GLBuffer* original) : Parent(backend, buffer, allocate()) {
|
||||
glNamedBufferStorage(_buffer, _size == 0 ? 256 : _size, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||
if (original && original->_size) {
|
||||
glCopyNamedBufferSubData(original->_buffer, _buffer, 0, 0, std::min(original->_size, _size));
|
||||
}
|
||||
Backend::setGPUObject(buffer, this);
|
||||
}
|
||||
class GL45Buffer : public GLBuffer {
|
||||
using Parent = GLBuffer;
|
||||
static GLuint allocate() {
|
||||
GLuint result;
|
||||
glCreateBuffers(1, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void transfer() override {
|
||||
Size offset;
|
||||
Size size;
|
||||
Size currentPage { 0 };
|
||||
auto data = _gpuObject._renderSysmem.readData();
|
||||
while (_gpuObject._renderPages.getNextTransferBlock(offset, size, currentPage)) {
|
||||
glNamedBufferSubData(_buffer, (GLintptr)offset, (GLsizeiptr)size, data + offset);
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
_gpuObject._renderPages._flags &= ~PageManager::DIRTY;
|
||||
public:
|
||||
GL45Buffer(const std::weak_ptr<GLBackend>& backend, const Buffer& buffer, GLBuffer* original) : Parent(backend, buffer, allocate()) {
|
||||
glNamedBufferStorage(_buffer, _size == 0 ? 256 : _size, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||
if (original && original->_size) {
|
||||
glCopyNamedBufferSubData(original->_buffer, _buffer, 0, 0, std::min(original->_size, _size));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Backend::setGPUObject(buffer, this);
|
||||
}
|
||||
|
||||
void transfer() override {
|
||||
Size offset;
|
||||
Size size;
|
||||
Size currentPage { 0 };
|
||||
auto data = _gpuObject._renderSysmem.readData();
|
||||
while (_gpuObject._renderPages.getNextTransferBlock(offset, size, currentPage)) {
|
||||
glNamedBufferSubData(_buffer, (GLintptr)offset, (GLsizeiptr)size, data + offset);
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
_gpuObject._renderPages._flags &= ~PageManager::DIRTY;
|
||||
}
|
||||
};
|
||||
} }
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl45;
|
||||
|
||||
|
||||
|
@ -50,6 +51,6 @@ GLuint GL45Backend::getBufferID(const Buffer& buffer) {
|
|||
return GL45Buffer::getId<GL45Buffer>(*this, buffer);
|
||||
}
|
||||
|
||||
gl::GLBuffer* GL45Backend::syncGPUObject(const Buffer& buffer) {
|
||||
GLBuffer* GL45Backend::syncGPUObject(const Buffer& buffer) {
|
||||
return GL45Buffer::sync<GL45Buffer>(*this, buffer);
|
||||
}
|
||||
|
|
|
@ -12,14 +12,15 @@
|
|||
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include "../gl/GLTexelFormat.h"
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
using namespace gpu::gl45;
|
||||
|
||||
using GLTexelFormat = gl::GLTexelFormat;
|
||||
using GL45Texture = GL45Backend::GL45Texture;
|
||||
|
||||
GLuint GL45Texture::allocate(const Texture& texture) {
|
||||
|
@ -33,15 +34,15 @@ GLuint GL45Backend::getTextureID(const TexturePointer& texture, bool transfer) {
|
|||
return GL45Texture::getId<GL45Texture>(*this, texture, transfer);
|
||||
}
|
||||
|
||||
gl::GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texture, bool transfer) {
|
||||
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texture, bool transfer) {
|
||||
return GL45Texture::sync<GL45Texture>(*this, texture, transfer);
|
||||
}
|
||||
|
||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, bool transferrable)
|
||||
: gl::GLTexture(backend, texture, allocate(texture), transferrable) {}
|
||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, bool transferrable)
|
||||
: GLTexture(backend, texture, allocate(texture), transferrable) {}
|
||||
|
||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLTexture* original)
|
||||
: gl::GLTexture(backend, texture, allocate(texture), original) {}
|
||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLTexture* original)
|
||||
: GLTexture(backend, texture, allocate(texture), original) {}
|
||||
|
||||
void GL45Backend::GL45Texture::withPreservedTexture(std::function<void()> f) const {
|
||||
f();
|
||||
|
@ -53,7 +54,7 @@ void GL45Backend::GL45Texture::generateMips() const {
|
|||
}
|
||||
|
||||
void GL45Backend::GL45Texture::allocateStorage() const {
|
||||
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||
if (_gpuObject.getTexelFormat().isCompressed()) {
|
||||
|
@ -79,7 +80,7 @@ void GL45Backend::GL45Texture::updateSize() const {
|
|||
// Move content bits from the CPU to the GPU for a given mip / face
|
||||
void GL45Backend::GL45Texture::transferMip(uint16_t mipLevel, uint8_t face) const {
|
||||
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
||||
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||
if (GL_TEXTURE_2D == _target) {
|
||||
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||
|
@ -167,7 +168,7 @@ void GL45Backend::GL45Texture::syncSampler() const {
|
|||
|
||||
if (sampler.doComparison()) {
|
||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_FUNC, gl::COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||
} else {
|
||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
_windowGeometry("WindowGeometry"),
|
||||
_windowState("WindowState", 0)
|
||||
{
|
||||
setAttribute(Qt::WA_NoSystemBackground);
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,12 @@
|
|||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include <gpu/Frame.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
#include <PathUtils.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
|
@ -56,7 +59,7 @@ public:
|
|||
using Condition = std::condition_variable;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
friend class OpenVrDisplayPlugin;
|
||||
std::shared_ptr<OffscreenGLCanvas> _canvas;
|
||||
std::shared_ptr<gl::OffscreenContext> _canvas;
|
||||
BasicFramebufferWrapperPtr _framebuffer;
|
||||
ProgramPtr _program;
|
||||
ShapeWrapperPtr _plane;
|
||||
|
@ -129,7 +132,6 @@ public:
|
|||
|
||||
void run() override {
|
||||
QThread::currentThread()->setPriority(QThread::Priority::TimeCriticalPriority);
|
||||
assert(_canvas->thread() == QThread::currentThread());
|
||||
_canvas->makeCurrent();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, _plugin._renderTargetSize.x, _plugin._renderTargetSize.y);
|
||||
|
@ -206,7 +208,6 @@ public:
|
|||
_program.reset();
|
||||
_framebuffer.reset();
|
||||
_canvas->doneCurrent();
|
||||
_canvas->moveToThreadWithContext(qApp->thread());
|
||||
}
|
||||
|
||||
void update(const CompositeInfo& newCompositeInfo) {
|
||||
|
@ -309,14 +310,11 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
|||
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
||||
if (!_submitCanvas) {
|
||||
withMainThreadContext([&] {
|
||||
_submitCanvas = std::make_shared<OffscreenGLCanvas>();
|
||||
_submitCanvas->setObjectName("OpenVRSubmitContext");
|
||||
_submitCanvas->create(_container->getPrimaryContext());
|
||||
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
||||
_submitCanvas->create();
|
||||
_submitCanvas->doneCurrent();
|
||||
});
|
||||
}
|
||||
_submitCanvas->moveToThreadWithContext(_submitThread.get());
|
||||
assert(_submitCanvas->thread() == _submitThread.get());
|
||||
#endif
|
||||
|
||||
return Parent::internalActivate();
|
||||
|
@ -354,7 +352,6 @@ void OpenVrDisplayPlugin::customizeContext() {
|
|||
}
|
||||
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
||||
}
|
||||
assert(_submitCanvas->thread() == _submitThread.get());
|
||||
_submitThread->_canvas = _submitCanvas;
|
||||
_submitThread->start(QThread::HighPriority);
|
||||
#endif
|
||||
|
@ -367,7 +364,6 @@ void OpenVrDisplayPlugin::uncustomizeContext() {
|
|||
_submitThread->_quit = true;
|
||||
_submitThread->wait();
|
||||
_submitThread.reset();
|
||||
assert(_submitCanvas->thread() == qApp->thread());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p
|
|||
#define OPENVR_THREADED_SUBMIT 1
|
||||
|
||||
#if OPENVR_THREADED_SUBMIT
|
||||
namespace gl {
|
||||
class OffscreenContext;
|
||||
}
|
||||
class OpenVrSubmitThread;
|
||||
class OffscreenGLCanvas;
|
||||
static const size_t COMPOSITING_BUFFER_SIZE = 3;
|
||||
|
@ -79,7 +82,7 @@ private:
|
|||
CompositeInfo::Array _compositeInfos;
|
||||
size_t _renderingIndex { 0 };
|
||||
std::shared_ptr<OpenVrSubmitThread> _submitThread;
|
||||
std::shared_ptr<OffscreenGLCanvas> _submitCanvas;
|
||||
std::shared_ptr<gl::OffscreenContext> _submitCanvas;
|
||||
friend class OpenVrSubmitThread;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -73,7 +73,6 @@ void TestWindow::initGl() {
|
|||
DependencyManager::set<DeferredLightingEffect>();
|
||||
resize(QSize(800, 600));
|
||||
|
||||
GLDebug::setupLogger(this);
|
||||
#ifdef DEFERRED_LIGHTING
|
||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||
deferredLightingEffect->init();
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
DOWN,
|
||||
BACK,
|
||||
FORWARD,
|
||||
MLEFT,
|
||||
MMIDDLE,
|
||||
MRIGHT,
|
||||
KEYS_SIZE,
|
||||
INVALID = -1,
|
||||
};
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <gl/Config.h>
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
@ -27,12 +30,13 @@
|
|||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
|
||||
#include <shared/RateCounter.h>
|
||||
#include <AssetClient.h>
|
||||
|
||||
#include <gl/OffscreenGLCanvas.h>
|
||||
#include <gl/GLHelpers.h>
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
//#include <gl/OffscreenGLCanvas.h>
|
||||
//#include <gl/GLHelpers.h>
|
||||
//#include <gl/QOpenGLContextWrapper.h>
|
||||
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <gpu/gl/GLFramebuffer.h>
|
||||
|
@ -61,6 +65,7 @@
|
|||
#include "Camera.hpp"
|
||||
#include "TextOverlay.hpp"
|
||||
|
||||
|
||||
static const QString LAST_SCENE_KEY = "lastSceneFile";
|
||||
static const QString LAST_LOCATION_KEY = "lastLocation";
|
||||
|
||||
|
@ -94,7 +99,56 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
class GlfwCamera : public Camera {
|
||||
Key forKey(int key) {
|
||||
switch (key) {
|
||||
case GLFW_KEY_W: return FORWARD;
|
||||
case GLFW_KEY_S: return BACK;
|
||||
case GLFW_KEY_A: return LEFT;
|
||||
case GLFW_KEY_D: return RIGHT;
|
||||
case GLFW_KEY_E: return UP;
|
||||
case GLFW_KEY_C: return DOWN;
|
||||
case GLFW_MOUSE_BUTTON_LEFT: return MLEFT;
|
||||
case GLFW_MOUSE_BUTTON_RIGHT: return MRIGHT;
|
||||
case GLFW_MOUSE_BUTTON_MIDDLE: return MMIDDLE;
|
||||
default: break;
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
vec2 _lastMouse;
|
||||
public:
|
||||
void keyHandler(int key, int scancode, int action, int mods) {
|
||||
Key k = forKey(key);
|
||||
if (k == INVALID) {
|
||||
return;
|
||||
}
|
||||
if (action == GLFW_PRESS) {
|
||||
keys.set(k);
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
keys.reset(k);
|
||||
}
|
||||
}
|
||||
|
||||
//static void MouseMoveHandler(GLFWwindow* window, double posx, double posy);
|
||||
//static void MouseScrollHandler(GLFWwindow* window, double xoffset, double yoffset);
|
||||
void onMouseMove(double posx, double posy) {
|
||||
vec2 mouse = vec2(posx, posy);
|
||||
vec2 delta = mouse - _lastMouse;
|
||||
if (keys.at(Key::MRIGHT)) {
|
||||
dolly(delta.y * 0.01f);
|
||||
} else if (keys.at(Key::MLEFT)) {
|
||||
rotate(delta.x * -0.01f);
|
||||
} else if (keys.at(Key::MMIDDLE)) {
|
||||
delta.y *= -1.0f;
|
||||
translate(delta * -0.01f);
|
||||
}
|
||||
_lastMouse = mouse;
|
||||
}
|
||||
|
||||
};
|
||||
#else
|
||||
class QWindowCamera : public Camera {
|
||||
Key forKey(int key) {
|
||||
switch (key) {
|
||||
|
@ -143,6 +197,7 @@ public:
|
|||
_lastMouse = mouse;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static QString toHumanSize(size_t size, size_t maxUnit = std::numeric_limits<size_t>::max()) {
|
||||
static const std::vector<QString> SUFFIXES{ { "B", "KB", "MB", "GB", "TB", "PB" } };
|
||||
|
@ -175,8 +230,7 @@ extern QThread* RENDER_THREAD;
|
|||
class RenderThread : public GenericThread {
|
||||
using Parent = GenericThread;
|
||||
public:
|
||||
QOpenGLContextWrapper* _displayContext{ nullptr };
|
||||
QSurface* _displaySurface{ nullptr };
|
||||
gl::Context _context;
|
||||
gpu::PipelinePointer _presentPipeline;
|
||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||
std::atomic<size_t> _presentCount;
|
||||
|
@ -198,38 +252,44 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void initialize(QOpenGLContextWrapper* displayContext, QWindow* surface) {
|
||||
void initialize(QWindow* window, gl::Context& initContext) {
|
||||
setObjectName("RenderThread");
|
||||
_displayContext = displayContext;
|
||||
_displaySurface = surface;
|
||||
_displayContext->makeCurrent(_displaySurface);
|
||||
_context.setWindow(window);
|
||||
_context.create();
|
||||
_context.makeCurrent();
|
||||
window->setSurfaceType(QSurface::OpenGLSurface);
|
||||
_context.makeCurrent(_context.qglContext(), window);
|
||||
#ifdef Q_OS_WIN
|
||||
wglSwapIntervalEXT(0);
|
||||
#endif
|
||||
// GPU library init
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
_gpuContext = std::make_shared<gpu::Context>();
|
||||
_backend = _gpuContext->getBackend();
|
||||
_displayContext->makeCurrent(_displaySurface);
|
||||
_context.makeCurrent();
|
||||
DependencyManager::get<DeferredLightingEffect>()->init();
|
||||
_displayContext->doneCurrent();
|
||||
_context.makeCurrent();
|
||||
initContext.create();
|
||||
_context.doneCurrent();
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
Parent::initialize();
|
||||
if (isThreaded()) {
|
||||
_displayContext->moveToThread(thread());
|
||||
}
|
||||
_context.moveToThread(_thread);
|
||||
}
|
||||
|
||||
void setup() override {
|
||||
RENDER_THREAD = QThread::currentThread();
|
||||
QThread::currentThread()->setPriority(QThread::HighestPriority);
|
||||
|
||||
// Wait until the context has been moved to this thread
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
}
|
||||
_displayContext->makeCurrent(_displaySurface);
|
||||
|
||||
_context.makeCurrent();
|
||||
glewExperimental = true;
|
||||
glewInit();
|
||||
glGetError();
|
||||
_frameTimes.resize(FRAME_TIME_BUFFER_SIZE, 0);
|
||||
|
||||
_frameTimes.resize(FRAME_TIME_BUFFER_SIZE, 0);
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(SRGB_TO_LINEAR_FRAG));
|
||||
|
@ -254,14 +314,11 @@ public:
|
|||
}
|
||||
_presentPipeline.reset();
|
||||
_gpuContext.reset();
|
||||
if (isThreaded()) {
|
||||
_displayContext->moveToThread(qApp->thread());
|
||||
}
|
||||
}
|
||||
|
||||
void renderFrame(gpu::FramePointer& frame) {
|
||||
++_presentCount;
|
||||
_displayContext->makeCurrent(_displaySurface);
|
||||
_context.makeCurrent();
|
||||
_backend->recycle();
|
||||
_backend->syncCache();
|
||||
if (frame && !frame->batches.empty()) {
|
||||
|
@ -280,7 +337,8 @@ public:
|
|||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
_displayContext->swapBuffers(_displaySurface);
|
||||
_context.makeCurrent();
|
||||
_context.swapBuffers();
|
||||
_fpsCounter.increment();
|
||||
static size_t _frameCount{ 0 };
|
||||
++_frameCount;
|
||||
|
@ -290,7 +348,7 @@ public:
|
|||
_elapsed.restart();
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
_displayContext->doneCurrent();
|
||||
_context.doneCurrent();
|
||||
}
|
||||
|
||||
void report() {
|
||||
|
@ -350,7 +408,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// Background Render Data & rendering functions
|
||||
class BackgroundRenderData {
|
||||
public:
|
||||
|
@ -396,7 +453,6 @@ namespace render {
|
|||
|
||||
// Create a simple OpenGL window that renders text in various ways
|
||||
class QTestWindow : public QWindow, public AbstractViewStateInterface {
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
void copyCurrentViewFrustum(ViewFrustum& viewOut) const override {
|
||||
|
@ -476,28 +532,47 @@ public:
|
|||
nodeList->setPermissions(permissions);
|
||||
|
||||
ResourceManager::init();
|
||||
setSurfaceType(QSurface::OpenGLSurface);
|
||||
auto format = getDefaultOpenGLSurfaceFormat();
|
||||
format.setOption(QSurfaceFormat::DebugContext);
|
||||
setFormat(format);
|
||||
|
||||
resize(QSize(800, 600));
|
||||
setFlags(Qt::MSWindowsOwnDC);
|
||||
_size = QSize(800, 600);
|
||||
setGeometry(QRect(QPoint(), _size));
|
||||
create();
|
||||
show();
|
||||
QCoreApplication::processEvents();
|
||||
// Create the initial context
|
||||
_renderThread.initialize(this, _initContext);
|
||||
_initContext.makeCurrent();
|
||||
|
||||
_context.setFormat(format);
|
||||
_context.create();
|
||||
_context.makeCurrent(this);
|
||||
glewExperimental = true;
|
||||
glewInit();
|
||||
glGetError();
|
||||
#if 0
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
resizeWindow(QSize(800, 600));
|
||||
_window = glfwCreateWindow(_size.width(), _size.height(), "Window Title", NULL, NULL);
|
||||
if (!_window) {
|
||||
throw std::runtime_error("Could not create window");
|
||||
}
|
||||
|
||||
glfwSetWindowUserPointer(_window, this);
|
||||
glfwSetKeyCallback(_window, KeyboardHandler);
|
||||
glfwSetMouseButtonCallback(_window, MouseHandler);
|
||||
glfwSetCursorPosCallback(_window, MouseMoveHandler);
|
||||
glfwSetWindowCloseCallback(_window, CloseHandler);
|
||||
glfwSetFramebufferSizeCallback(_window, FramebufferSizeHandler);
|
||||
glfwSetScrollCallback(_window, MouseScrollHandler);
|
||||
|
||||
|
||||
glfwMakeContextCurrent(_window);
|
||||
GLDebug::setupLogger(this);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
wglSwapIntervalEXT(0);
|
||||
#endif
|
||||
_context.doneCurrent();
|
||||
|
||||
_initContext.create(_context.getContext());
|
||||
_renderThread.initialize(&_context, this);
|
||||
// FIXME use a wait condition
|
||||
QThread::msleep(1000);
|
||||
_renderThread.submitFrame(gpu::FramePointer());
|
||||
|
@ -627,7 +702,7 @@ private:
|
|||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
QSize windowSize = size();
|
||||
QSize windowSize = _size;
|
||||
framebufferCache->setFrameBufferSize(windowSize);
|
||||
|
||||
renderArgs._blitFramebuffer = framebufferCache->getFramebuffer();
|
||||
|
@ -676,11 +751,11 @@ private:
|
|||
};
|
||||
|
||||
void updateText() {
|
||||
setTitle(QString("FPS %1 Culling %2 TextureMemory GPU %3 CPU %4")
|
||||
QString title = QString("FPS %1 Culling %2 TextureMemory GPU %3 CPU %4")
|
||||
.arg(_fps).arg(_cullingEnabled)
|
||||
.arg(toHumanSize(gpu::Context::getTextureGPUMemoryUsage(), 2))
|
||||
.arg(toHumanSize(gpu::Texture::getTextureCPUMemoryUsage(), 2)));
|
||||
|
||||
.arg(toHumanSize(gpu::Texture::getTextureCPUMemoryUsage(), 2));
|
||||
setTitle(title);
|
||||
#if 0
|
||||
{
|
||||
_textBlocks.erase(TextBlock::Info);
|
||||
|
@ -801,12 +876,6 @@ private:
|
|||
|
||||
}
|
||||
|
||||
bool makeCurrent() {
|
||||
bool currentResult = _context.makeCurrent(this);
|
||||
Q_ASSERT(currentResult);
|
||||
return currentResult;
|
||||
}
|
||||
|
||||
void resizeWindow(const QSize& size) {
|
||||
_size = size;
|
||||
_camera.setAspectRatio((float)_size.width() / (float)_size.height());
|
||||
|
@ -960,12 +1029,11 @@ private:
|
|||
|
||||
render::EnginePointer _renderEngine { new render::Engine() };
|
||||
render::ScenePointer _main3DScene { new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||
QOpenGLContextWrapper _context;
|
||||
QSize _size;
|
||||
QSettings _settings;
|
||||
|
||||
std::atomic<size_t> _renderCount;
|
||||
OffscreenGLCanvas _initContext;
|
||||
gl::OffscreenContext _initContext;
|
||||
RenderThread _renderThread;
|
||||
QWindowCamera _camera;
|
||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||
|
|
|
@ -112,8 +112,6 @@ public:
|
|||
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
|
||||
|
||||
GLDebug::setupLogger(this);
|
||||
qDebug() << (const char*)glGetString(GL_VERSION);
|
||||
|
||||
//_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false);
|
||||
|
|
|
@ -108,9 +108,7 @@ public:
|
|||
|
||||
show();
|
||||
makeCurrent();
|
||||
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
GLDebug::setupLogger(this);
|
||||
makeCurrent();
|
||||
resize(QSize(800, 600));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue