Consolidating GL display plugins

This commit is contained in:
Brad Davis 2015-05-31 00:24:19 -07:00
parent fec214c552
commit 23d6725a6a
26 changed files with 496 additions and 537 deletions

View file

@ -123,8 +123,9 @@ else()
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
endif()
add_dependency_external_projects(glm bullet LibOVR)
# set up the external glm library
add_dependency_external_projects(glm bullet)
find_package(GLM REQUIRED)
target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS})
@ -132,6 +133,11 @@ find_package(Bullet REQUIRED)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
find_package(LibOVR REQUIRED)
target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS})
#target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
# link required hifi libraries
link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars
audio audio-client animation script-engine physics

View file

@ -4581,18 +4581,6 @@ qreal Application::getDevicePixelRatio() {
return _window ? _window->windowHandle()->devicePixelRatio() : 1.0;
}
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
#include <display-plugins/NullDisplayPlugin.h>
#include "LegacyDisplayPlugin.h"
//#include <display-plugins/Oculus.h>
#include <display-plugins/Tv3dDisplayPlugin.h>
//#include <display-plugins/WindowDisplayPlugin.h>
static DisplayPluginPointer _displayPlugin{ nullptr };
DisplayPlugin * Application::getActiveDisplayPlugin() {
if (nullptr == _displayPlugin) {
updateDisplayMode();
@ -4605,63 +4593,6 @@ const DisplayPlugin * Application::getActiveDisplayPlugin() const {
return ((Application*)this)->getActiveDisplayPlugin();
}
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
auto menu = Menu::getInstance();
QString name = displayPlugin->getName();
Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name));
static QActionGroup* displayPluginGroup = nullptr;
if (!displayPluginGroup) {
displayPluginGroup = new QActionGroup(menu);
displayPluginGroup->setExclusive(true);
}
auto parent = menu->getMenu(MenuOption::OutputMenu);
auto action = menu->addActionToQMenuAndActionHash(parent,
name, 0, qApp,
SLOT(updateDisplayMode()));
action->setCheckable(true);
action->setChecked(active);
displayPluginGroup->addAction(action);
Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));
}
using DisplayPluginList = QVector<DisplayPluginPointer>;
static DisplayPlugin* PLUGIN_POOL[] = {
new LegacyDisplayPlugin(),
#ifdef DEBUG
new NullDisplayPlugin(),
#endif
new Tv3dDisplayPlugin(),
// new WindowDisplayPlugin(),
nullptr
};
// FIXME move to a plugin manager class
static const DisplayPluginList & getDisplayPlugins() {
static DisplayPluginList RENDER_PLUGINS;
static bool init = false;
if (!init) {
init = true;
for (int i = 0; PLUGIN_POOL[i]; ++i) {
DisplayPlugin * plugin = PLUGIN_POOL[i];
if (plugin->isSupported()) {
plugin->init();
QObject::connect(plugin, &DisplayPlugin::requestRender, [] {
qApp->paintGL();
});
QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) {
qApp->resizeGL();
});
DisplayPluginPointer pluginPointer(plugin);
addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL);
RENDER_PLUGINS.push_back(pluginPointer);
}
}
}
return RENDER_PLUGINS;
}
void Application::updateDisplayMode() {
auto menu = Menu::getInstance();
DisplayPluginPointer newDisplayPlugin;
@ -4709,3 +4640,7 @@ glm::ivec2 Application::getMouse() const {
void Application::addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName) {
}
QMainWindow* Application::getAppMainWindow() {
return _window;
}

View file

@ -76,8 +76,8 @@
#include "octree/OctreeFade.h"
#include "octree/OctreePacketProcessor.h"
#include "UndoStackScriptingInterface.h"
#include "DisplayPlugins.h"
class DisplayPlugin;
class QGLWidget;
class QKeyEvent;
class QMouseEvent;
@ -282,19 +282,6 @@ public:
void displaySide(const Camera& camera, bool selfAvatarOnly = false);
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName);
/*
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
/// the view matrix translation.
void updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation = glm::vec3());
const glm::mat4& getUntranslatedViewMatrix() const { return _untranslatedViewMatrix; }
/// Loads a view matrix that incorporates the specified model translation without the precision issues that can
/// result from matrix multiplication at high translation magnitudes.
void loadTranslatedViewMatrix(const glm::vec3& translation);
*/
void getModelViewMatrix(glm::dmat4* modelViewMatrix);
void getProjectionMatrix(glm::dmat4* projectionMatrix);
@ -311,6 +298,10 @@ public:
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
virtual qreal getDevicePixelRatio();
// Plugin container support
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName);
virtual QMainWindow* getAppMainWindow();
private:
DisplayPlugin * getActiveDisplayPlugin();
const DisplayPlugin * getActiveDisplayPlugin() const;
@ -516,6 +507,7 @@ private:
bool _dependencyManagerIsSetup;
OffscreenGlCanvas* _offscreenContext;
DisplayPluginPointer _displayPlugin;
MainWindow* _window;

View file

@ -0,0 +1,77 @@
//
// Created by Bradley Austin Davis on 2015/05/30
// Copyright 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 "DisplayPlugins.h"
#include "Application.h"
#include <display-plugins/DisplayPlugin.h>
#include <display-plugins/NullDisplayPlugin.h>
#include <display-plugins/Tv3dDisplayPlugin.h>
#include <display-plugins/WindowDisplayPlugin.h>
#ifdef Q_OS_WIN
#include <display-plugins/OculusWin32DisplayPlugin.h>
#else
#endif
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
auto menu = Menu::getInstance();
QString name = displayPlugin->getName();
Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name));
static QActionGroup* displayPluginGroup = nullptr;
if (!displayPluginGroup) {
displayPluginGroup = new QActionGroup(menu);
displayPluginGroup->setExclusive(true);
}
auto parent = menu->getMenu(MenuOption::OutputMenu);
auto action = menu->addActionToQMenuAndActionHash(parent,
name, 0, qApp,
SLOT(updateDisplayMode()));
action->setCheckable(true);
action->setChecked(active);
displayPluginGroup->addAction(action);
Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));
}
// FIXME move to a plugin manager class
const DisplayPluginList& getDisplayPlugins() {
static DisplayPluginList RENDER_PLUGINS;
static bool init = false;
if (!init) {
init = true;
DisplayPlugin* PLUGIN_POOL[] = {
new WindowDisplayPlugin(),
#ifdef DEBUG
new NullDisplayPlugin(),
#endif
new Tv3dDisplayPlugin(),
new OculusWin32DisplayPlugin(),
nullptr
};
for (int i = 0; PLUGIN_POOL[i]; ++i) {
DisplayPlugin * plugin = PLUGIN_POOL[i];
if (plugin->isSupported()) {
plugin->init();
QObject::connect(plugin, &DisplayPlugin::requestRender, [] {
qApp->paintGL();
});
QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) {
qApp->resizeGL();
});
DisplayPluginPointer pluginPointer(plugin);
addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL);
RENDER_PLUGINS.push_back(pluginPointer);
}
}
}
return RENDER_PLUGINS;
}

View file

@ -0,0 +1,18 @@
//
// Created by Bradley Austin Davis on 2015/05/30
// Copyright 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
//
#pragma once
class DisplayPlugin;
#include <QVector>
#include <QSharedPointer>
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
using DisplayPluginList = QVector<DisplayPluginPointer>;
const DisplayPluginList& getDisplayPlugins();

View file

@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#if 0
#include "Application.h"
#include "GLCanvas.h"
@ -162,3 +162,4 @@ bool GLCanvas::eventFilter(QObject*, QEvent* event) {
}
return false;
}
#endif

View file

@ -9,6 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#if 0
#ifndef hifi_GLCanvas_h
#define hifi_GLCanvas_h
@ -51,3 +52,4 @@ private slots:
#endif // hifi_GLCanvas_h
#endif

View file

@ -1,124 +0,0 @@
//
// LegacyDisplayPlugin.cpp
//
// Created by Bradley Austin Davis on 2014/04/13.
// Copyright 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 "Application.h"
#include "LegacyDisplayPlugin.h"
#include "MainWindow.h"
#include <RenderUtil.h>
#include <QOpenGLDebugLogger>
const QString LegacyDisplayPlugin::NAME("2D Monitor (GL Windgets)");
const QString & LegacyDisplayPlugin::getName() {
return NAME;
}
LegacyDisplayPlugin::LegacyDisplayPlugin() {
connect(&_timer, &QTimer::timeout, this, [&] {
emit requestRender();
});
}
static QWidget * oldWidget = nullptr;
void LegacyDisplayPlugin::activate(PluginContainer * container) {
_window = new GLCanvas();
QOpenGLContext * sourceContext = QOpenGLContext::currentContext();
QOpenGLContext * newContext = new QOpenGLContext();
{
QSurfaceFormat format;
format.setOption(QSurfaceFormat::DebugContext);
newContext->setFormat(format);
}
_window->setContext(
QGLContext::fromOpenGLContext(newContext),
QGLContext::fromOpenGLContext(sourceContext));
oldWidget = qApp->getWindow()->centralWidget();
// FIXME necessary?
makeCurrent();
qApp->getWindow()->setCentralWidget(_window);
doneCurrent();
_window->setFocusPolicy(Qt::StrongFocus);
_window->setFocus();
_window->setMouseTracking(true);
_timer.start(8);
}
void LegacyDisplayPlugin::deactivate() {
_timer.stop();
// FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed.
// if (qApp->getWindow()) {
// qApp->getWindow()->setCentralWidget(oldWidget);
// }
// stop the glWidget frame timer so it doesn't call paintGL
_window->stopFrameTimer();
_window->doneCurrent();
_window->deleteLater();
_window = nullptr;
}
QSize LegacyDisplayPlugin::getDeviceSize() const {
return _window->getDeviceSize();
}
void LegacyDisplayPlugin::idle() {
_window->updateGL();
}
glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const {
return toGlm(_window->size());
}
bool LegacyDisplayPlugin::hasFocus() const {
return _window->hasFocus();
}
PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const {
return PickRay();
}
void LegacyDisplayPlugin::preDisplay() {
OpenGlDisplayPlugin::preDisplay();
auto size = toGlm(_window->size());
glViewport(0, 0, size.x, size.y);
}
bool LegacyDisplayPlugin::isThrottled() const {
return _window->isThrottleRendering();
}
void LegacyDisplayPlugin::makeCurrent() {
_window->makeCurrent();
}
void LegacyDisplayPlugin::doneCurrent() {
_window->doneCurrent();
}
void LegacyDisplayPlugin::swapBuffers() {
_window->swapBuffers();
}
ivec2 LegacyDisplayPlugin::getTrueMousePosition() const {
return toGlm(_window->mapFromGlobal(QCursor::pos()));
}
QWindow* LegacyDisplayPlugin::getWindow() const {
return _window->windowHandle();
}
void LegacyDisplayPlugin::installEventFilter(QObject* filter) {
_window->installEventFilter(filter);
}
void LegacyDisplayPlugin::removeEventFilter(QObject* filter) {
_window->removeEventFilter(filter);
}

View file

@ -1,47 +0,0 @@
//
// LegacyDisplayPlugin.h
//
// Created by Bradley Austin Davis on 2014/04/13.
// Copyright 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
//
#pragma once
#include <display-plugins/OpenGlDisplayPlugin.h>
#include "GLCanvas.h"
class LegacyDisplayPlugin : public OpenGlDisplayPlugin {
Q_OBJECT
public:
LegacyDisplayPlugin();
static const QString NAME;
virtual const QString & getName();
virtual void activate(PluginContainer * container);
virtual void deactivate();
virtual QSize getDeviceSize() const;
virtual ivec2 getCanvasSize() const;
virtual bool hasFocus() const;
virtual PickRay computePickRay(const glm::vec2 & pos) const;
virtual bool isMouseOnScreen() const { return true; }
virtual bool isThrottled() const;
virtual void preDisplay();
virtual void idle();
virtual ivec2 getTrueMousePosition() const;
virtual QWindow* getWindow() const;
virtual void installEventFilter(QObject* filter);
virtual void removeEventFilter(QObject* filter);
protected:
virtual void makeCurrent() final;
virtual void doneCurrent() final;
virtual void swapBuffers() final;
private:
GLCanvas * _window;
QTimer _timer;
};

View file

@ -311,7 +311,6 @@ glm::quat Head::getCameraOrientation() const {
if (qApp->isHMDMode()) {
return getOrientation();
}
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f)));
}

View file

@ -194,6 +194,11 @@ void ApplicationOverlay::renderOverlay() {
Overlays& overlays = qApp->getOverlays();
glm::uvec2 size = qApp->getCanvasSize();
if (size == uvec2(0)) {
qDebug() << "Bad size from display plugin";
glm::uvec2 size = qApp->getCanvasSize();
}
if (!_framebufferObject || size != toGlm(_framebufferObject->size())) {
if(_framebufferObject) {
delete _framebufferObject;

View file

@ -1,113 +0,0 @@
//
// Created by Bradley Austin Davis on 2015/05/29
// Copyright 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 "GlWindowDisplayPlugin.h"
#include <QOpenGLContext>
#include <QCursor>
#include <QTimer>
#include <QCoreApplication>
#include <GLWindow.h>
#include <GLMHelpers.h>
GlWindowDisplayPlugin::GlWindowDisplayPlugin() : _timer(new QTimer()) {
connect(_timer, &QTimer::timeout, this, [&] {
// if (qApp->getActiveDisplayPlugin() == this) {
emit requestRender();
// }
});
}
GlWindowDisplayPlugin::~GlWindowDisplayPlugin() {
delete _timer;
}
void GlWindowDisplayPlugin::makeCurrent() {
_window->makeCurrent();
}
void GlWindowDisplayPlugin::doneCurrent() {
_window->doneCurrent();
}
void GlWindowDisplayPlugin::swapBuffers() {
_window->swapBuffers();
}
glm::ivec2 GlWindowDisplayPlugin::getTrueMousePosition() const {
return toGlm(_window->mapFromGlobal(QCursor::pos()));
}
QWindow* GlWindowDisplayPlugin::getWindow() const {
return _window;
}
void GlWindowDisplayPlugin::activate(PluginContainer * container) {
Q_ASSERT(nullptr == _window);
_window = new GlWindow(QOpenGLContext::currentContext());
_window->installEventFilter(this);
customizeWindow();
_window->show();
_timer->start(8);
makeCurrent();
customizeContext();
}
void GlWindowDisplayPlugin::deactivate() {
_timer->stop();
Q_ASSERT(nullptr != _window);
_window->hide();
_window->destroy();
_window->deleteLater();
_window = nullptr;
}
QSize GlWindowDisplayPlugin::getDeviceSize() const {
return _window->geometry().size() * _window->devicePixelRatio();
}
glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const {
return toGlm(_window->geometry().size());
}
bool GlWindowDisplayPlugin::hasFocus() const {
return _window->isActive();
}
void GlWindowDisplayPlugin::installEventFilter(QObject* filter) {
_window->installEventFilter(filter);
}
void GlWindowDisplayPlugin::removeEventFilter(QObject* filter) {
_window->removeEventFilter(filter);
}
bool GlWindowDisplayPlugin::eventFilter(QObject* receiver, 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;
}
return false;
}

View file

@ -1,48 +0,0 @@
//
// Created by Bradley Austin Davis on 2015/05/29
// Copyright 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
//
#pragma once
#include "OpenGlDisplayPlugin.h"
class GlWindow;
class QTimer;
class GlWindowDisplayPlugin : public OpenGlDisplayPlugin {
public:
GlWindowDisplayPlugin();
virtual ~GlWindowDisplayPlugin();
virtual void activate(PluginContainer * container);
virtual void deactivate();
virtual QSize getDeviceSize() const final;
virtual glm::ivec2 getCanvasSize() const final;
virtual bool hasFocus() const;
virtual glm::ivec2 getTrueMousePosition() const;
virtual QWindow* getWindow() const;
virtual bool eventFilter(QObject* receiver, QEvent* event);
virtual void installEventFilter(QObject* filter);
virtual void removeEventFilter(QObject* filter);
protected:
virtual void makeCurrent() final;
virtual void doneCurrent() final;
virtual void swapBuffers() final;
// Called by the activate method to specify the initial window geometry
// flags, etc
virtual void customizeWindow() = 0;
// Called by the activate method after the GL context has been created to
// initialize OpenGL context settings needed by the plugin
virtual void customizeContext() = 0;
private:
QTimer* _timer{ nullptr };
protected:
GlWindow* _window{ nullptr };
};

View file

@ -12,16 +12,23 @@
#include "../OculusHelpers.h"
void OculusBaseDisplayPlugin::activate(PluginContainer * container) {
OpenGlDisplayPlugin::activate(container);
glm::uvec2 eyeSizes[2];
ovr_for_each_eye([&](ovrEyeType eye) {
ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]);
ovrMatrix4f ovrPerspectiveProjection =
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
_eyeOffsets[eye] = erd.HmdToEyeViewOffset;
eyeSizes[eye] = toGlm(ovrHmd_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f));
});
_desiredFramebufferSize = QSize(
eyeSizes[0].x + eyeSizes[1].x,
std::max(eyeSizes[0].y, eyeSizes[1].y));
}
void OculusBaseDisplayPlugin::deactivate() {
QSize OculusBaseDisplayPlugin::getRecommendedFramebufferSize() const {
return _desiredFramebufferSize;
}
void OculusBaseDisplayPlugin::preRender() {
@ -35,4 +42,3 @@ glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseP
glm::mat4 OculusBaseDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const {
return toGlm(_eyePoses[eye]);
}

View file

@ -7,20 +7,20 @@
//
#pragma once
#include "DisplayPlugin.h"
#include "OpenGlDisplayPlugin.h"
#include <OVR_CAPI.h>
class OculusBaseDisplayPlugin : public DisplayPlugin {
class OculusBaseDisplayPlugin : public OpenGlDisplayPlugin {
public:
// Stereo specific methods
virtual bool isHmd() const { return true; }
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const;
virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const;
virtual void activate(PluginContainer * container);
virtual void deactivate();
virtual void preRender();
virtual void configureRendering() = 0;
virtual QSize getRecommendedFramebufferSize() const;
protected:
ovrHmd _hmd;
unsigned int _frameIndex{ 0 };
@ -28,4 +28,5 @@ protected:
ovrPosef _eyePoses[2];
ovrVector3f _eyeOffsets[2];
glm::mat4 _eyeProjections[2];
QSize _desiredFramebufferSize;
};

View file

@ -8,22 +8,69 @@
#include "OculusWin32DisplayPlugin.h"
#include <memory>
#include <QMainWindow>
#include <GLMHelpers.h>
#include <GlWindow.h>
#include <OVR_CAPI_GL.h>
#include "plugins/PluginContainer.h"
#include "../OglplusHelpers.h"
const QString OculusWin32DisplayPlugin::NAME("Oculus Rift");
const QString & OculusWin32DisplayPlugin::getName() {
return NAME;
}
bool OculusWin32DisplayPlugin::isSupported() {
ovr_Initialize(nullptr);
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
return false;
}
bool result = false;
if (ovrHmd_Detect() != 0) {
if (ovrHmd_Detect() > 0) {
result = true;
}
ovr_Shutdown();
return result;
}
void OculusWin32DisplayPlugin::activate(PluginContainer * container) {
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
Q_ASSERT(false);
qFatal("Failed to Initialize SDK");
}
if (!OVR_SUCCESS(ovrHmd_Create(0, &_hmd))) {
Q_ASSERT(false);
qFatal("Failed to acquire HMD");
}
// Parent class relies on our _hmd intialization, so it must come after that.
OculusBaseDisplayPlugin::activate(container);
}
void OculusWin32DisplayPlugin::customizeWindow(PluginContainer * container) {
container->getAppMainWindow()->setCentralWidget(QWidget::createWindowContainer(_window));
}
void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) {
}
void OculusWin32DisplayPlugin::deactivate() {
ovrHmd_Destroy(_hmd);
_hmd = nullptr;
ovr_Shutdown();
}
void OculusWin32DisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
}
#if 0
// A basic wrapper for constructing a framebuffer with a renderbuffer
// for the depth attachment and an undefined type for the color attachement

View file

@ -8,12 +8,26 @@
#pragma once
#include "OculusBaseDisplayPlugin.h"
#include <QTimer>
class OffscreenGlCanvas;
class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin {
public:
virtual bool isSupported();
virtual const QString & getName();
virtual void activate(PluginContainer * container);
virtual void deactivate();
// virtual QSize getDeviceSize() const final;
// virtual glm::ivec2 getCanvasSize() const final;
void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
protected:
virtual void customizeWindow(PluginContainer * container);
virtual void customizeContext(PluginContainer * container);
private:
OffscreenGlCanvas* _canvas;
static const QString NAME;
};

View file

@ -8,6 +8,59 @@
#include "OpenGlDisplayPlugin.h"
#include <QOpenGLContext>
#include <TextureCache.h>
#include <PathUtils.h>
#include <QOpenGLContext>
#include <QCursor>
#include <QCoreApplication>
#include <GLWindow.h>
#include <GLMHelpers.h>
OpenGlDisplayPlugin::OpenGlDisplayPlugin() {
connect(&_timer, &QTimer::timeout, this, [&] {
if (_window) {
emit requestRender();
}
});
}
OpenGlDisplayPlugin::~OpenGlDisplayPlugin() {
}
QWindow* OpenGlDisplayPlugin::getWindow() const {
return _window;
}
glm::ivec2 OpenGlDisplayPlugin::getTrueMousePosition() const {
return toGlm(_window->mapFromGlobal(QCursor::pos()));
}
QSize OpenGlDisplayPlugin::getDeviceSize() const {
return _window->geometry().size() * _window->devicePixelRatio();
}
glm::ivec2 OpenGlDisplayPlugin::getCanvasSize() const {
return toGlm(_window->geometry().size());
}
bool OpenGlDisplayPlugin::hasFocus() const {
return _window->isActive();
}
void OpenGlDisplayPlugin::makeCurrent() {
_window->makeCurrent();
}
void OpenGlDisplayPlugin::doneCurrent() {
_window->doneCurrent();
}
void OpenGlDisplayPlugin::swapBuffers() {
_window->swapBuffers();
}
void OpenGlDisplayPlugin::preDisplay() {
makeCurrent();
@ -22,67 +75,96 @@ void OpenGlDisplayPlugin::finishFrame() {
doneCurrent();
};
void OpenGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
void OpenGlDisplayPlugin::activate(PluginContainer * container) {
Q_ASSERT(nullptr == _window);
_window = new GlWindow(QOpenGLContext::currentContext());
_window->installEventFilter(this);
customizeWindow(container);
// _window->show();
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height());
if (sceneTexture) {
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1, 0);
glVertex2f(+1, -1);
glTexCoord2f(1, 1);
glVertex2f(+1, +1);
glTexCoord2f(0, 1);
glVertex2f(-1, +1);
glEnd();
}
makeCurrent();
customizeContext(container);
if (overlayTexture) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1, 0);
glVertex2f(+1, -1);
glTexCoord2f(1, 1);
glVertex2f(+1, +1);
glTexCoord2f(0, 1);
glVertex2f(-1, +1);
glEnd();
}
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
//Q_ASSERT(!glGetError());
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glFinish();
_timer.start(1);
}
void OpenGlDisplayPlugin::customizeContext(PluginContainer * container) {
using namespace oglplus;
Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha);
Context::Disable(Capability::Blend);
Context::Disable(Capability::DepthTest);
Context::Disable(Capability::CullFace);
program = loadDefaultShader();
plane = loadPlane(program);
Context::ClearColor(0, 0, 0, 1);
crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
void OpenGlDisplayPlugin::deactivate() {
_timer.stop();
makeCurrent();
plane.reset();
program.reset();
crosshairTexture.reset();
doneCurrent();
Q_ASSERT(nullptr != _window);
_window->hide();
_window->destroy();
_window->deleteLater();
_window = nullptr;
}
void OpenGlDisplayPlugin::installEventFilter(QObject* filter) {
_window->installEventFilter(filter);
}
void OpenGlDisplayPlugin::removeEventFilter(QObject* filter) {
_window->removeEventFilter(filter);
}
// 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
// Pass input events on to the application
bool OpenGlDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::Wheel:
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate:
case QEvent::FocusIn:
case QEvent::FocusOut:
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
case QEvent::DragEnter:
case QEvent::Drop:
case QEvent::Resize:
if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) {
return true;
}
break;
}
return false;
}

View file

@ -7,18 +7,55 @@
//
#pragma once
#include <QTimer>
#include <gpu/Texture.h>
#include "DisplayPlugin.h"
#include "../OglplusHelpers.h"
class GlWindow;
class OpenGlDisplayPlugin : public DisplayPlugin {
public:
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
OpenGlDisplayPlugin();
virtual ~OpenGlDisplayPlugin();
virtual void preRender();
virtual void preDisplay();
virtual void finishFrame();
virtual void activate(PluginContainer * container);
virtual void deactivate();
virtual QSize getDeviceSize() const;
virtual glm::ivec2 getCanvasSize() const;
virtual bool hasFocus() const;
virtual glm::ivec2 getTrueMousePosition() const;
virtual QWindow* getWindow() const;
virtual bool eventFilter(QObject* receiver, QEvent* event);
virtual void installEventFilter(QObject* filter);
virtual void removeEventFilter(QObject* filter);
protected:
virtual void makeCurrent() = 0;
virtual void doneCurrent() = 0;
virtual void swapBuffers() = 0;
// Called by the activate method to specify the initial
// window geometry flags, etc
virtual void customizeWindow(PluginContainer * container) = 0;
// Needs to be called by the activate method after the GL context has been created to
// initialize OpenGL context settings needed by the plugin
virtual void customizeContext(PluginContainer * container);
virtual void makeCurrent() final;
virtual void doneCurrent() final;
virtual void swapBuffers() final;
GlWindow* _window{ nullptr };
QTimer _timer;
ProgramPtr program;
ShapeWrapperPtr plane;
gpu::TexturePointer crosshairTexture;
};

View file

@ -14,13 +14,9 @@
#include <GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <PathUtils.h>
#include <TextureCache.h>
#include <gpu/GLBackend.h>
#include "../OglplusHelpers.h"
const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin");
const QString & Tv3dDisplayPlugin::getName() {
@ -35,11 +31,7 @@ bool Tv3dDisplayPlugin::isSupported() const {
return true;
}
static ProgramPtr program;
static ShapeWrapperPtr plane;
static gpu::TexturePointer crosshairTexture;
void Tv3dDisplayPlugin::customizeWindow() {
void Tv3dDisplayPlugin::customizeWindow(PluginContainer * container) {
_window->setFlags(Qt::FramelessWindowHint);
auto desktop = QApplication::desktop();
QRect primaryGeometry = desktop->screenGeometry();
@ -56,22 +48,9 @@ void Tv3dDisplayPlugin::customizeWindow() {
break;
}
_window->setCursor(Qt::BlankCursor);
_window->show();
}
void Tv3dDisplayPlugin::customizeContext() {
using namespace oglplus;
Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha);
Context::Disable(Capability::Blend);
Context::Disable(Capability::DepthTest);
Context::Disable(Capability::CullFace);
program = loadDefaultShader();
plane = loadPlane(program);
Context::ClearColor(0, 0, 0, 1);
crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
// FIXME make this into a setting that can be adjusted
const float DEFAULT_IPD = 0.064f;
const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f;
@ -112,10 +91,14 @@ void sbs_for_each_eye(const uvec2& size, F f) {
void Tv3dDisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
makeCurrent();
GLenum err = glGetError();
uvec2 size = toGlm(getDeviceSize());
err = glGetError();
using namespace oglplus;
err = glGetError();
Context::Viewport(size.x, size.y);
err = glGetError();
Context::Clear().ColorBuffer().DepthBuffer();
Mat4Uniform(*program, "ModelView").Set(mat4());
@ -178,15 +161,6 @@ void Tv3dDisplayPlugin::display(
void Tv3dDisplayPlugin::activate(PluginContainer * container) {
GlWindowDisplayPlugin::activate(container);
_window->show();
}
void Tv3dDisplayPlugin::deactivate() {
makeCurrent();
plane.reset();
program.reset();
crosshairTexture.reset();
doneCurrent();
GlWindowDisplayPlugin::deactivate();
OpenGlDisplayPlugin::activate(container);
// FIXME Add menu items
}

View file

@ -7,27 +7,29 @@
//
#pragma once
#include "GlWindowDisplayPlugin.h"
#include "OpenGlDisplayPlugin.h"
class Tv3dDisplayPlugin : public GlWindowDisplayPlugin {
class Tv3dDisplayPlugin : public OpenGlDisplayPlugin {
Q_OBJECT
public:
static const QString NAME;
virtual const QString & getName();
Tv3dDisplayPlugin();
virtual const QString & getName();
virtual bool isStereo() const final { return true; }
virtual bool isSupported() const final;
virtual void activate(PluginContainer * container);
void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
virtual void activate(PluginContainer * container);
virtual void deactivate();
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const;
virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const;
protected:
virtual void customizeWindow();
virtual void customizeContext();
virtual void customizeWindow(PluginContainer * container);
//virtual std::function<QPointF(const QPointF&)> getMouseTranslator();
//virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const;
private:
static const QString NAME;
};

View file

@ -7,6 +7,12 @@
//
#include "WindowDisplayPlugin.h"
#include <QMainWindow>
#include <GlWindow.h>
#include "plugins/PluginContainer.h"
WindowDisplayPlugin::WindowDisplayPlugin() {
}
@ -16,3 +22,73 @@ const QString & WindowDisplayPlugin::getName() {
return NAME;
}
void WindowDisplayPlugin::customizeWindow(PluginContainer * container) {
QMainWindow* mainWindow = container->getAppMainWindow();
QWidget* widget = QWidget::createWindowContainer(_window);
mainWindow->setCentralWidget(widget);
}
void WindowDisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height());
if (sceneTexture) {
glBindTexture(GL_TEXTURE_2D, sceneTexture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1, 0);
glVertex2f(+1, -1);
glTexCoord2f(1, 1);
glVertex2f(+1, +1);
glTexCoord2f(0, 1);
glVertex2f(-1, +1);
glEnd();
}
if (overlayTexture) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1, 0);
glVertex2f(+1, -1);
glTexCoord2f(1, 1);
glVertex2f(+1, +1);
glTexCoord2f(0, 1);
glVertex2f(-1, +1);
glEnd();
}
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
//Q_ASSERT(!glGetError());
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glFinish();
}

View file

@ -7,9 +7,9 @@
//
#pragma once
#include "GlWindowDisplayPlugin.h"
#include "OpenGlDisplayPlugin.h"
class WindowDisplayPlugin : public GlWindowDisplayPlugin {
class WindowDisplayPlugin : public OpenGlDisplayPlugin {
Q_OBJECT
public:
static const QString NAME;
@ -17,5 +17,12 @@ public:
WindowDisplayPlugin();
virtual const QString & getName();
private:
void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
protected:
// Called by the activate method to specify the initial
// window geometry flags, etc
virtual void customizeWindow(PluginContainer * container);
};

View file

@ -2,6 +2,10 @@
#include <QString>
class QMainWindow;
class PluginContainer {
public:
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0;
virtual QMainWindow* getAppMainWindow() = 0;
};

View file

@ -47,6 +47,9 @@ void GlWindow::makeCurrent() {
_logger = new QOpenGLDebugLogger(this);
if (_logger->initialize()) {
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
if (message.type() == QOpenGLDebugMessage::Type::ErrorType) {
qDebug() << "Error";
}
qDebug() << message;
});
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);

View file

@ -48,6 +48,9 @@ bool OffscreenGlCanvas::makeCurrent() {
_logger = new QOpenGLDebugLogger(this);
if (_logger->initialize()) {
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
if (message.type() == QOpenGLDebugMessage::Type::ErrorType) {
qDebug() << "Error";
}
qDebug() << message;
});
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);