mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 20:55:10 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into arrow-actions
This commit is contained in:
commit
87fbbd68ae
35 changed files with 873 additions and 323 deletions
|
@ -778,8 +778,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
|
|
||||||
// enable mouse tracking; otherwise, we only get drag events
|
// enable mouse tracking; otherwise, we only get drag events
|
||||||
_glWidget->setMouseTracking(true);
|
_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->makeCurrent();
|
||||||
_glWidget->initializeGL();
|
|
||||||
|
|
||||||
initializeGL();
|
initializeGL();
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
|
@ -1484,7 +1486,7 @@ void Application::initializeGL() {
|
||||||
_glWidget->makeCurrent();
|
_glWidget->makeCurrent();
|
||||||
_chromiumShareContext = new OffscreenGLCanvas();
|
_chromiumShareContext = new OffscreenGLCanvas();
|
||||||
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
||||||
_chromiumShareContext->create(_glWidget->context()->contextHandle());
|
_chromiumShareContext->create(_glWidget->qglContext());
|
||||||
_chromiumShareContext->makeCurrent();
|
_chromiumShareContext->makeCurrent();
|
||||||
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
||||||
|
|
||||||
|
@ -1531,7 +1533,7 @@ void Application::initializeGL() {
|
||||||
|
|
||||||
_offscreenContext = new OffscreenGLCanvas();
|
_offscreenContext = new OffscreenGLCanvas();
|
||||||
_offscreenContext->setObjectName("MainThreadContext");
|
_offscreenContext->setObjectName("MainThreadContext");
|
||||||
_offscreenContext->create(_glWidget->context()->contextHandle());
|
_offscreenContext->create(_glWidget->qglContext());
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
// update before the first render
|
// update before the first render
|
||||||
|
@ -1553,7 +1555,7 @@ void Application::initializeUi() {
|
||||||
|
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
offscreenUi->create(_glWidget->context()->contextHandle());
|
offscreenUi->create(_glWidget->qglContext());
|
||||||
|
|
||||||
auto rootContext = offscreenUi->getRootContext();
|
auto rootContext = offscreenUi->getRootContext();
|
||||||
|
|
||||||
|
@ -5675,7 +5677,7 @@ MainWindow* Application::getPrimaryWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLContext* Application::getPrimaryContext() {
|
QOpenGLContext* Application::getPrimaryContext() {
|
||||||
return _glWidget->context()->contextHandle();
|
return _glWidget->qglContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::makeRenderingContextCurrent() {
|
bool Application::makeRenderingContextCurrent() {
|
||||||
|
|
|
@ -22,7 +22,7 @@ class AddressBarDialog : public OffscreenQmlDialog {
|
||||||
Q_PROPERTY(bool backEnabled READ backEnabled NOTIFY backEnabledChanged)
|
Q_PROPERTY(bool backEnabled READ backEnabled NOTIFY backEnabledChanged)
|
||||||
Q_PROPERTY(bool forwardEnabled READ forwardEnabled NOTIFY forwardEnabledChanged)
|
Q_PROPERTY(bool forwardEnabled READ forwardEnabled NOTIFY forwardEnabledChanged)
|
||||||
Q_PROPERTY(bool useFeed READ useFeed WRITE setUseFeed NOTIFY useFeedChanged)
|
Q_PROPERTY(bool useFeed READ useFeed WRITE setUseFeed NOTIFY useFeedChanged)
|
||||||
Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl)
|
Q_PROPERTY(QString metaverseServerUrl READ metaverseServerUrl NOTIFY metaverseServerUrlChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AddressBarDialog(QQuickItem* parent = nullptr);
|
AddressBarDialog(QQuickItem* parent = nullptr);
|
||||||
|
@ -37,6 +37,7 @@ signals:
|
||||||
void forwardEnabledChanged();
|
void forwardEnabledChanged();
|
||||||
void useFeedChanged();
|
void useFeedChanged();
|
||||||
void receivedHifiSchemeURL(const QString& url);
|
void receivedHifiSchemeURL(const QString& url);
|
||||||
|
void metaverseServerUrlChanged(); // While it is a constant, qml will complain about not seeing a change signal.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void displayAddressOfflineMessage();
|
void displayAddressOfflineMessage();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <gl/GLWidget.h>
|
#include <gl/GLWidget.h>
|
||||||
#include <gl/Config.h>
|
#include <gl/Config.h>
|
||||||
#include <gl/GLEscrow.h>
|
#include <gl/GLEscrow.h>
|
||||||
|
#include <gl/Context.h>
|
||||||
|
|
||||||
#include <gpu/Texture.h>
|
#include <gpu/Texture.h>
|
||||||
#include <gpu/StandardShaderLib.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
|
// Move the OpenGL context to the present thread
|
||||||
// Extra code because of the widget 'wrapper' context
|
// Extra code because of the widget 'wrapper' context
|
||||||
_context = context;
|
_context = context;
|
||||||
|
@ -126,7 +127,6 @@ public:
|
||||||
OpenGLDisplayPlugin* currentPlugin{ nullptr };
|
OpenGLDisplayPlugin* currentPlugin{ nullptr };
|
||||||
Q_ASSERT(_context);
|
Q_ASSERT(_context);
|
||||||
_context->makeCurrent();
|
_context->makeCurrent();
|
||||||
Q_ASSERT(isCurrentContext(_context->contextHandle()));
|
|
||||||
while (!_shutdown) {
|
while (!_shutdown) {
|
||||||
if (_pendingMainThreadOperation) {
|
if (_pendingMainThreadOperation) {
|
||||||
PROFILE_RANGE("MainThreadOp")
|
PROFILE_RANGE("MainThreadOp")
|
||||||
|
@ -250,7 +250,7 @@ private:
|
||||||
bool _finishedMainThreadOperation { false };
|
bool _finishedMainThreadOperation { false };
|
||||||
QThread* _mainThread { nullptr };
|
QThread* _mainThread { nullptr };
|
||||||
std::queue<OpenGLDisplayPlugin*> _newPluginQueue;
|
std::queue<OpenGLDisplayPlugin*> _newPluginQueue;
|
||||||
QGLContext* _context { nullptr };
|
gl::Context* _context { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
bool OpenGLDisplayPlugin::activate() {
|
bool OpenGLDisplayPlugin::activate() {
|
||||||
|
@ -649,8 +649,8 @@ float OpenGLDisplayPlugin::presentRate() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::swapBuffers() {
|
void OpenGLDisplayPlugin::swapBuffers() {
|
||||||
static auto widget = _container->getPrimaryWidget();
|
static auto context = _container->getPrimaryWidget()->context();
|
||||||
widget->swapBuffers();
|
context->swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
|
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.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
||||||
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
||||||
setGLFormatVersion(format);
|
setGLFormatVersion(format);
|
||||||
if (GLDebug::enabled()) {
|
|
||||||
qDebug() << "Enabling debug context";
|
|
||||||
format.setOption(QSurfaceFormat::DebugContext);
|
|
||||||
}
|
|
||||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
});
|
});
|
||||||
return 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) {
|
int glVersionToInteger(QString glVersion) {
|
||||||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||||
int majorNumber = versionParts[0].toInt();
|
int majorNumber = versionParts[0].toInt();
|
||||||
int minorNumber = versionParts[1].toInt();
|
int minorNumber = versionParts[1].toInt();
|
||||||
return majorNumber * 100 + minorNumber * 10;
|
return (majorNumber << 16) | minorNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject getGLContextData() {
|
QJsonObject getGLContextData() {
|
||||||
if (!QOpenGLContext::currentContext()) {
|
|
||||||
return QJsonObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString glVersion = QString((const char*)glGetString(GL_VERSION));
|
QString glVersion = QString((const char*)glGetString(GL_VERSION));
|
||||||
QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
QString glslVersion = QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
QString glVendor = QString((const char*) glGetString(GL_VENDOR));
|
QString glVendor = QString((const char*) glGetString(GL_VENDOR));
|
||||||
|
@ -77,31 +53,3 @@ QThread* RENDER_THREAD = nullptr;
|
||||||
bool isRenderThread() {
|
bool isRenderThread() {
|
||||||
return QThread::currentThread() == RENDER_THREAD;
|
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); }
|
void setGLFormatVersion(F& format, int major = 4, int minor = 5) { format.setVersion(major, minor); }
|
||||||
|
|
||||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
||||||
const QGLFormat& getDefaultGLFormat();
|
|
||||||
QJsonObject getGLContextData();
|
QJsonObject getGLContextData();
|
||||||
int glVersionToInteger(QString glVersion);
|
int glVersionToInteger(QString glVersion);
|
||||||
|
|
||||||
bool isRenderThread();
|
bool isRenderThread();
|
||||||
|
|
||||||
|
|
||||||
class GLDebug {
|
|
||||||
public:
|
|
||||||
static bool enabled();
|
|
||||||
static void log(const QOpenGLDebugMessage& debugMessage);
|
|
||||||
static void setupLogger(QObject* window = nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,30 +7,52 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#include "GLWidget.h"
|
#include "GLWidget.h"
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
#include <QtCore/QMimeData>
|
#include <QtCore/QMimeData>
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
|
|
||||||
#include <QtGui/QOpenGLContext>
|
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
|
#include <QtGui/QPaintEngine>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
|
#include "Context.h"
|
||||||
#include "GLHelpers.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
|
#ifdef Q_OS_LINUX
|
||||||
// Cause GLWidget::eventFilter to be called.
|
// 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.
|
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
|
||||||
qApp->installEventFilter(this);
|
qApp->installEventFilter(this);
|
||||||
#endif
|
#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 {
|
int GLWidget::getDeviceWidth() const {
|
||||||
|
@ -41,31 +63,25 @@ int GLWidget::getDeviceHeight() const {
|
||||||
return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
|
return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::initializeGL() {
|
void GLWidget::createContext() {
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
_context = new gl::Context();
|
||||||
grabGesture(Qt::PinchGesture);
|
_context->setWindow(windowHandle());
|
||||||
setAcceptDrops(true);
|
_context->create();
|
||||||
// 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.
|
_context->clear();
|
||||||
setAutoBufferSwap(false);
|
_context->makeCurrent();
|
||||||
|
|
||||||
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::paintEvent(QPaintEvent* event) {
|
bool GLWidget::makeCurrent() {
|
||||||
QWidget::paintEvent(event);
|
gl::Context::makeCurrent(_context->qglContext(), windowHandle());
|
||||||
|
return _context->makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLWidget::resizeEvent(QResizeEvent* event) {
|
QOpenGLContext* GLWidget::qglContext() {
|
||||||
QWidget::resizeEvent(event);
|
return _context->qglContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLWidget::doneCurrent() {
|
||||||
|
_context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLWidget::event(QEvent* event) {
|
bool GLWidget::event(QEvent* event) {
|
||||||
|
@ -94,10 +110,9 @@ bool GLWidget::event(QEvent* event) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return QGLWidget::event(event);
|
return QWidget::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
// 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
|
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
|
||||||
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
|
// 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) {
|
} else if (event->type() == QEvent::KeyRelease) {
|
||||||
keyReleaseEvent(keyEvent);
|
keyReleaseEvent(keyEvent);
|
||||||
} else {
|
} else {
|
||||||
QGLWidget::event(event);
|
QWidget::event(event);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +145,22 @@ bool GLWidget::eventFilter(QObject*, QEvent* event) {
|
||||||
return false;
|
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
|
#ifndef hifi_GLWidget_h
|
||||||
#define 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
|
/// customized canvas that simply forwards requests/events to the singleton application
|
||||||
class GLWidget : public QGLWidget {
|
class GLWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLWidget();
|
GLWidget();
|
||||||
|
~GLWidget();
|
||||||
int getDeviceWidth() const;
|
int getDeviceWidth() const;
|
||||||
int getDeviceHeight() const;
|
int getDeviceHeight() const;
|
||||||
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
|
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
|
||||||
bool isVsyncSupported() const;
|
QPaintEngine* paintEngine() const override;
|
||||||
virtual void initializeGL() override;
|
void createContext();
|
||||||
|
bool makeCurrent();
|
||||||
|
void doneCurrent();
|
||||||
|
gl::Context* context() { return _context; }
|
||||||
|
QOpenGLContext* qglContext();
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||||
virtual bool event(QEvent* event) override;
|
virtual bool event(QEvent* event) override;
|
||||||
virtual void paintEvent(QPaintEvent* event) override;
|
gl::Context* _context { nullptr };
|
||||||
virtual void resizeEvent(QResizeEvent* event) override;
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
virtual bool eventFilter(QObject*, QEvent* event) override;
|
virtual bool eventFilter(QObject*, QEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QPaintEngine* _paintEngine { nullptr };
|
||||||
bool _vsyncSupported { false };
|
bool _vsyncSupported { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_GLCanvas_h
|
#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 Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||||
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||||
GLDebug::setupLogger(this);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -10,27 +10,46 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "OpenGLVersionChecker.h"
|
#include "OpenGLVersionChecker.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "GLWidget.h"
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <QtCore/QRegularExpression>
|
||||||
|
#include <QtCore/QJsonObject>
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
|
#include <QtOpenGL/QGLWidget>
|
||||||
|
|
||||||
#include "GLHelpers.h"
|
#include "GLHelpers.h"
|
||||||
|
|
||||||
#define MINIMUM_GL_VERSION 410
|
#define MINIMUM_GL_VERSION 0x0401
|
||||||
|
|
||||||
OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) :
|
OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) :
|
||||||
QApplication(argc, 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) {
|
QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||||
valid = true;
|
valid = true;
|
||||||
override = false;
|
override = false;
|
||||||
|
|
||||||
GLWidget* glWidget = new GLWidget();
|
QGLWidget* glWidget = new QGLWidget();
|
||||||
valid = glWidget->isValid();
|
valid = glWidget->isValid();
|
||||||
// Inform user if no OpenGL support
|
// Inform user if no OpenGL support
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
@ -46,7 +65,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve OpenGL version
|
// Retrieve OpenGL version
|
||||||
glWidget->initializeGL();
|
// glWidget->initializeGL();
|
||||||
|
glWidget->makeCurrent();
|
||||||
QJsonObject glData = getGLContextData();
|
QJsonObject glData = getGLContextData();
|
||||||
delete glWidget;
|
delete glWidget;
|
||||||
|
|
||||||
|
@ -60,8 +80,8 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||||
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||||
int majorNumber = versionParts[0].toInt();
|
int majorNumber = versionParts[0].toInt();
|
||||||
int minorNumber = versionParts[1].toInt();
|
int minorNumber = versionParts[1].toInt();
|
||||||
int minimumMajorNumber = MINIMUM_GL_VERSION / 100;
|
int minimumMajorNumber = (MINIMUM_GL_VERSION >> 16);
|
||||||
int minimumMinorNumber = (MINIMUM_GL_VERSION - minimumMajorNumber * 100) / 10;
|
int minimumMinorNumber = (MINIMUM_GL_VERSION & 0xFF);
|
||||||
valid = (majorNumber > minimumMajorNumber
|
valid = (majorNumber > minimumMajorNumber
|
||||||
|| (majorNumber == minimumMajorNumber && minorNumber >= minimumMinorNumber));
|
|| (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 no memory limit has been set, use a percentage of the total dedicated memory
|
||||||
if (!availableTextureMemory) {
|
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,
|
// If no limit has been explicitly set, and the dedicated memory can't be determined,
|
||||||
// just use a fallback fixed value of 256 MB
|
// just use a fallback fixed value of 256 MB
|
||||||
|
@ -118,7 +118,7 @@ float GLTexture::getMemoryPressure() {
|
||||||
return (float)consumedGpuMemory / (float)availableTextureMemory;
|
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),
|
_backend(backend),
|
||||||
_size(oldTexture ? oldTexture->_size : 0),
|
_size(oldTexture ? oldTexture->_size : 0),
|
||||||
_texture(oldTexture ? oldTexture->takeOwnership() : 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
|
// 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)
|
GLTexture(backend, texture, id, nullptr, transferrable)
|
||||||
{
|
{
|
||||||
// FIXME, do during allocation
|
// 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
|
// 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)
|
GLTexture(backend, texture, id, originalTexture, originalTexture->_transferrable)
|
||||||
{
|
{
|
||||||
Q_ASSERT(_minMip >= originalTexture->_minMip);
|
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 we just did a transfer, return the object after doing post-transfer work
|
||||||
if (GLSyncState::Transferred == object->getSyncState()) {
|
if (GLSyncState::Transferred == object->getSyncState()) {
|
||||||
object->postTransfer();
|
object->postTransfer();
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object->isOutdated()) {
|
if (object->isOutdated()) {
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
//
|
//
|
||||||
#include "GLTextureTransfer.h"
|
#include "GLTextureTransfer.h"
|
||||||
|
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#include <gl/GLHelpers.h>
|
||||||
#include <gl/OffscreenGLCanvas.h>
|
#include <gl/Context.h>
|
||||||
#include <gl/QOpenGLContextWrapper.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "GLShared.h"
|
#include "GLShared.h"
|
||||||
#include "GLTexture.h"
|
#include "GLTexture.h"
|
||||||
|
@ -20,16 +18,9 @@ using namespace gpu::gl;
|
||||||
|
|
||||||
GLTextureTransferHelper::GLTextureTransferHelper() {
|
GLTextureTransferHelper::GLTextureTransferHelper() {
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
_canvas = QSharedPointer<OffscreenGLCanvas>(new OffscreenGLCanvas(), &QObject::deleteLater);
|
setObjectName("TextureTransferThread");
|
||||||
_canvas->setObjectName("TextureTransferCanvas");
|
_context.create();
|
||||||
_canvas->create(QOpenGLContextWrapper::currentContext());
|
|
||||||
if (!_canvas->makeCurrent()) {
|
|
||||||
qFatal("Unable to create texture transfer context");
|
|
||||||
}
|
|
||||||
_canvas->doneCurrent();
|
|
||||||
initialize(true, QThread::LowPriority);
|
initialize(true, QThread::LowPriority);
|
||||||
_canvas->moveToThreadWithContext(_thread);
|
|
||||||
|
|
||||||
// Clean shutdown on UNIX, otherwise _canvas is freed early
|
// Clean shutdown on UNIX, otherwise _canvas is freed early
|
||||||
connect(qApp, &QCoreApplication::aboutToQuit, [&] { terminate(); });
|
connect(qApp, &QCoreApplication::aboutToQuit, [&] { terminate(); });
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,17 +55,9 @@ void GLTextureTransferHelper::transferTexture(const gpu::TexturePointer& texture
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTextureTransferHelper::setup() {
|
void GLTextureTransferHelper::setup() {
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
|
||||||
_canvas->makeCurrent();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTextureTransferHelper::shutdown() {
|
void GLTextureTransferHelper::shutdown() {
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
|
||||||
_canvas->doneCurrent();
|
|
||||||
_canvas->moveToThreadWithContext(qApp->thread());
|
|
||||||
_canvas.reset();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLTextureTransferHelper::do_transfer(GLTexture& texture) {
|
void GLTextureTransferHelper::do_transfer(GLTexture& texture) {
|
||||||
|
@ -85,6 +68,9 @@ void GLTextureTransferHelper::do_transfer(GLTexture& texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLTextureTransferHelper::processQueueItems(const Queue& messages) {
|
bool GLTextureTransferHelper::processQueueItems(const Queue& messages) {
|
||||||
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
|
_context.makeCurrent();
|
||||||
|
#endif
|
||||||
for (auto package : messages) {
|
for (auto package : messages) {
|
||||||
TexturePointer texturePointer = package.texture.lock();
|
TexturePointer texturePointer = package.texture.lock();
|
||||||
// Texture no longer exists, move on to the next
|
// Texture no longer exists, move on to the next
|
||||||
|
@ -93,21 +79,39 @@ bool GLTextureTransferHelper::processQueueItems(const Queue& messages) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (package.fence) {
|
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);
|
glDeleteSync(package.fence);
|
||||||
package.fence = 0;
|
package.fence = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLTexture* object = Backend::getGPUObject<GLTexture>(*texturePointer);
|
GLTexture* object = Backend::getGPUObject<GLTexture>(*texturePointer);
|
||||||
|
|
||||||
do_transfer(*object);
|
do_transfer(*object);
|
||||||
glBindTexture(object->_target, 0);
|
glBindTexture(object->_target, 0);
|
||||||
|
|
||||||
auto writeSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
{
|
||||||
glClientWaitSync(writeSync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
|
auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glDeleteSync(writeSync);
|
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->_contentStamp = texturePointer->getDataStamp();
|
||||||
object->setSyncState(GLSyncState::Transferred);
|
object->setSyncState(GLSyncState::Transferred);
|
||||||
}
|
}
|
||||||
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
|
_context.doneCurrent();
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
#include <GenericQueueThread.h>
|
#include <GenericQueueThread.h>
|
||||||
|
|
||||||
|
#include <gl/Context.h>
|
||||||
|
|
||||||
#include "GLShared.h"
|
#include "GLShared.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#define THREADED_TEXTURE_TRANSFER
|
#define THREADED_TEXTURE_TRANSFER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class OffscreenGLCanvas;
|
|
||||||
|
|
||||||
namespace gpu { namespace gl {
|
namespace gpu { namespace gl {
|
||||||
|
|
||||||
struct TextureTransferPackage {
|
struct TextureTransferPackage {
|
||||||
|
@ -43,7 +43,7 @@ protected:
|
||||||
void do_transfer(GLTexture& texturePointer);
|
void do_transfer(GLTexture& texturePointer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<OffscreenGLCanvas> _canvas;
|
::gl::OffscreenContext _context;
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -27,8 +27,10 @@
|
||||||
|
|
||||||
namespace gpu { namespace gl41 {
|
namespace gpu { namespace gl41 {
|
||||||
|
|
||||||
class GL41Backend : public gl::GLBackend {
|
using namespace gpu::gl;
|
||||||
using Parent = gl::GLBackend;
|
|
||||||
|
class GL41Backend : public GLBackend {
|
||||||
|
using Parent = GLBackend;
|
||||||
// Context Backend static interface required
|
// Context Backend static interface required
|
||||||
friend class Context;
|
friend class Context;
|
||||||
|
|
||||||
|
@ -36,12 +38,12 @@ public:
|
||||||
explicit GL41Backend(bool syncCache) : Parent(syncCache) {}
|
explicit GL41Backend(bool syncCache) : Parent(syncCache) {}
|
||||||
GL41Backend() : Parent() {}
|
GL41Backend() : Parent() {}
|
||||||
|
|
||||||
class GL41Texture : public gpu::gl::GLTexture {
|
class GL41Texture : public GLTexture {
|
||||||
using Parent = gpu::gl::GLTexture;
|
using Parent = GLTexture;
|
||||||
GLuint allocate();
|
GLuint allocate();
|
||||||
public:
|
public:
|
||||||
GL41Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& buffer, bool transferrable);
|
GL41Texture(const std::weak_ptr<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, GL41Texture* original);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
||||||
|
@ -56,16 +58,16 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
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;
|
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;
|
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;
|
GLuint getQueryID(const QueryPointer& query) override;
|
||||||
gl::GLQuery* syncGPUObject(const Query& query) override;
|
GLQuery* syncGPUObject(const Query& query) override;
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace gl41 {
|
namespace gl41 {
|
||||||
class GL41Buffer : public gl::GLBuffer {
|
class GL41Buffer : public gpu::gl::GLBuffer {
|
||||||
using Parent = gpu::gl::GLBuffer;
|
using Parent = gpu::gl::GLBuffer;
|
||||||
static GLuint allocate() {
|
static GLuint allocate() {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
|
@ -55,6 +55,7 @@ namespace gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,6 +63,6 @@ GLuint GL41Backend::getBufferID(const Buffer& buffer) {
|
||||||
return GL41Buffer::getId<GL41Buffer>(*this, 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);
|
return GL41Buffer::sync<GL41Buffer>(*this, buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,11 @@
|
||||||
#include "../gl/GLQuery.h"
|
#include "../gl/GLQuery.h"
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
class GL41Query : public gpu::gl::GLQuery {
|
class GL41Query : public GLQuery {
|
||||||
using Parent = gpu::gl::GLQuery;
|
using Parent = GLQuery;
|
||||||
public:
|
public:
|
||||||
static GLuint allocateQuery() {
|
static GLuint allocateQuery() {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
|
@ -24,11 +25,11 @@ public:
|
||||||
return result;
|
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()) { }
|
: Parent(backend, query, allocateQuery(), allocateQuery()) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
gl::GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
||||||
return GL41Query::sync<GL41Query>(*this, query);
|
return GL41Query::sync<GL41Query>(*this, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
#include "../gl/GLTexelFormat.h"
|
#include "../gl/GLTexelFormat.h"
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
using GL41TexelFormat = gl::GLTexelFormat;
|
using GL41TexelFormat = GLTexelFormat;
|
||||||
using GL41Texture = GL41Backend::GL41Texture;
|
using GL41Texture = GL41Backend::GL41Texture;
|
||||||
|
|
||||||
GLuint GL41Texture::allocate() {
|
GLuint GL41Texture::allocate() {
|
||||||
|
@ -33,13 +34,13 @@ GLuint GL41Backend::getTextureID(const TexturePointer& texture, bool transfer) {
|
||||||
return GL41Texture::getId<GL41Texture>(*this, texture, 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);
|
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 {
|
void GL41Backend::GL41Texture::withPreservedTexture(std::function<void()> f) const {
|
||||||
GLint boundTex = -1;
|
GLint boundTex = -1;
|
||||||
|
@ -71,7 +72,7 @@ void GL41Backend::GL41Texture::generateMips() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL41Backend::GL41Texture::allocateStorage() 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);
|
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
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
|
// 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 {
|
void GL41Backend::GL41Texture::transferMip(uint16_t mipLevel, uint8_t face) const {
|
||||||
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
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 = getFaceTargets()[face];
|
||||||
GLenum target = _target == GL_TEXTURE_2D ? GL_TEXTURE_2D : CUBE_FACE_LAYOUT[face];
|
GLenum target = _target == GL_TEXTURE_2D ? GL_TEXTURE_2D : CUBE_FACE_LAYOUT[face];
|
||||||
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||||
|
@ -216,7 +217,7 @@ void GL41Backend::GL41Texture::syncSampler() const {
|
||||||
|
|
||||||
if (sampler.doComparison()) {
|
if (sampler.doComparison()) {
|
||||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
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 {
|
} else {
|
||||||
glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
glTexParameteri(_target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,9 @@ void GL41Backend::transferTransformState(const Batch& batch) const {
|
||||||
#else
|
#else
|
||||||
glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT);
|
glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT);
|
||||||
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
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
|
#endif
|
||||||
|
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
#include "../gl/GLTexture.h"
|
#include "../gl/GLTexture.h"
|
||||||
|
|
||||||
namespace gpu { namespace gl45 {
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
using namespace gpu::gl;
|
||||||
|
|
||||||
class GL45Backend : public gl::GLBackend {
|
class GL45Backend : public GLBackend {
|
||||||
using Parent = gl::GLBackend;
|
using Parent = GLBackend;
|
||||||
// Context Backend static interface required
|
// Context Backend static interface required
|
||||||
friend class Context;
|
friend class Context;
|
||||||
|
|
||||||
|
@ -25,12 +27,12 @@ public:
|
||||||
explicit GL45Backend(bool syncCache) : Parent(syncCache) {}
|
explicit GL45Backend(bool syncCache) : Parent(syncCache) {}
|
||||||
GL45Backend() : Parent() {}
|
GL45Backend() : Parent() {}
|
||||||
|
|
||||||
class GL45Texture : public gpu::gl::GLTexture {
|
class GL45Texture : public GLTexture {
|
||||||
using Parent = gpu::gl::GLTexture;
|
using Parent = GLTexture;
|
||||||
GLuint allocate(const Texture& texture);
|
GLuint allocate(const Texture& texture);
|
||||||
public:
|
public:
|
||||||
GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, bool transferrable);
|
GL45Texture(const std::weak_ptr<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, GLTexture* original);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
||||||
|
@ -45,16 +47,16 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
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;
|
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;
|
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;
|
GLuint getQueryID(const QueryPointer& query) override;
|
||||||
gl::GLQuery* syncGPUObject(const Query& query) override;
|
GLQuery* syncGPUObject(const Query& query) override;
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
|
@ -8,41 +8,42 @@
|
||||||
#include "GL45Backend.h"
|
#include "GL45Backend.h"
|
||||||
#include "../gl/GLBuffer.h"
|
#include "../gl/GLBuffer.h"
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu { namespace gl45 {
|
||||||
namespace gl45 {
|
using namespace gpu::gl;
|
||||||
class GL45Buffer : public gl::GLBuffer {
|
|
||||||
using Parent = gpu::gl::GLBuffer;
|
|
||||||
static GLuint allocate() {
|
|
||||||
GLuint result;
|
|
||||||
glCreateBuffers(1, &result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
class GL45Buffer : public GLBuffer {
|
||||||
GL45Buffer(const std::weak_ptr<gl::GLBackend>& backend, const Buffer& buffer, GLBuffer* original) : Parent(backend, buffer, allocate()) {
|
using Parent = GLBuffer;
|
||||||
glNamedBufferStorage(_buffer, _size == 0 ? 256 : _size, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
static GLuint allocate() {
|
||||||
if (original && original->_size) {
|
GLuint result;
|
||||||
glCopyNamedBufferSubData(original->_buffer, _buffer, 0, 0, std::min(original->_size, _size));
|
glCreateBuffers(1, &result);
|
||||||
}
|
return result;
|
||||||
Backend::setGPUObject(buffer, this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void transfer() override {
|
public:
|
||||||
Size offset;
|
GL45Buffer(const std::weak_ptr<GLBackend>& backend, const Buffer& buffer, GLBuffer* original) : Parent(backend, buffer, allocate()) {
|
||||||
Size size;
|
glNamedBufferStorage(_buffer, _size == 0 ? 256 : _size, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||||
Size currentPage { 0 };
|
if (original && original->_size) {
|
||||||
auto data = _gpuObject._renderSysmem.readData();
|
glCopyNamedBufferSubData(original->_buffer, _buffer, 0, 0, std::min(original->_size, _size));
|
||||||
while (_gpuObject._renderPages.getNextTransferBlock(offset, size, currentPage)) {
|
|
||||||
glNamedBufferSubData(_buffer, (GLintptr)offset, (GLsizeiptr)size, data + offset);
|
|
||||||
}
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
_gpuObject._renderPages._flags &= ~PageManager::DIRTY;
|
|
||||||
}
|
}
|
||||||
};
|
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;
|
||||||
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +51,6 @@ GLuint GL45Backend::getBufferID(const Buffer& buffer) {
|
||||||
return GL45Buffer::getId<GL45Buffer>(*this, 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);
|
return GL45Buffer::sync<GL45Buffer>(*this, buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,15 @@
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include "../gl/GLTexelFormat.h"
|
#include "../gl/GLTexelFormat.h"
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
using GLTexelFormat = gl::GLTexelFormat;
|
|
||||||
using GL45Texture = GL45Backend::GL45Texture;
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
|
|
||||||
GLuint GL45Texture::allocate(const Texture& texture) {
|
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);
|
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);
|
return GL45Texture::sync<GL45Texture>(*this, texture, transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, bool transferrable)
|
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, bool transferrable)
|
||||||
: gl::GLTexture(backend, texture, allocate(texture), transferrable) {}
|
: GLTexture(backend, texture, allocate(texture), transferrable) {}
|
||||||
|
|
||||||
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<gl::GLBackend>& backend, const Texture& texture, GLTexture* original)
|
GL45Backend::GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture, GLTexture* original)
|
||||||
: gl::GLTexture(backend, texture, allocate(texture), original) {}
|
: GLTexture(backend, texture, allocate(texture), original) {}
|
||||||
|
|
||||||
void GL45Backend::GL45Texture::withPreservedTexture(std::function<void()> f) const {
|
void GL45Backend::GL45Texture::withPreservedTexture(std::function<void()> f) const {
|
||||||
f();
|
f();
|
||||||
|
@ -53,7 +54,7 @@ void GL45Backend::GL45Texture::generateMips() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Backend::GL45Texture::allocateStorage() 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_BASE_LEVEL, 0);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||||
if (_gpuObject.getTexelFormat().isCompressed()) {
|
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
|
// 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 {
|
void GL45Backend::GL45Texture::transferMip(uint16_t mipLevel, uint8_t face) const {
|
||||||
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
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);
|
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||||
if (GL_TEXTURE_2D == _target) {
|
if (GL_TEXTURE_2D == _target) {
|
||||||
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
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()) {
|
if (sampler.doComparison()) {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
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 {
|
} else {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,12 @@ Skybox::Skybox() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skybox::setColor(const Color& color) {
|
void Skybox::setColor(const Color& color) {
|
||||||
|
_empty = false;
|
||||||
_schemaBuffer.edit<Schema>().color = color;
|
_schemaBuffer.edit<Schema>().color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
||||||
|
_empty = false;
|
||||||
_cubemap = cubemap;
|
_cubemap = cubemap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,7 @@ void Skybox::updateSchemaBuffer() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skybox::clear() {
|
void Skybox::clear() {
|
||||||
|
_empty = true;
|
||||||
_schemaBuffer.edit<Schema>().color = vec3(0);
|
_schemaBuffer.edit<Schema>().color = vec3(0);
|
||||||
setCubemap(nullptr);
|
setCubemap(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void setCubemap(const gpu::TexturePointer& cubemap);
|
void setCubemap(const gpu::TexturePointer& cubemap);
|
||||||
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
|
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
|
||||||
|
|
||||||
virtual bool empty() { return _schemaBuffer.get<Schema>().color == vec3(0) && !_cubemap; }
|
virtual bool empty() { return _empty; }
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const;
|
void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const;
|
||||||
|
@ -47,17 +47,17 @@ protected:
|
||||||
static const int SKYBOX_SKYMAP_SLOT { 0 };
|
static const int SKYBOX_SKYMAP_SLOT { 0 };
|
||||||
static const int SKYBOX_CONSTANTS_SLOT { 0 };
|
static const int SKYBOX_CONSTANTS_SLOT { 0 };
|
||||||
|
|
||||||
gpu::TexturePointer _cubemap;
|
|
||||||
|
|
||||||
class Schema {
|
class Schema {
|
||||||
public:
|
public:
|
||||||
glm::vec3 color { 0.0f, 0.0f, 0.0f };
|
glm::vec3 color { 0.0f, 0.0f, 0.0f };
|
||||||
float blend { 0.0f };
|
float blend { 0.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
mutable gpu::BufferView _schemaBuffer;
|
|
||||||
|
|
||||||
void updateSchemaBuffer() const;
|
void updateSchemaBuffer() const;
|
||||||
|
|
||||||
|
mutable gpu::BufferView _schemaBuffer;
|
||||||
|
gpu::TexturePointer _cubemap;
|
||||||
|
bool _empty{ true };
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr<Skybox> SkyboxPointer;
|
typedef std::shared_ptr<Skybox> SkyboxPointer;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||||
_windowGeometry("WindowGeometry"),
|
_windowGeometry("WindowGeometry"),
|
||||||
_windowState("WindowState", 0)
|
_windowState("WindowState", 0)
|
||||||
{
|
{
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground);
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,12 @@
|
||||||
|
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
#include <gl/Context.h>
|
||||||
|
|
||||||
#include <gpu/Frame.h>
|
#include <gpu/Frame.h>
|
||||||
#include <gpu/gl/GLBackend.h>
|
#include <gpu/gl/GLBackend.h>
|
||||||
|
|
||||||
|
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <shared/NsightHelpers.h>
|
#include <shared/NsightHelpers.h>
|
||||||
|
@ -56,7 +59,7 @@ public:
|
||||||
using Condition = std::condition_variable;
|
using Condition = std::condition_variable;
|
||||||
using Lock = std::unique_lock<Mutex>;
|
using Lock = std::unique_lock<Mutex>;
|
||||||
friend class OpenVrDisplayPlugin;
|
friend class OpenVrDisplayPlugin;
|
||||||
std::shared_ptr<OffscreenGLCanvas> _canvas;
|
std::shared_ptr<gl::OffscreenContext> _canvas;
|
||||||
BasicFramebufferWrapperPtr _framebuffer;
|
BasicFramebufferWrapperPtr _framebuffer;
|
||||||
ProgramPtr _program;
|
ProgramPtr _program;
|
||||||
ShapeWrapperPtr _plane;
|
ShapeWrapperPtr _plane;
|
||||||
|
@ -129,7 +132,6 @@ public:
|
||||||
|
|
||||||
void run() override {
|
void run() override {
|
||||||
QThread::currentThread()->setPriority(QThread::Priority::TimeCriticalPriority);
|
QThread::currentThread()->setPriority(QThread::Priority::TimeCriticalPriority);
|
||||||
assert(_canvas->thread() == QThread::currentThread());
|
|
||||||
_canvas->makeCurrent();
|
_canvas->makeCurrent();
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glViewport(0, 0, _plugin._renderTargetSize.x, _plugin._renderTargetSize.y);
|
glViewport(0, 0, _plugin._renderTargetSize.x, _plugin._renderTargetSize.y);
|
||||||
|
@ -206,7 +208,6 @@ public:
|
||||||
_program.reset();
|
_program.reset();
|
||||||
_framebuffer.reset();
|
_framebuffer.reset();
|
||||||
_canvas->doneCurrent();
|
_canvas->doneCurrent();
|
||||||
_canvas->moveToThreadWithContext(qApp->thread());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const CompositeInfo& newCompositeInfo) {
|
void update(const CompositeInfo& newCompositeInfo) {
|
||||||
|
@ -309,14 +310,11 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
||||||
if (!_submitCanvas) {
|
if (!_submitCanvas) {
|
||||||
withMainThreadContext([&] {
|
withMainThreadContext([&] {
|
||||||
_submitCanvas = std::make_shared<OffscreenGLCanvas>();
|
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
||||||
_submitCanvas->setObjectName("OpenVRSubmitContext");
|
_submitCanvas->create();
|
||||||
_submitCanvas->create(_container->getPrimaryContext());
|
|
||||||
_submitCanvas->doneCurrent();
|
_submitCanvas->doneCurrent();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_submitCanvas->moveToThreadWithContext(_submitThread.get());
|
|
||||||
assert(_submitCanvas->thread() == _submitThread.get());
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return Parent::internalActivate();
|
return Parent::internalActivate();
|
||||||
|
@ -354,7 +352,6 @@ void OpenVrDisplayPlugin::customizeContext() {
|
||||||
}
|
}
|
||||||
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
||||||
}
|
}
|
||||||
assert(_submitCanvas->thread() == _submitThread.get());
|
|
||||||
_submitThread->_canvas = _submitCanvas;
|
_submitThread->_canvas = _submitCanvas;
|
||||||
_submitThread->start(QThread::HighPriority);
|
_submitThread->start(QThread::HighPriority);
|
||||||
#endif
|
#endif
|
||||||
|
@ -367,7 +364,6 @@ void OpenVrDisplayPlugin::uncustomizeContext() {
|
||||||
_submitThread->_quit = true;
|
_submitThread->_quit = true;
|
||||||
_submitThread->wait();
|
_submitThread->wait();
|
||||||
_submitThread.reset();
|
_submitThread.reset();
|
||||||
assert(_submitCanvas->thread() == qApp->thread());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p
|
||||||
#define OPENVR_THREADED_SUBMIT 1
|
#define OPENVR_THREADED_SUBMIT 1
|
||||||
|
|
||||||
#if OPENVR_THREADED_SUBMIT
|
#if OPENVR_THREADED_SUBMIT
|
||||||
|
namespace gl {
|
||||||
|
class OffscreenContext;
|
||||||
|
}
|
||||||
class OpenVrSubmitThread;
|
class OpenVrSubmitThread;
|
||||||
class OffscreenGLCanvas;
|
class OffscreenGLCanvas;
|
||||||
static const size_t COMPOSITING_BUFFER_SIZE = 3;
|
static const size_t COMPOSITING_BUFFER_SIZE = 3;
|
||||||
|
@ -79,7 +82,7 @@ private:
|
||||||
CompositeInfo::Array _compositeInfos;
|
CompositeInfo::Array _compositeInfos;
|
||||||
size_t _renderingIndex { 0 };
|
size_t _renderingIndex { 0 };
|
||||||
std::shared_ptr<OpenVrSubmitThread> _submitThread;
|
std::shared_ptr<OpenVrSubmitThread> _submitThread;
|
||||||
std::shared_ptr<OffscreenGLCanvas> _submitCanvas;
|
std::shared_ptr<gl::OffscreenContext> _submitCanvas;
|
||||||
friend class OpenVrSubmitThread;
|
friend class OpenVrSubmitThread;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -803,7 +803,7 @@ function setupModelMenus() {
|
||||||
menuName: "Edit",
|
menuName: "Edit",
|
||||||
menuItemName: "Delete",
|
menuItemName: "Delete",
|
||||||
shortcutKeyEvent: {
|
shortcutKeyEvent: {
|
||||||
text: "backspace"
|
text: "delete"
|
||||||
},
|
},
|
||||||
afterItem: "Entities",
|
afterItem: "Entities",
|
||||||
grouping: "Advanced"
|
grouping: "Advanced"
|
||||||
|
@ -1215,7 +1215,7 @@ Controller.keyReleaseEvent.connect(function (event) {
|
||||||
cameraManager.keyReleaseEvent(event);
|
cameraManager.keyReleaseEvent(event);
|
||||||
}
|
}
|
||||||
// since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items
|
// since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items
|
||||||
if (event.text === "BACKSPACE" || event.text === "DELETE") {
|
if (event.text === "DELETE") {
|
||||||
deleteSelectedEntities();
|
deleteSelectedEntities();
|
||||||
} else if (event.text === "ESC") {
|
} else if (event.text === "ESC") {
|
||||||
selectionManager.clearSelections();
|
selectionManager.clearSelections();
|
||||||
|
|
|
@ -73,7 +73,6 @@ void TestWindow::initGl() {
|
||||||
DependencyManager::set<DeferredLightingEffect>();
|
DependencyManager::set<DeferredLightingEffect>();
|
||||||
resize(QSize(800, 600));
|
resize(QSize(800, 600));
|
||||||
|
|
||||||
GLDebug::setupLogger(this);
|
|
||||||
#ifdef DEFERRED_LIGHTING
|
#ifdef DEFERRED_LIGHTING
|
||||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||||
deferredLightingEffect->init();
|
deferredLightingEffect->init();
|
||||||
|
|
|
@ -32,6 +32,9 @@ public:
|
||||||
DOWN,
|
DOWN,
|
||||||
BACK,
|
BACK,
|
||||||
FORWARD,
|
FORWARD,
|
||||||
|
MLEFT,
|
||||||
|
MMIDDLE,
|
||||||
|
MRIGHT,
|
||||||
KEYS_SIZE,
|
KEYS_SIZE,
|
||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <gl/Config.h>
|
||||||
|
#include <gl/Context.h>
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QElapsedTimer>
|
#include <QtCore/QElapsedTimer>
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
|
@ -27,12 +30,13 @@
|
||||||
#include <QtWidgets/QMessageBox>
|
#include <QtWidgets/QMessageBox>
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
|
||||||
|
|
||||||
#include <shared/RateCounter.h>
|
#include <shared/RateCounter.h>
|
||||||
#include <AssetClient.h>
|
#include <AssetClient.h>
|
||||||
|
|
||||||
#include <gl/OffscreenGLCanvas.h>
|
//#include <gl/OffscreenGLCanvas.h>
|
||||||
#include <gl/GLHelpers.h>
|
//#include <gl/GLHelpers.h>
|
||||||
#include <gl/QOpenGLContextWrapper.h>
|
//#include <gl/QOpenGLContextWrapper.h>
|
||||||
|
|
||||||
#include <gpu/gl/GLBackend.h>
|
#include <gpu/gl/GLBackend.h>
|
||||||
#include <gpu/gl/GLFramebuffer.h>
|
#include <gpu/gl/GLFramebuffer.h>
|
||||||
|
@ -61,6 +65,7 @@
|
||||||
#include "Camera.hpp"
|
#include "Camera.hpp"
|
||||||
#include "TextOverlay.hpp"
|
#include "TextOverlay.hpp"
|
||||||
|
|
||||||
|
|
||||||
static const QString LAST_SCENE_KEY = "lastSceneFile";
|
static const QString LAST_SCENE_KEY = "lastSceneFile";
|
||||||
static const QString LAST_LOCATION_KEY = "lastLocation";
|
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 {
|
class QWindowCamera : public Camera {
|
||||||
Key forKey(int key) {
|
Key forKey(int key) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
@ -143,6 +197,7 @@ public:
|
||||||
_lastMouse = mouse;
|
_lastMouse = mouse;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static QString toHumanSize(size_t size, size_t maxUnit = std::numeric_limits<size_t>::max()) {
|
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" } };
|
static const std::vector<QString> SUFFIXES{ { "B", "KB", "MB", "GB", "TB", "PB" } };
|
||||||
|
@ -175,8 +230,7 @@ extern QThread* RENDER_THREAD;
|
||||||
class RenderThread : public GenericThread {
|
class RenderThread : public GenericThread {
|
||||||
using Parent = GenericThread;
|
using Parent = GenericThread;
|
||||||
public:
|
public:
|
||||||
QOpenGLContextWrapper* _displayContext{ nullptr };
|
gl::Context _context;
|
||||||
QSurface* _displaySurface{ nullptr };
|
|
||||||
gpu::PipelinePointer _presentPipeline;
|
gpu::PipelinePointer _presentPipeline;
|
||||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||||
std::atomic<size_t> _presentCount;
|
std::atomic<size_t> _presentCount;
|
||||||
|
@ -190,6 +244,7 @@ public:
|
||||||
std::mutex _frameLock;
|
std::mutex _frameLock;
|
||||||
std::queue<gpu::FramePointer> _pendingFrames;
|
std::queue<gpu::FramePointer> _pendingFrames;
|
||||||
gpu::FramePointer _activeFrame;
|
gpu::FramePointer _activeFrame;
|
||||||
|
QSize _size;
|
||||||
static const size_t FRAME_TIME_BUFFER_SIZE{ 8192 };
|
static const size_t FRAME_TIME_BUFFER_SIZE{ 8192 };
|
||||||
|
|
||||||
void submitFrame(const gpu::FramePointer& frame) {
|
void submitFrame(const gpu::FramePointer& frame) {
|
||||||
|
@ -198,38 +253,44 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initialize(QOpenGLContextWrapper* displayContext, QWindow* surface) {
|
void initialize(QWindow* window, gl::Context& initContext) {
|
||||||
setObjectName("RenderThread");
|
setObjectName("RenderThread");
|
||||||
_displayContext = displayContext;
|
_context.setWindow(window);
|
||||||
_displaySurface = surface;
|
_context.create();
|
||||||
_displayContext->makeCurrent(_displaySurface);
|
_context.makeCurrent();
|
||||||
|
window->setSurfaceType(QSurface::OpenGLSurface);
|
||||||
|
_context.makeCurrent(_context.qglContext(), window);
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wglSwapIntervalEXT(0);
|
||||||
|
#endif
|
||||||
// GPU library init
|
// GPU library init
|
||||||
gpu::Context::init<gpu::gl::GLBackend>();
|
gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
_gpuContext = std::make_shared<gpu::Context>();
|
_gpuContext = std::make_shared<gpu::Context>();
|
||||||
_backend = _gpuContext->getBackend();
|
_backend = _gpuContext->getBackend();
|
||||||
_displayContext->makeCurrent(_displaySurface);
|
_context.makeCurrent();
|
||||||
DependencyManager::get<DeferredLightingEffect>()->init();
|
DependencyManager::get<DeferredLightingEffect>()->init();
|
||||||
_displayContext->doneCurrent();
|
_context.makeCurrent();
|
||||||
|
initContext.create();
|
||||||
|
_context.doneCurrent();
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
Parent::initialize();
|
Parent::initialize();
|
||||||
if (isThreaded()) {
|
_context.moveToThread(_thread);
|
||||||
_displayContext->moveToThread(thread());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() override {
|
void setup() override {
|
||||||
RENDER_THREAD = QThread::currentThread();
|
RENDER_THREAD = QThread::currentThread();
|
||||||
QThread::currentThread()->setPriority(QThread::HighestPriority);
|
|
||||||
// Wait until the context has been moved to this thread
|
// Wait until the context has been moved to this thread
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
}
|
}
|
||||||
_displayContext->makeCurrent(_displaySurface);
|
|
||||||
|
_context.makeCurrent();
|
||||||
glewExperimental = true;
|
glewExperimental = true;
|
||||||
glewInit();
|
glewInit();
|
||||||
glGetError();
|
glGetError();
|
||||||
_frameTimes.resize(FRAME_TIME_BUFFER_SIZE, 0);
|
|
||||||
|
|
||||||
|
_frameTimes.resize(FRAME_TIME_BUFFER_SIZE, 0);
|
||||||
{
|
{
|
||||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||||
auto ps = gpu::Shader::createPixel(std::string(SRGB_TO_LINEAR_FRAG));
|
auto ps = gpu::Shader::createPixel(std::string(SRGB_TO_LINEAR_FRAG));
|
||||||
|
@ -254,22 +315,21 @@ public:
|
||||||
}
|
}
|
||||||
_presentPipeline.reset();
|
_presentPipeline.reset();
|
||||||
_gpuContext.reset();
|
_gpuContext.reset();
|
||||||
if (isThreaded()) {
|
|
||||||
_displayContext->moveToThread(qApp->thread());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderFrame(gpu::FramePointer& frame) {
|
void renderFrame(gpu::FramePointer& frame) {
|
||||||
++_presentCount;
|
++_presentCount;
|
||||||
_displayContext->makeCurrent(_displaySurface);
|
_context.makeCurrent();
|
||||||
_backend->recycle();
|
_backend->recycle();
|
||||||
_backend->syncCache();
|
_backend->syncCache();
|
||||||
if (frame && !frame->batches.empty()) {
|
if (frame && !frame->batches.empty()) {
|
||||||
_gpuContext->executeFrame(frame);
|
_gpuContext->executeFrame(frame);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
gpu::Batch presentBatch;
|
gpu::Batch presentBatch;
|
||||||
|
presentBatch.setViewportTransform({ 0, 0, _size.width(), _size.height() });
|
||||||
presentBatch.enableStereo(false);
|
presentBatch.enableStereo(false);
|
||||||
presentBatch.resetViewTransform();
|
presentBatch.resetViewTransform();
|
||||||
presentBatch.setFramebuffer(gpu::FramebufferPointer());
|
presentBatch.setFramebuffer(gpu::FramebufferPointer());
|
||||||
|
@ -280,7 +340,8 @@ public:
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
_displayContext->swapBuffers(_displaySurface);
|
_context.makeCurrent();
|
||||||
|
_context.swapBuffers();
|
||||||
_fpsCounter.increment();
|
_fpsCounter.increment();
|
||||||
static size_t _frameCount{ 0 };
|
static size_t _frameCount{ 0 };
|
||||||
++_frameCount;
|
++_frameCount;
|
||||||
|
@ -290,7 +351,7 @@ public:
|
||||||
_elapsed.restart();
|
_elapsed.restart();
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
_displayContext->doneCurrent();
|
_context.doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void report() {
|
void report() {
|
||||||
|
@ -350,7 +411,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Background Render Data & rendering functions
|
// Background Render Data & rendering functions
|
||||||
class BackgroundRenderData {
|
class BackgroundRenderData {
|
||||||
public:
|
public:
|
||||||
|
@ -396,7 +456,6 @@ namespace render {
|
||||||
|
|
||||||
// Create a simple OpenGL window that renders text in various ways
|
// Create a simple OpenGL window that renders text in various ways
|
||||||
class QTestWindow : public QWindow, public AbstractViewStateInterface {
|
class QTestWindow : public QWindow, public AbstractViewStateInterface {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void copyCurrentViewFrustum(ViewFrustum& viewOut) const override {
|
void copyCurrentViewFrustum(ViewFrustum& viewOut) const override {
|
||||||
|
@ -467,7 +526,8 @@ public:
|
||||||
_octree->init();
|
_octree->init();
|
||||||
// Prevent web entities from rendering
|
// Prevent web entities from rendering
|
||||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Web, WebEntityItem::factory);
|
REGISTER_ENTITY_TYPE_WITH_FACTORY(Web, WebEntityItem::factory);
|
||||||
|
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, LightEntityItem::factory);
|
||||||
|
|
||||||
DependencyManager::set<ParentFinder>(_octree->getTree());
|
DependencyManager::set<ParentFinder>(_octree->getTree());
|
||||||
getEntities()->setViewFrustum(_viewFrustum);
|
getEntities()->setViewFrustum(_viewFrustum);
|
||||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
@ -476,28 +536,48 @@ public:
|
||||||
nodeList->setPermissions(permissions);
|
nodeList->setPermissions(permissions);
|
||||||
|
|
||||||
ResourceManager::init();
|
ResourceManager::init();
|
||||||
setSurfaceType(QSurface::OpenGLSurface);
|
|
||||||
auto format = getDefaultOpenGLSurfaceFormat();
|
|
||||||
format.setOption(QSurfaceFormat::DebugContext);
|
|
||||||
setFormat(format);
|
|
||||||
|
|
||||||
resize(QSize(800, 600));
|
setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
|
||||||
|
_size = QSize(800, 600);
|
||||||
|
_renderThread._size = _size;
|
||||||
|
setGeometry(QRect(QPoint(), _size));
|
||||||
|
create();
|
||||||
show();
|
show();
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
// Create the initial context
|
||||||
|
_renderThread.initialize(this, _initContext);
|
||||||
|
_initContext.makeCurrent();
|
||||||
|
|
||||||
_context.setFormat(format);
|
#if 0
|
||||||
_context.create();
|
glfwInit();
|
||||||
_context.makeCurrent(this);
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
||||||
glewExperimental = true;
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
glewInit();
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||||
glGetError();
|
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);
|
GLDebug::setupLogger(this);
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
wglSwapIntervalEXT(0);
|
|
||||||
#endif
|
#endif
|
||||||
_context.doneCurrent();
|
|
||||||
|
|
||||||
_initContext.create(_context.getContext());
|
#ifdef Q_OS_WIN
|
||||||
_renderThread.initialize(&_context, this);
|
//wglSwapIntervalEXT(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME use a wait condition
|
// FIXME use a wait condition
|
||||||
QThread::msleep(1000);
|
QThread::msleep(1000);
|
||||||
_renderThread.submitFrame(gpu::FramePointer());
|
_renderThread.submitFrame(gpu::FramePointer());
|
||||||
|
@ -559,7 +639,7 @@ protected:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qt::Key_F4:
|
case Qt::Key_F4:
|
||||||
toggleStereo();
|
cycleMode();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qt::Key_F5:
|
case Qt::Key_F5:
|
||||||
|
@ -626,27 +706,43 @@ private:
|
||||||
0, RenderArgs::DEFAULT_RENDER_MODE,
|
0, RenderArgs::DEFAULT_RENDER_MODE,
|
||||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||||
|
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
|
||||||
QSize windowSize = size();
|
|
||||||
framebufferCache->setFrameBufferSize(windowSize);
|
|
||||||
|
|
||||||
renderArgs._blitFramebuffer = framebufferCache->getFramebuffer();
|
QSize windowSize = _size;
|
||||||
// Viewport is assigned to the size of the framebuffer
|
if (_renderMode == NORMAL) {
|
||||||
renderArgs._viewport = ivec4(0, 0, windowSize.width(), windowSize.height());
|
renderArgs._context->enableStereo(false);
|
||||||
|
} else {
|
||||||
renderArgs.setViewFrustum(_viewFrustum);
|
renderArgs._context->enableStereo(true);
|
||||||
|
|
||||||
renderArgs._context->enableStereo(_stereoEnabled);
|
|
||||||
if (_stereoEnabled) {
|
|
||||||
mat4 eyeOffsets[2];
|
mat4 eyeOffsets[2];
|
||||||
mat4 eyeProjections[2];
|
mat4 eyeProjections[2];
|
||||||
for (size_t i = 0; i < 2; ++i) {
|
if (_renderMode == STEREO) {
|
||||||
eyeProjections[i] = _viewFrustum.getProjection();
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
|
eyeProjections[i] = _viewFrustum.getProjection();
|
||||||
|
}
|
||||||
|
} else if (_renderMode == HMD) {
|
||||||
|
eyeOffsets[0][3] = vec4 { -0.0327499993, 0.0, 0.0149999997, 1.0 };
|
||||||
|
eyeOffsets[1][3] = vec4 { 0.0327499993, 0.0, 0.0149999997, 1.0 };
|
||||||
|
eyeProjections[0][0] = vec4 { 0.759056330, 0.000000000, 0.000000000, 0.000000000 };
|
||||||
|
eyeProjections[0][1] = vec4 { 0.000000000, 0.682773232, 0.000000000, 0.000000000 };
|
||||||
|
eyeProjections[0][2] = vec4 { -0.0580431037, -0.00619550655, -1.00000489, -1.00000000 };
|
||||||
|
eyeProjections[0][3] = vec4 { 0.000000000, 0.000000000, -0.0800003856, 0.000000000 };
|
||||||
|
eyeProjections[1][0] = vec4 { 0.752847493, 0.000000000, 0.000000000, 0.000000000 };
|
||||||
|
eyeProjections[1][1] = vec4 { 0.000000000, 0.678060353, 0.000000000, 0.000000000 };
|
||||||
|
eyeProjections[1][2] = vec4 { 0.0578232110, -0.00669418881, -1.00000489, -1.000000000 };
|
||||||
|
eyeProjections[1][3] = vec4 { 0.000000000, 0.000000000, -0.0800003856, 0.000000000 };
|
||||||
|
windowSize = { 2048, 2048 };
|
||||||
}
|
}
|
||||||
renderArgs._context->setStereoProjections(eyeProjections);
|
renderArgs._context->setStereoProjections(eyeProjections);
|
||||||
renderArgs._context->setStereoViews(eyeOffsets);
|
renderArgs._context->setStereoViews(eyeOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||||
|
framebufferCache->setFrameBufferSize(windowSize);
|
||||||
|
|
||||||
|
renderArgs._blitFramebuffer = framebufferCache->getFramebuffer();
|
||||||
|
// Viewport is assigned to the size of the framebuffer
|
||||||
|
renderArgs._viewport = ivec4(0, 0, windowSize.width(), windowSize.height());
|
||||||
|
renderArgs.setViewFrustum(_viewFrustum);
|
||||||
|
|
||||||
// Final framebuffer that will be handled to the display-plugin
|
// Final framebuffer that will be handled to the display-plugin
|
||||||
render(&renderArgs);
|
render(&renderArgs);
|
||||||
|
|
||||||
|
@ -676,11 +772,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void updateText() {
|
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(_fps).arg(_cullingEnabled)
|
||||||
.arg(toHumanSize(gpu::Context::getTextureGPUMemoryUsage(), 2))
|
.arg(toHumanSize(gpu::Context::getTextureGPUMemoryUsage(), 2))
|
||||||
.arg(toHumanSize(gpu::Texture::getTextureCPUMemoryUsage(), 2)));
|
.arg(toHumanSize(gpu::Texture::getTextureCPUMemoryUsage(), 2));
|
||||||
|
setTitle(title);
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
_textBlocks.erase(TextBlock::Info);
|
_textBlocks.erase(TextBlock::Info);
|
||||||
|
@ -801,18 +897,13 @@ private:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool makeCurrent() {
|
|
||||||
bool currentResult = _context.makeCurrent(this);
|
|
||||||
Q_ASSERT(currentResult);
|
|
||||||
return currentResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resizeWindow(const QSize& size) {
|
void resizeWindow(const QSize& size) {
|
||||||
_size = size;
|
_size = size;
|
||||||
_camera.setAspectRatio((float)_size.width() / (float)_size.height());
|
_camera.setAspectRatio((float)_size.width() / (float)_size.height());
|
||||||
if (!_ready) {
|
if (!_ready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_renderThread._size = size;
|
||||||
//_textOverlay->resize(toGlm(_size));
|
//_textOverlay->resize(toGlm(_size));
|
||||||
//glViewport(0, 0, size.width(), size.height());
|
//glViewport(0, 0, size.width(), size.height());
|
||||||
}
|
}
|
||||||
|
@ -928,8 +1019,18 @@ private:
|
||||||
_cullingEnabled = !_cullingEnabled;
|
_cullingEnabled = !_cullingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleStereo() {
|
void cycleMode() {
|
||||||
_stereoEnabled = !_stereoEnabled;
|
static auto defaultProjection = Camera().matrices.perspective;
|
||||||
|
_renderMode = (RenderMode)((_renderMode + 1) % RENDER_MODE_COUNT);
|
||||||
|
if (_renderMode == HMD) {
|
||||||
|
_camera.matrices.perspective[0] = vec4 { 0.759056330, 0.000000000, 0.000000000, 0.000000000 };
|
||||||
|
_camera.matrices.perspective[1] = vec4 { 0.000000000, 0.682773232, 0.000000000, 0.000000000 };
|
||||||
|
_camera.matrices.perspective[2] = vec4 { -0.0580431037, -0.00619550655, -1.00000489, -1.00000000 };
|
||||||
|
_camera.matrices.perspective[3] = vec4 { 0.000000000, 0.000000000, -0.0800003856, 0.000000000 };
|
||||||
|
} else {
|
||||||
|
_camera.matrices.perspective = defaultProjection;
|
||||||
|
_camera.setAspectRatio((float)_size.width() / (float)_size.height());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<EntityTreeRenderer> getEntities() {
|
QSharedPointer<EntityTreeRenderer> getEntities() {
|
||||||
|
@ -960,12 +1061,11 @@ private:
|
||||||
|
|
||||||
render::EnginePointer _renderEngine { new render::Engine() };
|
render::EnginePointer _renderEngine { new render::Engine() };
|
||||||
render::ScenePointer _main3DScene { new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
render::ScenePointer _main3DScene { new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||||
QOpenGLContextWrapper _context;
|
|
||||||
QSize _size;
|
QSize _size;
|
||||||
QSettings _settings;
|
QSettings _settings;
|
||||||
|
|
||||||
std::atomic<size_t> _renderCount;
|
std::atomic<size_t> _renderCount;
|
||||||
OffscreenGLCanvas _initContext;
|
gl::OffscreenContext _initContext;
|
||||||
RenderThread _renderThread;
|
RenderThread _renderThread;
|
||||||
QWindowCamera _camera;
|
QWindowCamera _camera;
|
||||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||||
|
@ -975,7 +1075,14 @@ private:
|
||||||
bool _ready { false };
|
bool _ready { false };
|
||||||
//TextOverlay* _textOverlay;
|
//TextOverlay* _textOverlay;
|
||||||
static bool _cullingEnabled;
|
static bool _cullingEnabled;
|
||||||
bool _stereoEnabled { false };
|
|
||||||
|
enum RenderMode {
|
||||||
|
NORMAL = 0,
|
||||||
|
STEREO,
|
||||||
|
HMD,
|
||||||
|
RENDER_MODE_COUNT
|
||||||
|
};
|
||||||
|
RenderMode _renderMode { NORMAL };
|
||||||
QSharedPointer<EntityTreeRenderer> _octree;
|
QSharedPointer<EntityTreeRenderer> _octree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,6 @@ public:
|
||||||
|
|
||||||
gpu::Context::init<gpu::gl::GLBackend>();
|
gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
|
|
||||||
|
|
||||||
GLDebug::setupLogger(this);
|
|
||||||
qDebug() << (const char*)glGetString(GL_VERSION);
|
qDebug() << (const char*)glGetString(GL_VERSION);
|
||||||
|
|
||||||
//_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false);
|
//_textRenderer[0] = TextRenderer::getInstance(SANS_FONT_FAMILY, 12, false);
|
||||||
|
|
|
@ -108,9 +108,7 @@ public:
|
||||||
|
|
||||||
show();
|
show();
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
|
|
||||||
gpu::Context::init<gpu::gl::GLBackend>();
|
gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
GLDebug::setupLogger(this);
|
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
resize(QSize(800, 600));
|
resize(QSize(800, 600));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue