Merge pull request #6506 from jherico/maggie

OpenGL class cleanup
This commit is contained in:
samcake 2015-12-03 13:55:29 -08:00
commit 902b6b8ea1
20 changed files with 251 additions and 200 deletions

View file

@ -78,7 +78,7 @@
#include <ObjectMotionState.h>
#include <OctalCode.h>
#include <OctreeSceneStats.h>
#include <gl/OffscreenGlCanvas.h>
#include <gl/OffscreenGLCanvas.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <PhysicsEngine.h>
@ -616,7 +616,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// enable mouse tracking; otherwise, we only get drag events
_glWidget->setMouseTracking(true);
_offscreenContext = new OffscreenGlCanvas();
_offscreenContext = new OffscreenGLCanvas();
_offscreenContext->create(_glWidget->context()->contextHandle());
_offscreenContext->makeCurrent();
initializeGL();

View file

@ -65,7 +65,7 @@
#include "ui/ToolWindow.h"
#include "UndoStackScriptingInterface.h"
class OffscreenGlCanvas;
class OffscreenGLCanvas;
class GLCanvas;
class FaceTracker;
class MainWindow;
@ -421,7 +421,7 @@ private:
bool _dependencyManagerIsSetup;
OffscreenGlCanvas* _offscreenContext { nullptr };
OffscreenGLCanvas* _offscreenContext { nullptr };
DisplayPluginPointer _displayPlugin;
InputPluginList _activeInputPlugins;

View file

@ -9,54 +9,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// FIXME ordering of headers
#include "Application.h"
#include "GLCanvas.h"
#include <QMimeData>
#include <QUrl>
#include <QWindow>
#include "MainWindow.h"
#include "Menu.h"
static QGLFormat& getDesiredGLFormat() {
// 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, [] {
glFormat.setVersion(4, 1);
glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0
glFormat.setSampleBuffers(false);
glFormat.setDepth(false);
glFormat.setStencil(false);
});
return glFormat;
}
GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()) {
#ifdef Q_OS_LINUX
// Cause GLCanvas::eventFilter to be called.
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
qApp->installEventFilter(this);
#endif
}
int GLCanvas::getDeviceWidth() const {
return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
}
int GLCanvas::getDeviceHeight() const {
return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
}
void GLCanvas::initializeGL() {
setAttribute(Qt::WA_AcceptTouchEvents);
setAcceptDrops(true);
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
setAutoBufferSwap(false);
}
void GLCanvas::paintGL() {
PROFILE_RANGE(__FUNCTION__);
@ -74,68 +35,8 @@ void GLCanvas::resizeGL(int width, int height) {
}
bool GLCanvas::event(QEvent* event) {
switch (event->type()) {
case QEvent::MouseMove:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::FocusIn:
case QEvent::FocusOut:
case QEvent::Resize:
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate:
case QEvent::Wheel:
case QEvent::DragEnter:
case QEvent::Drop:
if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) {
return true;
}
break;
case QEvent::Paint:
// Ignore paint events that occur after we've decided to quit
if (qApp->isAboutToQuit()) {
return true;
}
break;
default:
break;
if (QEvent::Paint == event->type() && qApp->isAboutToQuit()) {
return true;
}
return QGLWidget::event(event);
}
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
//
// This filter catches events before QMenuBar can steal the keyboard focus.
// The idea was borrowed from
// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html
bool GLCanvas::eventFilter(QObject*, QEvent* event) {
switch (event->type()) {
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) {
if (event->type() == QEvent::KeyPress) {
keyPressEvent(keyEvent);
} else if (event->type() == QEvent::KeyRelease) {
keyReleaseEvent(keyEvent);
} else {
QGLWidget::event(event);
}
return true;
}
}
default:
break;
}
return false;
return GLWidget::event(event);
}

View file

@ -12,31 +12,15 @@
#ifndef hifi_GLCanvas_h
#define hifi_GLCanvas_h
#include <QDebug>
#include <QGLWidget>
#include <QTimer>
#include <gl/GLWidget.h>
/// customized canvas that simply forwards requests/events to the singleton application
class GLCanvas : public QGLWidget {
class GLCanvas : public GLWidget {
Q_OBJECT
public:
GLCanvas();
int getDeviceWidth() const;
int getDeviceHeight() const;
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
protected:
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int width, int height);
virtual bool event(QEvent* event);
private slots:
bool eventFilter(QObject*, QEvent* event);
virtual void paintGL() override;
virtual void resizeGL(int width, int height) override;
virtual bool event(QEvent* event) override;
};

View file

@ -10,7 +10,6 @@
#include <QCoreApplication>
#include <gl/Config.h>
#include <gl/GlWindow.h>
#include <GLMHelpers.h>

View file

@ -14,7 +14,6 @@
#include <QMainWindow>
#include <QGLWidget>
#include <GLMHelpers.h>
#include <gl/GlWindow.h>
#include <QEvent>
#include <QResizeEvent>

View file

@ -8,15 +8,6 @@
#include "InterleavedStereoDisplayPlugin.h"
#include <QApplication>
#include <QDesktopWidget>
#include <gl/GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <gpu/GLBackend.h>
static const char * INTERLEAVED_TEXTURED_VS = R"VS(#version 410 core
#pragma line __LINE__
@ -81,4 +72,4 @@ void InterleavedStereoDisplayPlugin::display(
_program->Bind();
Uniform<ivec2>(*_program, "textureSize").SetValue(sceneSize);
WindowOpenGLDisplayPlugin::display(finalTexture, sceneSize);
}
}

View file

@ -7,17 +7,7 @@
//
#include "SideBySideStereoDisplayPlugin.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <gl/GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <gpu/GLBackend.h>
#include <plugins/PluginContainer.h>
#include <GLMHelpers.h>
const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo");

View file

@ -87,6 +87,11 @@ public:
_recycler = recycler;
}
size_t depth() {
Lock lock(_mutex);
return _submits.size();
}
// Submit a new resource from the producer context
// returns the number of prior submissions that were
// never consumed before becoming available.
@ -124,7 +129,7 @@ public:
}
return result;
}
// If fetch returns a non-zero value, it's the responsibility of the
// client to release it at some point
void release(T t, GLsync readSync = 0) {
@ -175,6 +180,7 @@ private:
// May be called on any thread, but must be inside a locked section
void pop(Deque& deque) {
Lock lock(_mutex);
auto& item = deque.front();
_trash.push_front(item);
deque.pop_front();

View file

@ -1,15 +1,37 @@
#include "GLHelpers.h"
#include <mutex>
QSurfaceFormat getDefaultOpenGlSurfaceFormat() {
QSurfaceFormat format;
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
format.setVersion(4, 1);
#include <QtGui/QSurfaceFormat>
#include <QtOpenGL/QGL>
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
static QSurfaceFormat format;
static std::once_flag once;
std::call_once(once, [] {
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
format.setVersion(4, 1);
#ifdef DEBUG
format.setOption(QSurfaceFormat::DebugContext);
format.setOption(QSurfaceFormat::DebugContext);
#endif
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
return format;
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
});
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, [] {
glFormat.setVersion(4, 1);
glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0
glFormat.setSampleBuffers(false);
glFormat.setDepth(false);
glFormat.setStencil(false);
});
return glFormat;
}

View file

@ -10,14 +10,15 @@
#ifndef hifi_GLHelpers_h
#define hifi_GLHelpers_h
#include <QSurfaceFormat>
// 16 bits of depth precision
#define DEFAULT_GL_DEPTH_BUFFER_BITS 16
// 8 bits of stencil buffer (typically you really only need 1 bit for functionality
// but GL implementations usually just come with buffer sizes in multiples of 8)
#define DEFAULT_GL_STENCIL_BUFFER_BITS 8
QSurfaceFormat getDefaultOpenGlSurfaceFormat();
class QSurfaceFormat;
class QGLFormat;
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
const QGLFormat& getDefaultGLFormat();
#endif

View file

@ -0,0 +1,114 @@
//
//
// Created by Bradley Austin Davis on 2015/12/03
// Derived from interface/src/GLCanvas.cpp created by Stephen Birarda on 8/14/13.
// Copyright 2013-2015 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 "GLWidget.h"
#include <mutex>
#include <QtCore/QMimeData>
#include <QtCore/QUrl>
#include <QtCore/QCoreApplication>
#include <QtGui/QKeyEvent>
#include <QtGui/QWindow>
#include "GLHelpers.h"
GLWidget::GLWidget() : QGLWidget(getDefaultGLFormat()) {
#ifdef Q_OS_LINUX
// Cause GLWidget::eventFilter to be called.
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
qApp->installEventFilter(this);
#endif
}
int GLWidget::getDeviceWidth() const {
return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
}
int GLWidget::getDeviceHeight() const {
return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
}
void GLWidget::initializeGL() {
setAttribute(Qt::WA_AcceptTouchEvents);
setAcceptDrops(true);
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
setAutoBufferSwap(false);
}
void GLWidget::paintEvent(QPaintEvent* event) {
QWidget::paintEvent(event);
}
void GLWidget::resizeEvent(QResizeEvent* event) {
QWidget::resizeEvent(event);
}
bool GLWidget::event(QEvent* event) {
switch (event->type()) {
case QEvent::MouseMove:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::FocusIn:
case QEvent::FocusOut:
case QEvent::Resize:
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate:
case QEvent::Wheel:
case QEvent::DragEnter:
case QEvent::Drop:
if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) {
return true;
}
break;
default:
break;
}
return QGLWidget::event(event);
}
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
//
// This filter catches events before QMenuBar can steal the keyboard focus.
// The idea was borrowed from
// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html
bool GLWidget::eventFilter(QObject*, QEvent* event) {
switch (event->type()) {
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) {
if (event->type() == QEvent::KeyPress) {
keyPressEvent(keyEvent);
} else if (event->type() == QEvent::KeyRelease) {
keyReleaseEvent(keyEvent);
} else {
QGLWidget::event(event);
}
return true;
}
}
default:
break;
}
return false;
}

View file

@ -0,0 +1,36 @@
//
// Created by Bradley Austin Davis on 2015/12/03
// Derived from interface/src/GLCanvas.h created by Stephen Birarda on 8/14/13.
// Copyright 2013-2015 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_GLWidget_h
#define hifi_GLWidget_h
#include <QGLWidget>
/// customized canvas that simply forwards requests/events to the singleton application
class GLWidget : public QGLWidget {
Q_OBJECT
public:
GLWidget();
int getDeviceWidth() const;
int getDeviceHeight() const;
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
protected:
virtual void initializeGL() override;
virtual bool event(QEvent* event) override;
virtual void paintEvent(QPaintEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
private slots:
virtual bool eventFilter(QObject*, QEvent* event) override;
};
#endif // hifi_GLCanvas_h

View file

@ -6,17 +6,18 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GlWindow.h"
#include "GLWindow.h"
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLDebugLogger>
#include "GLHelpers.h"
GlWindow::GlWindow(QOpenGLContext* shareContext) : GlWindow(getDefaultOpenGlSurfaceFormat(), shareContext) {
void GLWindow::createContext(QOpenGLContext* shareContext) {
createContext(getDefaultOpenGLSurfaceFormat(), shareContext);
}
GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext) {
void GLWindow::createContext(const QSurfaceFormat& format, QOpenGLContext* shareContext) {
setSurfaceType(QSurface::OpenGLSurface);
setFormat(format);
_context = new QOpenGLContext;
@ -27,13 +28,15 @@ GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext) {
_context->create();
}
GlWindow::~GlWindow() {
_context->doneCurrent();
_context->deleteLater();
_context = nullptr;
GLWindow::~GLWindow() {
if (_context) {
_context->doneCurrent();
_context->deleteLater();
_context = nullptr;
}
}
bool GlWindow::makeCurrent() {
bool GLWindow::makeCurrent() {
bool makeCurrentResult = _context->makeCurrent(this);
Q_ASSERT(makeCurrentResult);
@ -49,11 +52,16 @@ bool GlWindow::makeCurrent() {
return makeCurrentResult;
}
void GlWindow::doneCurrent() {
void GLWindow::doneCurrent() {
_context->doneCurrent();
}
void GlWindow::swapBuffers() {
void GLWindow::swapBuffers() {
_context->swapBuffers(this);
}
QOpenGLContext* GLWindow::context() const {
return _context;
}

View file

@ -7,8 +7,8 @@
//
#pragma once
#ifndef hifi_GlWindow_h
#define hifi_GlWindow_h
#ifndef hifi_GLWindow_h
#define hifi_GLWindow_h
#include <mutex>
#include <QtGui/QWindow>
@ -16,14 +16,15 @@
class QOpenGLContext;
class QOpenGLDebugLogger;
class GlWindow : public QWindow {
class GLWindow : public QWindow {
public:
GlWindow(QOpenGLContext* shareContext = nullptr);
GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext = nullptr);
virtual ~GlWindow();
virtual ~GLWindow();
void createContext(QOpenGLContext* shareContext = nullptr);
void createContext(const QSurfaceFormat& format, QOpenGLContext* shareContext = nullptr);
bool makeCurrent();
void doneCurrent();
void swapBuffers();
QOpenGLContext* context() const;
private:
std::once_flag _reportOnce;
QOpenGLContext* _context{ nullptr };

View file

@ -1,5 +1,5 @@
//
// OffscreenGlCanvas.cpp
// OffscreenGLCanvas.cpp
// interface/src/renderer
//
// Created by Bradley Austin Davis on 2014/04/09.
@ -10,7 +10,7 @@
//
#include "OffscreenGlCanvas.h"
#include "OffscreenGLCanvas.h"
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLDebugLogger>
@ -18,10 +18,10 @@
#include "GLHelpers.h"
OffscreenGlCanvas::OffscreenGlCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface){
OffscreenGLCanvas::OffscreenGLCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface){
}
OffscreenGlCanvas::~OffscreenGlCanvas() {
OffscreenGLCanvas::~OffscreenGLCanvas() {
#ifdef DEBUG
if (_logger) {
makeCurrent();
@ -32,12 +32,12 @@ OffscreenGlCanvas::~OffscreenGlCanvas() {
_context->doneCurrent();
}
void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) {
void OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
if (nullptr != sharedContext) {
sharedContext->doneCurrent();
_context->setShareContext(sharedContext);
}
_context->setFormat(getDefaultOpenGlSurfaceFormat());
_context->setFormat(getDefaultOpenGLSurfaceFormat());
_context->create();
_offscreenSurface->setFormat(_context->format());
@ -45,7 +45,7 @@ void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) {
}
bool OffscreenGlCanvas::makeCurrent() {
bool OffscreenGLCanvas::makeCurrent() {
bool result = _context->makeCurrent(_offscreenSurface);
Q_ASSERT(result);
@ -72,7 +72,7 @@ bool OffscreenGlCanvas::makeCurrent() {
return result;
}
void OffscreenGlCanvas::doneCurrent() {
void OffscreenGLCanvas::doneCurrent() {
_context->doneCurrent();
}

View file

@ -1,5 +1,5 @@
//
// OffscreenGlCanvas.h
// OffscreenGLCanvas.h
// interface/src/renderer
//
// Created by Bradley Austin Davis on 2014/04/09.
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_OffscreenGlCanvas_h
#define hifi_OffscreenGlCanvas_h
#ifndef hifi_OffscreenGLCanvas_h
#define hifi_OffscreenGLCanvas_h
#include <mutex>
#include <QObject>
@ -19,10 +19,10 @@ class QOpenGLContext;
class QOffscreenSurface;
class QOpenGLDebugLogger;
class OffscreenGlCanvas : public QObject {
class OffscreenGLCanvas : public QObject {
public:
OffscreenGlCanvas();
~OffscreenGlCanvas();
OffscreenGLCanvas();
~OffscreenGLCanvas();
void create(QOpenGLContext* sharedContext = nullptr);
bool makeCurrent();
void doneCurrent();
@ -40,4 +40,4 @@ protected:
};
#endif // hifi_OffscreenGlCanvas_h
#endif // hifi_OffscreenGLCanvas_h

View file

@ -23,7 +23,7 @@
#include <NumericalConstants.h>
#include "GLEscrow.h"
#include "OffscreenGlCanvas.h"
#include "OffscreenGLCanvas.h"
// FIXME move to threaded rendering with Qt 5.5
//#define QML_THREADED
@ -64,12 +64,12 @@ static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4);
static const QEvent::Type UPDATE = QEvent::Type(QEvent::User + 5);
#endif
class OffscreenQmlRenderer : public OffscreenGlCanvas {
class OffscreenQmlRenderer : public OffscreenGLCanvas {
friend class OffscreenQmlSurface;
public:
OffscreenQmlRenderer(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
OffscreenGlCanvas::create(shareContext);
OffscreenGLCanvas::create(shareContext);
#ifdef QML_THREADED
// Qt 5.5
_renderControl->prepareThread(_renderThread);

View file

@ -12,7 +12,6 @@
#include <QtWidgets/QMainWindow>
#include <QtOpenGL/QGLWidget>
#include <GLMHelpers.h>
#include <gl/GlWindow.h>
#include <QEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QOpenGLContext>

View file

@ -128,7 +128,7 @@ protected:
public:
QTestWindow() {
setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format = getDefaultOpenGlSurfaceFormat();
QSurfaceFormat format = getDefaultOpenGLSurfaceFormat();
setFormat(format);
_context = new QOpenGLContext;
_context->setFormat(format);