From 912c003d58e7932ff59b717169ee977000216883 Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Fri, 29 May 2015 16:49:11 -0700
Subject: [PATCH] Making (most) plugins into a library

---
 cmake/macros/SetupHifiOpenGL.cmake            |  43 +++
 interface/CMakeLists.txt                      |  21 +-
 interface/src/Application.cpp                 |  28 +-
 interface/src/Application.h                   |   5 +-
 .../display => }/LegacyDisplayPlugin.cpp      |  62 +++--
 .../display => }/LegacyDisplayPlugin.h        |  20 +-
 interface/src/avatar/MyAvatar.cpp             |   1 -
 interface/src/plugins/Plugin.cpp              |   1 -
 interface/src/plugins/Plugin.h                |  22 --
 .../src/plugins/display/HmdDisplayPlugin.cpp  |  11 -
 .../src/plugins/display/HmdDisplayPlugin.h    |  15 --
 .../plugins/display/SimpleDisplayPlugin.cpp   | 161 ------------
 .../src/plugins/display/SimpleDisplayPlugin.h |  62 -----
 .../plugins/display/StereoDisplayPlugin.cpp   |  10 -
 .../src/plugins/display/StereoDisplayPlugin.h |  17 --
 .../src/plugins/display/Tv3dDisplayPlugin.cpp | 245 ------------------
 .../plugins/display/WindowDisplayPlugin.cpp   |  38 ---
 libraries/display-plugins/CMakeLists.txt      |  30 +++
 .../display-plugins/src}/OculusHelpers.h      |   2 +-
 .../display-plugins/src/OglplusHelpers.cpp    | 122 +++++++++
 .../display-plugins/src}/OglplusHelpers.h     |  16 +-
 .../src/display-plugins}/DisplayPlugin.cpp    |   6 +-
 .../src/display-plugins}/DisplayPlugin.h      |  50 ++--
 .../display-plugins/GlWindowDisplayPlugin.cpp | 127 +++++++++
 .../display-plugins/GlWindowDisplayPlugin.h   |  41 +++
 .../display-plugins}/NullDisplayPlugin.cpp    |  13 +
 .../src/display-plugins}/NullDisplayPlugin.h  |  14 +-
 .../OculusBaseDisplayPlugin.cpp               |   9 +-
 .../OculusBaseDisplayPlugin.h                 |  11 +-
 .../OculusWin32DisplayPlugin.cpp              |  10 +-
 .../OculusWin32DisplayPlugin.h                |   2 +-
 .../display-plugins/OpenGlDisplayPlugin.cpp   |  88 +++++++
 .../src/display-plugins/OpenGlDisplayPlugin.h |  24 ++
 .../src/display-plugins/Tv3dDisplayPlugin.cpp | 176 +++++++++++++
 .../src/display-plugins}/Tv3dDisplayPlugin.h  |  19 +-
 .../display-plugins/WindowDisplayPlugin.cpp   |  18 ++
 .../display-plugins}/WindowDisplayPlugin.h    |  13 +-
 libraries/plugins/CMakeLists.txt              |   2 +-
 libraries/plugins/src/Plugin.h                |  20 --
 libraries/plugins/src/plugins/Plugin.cpp      |   9 +
 libraries/plugins/src/plugins/Plugin.h        |  29 +++
 .../src/{ => plugins}/PluginContainer.h       |   0
 .../plugins}/src/plugins/PluginManager.cpp    |   0
 .../plugins}/src/plugins/PluginManager.h      |   4 +-
 44 files changed, 889 insertions(+), 728 deletions(-)
 create mode 100644 cmake/macros/SetupHifiOpenGL.cmake
 rename interface/src/{plugins/display => }/LegacyDisplayPlugin.cpp (73%)
 rename interface/src/{plugins/display => }/LegacyDisplayPlugin.h (60%)
 delete mode 100644 interface/src/plugins/Plugin.cpp
 delete mode 100644 interface/src/plugins/Plugin.h
 delete mode 100644 interface/src/plugins/display/HmdDisplayPlugin.cpp
 delete mode 100644 interface/src/plugins/display/HmdDisplayPlugin.h
 delete mode 100644 interface/src/plugins/display/SimpleDisplayPlugin.cpp
 delete mode 100644 interface/src/plugins/display/SimpleDisplayPlugin.h
 delete mode 100644 interface/src/plugins/display/StereoDisplayPlugin.cpp
 delete mode 100644 interface/src/plugins/display/StereoDisplayPlugin.h
 delete mode 100644 interface/src/plugins/display/Tv3dDisplayPlugin.cpp
 delete mode 100644 interface/src/plugins/display/WindowDisplayPlugin.cpp
 create mode 100644 libraries/display-plugins/CMakeLists.txt
 rename {interface/src/plugins/display => libraries/display-plugins/src}/OculusHelpers.h (97%)
 create mode 100644 libraries/display-plugins/src/OglplusHelpers.cpp
 rename {interface/src/plugins/display => libraries/display-plugins/src}/OglplusHelpers.h (55%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/DisplayPlugin.cpp (86%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/DisplayPlugin.h (72%)
 create mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp
 create mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/NullDisplayPlugin.cpp (69%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/NullDisplayPlugin.h (72%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusBaseDisplayPlugin.cpp (87%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusBaseDisplayPlugin.h (74%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusWin32DisplayPlugin.cpp (97%)
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusWin32DisplayPlugin.h (87%)
 create mode 100644 libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp
 create mode 100644 libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h
 create mode 100644 libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/Tv3dDisplayPlugin.h (67%)
 create mode 100644 libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp
 rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/WindowDisplayPlugin.h (62%)
 delete mode 100644 libraries/plugins/src/Plugin.h
 create mode 100644 libraries/plugins/src/plugins/Plugin.cpp
 create mode 100644 libraries/plugins/src/plugins/Plugin.h
 rename libraries/plugins/src/{ => plugins}/PluginContainer.h (100%)
 rename {interface => libraries/plugins}/src/plugins/PluginManager.cpp (100%)
 rename {interface => libraries/plugins}/src/plugins/PluginManager.h (51%)

diff --git a/cmake/macros/SetupHifiOpenGL.cmake b/cmake/macros/SetupHifiOpenGL.cmake
new file mode 100644
index 0000000000..c62e43c27e
--- /dev/null
+++ b/cmake/macros/SetupHifiOpenGL.cmake
@@ -0,0 +1,43 @@
+
+
+macro(SETUP_HIFI_OPENGL)
+
+    if (APPLE)
+
+      # link in required OS X frameworks and include the right GL headers
+      find_library(OpenGL OpenGL)
+      target_link_libraries(${TARGET_NAME} ${OpenGL})
+
+    elseif (WIN32)
+
+      add_dependency_external_projects(glew)
+      find_package(GLEW REQUIRED)
+      target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS})
+      target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib)
+
+      if (USE_NSIGHT)
+        # try to find the Nsight package and add it to the build if we find it
+        find_package(NSIGHT)
+        if (NSIGHT_FOUND)
+          include_directories(${NSIGHT_INCLUDE_DIRS})
+          add_definitions(-DNSIGHT_FOUND)
+          target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}")
+        endif()
+      endif()
+
+    elseif(ANDROID)
+
+      target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL")
+
+    else()
+
+      find_package(OpenGL REQUIRED)
+      if (${OPENGL_INCLUDE_DIR})
+        include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}")
+      endif()
+      target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}")
+      target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
+
+    endif()
+
+endmacro()
diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index bb9960643c..458b6a7d7c 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -128,25 +128,6 @@ add_dependency_external_projects(glm bullet)
 find_package(GLM REQUIRED)
 target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS})
 
-add_dependency_external_projects(boostconfig)
-find_package(BOOSTCONFIG REQUIRED)
-target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS})
-
-add_dependency_external_projects(oglplus)
-find_package(OGLPLUS REQUIRED)
-target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS})
-
-
-add_dependency_external_projects(LibOVR)
-find_package(LibOVR REQUIRED)
-target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS})
-target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
-
-add_dependency_external_projects(OpenVR)
-find_package(OpenVR REQUIRED)
-target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
-target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
-
 find_package(Bullet REQUIRED)
 target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
 target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
@@ -154,7 +135,7 @@ target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
 # link required hifi libraries
 link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars 
                     audio audio-client animation script-engine physics 
-                    render-utils entities-renderer ui)
+                    render-utils entities-renderer ui plugins display-plugins)
 
 add_dependency_external_projects(sdl2)
 
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 90730e8c82..f42d86d8eb 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -116,7 +116,7 @@
 #include "gpu/Batch.h"
 #include "gpu/GLBackend.h"
 
-#include "plugins/display/DisplayPlugin.h"
+#include <display-plugins/DisplayPlugin.h>
 
 #include "scripting/AccountScriptingInterface.h"
 #include "scripting/AudioDeviceScriptingInterface.h"
@@ -4582,12 +4582,11 @@ qreal Application::getDevicePixelRatio() {
 
 using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
 
-#include "plugins/display/NullDisplayPlugin.h"
-#include "plugins/display/WindowDisplayPlugin.h"
-#include "plugins/display/LegacyDisplayPlugin.h"
-#include "plugins/display/OculusDisplayPlugin.h"
-#include "plugins/display/Tv3dDisplayPlugin.h"
-#include "plugins/display/WindowDisplayPlugin.h"
+#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 };
 
@@ -4631,7 +4630,7 @@ static DisplayPlugin* PLUGIN_POOL[] = {
     new NullDisplayPlugin(),
 #endif
     new Tv3dDisplayPlugin(),
-    new WindowDisplayPlugin(),
+//    new WindowDisplayPlugin(),
     nullptr
 };
 
@@ -4674,9 +4673,17 @@ void Application::updateDisplayMode() {
     if (_displayPlugin != newDisplayPlugin) {
         if (newDisplayPlugin) {
             _offscreenContext->makeCurrent();
-            newDisplayPlugin->activate();
+            newDisplayPlugin->activate(this);
+            QWindow* pluginWindow = newDisplayPlugin->getWindow();
+            if (pluginWindow) {
+                //  Event filter queue is 'last in, first used'
+                pluginWindow->installEventFilter(DependencyManager::get<OffscreenUi>().data());
+                pluginWindow->installEventFilter(qApp);
+                DependencyManager::get<OffscreenUi>()->setProxyWindow(pluginWindow);
+            }
             _offscreenContext->makeCurrent();
         }
+
         std::swap(newDisplayPlugin, _displayPlugin);
         if (newDisplayPlugin) {
             newDisplayPlugin->deactivate();
@@ -4694,3 +4701,6 @@ glm::ivec2 Application::getMouse() const {
     return getActiveDisplayPlugin()->getUiMousePosition();
 }
 
+void Application::addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName) {
+
+}
diff --git a/interface/src/Application.h b/interface/src/Application.h
index a94859263a..a91e5f77f2 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -40,6 +40,7 @@
 #include <StDev.h>
 #include <TextureCache.h>
 #include <ViewFrustum.h>
+#include <plugins/PluginContainer.h>
 
 #include "AudioClient.h"
 #include "Bookmarks.h"
@@ -136,7 +137,7 @@ class Application;
 
 typedef bool (Application::* AcceptURLMethod)(const QString &);
 
-class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface {
+class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface, PluginContainer {
     Q_OBJECT
 
     friend class OctreePacketProcessor;
@@ -280,6 +281,8 @@ public:
     QImage renderAvatarBillboard();
 
     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
diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.cpp b/interface/src/LegacyDisplayPlugin.cpp
similarity index 73%
rename from interface/src/plugins/display/LegacyDisplayPlugin.cpp
rename to interface/src/LegacyDisplayPlugin.cpp
index a6b79fa5ef..4fbb02e454 100644
--- a/interface/src/plugins/display/LegacyDisplayPlugin.cpp
+++ b/interface/src/LegacyDisplayPlugin.cpp
@@ -19,38 +19,46 @@ const QString & LegacyDisplayPlugin::getName() {
     return NAME;
 }
 
+LegacyDisplayPlugin::LegacyDisplayPlugin() {
+    connect(&_timer, &QTimer::timeout, this, [&] {
+        emit requestRender();
+    });
+}
+
 static QWidget * oldWidget = nullptr;
 
-void LegacyDisplayPlugin::activate() {
+void LegacyDisplayPlugin::activate(PluginContainer * container) {
     _window = new GLCanvas();
 
     QOpenGLContext * sourceContext = QOpenGLContext::currentContext();
-    QSurfaceFormat format;
-    format.setOption(QSurfaceFormat::DebugContext);
 
 
     QOpenGLContext * newContext = new QOpenGLContext();
-    newContext->setFormat(format);
+
+    {
+        QSurfaceFormat format;
+        format.setOption(QSurfaceFormat::DebugContext);
+        newContext->setFormat(format);
+    }
+
     _window->setContext(
         QGLContext::fromOpenGLContext(newContext),
         QGLContext::fromOpenGLContext(sourceContext));
-    _window->makeCurrent();
-
     oldWidget = qApp->getWindow()->centralWidget();
+
+    // FIXME necessary?
+    makeCurrent();
     qApp->getWindow()->setCentralWidget(_window);
-    _window->doneCurrent();
+    doneCurrent();
     _window->setFocusPolicy(Qt::StrongFocus);
     _window->setFocus();
     _window->setMouseTracking(true);
-
-    _window->installEventFilter(qApp);
-    _window->installEventFilter(DependencyManager::get<OffscreenUi>().data());
-
-    DependencyManager::get<OffscreenUi>()->setProxyWindow(_window->windowHandle());
-    SimpleDisplayPlugin::activate();
+    _timer.start(8);
 }
 
+
 void LegacyDisplayPlugin::deactivate() {
+    _timer.stop();
     _window->removeEventFilter(DependencyManager::get<OffscreenUi>().data());
     _window->removeEventFilter(qApp);
     // FIXME, during shutdown, this causes an NPE.  Need to deactivate the plugin before the main window is destroyed.
@@ -84,16 +92,32 @@ PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const {
     return PickRay();
 }
 
-bool isMouseOnScreen() {
-    return false;
-}
-
 void LegacyDisplayPlugin::preDisplay() {
-    SimpleDisplayPlugin::preDisplay();
+    OpenGlDisplayPlugin::preDisplay();
     auto size = toGlm(_window->size());
     glViewport(0, 0, size.x, size.y);
 }
 
 bool LegacyDisplayPlugin::isThrottled() const {
     return _window->isThrottleRendering();
-}
\ No newline at end of file
+}
+
+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();
+}
diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.h b/interface/src/LegacyDisplayPlugin.h
similarity index 60%
rename from interface/src/plugins/display/LegacyDisplayPlugin.h
rename to interface/src/LegacyDisplayPlugin.h
index 33ea6187c3..223f4d9e01 100644
--- a/interface/src/plugins/display/LegacyDisplayPlugin.h
+++ b/interface/src/LegacyDisplayPlugin.h
@@ -9,26 +9,36 @@
 //
 #pragma once
 
-#include "SimpleDisplayPlugin.h"
+#include <display-plugins/OpenGlDisplayPlugin.h>
 #include "GLCanvas.h"
 
-class LegacyDisplayPlugin : public SimpleDisplayPlugin<GLCanvas> {
+class LegacyDisplayPlugin : public OpenGlDisplayPlugin {
     Q_OBJECT
 public:
+    LegacyDisplayPlugin();
     static const QString NAME;
     virtual const QString & getName();
 
-    virtual void activate();
+    virtual void activate(PluginContainer * container);
     virtual void deactivate();
 
     virtual QSize getDeviceSize() const;
-    virtual glm::ivec2 getCanvasSize() 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;
 
 protected:
-    virtual void idle();
+    virtual void makeCurrent() final;
+    virtual void doneCurrent() final;
+    virtual void swapBuffers() final;
+
+private:
+    GLCanvas * _window;
+    QTimer _timer;
 };
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index 0ba4d1637b..e573110157 100644
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -34,7 +34,6 @@
 #include <UserActivityLogger.h>
 
 #include "Application.h"
-#include "plugins/display/DisplayPlugin.h"
 #include "AvatarManager.h"
 #include "Environment.h"
 #include "Menu.h"
diff --git a/interface/src/plugins/Plugin.cpp b/interface/src/plugins/Plugin.cpp
deleted file mode 100644
index d882c538b4..0000000000
--- a/interface/src/plugins/Plugin.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "Plugin.h"
diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h
deleted file mode 100644
index ff91a6e1e2..0000000000
--- a/interface/src/plugins/Plugin.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include <QString>
-#include <QObject>
-
-class PluginContainer {
-    virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0;
-};
-
-class Plugin : public QObject {
-public:
-    virtual const QString & getName() = 0;
-    virtual bool isSupported() const { return true; }
-
-    virtual void init() {}
-    virtual void deinit() {}
-
-    virtual void activate(PluginContainer * container) {}
-    virtual void deactivate() {}
-
-    virtual void idle() {}
-};
diff --git a/interface/src/plugins/display/HmdDisplayPlugin.cpp b/interface/src/plugins/display/HmdDisplayPlugin.cpp
deleted file mode 100644
index bfe4a088fa..0000000000
--- a/interface/src/plugins/display/HmdDisplayPlugin.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-//  HmdDisplayPlugin.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 "HmdDisplayPlugin.h"
diff --git a/interface/src/plugins/display/HmdDisplayPlugin.h b/interface/src/plugins/display/HmdDisplayPlugin.h
deleted file mode 100644
index 1156bafcda..0000000000
--- a/interface/src/plugins/display/HmdDisplayPlugin.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-//  HmdDisplayPlugin.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 "StereoDisplayPlugin.h"
-
-class HmdDisplayPlugin : public StereoDisplayPlugin {
-    virtual bool isHmd() const final { return true; }
-};
diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.cpp b/interface/src/plugins/display/SimpleDisplayPlugin.cpp
deleted file mode 100644
index 3c7ec2fb3f..0000000000
--- a/interface/src/plugins/display/SimpleDisplayPlugin.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-//  SimpleDisplayPlugin.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 "SimpleDisplayPlugin.h"
-#include <QOpenGLContext>
-#include <QCursor>
-#include <QCoreApplication>
-
-#include <RenderUtil.h>
-#include "DependencyManager.h"
-#include "TextureCache.h"
-#include "gpu/GLBackend.h"
-#include "OffscreenUi.h"
-
-void SimpleGlDisplayPlugin::activate() {
-    makeCurrent();
-    doneCurrent();
-}
-
-void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize,
-                                    GLuint overlayTexture, const glm::uvec2& overlaySize) {
-    makeCurrent();
-    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();
-}
-
-bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) {
-    if (qApp->eventFilter(object, event)) {
-        return true;
-    }
-
-    auto offscreenUi = DependencyManager::get<OffscreenUi>();
-    if (offscreenUi->eventFilter(object, event)) {
-        return true;
-    }
-
-    switch (event->type()) {
-        case QEvent::KeyPress:
-        case QEvent::KeyRelease:
-            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
-            break;
-
-        case QEvent::MouseButtonPress:
-        case QEvent::MouseButtonRelease:
-        case QEvent::FocusIn:
-        case QEvent::FocusOut:
-        case QEvent::Resize:
-        case QEvent::MouseMove:
-            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
-            break;
-        default:
-            break;
-    }
-    return false;
-}
-
-
-static QSurfaceFormat getPluginFormat() {
-    QSurfaceFormat format;
-    // Qt Quick may need a depth and stencil buffer. Always make sure these are available.
-    format.setDepthBufferSize(16);
-    format.setStencilBufferSize(8);
-    format.setVersion(4, 1);
-#ifdef DEBUG
-    format.setOption(QSurfaceFormat::DebugContext);
-#endif
-    format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
-    return format;
-}
-
-
-void GlWindowDisplayPlugin::activate() {
-    Q_ASSERT(nullptr == _window);
-    _window = new GlWindow(getPluginFormat(), QOpenGLContext::currentContext());
-    _window->installEventFilter(this);
-    DependencyManager::get<OffscreenUi>()->setProxyWindow(_window);
-}
-
-void GlWindowDisplayPlugin::deactivate() {
-    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();
-}
diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.h b/interface/src/plugins/display/SimpleDisplayPlugin.h
deleted file mode 100644
index ca86d85875..0000000000
--- a/interface/src/plugins/display/SimpleDisplayPlugin.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-//  SimpleDisplayPlugin.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 "DisplayPlugin.h"
-
-#include <QCursor>
-
-#include <QOpenGLContext>
-#include <GLMHelpers.h>
-#include <RenderUtil.h>
-#include <GlWindow.h>
-
-class SimpleGlDisplayPlugin : public DisplayPlugin {
-public:
-    virtual void activate();
-    virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
-                         GLuint overlayTexture, const glm::uvec2& overlaySize);
-};
-
-template <typename T>
-class SimpleDisplayPlugin : public SimpleGlDisplayPlugin {
-public:
-    virtual glm::ivec2 getTrueMousePosition() const {
-        return toGlm(_window->mapFromGlobal(QCursor::pos()));
-    }
-
-protected:
-    void makeCurrent() final {
-        _window->makeCurrent();
-    }
-
-    void doneCurrent() final {
-        _window->doneCurrent();
-    }
-
-    void swapBuffers() final {
-        _window->swapBuffers();
-    }
-
-protected:
-    T * _window{ nullptr };
-};
-
-
-class GlWindowDisplayPlugin : public SimpleDisplayPlugin<GlWindow> {
-public:
-    virtual void activate();
-    virtual void deactivate();
-    virtual QSize getDeviceSize() const final;
-    virtual glm::ivec2 getCanvasSize() const final;
-    virtual bool hasFocus() const;
-    virtual bool eventFilter(QObject* object, QEvent* event);
-};
-
diff --git a/interface/src/plugins/display/StereoDisplayPlugin.cpp b/interface/src/plugins/display/StereoDisplayPlugin.cpp
deleted file mode 100644
index 25070a4967..0000000000
--- a/interface/src/plugins/display/StereoDisplayPlugin.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-//
-//  StereoDisplayPlugin.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 "StereoDisplayPlugin.h"
diff --git a/interface/src/plugins/display/StereoDisplayPlugin.h b/interface/src/plugins/display/StereoDisplayPlugin.h
deleted file mode 100644
index e3944ff878..0000000000
--- a/interface/src/plugins/display/StereoDisplayPlugin.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-//  StereoDisplayPlugin.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 "DisplayPlugin.h"
-
-class StereoDisplayPlugin : public DisplayPlugin {
-    virtual bool isStereo() const final { return true; }
-};
-
diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp
deleted file mode 100644
index efd6c055c9..0000000000
--- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-//  Tv3dDisplayPlugin.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 "Tv3dDisplayPlugin.h"
-#include <GlWindow.h>
-#include <QApplication>
-#include <QDesktopWidget>
-
-#include "gpu/Texture.h"
-#include "gpu/GLBackend.h"
-#include "PathUtils.h"
-
-#include "Application.h"
-#include "ui/ApplicationOverlay.h"
-
-
-#include <GL/glew.h>
-#define OGLPLUS_LOW_PROFILE 1
-#define OGLPLUS_USE_GLEW 1
-#define OGLPLUS_USE_BOOST_CONFIG 1
-#define OGLPLUS_NO_SITE_CONFIG 1
-#define OGLPLUS_USE_GLCOREARB_H 0
-#include <oglplus/gl.hpp>
-
-#pragma warning(disable : 4068)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
-#pragma warning( disable : 4244 4267 4065 4101)
-#include <oglplus/all.hpp>
-#include <oglplus/interop/glm.hpp>
-#include <oglplus/bound/texture.hpp>
-#include <oglplus/bound/framebuffer.hpp>
-#include <oglplus/bound/renderbuffer.hpp>
-#include <oglplus/shapes/wrapper.hpp>
-#include <oglplus/shapes/plane.hpp>
-#pragma warning( default : 4244 4267 4065 4101)
-#pragma clang diagnostic pop
-
-typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr;
-typedef std::shared_ptr<oglplus::Buffer> BufferPtr;
-typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr;
-typedef std::shared_ptr<oglplus::Program> ProgramPtr;
-typedef oglplus::Uniform<mat4> Mat4Uniform;
-
-const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin");
-
-const QString & Tv3dDisplayPlugin::getName() {
-    return NAME;
-}
-
-Tv3dDisplayPlugin::Tv3dDisplayPlugin() {
-    connect(&_timer, &QTimer::timeout, this, [&] {
-        emit requestRender();
-    });
-}
-
-bool Tv3dDisplayPlugin::isSupported() const {
-    // FIXME this should attempt to do a scan for supported 3D output
-    return true;
-}
-
-gpu::TexturePointer _crosshairTexture; 
-
-
-void compileProgram(ProgramPtr & result, std::string vs, std::string fs) {
-    using namespace oglplus;
-    try {
-        result = ProgramPtr(new Program());
-        // attach the shaders to the program
-        result->AttachShader(
-            VertexShader()
-            .Source(GLSLSource(vs))
-            .Compile()
-            );
-        result->AttachShader(
-            FragmentShader()
-            .Source(GLSLSource(fs))
-            .Compile()
-            );
-        result->Link();
-    } catch (ProgramBuildError & err) {
-        qFatal((const char*)err.Message);
-        result.reset();
-    }
-}
-
-
-ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) {
-    using namespace oglplus;
-    Vec3f a(1, 0, 0);
-    Vec3f b(0, 1, 0);
-    if (aspect > 1) {
-        b[1] /= aspect;
-    } else {
-        a[0] *= aspect;
-    }
-    return ShapeWrapperPtr(
-        new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program)
-    );
-}
-
-
-static const char * QUAD_VS = R"VS(#version 330
-
-uniform mat4 Projection = mat4(1);
-uniform mat4 ModelView = mat4(1);
-uniform vec2 UvMultiplier = vec2(1);
-
-layout(location = 0) in vec3 Position;
-layout(location = 1) in vec2 TexCoord;
-
-out vec2 vTexCoord;
-
-void main() {
-  gl_Position = Projection * ModelView * vec4(Position, 1);
-  vTexCoord = TexCoord * UvMultiplier;
-}
-)VS";
-
-static const char * QUAD_FS = R"FS(#version 330
-uniform sampler2D sampler;
-uniform float Alpha = 1.0;
-
-in vec2 vTexCoord;
-out vec4 vFragColor;
-
-void main() {
-    vec4 c = texture(sampler, vTexCoord);
-    c.a = min(Alpha, c.a);
-    vFragColor = c; 
-    //vFragColor = vec4(fract(vTexCoord), log(vTexCoord.x), 1.0);
-}
-)FS";
-
-static ProgramPtr program;
-static ShapeWrapperPtr plane;
-
-void Tv3dDisplayPlugin::display(
-    GLuint sceneTexture, const glm::uvec2& sceneSize,
-    GLuint overlayTexture, const glm::uvec2& overlaySize) {
-    QSize size = getDeviceSize();
-    makeCurrent();
-
-
-    if (!program) {
-        using namespace oglplus;
-        Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha);
-        Context::Disable(Capability::Blend);
-        Context::Disable(Capability::DepthTest);
-        Context::Disable(Capability::CullFace);
-
-        program = ProgramPtr(new oglplus::Program());
-        compileProgram(program, QUAD_VS, QUAD_FS);
-        plane = loadPlane(program, 1.0f);
-        _crosshairTexture = DependencyManager::get<TextureCache>()->
-            getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
-    }
-
-
-
-    glClearColor(0, 0, 0, 1);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    glViewport(0, 0, size.width(), size.height());
-    Mat4Uniform(*program, "ModelView").Set(mat4());
-    Mat4Uniform(*program, "Projection").Set(mat4());
-    glBindTexture(GL_TEXTURE_2D, sceneTexture);
-    plane->Draw();
-
-    const float overlayAspect = aspect(toGlm(size));
-    const GLfloat distance = 1.0f;
-    const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES);
-    const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height();
-    const GLfloat quadWidth = halfQuadWidth * 2.0f;
-    const GLfloat quadHeight = halfQuadHeight * 2.0f;
-
-    vec3 quadSize(quadWidth, quadHeight, 1.0f);
-    quadSize = vec3(1.0f) / quadSize;
-
-    using namespace oglplus;
-
-    Context::Enable(Capability::Blend);
-    glBindTexture(GL_TEXTURE_2D, overlayTexture);
-    
-    mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP);
-    Mat4Uniform(*program, "Projection").Set(pr);
-
-    MatrixStack mv;
-    mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0));
-
-    QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height()));
-    for (int i = 0; i < 2; ++i) {
-        Context::Viewport(r.x(), r.y(), r.width(), r.height());
-        Mat4Uniform(*program, "ModelView").Set(mv.top());
-        plane->Draw();
-        r.moveLeft(r.width());
-    }
-
-    glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
-    glm::vec2 canvasSize = qApp->getCanvasSize();
-    glm::vec2 mouse = qApp->getMouse();
-    mouse /= canvasSize;
-    mouse *= 2.0f;
-    mouse -= 1.0f;
-    mouse.y *= -1.0f;
-    mv.translate(mouse);
-    mv.scale(0.1f);
-    Mat4Uniform(*program, "ModelView").Set(mv.top());
-    r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height()));
-    for (int i = 0; i < 2; ++i) {
-        Context::Viewport(r.x(), r.y(), r.width(), r.height());
-        plane->Draw();
-        r.moveLeft(r.width());
-    }
-    Context::Disable(Capability::Blend);
-}
-
-
-void Tv3dDisplayPlugin::activate() {
-    GlWindowDisplayPlugin::activate();
-    _window->installEventFilter(this);
-    _window->setFlags(Qt::FramelessWindowHint);
-    auto desktop = QApplication::desktop();
-    _window->setGeometry(desktop->screenGeometry());
-    _window->setCursor(Qt::BlankCursor);
-    _window->show();
-
-    _timer.start(8);
-}
-
-void Tv3dDisplayPlugin::deactivate() {
-    makeCurrent();
-    if (plane) {
-        plane.reset();
-        program.reset();
-        _crosshairTexture.reset();
-    }
-    _timer.stop();
-    GlWindowDisplayPlugin::deactivate();
-}
diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp
deleted file mode 100644
index 25162e9343..0000000000
--- a/interface/src/plugins/display/WindowDisplayPlugin.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-//  WindowDisplayPlugin.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 "WindowDisplayPlugin.h"
-#include "RenderUtil.h"
-#include "Application.h"
-
-WindowDisplayPlugin::WindowDisplayPlugin() {
-    connect(&_timer, &QTimer::timeout, this, [&] {
-//        if (qApp->getActiveDisplayPlugin() == this) {
-            emit requestRender();
-//        }
-    });
-}
-
-const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer");
-
-const QString & WindowDisplayPlugin::getName() {
-    return NAME;
-}
-
-void WindowDisplayPlugin::activate() {
-    GlWindowDisplayPlugin::activate();
-    _window->show();
-    _timer.start(8);
-}
-
-void WindowDisplayPlugin::deactivate() {
-    _timer.stop();
-    GlWindowDisplayPlugin::deactivate();
-}
-
diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt
new file mode 100644
index 0000000000..cbfecfb0da
--- /dev/null
+++ b/libraries/display-plugins/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(TARGET_NAME display-plugins)
+
+# use setup_hifi_library macro to setup our project and link appropriate Qt modules
+setup_hifi_library(OpenGL)
+
+setup_hifi_opengl()
+
+link_hifi_libraries(shared plugins )
+
+add_dependency_external_projects(glm)
+find_package(GLM REQUIRED)
+target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
+
+add_dependency_external_projects(boostconfig)
+find_package(BOOSTCONFIG REQUIRED)
+target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS})
+
+add_dependency_external_projects(oglplus)
+find_package(OGLPLUS REQUIRED)
+target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS})
+
+add_dependency_external_projects(LibOVR)
+find_package(LibOVR REQUIRED)
+target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS})
+target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
+
+add_dependency_external_projects(OpenVR)
+find_package(OpenVR REQUIRED)
+target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS})
+target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES})
diff --git a/interface/src/plugins/display/OculusHelpers.h b/libraries/display-plugins/src/OculusHelpers.h
similarity index 97%
rename from interface/src/plugins/display/OculusHelpers.h
rename to libraries/display-plugins/src/OculusHelpers.h
index 553a1671e5..acd02e1af9 100644
--- a/interface/src/plugins/display/OculusHelpers.h
+++ b/libraries/display-plugins/src/OculusHelpers.h
@@ -1,5 +1,5 @@
 //
-//  Created by Bradley Austin Davis on 2015/05/26.
+//  Created by Bradley Austin Davis on 2015/05/26
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
diff --git a/libraries/display-plugins/src/OglplusHelpers.cpp b/libraries/display-plugins/src/OglplusHelpers.cpp
new file mode 100644
index 0000000000..fd9d9500f1
--- /dev/null
+++ b/libraries/display-plugins/src/OglplusHelpers.cpp
@@ -0,0 +1,122 @@
+//
+//  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 "OglplusHelpers.h"
+
+
+static const char * SIMPLE_TEXTURED_VS = R"VS(#version 410 core
+#pragma line __LINE__
+
+uniform mat4 Projection = mat4(1);
+uniform mat4 ModelView = mat4(1);
+
+layout(location = 0) in vec3 Position;
+layout(location = 1) in vec2 TexCoord;
+
+out vec2 vTexCoord;
+
+void main() {
+  gl_Position = Projection * ModelView * vec4(Position, 1);
+  vTexCoord = TexCoord;
+}
+
+)VS";
+
+static const char * SIMPLE_TEXTURED_FS = R"FS(#version 410 core
+#pragma line __LINE__
+
+uniform sampler2D sampler;
+uniform float Alpha = 1.0;
+
+in vec2 vTexCoord;
+out vec4 vFragColor;
+
+void main() {
+    vec4 c = texture(sampler, vTexCoord);
+    c.a = min(Alpha, c.a);
+    vFragColor = c; 
+}
+
+)FS";
+
+
+ProgramPtr loadDefaultShader() {
+    ProgramPtr result;
+    compileProgram(result, SIMPLE_TEXTURED_VS, SIMPLE_TEXTURED_FS);
+    return result;
+}
+
+void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs) {
+    using namespace oglplus;
+    try {
+        result = ProgramPtr(new Program());
+        // attach the shaders to the program
+        result->AttachShader(
+            VertexShader()
+            .Source(GLSLSource(vs))
+            .Compile()
+            );
+        result->AttachShader(
+            FragmentShader()
+            .Source(GLSLSource(fs))
+            .Compile()
+            );
+        result->Link();
+    } catch (ProgramBuildError & err) {
+        Q_UNUSED(err);
+        Q_ASSERT_X(false, "compileProgram", "Failed to build shader program");
+        qFatal((const char*)err.Message);
+        result.reset();
+    }
+}
+
+
+ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) {
+    using namespace oglplus;
+    Vec3f a(1, 0, 0);
+    Vec3f b(0, 1, 0);
+    if (aspect > 1) {
+        b[1] /= aspect;
+    } else {
+        a[0] *= aspect;
+    }
+    return ShapeWrapperPtr(
+        new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program)
+    );
+}
+
+
+static const char * QUAD_VS = R"VS(#version 330
+
+uniform mat4 Projection = mat4(1);
+uniform mat4 ModelView = mat4(1);
+uniform vec2 UvMultiplier = vec2(1);
+
+layout(location = 0) in vec3 Position;
+layout(location = 1) in vec2 TexCoord;
+
+out vec2 vTexCoord;
+
+void main() {
+  gl_Position = Projection * ModelView * vec4(Position, 1);
+  vTexCoord = TexCoord * UvMultiplier;
+}
+)VS";
+
+static const char * QUAD_FS = R"FS(#version 330
+uniform sampler2D sampler;
+uniform float Alpha = 1.0;
+
+in vec2 vTexCoord;
+out vec4 vFragColor;
+
+void main() {
+    vec4 c = texture(sampler, vTexCoord);
+    c.a = min(Alpha, c.a);
+    vFragColor = c; 
+}
+)FS";
diff --git a/interface/src/plugins/display/OglplusHelpers.h b/libraries/display-plugins/src/OglplusHelpers.h
similarity index 55%
rename from interface/src/plugins/display/OglplusHelpers.h
rename to libraries/display-plugins/src/OglplusHelpers.h
index b74362a617..ddeff20506 100644
--- a/interface/src/plugins/display/OglplusHelpers.h
+++ b/libraries/display-plugins/src/OglplusHelpers.h
@@ -1,5 +1,5 @@
 //
-//  Created by Bradley Austin Davis on 2015/05/26.
+//  Created by Bradley Austin Davis on 2015/05/26
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -7,6 +7,10 @@
 //
 #pragma once
 
+#include <GLMHelpers.h>
+
+#pragma warning(disable : 4068)
+
 #define OGLPLUS_USE_GLEW 1
 #define OGLPLUS_USE_GLCOREARB_H 0
 #define OGLPLUS_USE_BOOST_CONFIG 1
@@ -24,3 +28,13 @@
 #include <oglplus/shapes/plane.hpp>
 
 typedef std::shared_ptr<oglplus::Framebuffer> FramebufferPtr;
+typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr;
+typedef std::shared_ptr<oglplus::Buffer> BufferPtr;
+typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr;
+typedef std::shared_ptr<oglplus::Program> ProgramPtr;
+typedef oglplus::Uniform<mat4> Mat4Uniform;
+
+ProgramPtr loadDefaultShader();
+void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs);
+ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect = 1.0f);
+
diff --git a/interface/src/plugins/display/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp
similarity index 86%
rename from interface/src/plugins/display/DisplayPlugin.cpp
rename to libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp
index d9d649019f..55e4dbd8ae 100644
--- a/interface/src/plugins/display/DisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp
@@ -1,7 +1,5 @@
 //
-//  DisplayPlugin.cpp
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -13,4 +11,4 @@ bool DisplayPlugin::isMouseOnScreen() const {
     glm::ivec2 mousePosition = getTrueMousePosition();
     return (glm::all(glm::greaterThanEqual(mousePosition, glm::ivec2(0))) &&
         glm::all(glm::lessThanEqual(mousePosition, glm::ivec2(getCanvasSize()))));
-}
\ No newline at end of file
+}
diff --git a/interface/src/plugins/display/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h
similarity index 72%
rename from interface/src/plugins/display/DisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/DisplayPlugin.h
index 711b53e9f4..b2726288cf 100644
--- a/interface/src/plugins/display/DisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h
@@ -1,7 +1,5 @@
 //
-//  DisplayPlugin.h
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -46,28 +44,43 @@ void for_each_eye(F f, FF ff) {
     f(Eye::Right);
 }
 
+class QWindow;
+
 class DisplayPlugin : public Plugin {
     Q_OBJECT
 public:
     virtual bool isHmd() const { return false; }
-    virtual bool isStereo() const { return false; }
+    /// By default, all HMDs are stereo
+    virtual bool isStereo() const { return isHmd(); }
     virtual bool isThrottled() const { return false; }
 
     // Rendering support
-    virtual void preRender() {};
-
-    virtual void preDisplay() {
-        makeCurrent();
-    };
 
+    /**
+     *  Called by the application before the frame rendering.  Can be used for
+     *  render timing related calls (for instance, the Oculus begin frame timing
+     *  call)
+     */
+    virtual void preRender() = 0;
+    /**
+     *  Called by the application immediately before calling the display function.
+     *  For OpenGL based plugins, this is the best place to put activate the output
+     *  OpenGL context
+     */
+    virtual void preDisplay() = 0;
+    /**
+     *  Sends the scene texture and the overlay texture to the display plugin.
+     *  The plugin is responsible for compositing these and adding rendering of
+     *  additional elements like mouse and hydra pointers as required
+     */
     virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
                          GLuint overlayTexture, const glm::uvec2& overlaySize) = 0;
+    /**
+     *  Called by the application immeidately after display.  For OpenGL based
+     *  displays, this is the best place to put the buffer swap
+     */
+    virtual void finishFrame() = 0;
 
-    virtual void finishFrame() {
-        swapBuffers();
-        doneCurrent();
-    };
-    
     // Does the rendering surface have current focus?
     virtual bool hasFocus() const = 0;
     // The size of the rendering surface
@@ -76,13 +89,15 @@ public:
     virtual QSize getRecommendedFramebufferSize() const { return getDeviceSize(); };
     // The size of the window (differs from the framebuffers size in instances like Retina macs)
     virtual glm::ivec2 getCanvasSize() const = 0;
+    // The window for the surface, used for event interception.  May be null.
+    virtual QWindow* getWindow() const = 0;
 
     // The mouse position relative to the window (or proxy window) surface
     virtual glm::ivec2 getTrueMousePosition() const = 0;
 
     // The mouse position relative to the UI elements
     virtual glm::ivec2 getUiMousePosition() const {
-        return trueMouseToUiMouse(getTrueMousePosition()); 
+        return trueMouseToUiMouse(getTrueMousePosition());
     }
 
     virtual std::function<QPointF(const QPointF&)> getMouseTranslator() { return [](const QPointF& p) { return p; }; };
@@ -123,10 +138,5 @@ public:
 signals:
     void recommendedFramebufferSizeChanged(const QSize & size);
     void requestRender();
-
-protected:
-    virtual void makeCurrent() {}
-    virtual void doneCurrent() {}
-    virtual void swapBuffers() {}
 };
 
diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp
new file mode 100644
index 0000000000..a456bf667b
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp
@@ -0,0 +1,127 @@
+//
+//  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;
+}
+
+bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) {
+    if (qApp->eventFilter(object, event)) {
+        return true;
+    }
+
+    // FIXME
+    /*
+    auto offscreenUi = DependencyManager::get<OffscreenUi>();
+    if (offscreenUi->eventFilter(object, event)) {
+        return true;
+    }
+    */
+
+    // distinct calls for easier debugging with breakpoints
+    switch (event->type()) {
+        case QEvent::KeyPress:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::KeyRelease:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::MouseButtonPress:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::MouseButtonRelease:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::FocusIn:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::FocusOut:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::Resize:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        case QEvent::MouseMove:
+            QCoreApplication::sendEvent(QCoreApplication::instance(), event);
+            break;
+        default:
+            break;
+    }
+    return false;
+}
+
+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();
+    // FIXME
+    //DependencyManager::get<OffscreenUi>()->setProxyWindow(_window);
+}
+
+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();
+}
diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h
new file mode 100644
index 0000000000..1833ab3a84
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h
@@ -0,0 +1,41 @@
+//
+//  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 bool eventFilter(QObject* object, QEvent* event);
+
+    virtual glm::ivec2 getTrueMousePosition() const;
+    virtual QWindow* getWindow() const;
+
+protected:
+    virtual void makeCurrent() final;
+    virtual void doneCurrent() final;
+    virtual void swapBuffers() final;
+    virtual void customizeWindow() = 0;
+    virtual void customizeContext() = 0;
+
+private:
+    QTimer* _timer{ nullptr };
+protected:
+    GlWindow* _window{ nullptr };
+};
+
diff --git a/interface/src/plugins/display/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
similarity index 69%
rename from interface/src/plugins/display/NullDisplayPlugin.cpp
rename to libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
index 9b5ab8ed0a..2204c0499c 100644
--- a/interface/src/plugins/display/NullDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp
@@ -42,3 +42,16 @@ PickRay NullDisplayPlugin::computePickRay(const glm::vec2 & pos) const {
 bool NullDisplayPlugin::isMouseOnScreen() const {
     return false;
 }
+
+QWindow* NullDisplayPlugin::getWindow() const {
+    return nullptr;
+}
+
+void NullDisplayPlugin::preRender() {}
+void NullDisplayPlugin::preDisplay() {}
+void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize,
+    GLuint overlayTexture, const glm::uvec2& overlaySize) {}
+void NullDisplayPlugin::finishFrame() {}
+
+void NullDisplayPlugin::activate(PluginContainer * container) {}
+void NullDisplayPlugin::deactivate() {}
diff --git a/interface/src/plugins/display/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
similarity index 72%
rename from interface/src/plugins/display/NullDisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
index 8a06febb7b..0fedf872b1 100644
--- a/interface/src/plugins/display/NullDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h
@@ -1,7 +1,5 @@
 //
-//  NullDisplayPlugin.h
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -18,6 +16,9 @@ public:
     virtual ~NullDisplayPlugin() final {}
     virtual const QString & getName();
 
+    void activate(PluginContainer * container);
+    void deactivate();
+
     virtual QSize getDeviceSize() const;
     virtual glm::ivec2 getCanvasSize() const;
     virtual bool hasFocus() const;
@@ -25,8 +26,11 @@ public:
     virtual glm::ivec2 getTrueMousePosition() const;
     virtual PickRay computePickRay(const glm::vec2 & pos) const;
     virtual bool isMouseOnScreen() const;
-
+    virtual QWindow* getWindow() const;
+    virtual void preRender();
+    virtual void preDisplay();
     virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
-                         GLuint overlayTexture, const glm::uvec2& overlaySize) {};
+        GLuint overlayTexture, const glm::uvec2& overlaySize);
+    virtual void finishFrame();
 
 };
diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp
similarity index 87%
rename from interface/src/plugins/display/OculusBaseDisplayPlugin.cpp
rename to libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp
index 50e1583548..7648be1d25 100644
--- a/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp
@@ -1,7 +1,5 @@
 //
-//  OculusBaseDisplayPlugin.cpp
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -11,10 +9,9 @@
 
 #include <ViewFrustum.h>
 
-#include "OculusHelpers.h"
+#include "../OculusHelpers.h"
 
-
-void OculusBaseDisplayPlugin::activate() {
+void OculusBaseDisplayPlugin::activate(PluginContainer * container) {
     ovr_for_each_eye([&](ovrEyeType eye) {
         ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]);
         ovrMatrix4f ovrPerspectiveProjection =
diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h
similarity index 74%
rename from interface/src/plugins/display/OculusBaseDisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h
index 94f73522b5..0462f00321 100644
--- a/interface/src/plugins/display/OculusBaseDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h
@@ -1,7 +1,5 @@
 //
-//  OculusBaseDisplayPlugin.h
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -9,16 +7,17 @@
 //
 #pragma once
 
-#include "HmdDisplayPlugin.h"
+#include "DisplayPlugin.h"
 
 #include <OVR_CAPI.h>
 
-class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
+class OculusBaseDisplayPlugin : public DisplayPlugin {
 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();
+    virtual void activate(PluginContainer * container);
     virtual void deactivate();
     virtual void preRender();
     virtual void configureRendering() = 0;
diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp
similarity index 97%
rename from interface/src/plugins/display/OculusWin32DisplayPlugin.cpp
rename to libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp
index f7414cc551..a15550a20b 100644
--- a/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp
+++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp
@@ -7,11 +7,16 @@
 //
 #include "OculusWin32DisplayPlugin.h"
 
+#include <memory>
+#include <GLMHelpers.h>
 
 #include <OVR_CAPI_GL.h>
 
+#include "../OglplusHelpers.h"
+
+#if 0
 bool OculusWin32DisplayPlugin::isSupported() {
-    ovr_Initialize();
+    ovr_Initialize(nullptr);
     bool result = false;
     if (ovrHmd_Detect() != 0) {
         result = true;
@@ -29,7 +34,7 @@ bool OculusWin32DisplayPlugin::isSupported() {
 // the screen.
 template <typename C = GLuint, typename D = GLuint>
 struct FramebufferWrapper {
-    glm::uvec2  size;
+    uvec2  size;
     oglplus::Framebuffer fbo;
     C           color{ 0 };
     GLuint      depth{ 0 };
@@ -198,3 +203,4 @@ private:
 };
 
 using MirrorFboPtr = std::shared_ptr<MirrorFramebufferWrapper>;
+#endif
\ No newline at end of file
diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h
similarity index 87%
rename from interface/src/plugins/display/OculusWin32DisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h
index 436efb5742..6866f096fc 100644
--- a/interface/src/plugins/display/OculusWin32DisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h
@@ -1,5 +1,5 @@
 //
-//  Created by Bradley Austin Davis on 2015/05/26.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp
new file mode 100644
index 0000000000..f2bd328915
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp
@@ -0,0 +1,88 @@
+//
+//  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 "OpenGlDisplayPlugin.h"
+
+#include <QOpenGLContext>
+
+void OpenGlDisplayPlugin::preDisplay() {
+    makeCurrent();
+};
+
+void OpenGlDisplayPlugin::preRender() {
+    // NOOP
+}
+
+void OpenGlDisplayPlugin::finishFrame() {
+    swapBuffers();
+    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();
+
+    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();
+}
+
diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h
new file mode 100644
index 0000000000..19587b997e
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h
@@ -0,0 +1,24 @@
+//
+//  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 "DisplayPlugin.h"
+
+class OpenGlDisplayPlugin : public DisplayPlugin {
+public:
+    virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
+                         GLuint overlayTexture, const glm::uvec2& overlaySize);
+    virtual void preRender();
+    virtual void preDisplay();
+    virtual void finishFrame();
+
+protected:
+    virtual void makeCurrent() = 0;
+    virtual void doneCurrent() = 0;
+    virtual void swapBuffers() = 0;
+};
diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp
new file mode 100644
index 0000000000..b6607e5518
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp
@@ -0,0 +1,176 @@
+//
+//  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 "Tv3dDisplayPlugin.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+
+#include <GlWindow.h>
+#include <ViewFrustum.h>
+#include <MatrixStack.h>
+#include <PathUtils.h>
+
+
+#include "../OglplusHelpers.h"
+
+const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin");
+
+const QString & Tv3dDisplayPlugin::getName() {
+    return NAME;
+}
+
+Tv3dDisplayPlugin::Tv3dDisplayPlugin() {
+}
+
+bool Tv3dDisplayPlugin::isSupported() const {
+    // FIXME this should attempt to do a scan for supported 3D output
+    return true;
+}
+
+static ProgramPtr program;
+static ShapeWrapperPtr plane;
+
+void Tv3dDisplayPlugin::customizeWindow() {
+    _window->setFlags(Qt::FramelessWindowHint);
+    auto desktop = QApplication::desktop();
+    QRect primaryGeometry = desktop->screenGeometry();
+    for (int i = 0; i < desktop->screenCount(); ++i) {
+        QRect geometry = desktop->screen(i)->geometry();
+        if (geometry.topLeft() == primaryGeometry.topLeft()) {
+            continue;
+        }
+        float aspect = (float)geometry.width() / (float)geometry.height();
+        if (aspect < 1.0f) {
+            continue;
+        }
+        _window->setGeometry(geometry);
+        break;
+    }
+    _window->setCursor(Qt::BlankCursor);
+}
+
+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");
+}
+
+
+const float DEFAULT_IPD = 0.064f;
+const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f;
+
+glm::mat4 Tv3dDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const {
+    float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane
+    float screenZ = 0.25f; // screen projection plane
+    // FIXME verify this is the right calculation
+    float frustumshift = HALF_DEFAULT_IPD * nearZ / screenZ;
+    if (eye == Right) {
+        frustumshift = -frustumshift;
+    }
+    return glm::translate(baseProjection, vec3(frustumshift, 0, 0));
+}
+
+glm::mat4 Tv3dDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const {
+    float modelviewShift = HALF_DEFAULT_IPD;
+    if (eye == Left) {
+        modelviewShift = -modelviewShift;
+    }
+    return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0));
+}
+
+
+
+void Tv3dDisplayPlugin::display(
+    GLuint sceneTexture, const glm::uvec2& sceneSize,
+    GLuint overlayTexture, const glm::uvec2& overlaySize) {
+
+    QSize size = getDeviceSize();
+    using namespace oglplus;
+    Context::Viewport(size.width(), size.height());
+    Context::Clear().ColorBuffer().DepthBuffer();
+
+    Mat4Uniform(*program, "ModelView").Set(mat4());
+    Mat4Uniform(*program, "Projection").Set(mat4());
+
+    glBindTexture(GL_TEXTURE_2D, sceneTexture);
+
+    plane->Draw();
+
+    const float overlayAspect = aspect(toGlm(size));
+    const GLfloat distance = 1.0f;
+    const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES);
+    const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height();
+    const GLfloat quadWidth = halfQuadWidth * 2.0f;
+    const GLfloat quadHeight = halfQuadHeight * 2.0f;
+
+    vec3 quadSize(quadWidth, quadHeight, 1.0f);
+    quadSize = vec3(1.0f) / quadSize;
+
+    using namespace oglplus;
+    Context::Enable(Capability::Blend);
+    glBindTexture(GL_TEXTURE_2D, overlayTexture);
+    
+    mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP);
+    Mat4Uniform(*program, "Projection").Set(pr);
+
+    MatrixStack mv;
+    mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0));
+
+    QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height()));
+    for (int i = 0; i < 2; ++i) {
+        Context::Viewport(r.x(), r.y(), r.width(), r.height());
+        Mat4Uniform(*program, "ModelView").Set(mv.top());
+        plane->Draw();
+        r.moveLeft(r.width());
+    }
+
+#if 0
+    glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
+    glm::vec2 canvasSize = qApp->getCanvasSize();
+    glm::vec2 mouse = qApp->getMouse();
+    mouse /= canvasSize;
+    mouse *= 2.0f;
+    mouse -= 1.0f;
+    mouse.y *= -1.0f;
+    mv.translate(mouse);
+    mv.scale(0.1f);
+    Mat4Uniform(*program, "ModelView").Set(mv.top());
+    r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height()));
+    for (int i = 0; i < 2; ++i) {
+        Context::Viewport(r.x(), r.y(), r.width(), r.height());
+        plane->Draw();
+        r.moveLeft(r.width());
+    }
+#endif
+    Context::Disable(Capability::Blend);
+}
+
+
+void Tv3dDisplayPlugin::activate(PluginContainer * container) {
+    GlWindowDisplayPlugin::activate(container);
+    _window->show();
+}
+
+void Tv3dDisplayPlugin::deactivate() {
+    makeCurrent();
+    if (plane) {
+        plane.reset();
+        program.reset();
+//        _crosshairTexture.reset();
+    }
+    doneCurrent();
+    GlWindowDisplayPlugin::deactivate();
+}
diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h
similarity index 67%
rename from interface/src/plugins/display/Tv3dDisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h
index ad2ccc7369..9baa9261ef 100644
--- a/interface/src/plugins/display/Tv3dDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h
@@ -1,17 +1,13 @@
 //
-//  Tv3dDisplayPlugin.h
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  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 "SimpleDisplayPlugin.h"
-#include <QTimer>
+#include "GlWindowDisplayPlugin.h"
 
 class Tv3dDisplayPlugin : public GlWindowDisplayPlugin {
     Q_OBJECT
@@ -23,12 +19,15 @@ public:
     virtual bool isSupported() const final;
     void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
         GLuint overlayTexture, const glm::uvec2& overlaySize);
-    virtual void activate();
+    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 std::function<QPointF(const QPointF&)> getMouseTranslator();
     //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const;
-
-private:
-    QTimer _timer;
 };
diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp
new file mode 100644
index 0000000000..0298d6b823
--- /dev/null
+++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp
@@ -0,0 +1,18 @@
+//
+//  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 "WindowDisplayPlugin.h"
+
+WindowDisplayPlugin::WindowDisplayPlugin() {
+}
+
+const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer");
+
+const QString & WindowDisplayPlugin::getName() {
+    return NAME;
+}
+
diff --git a/interface/src/plugins/display/WindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h
similarity index 62%
rename from interface/src/plugins/display/WindowDisplayPlugin.h
rename to libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h
index 7bc0d5163d..208dc26975 100644
--- a/interface/src/plugins/display/WindowDisplayPlugin.h
+++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h
@@ -1,7 +1,5 @@
 //
-//  WindowDisplayPlugin.h
-//
-//  Created by Bradley Austin Davis on 2014/04/13.
+//  Created by Bradley Austin Davis on 2015/05/29
 //  Copyright 2015 High Fidelity, Inc.
 //
 //  Distributed under the Apache License, Version 2.0.
@@ -9,10 +7,7 @@
 //
 #pragma once
 
-#include "SimpleDisplayPlugin.h"
-
-#include <GlWindow.h>
-#include <QTimer>
+#include "GlWindowDisplayPlugin.h"
 
 class WindowDisplayPlugin : public GlWindowDisplayPlugin {
     Q_OBJECT
@@ -22,9 +17,5 @@ public:
     WindowDisplayPlugin();
 
     virtual const QString & getName();
-
-    virtual void activate();
-    virtual void deactivate();
 private:
-    QTimer _timer;
 };
diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt
index 9401f73174..28b136ccf4 100644
--- a/libraries/plugins/CMakeLists.txt
+++ b/libraries/plugins/CMakeLists.txt
@@ -1,7 +1,7 @@
 set(TARGET_NAME plugins)
 
 # use setup_hifi_library macro to setup our project and link appropriate Qt modules
-setup_hifi_library(OpenGL Network Qml Quick Script XmlPatterns)
+setup_hifi_library(OpenGL)
 
 link_hifi_libraries(shared)
 
diff --git a/libraries/plugins/src/Plugin.h b/libraries/plugins/src/Plugin.h
deleted file mode 100644
index db01aa74ca..0000000000
--- a/libraries/plugins/src/Plugin.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <QString>
-#include <QObject>
-
-class PluginContainer;
-
-class Plugin : public QObject {
-public:
-    virtual const QString& getName() = 0;
-    virtual bool isSupported() const { return true; }
-
-    virtual void init() {}
-    virtual void deinit() {}
-
-    virtual void activate(PluginContainer * container) {}
-    virtual void deactivate() {}
-
-    virtual void idle() {}
-};
diff --git a/libraries/plugins/src/plugins/Plugin.cpp b/libraries/plugins/src/plugins/Plugin.cpp
new file mode 100644
index 0000000000..1910b525c2
--- /dev/null
+++ b/libraries/plugins/src/plugins/Plugin.cpp
@@ -0,0 +1,9 @@
+#include "Plugin.h"
+
+bool Plugin::isSupported() const { return true; }
+
+void Plugin::init() {}
+
+void Plugin::deinit() {}
+
+void Plugin::idle() {}
diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h
new file mode 100644
index 0000000000..6f55cb2b1d
--- /dev/null
+++ b/libraries/plugins/src/plugins/Plugin.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <QString>
+#include <QObject>
+
+class PluginContainer;
+
+class Plugin : public QObject {
+public:
+    virtual const QString& getName() = 0;
+    virtual bool isSupported() const;
+
+    /// Called when plugin is initially loaded, typically at application start
+    virtual void init();
+    /// Called when application is shutting down
+    virtual void deinit();
+
+    /// Called when a plugin is being activated for use.  May be called multiple times.
+    virtual void activate(PluginContainer * container) = 0;
+    /// Called when a plugin is no longer being used.  May be called multiple times.
+    virtual void deactivate() = 0;
+
+    /**
+     * Called by the application during it's idle phase.  If the plugin needs to do
+     * CPU intensive work, it should launch a thread for that, rather than trying to
+     * do long operations in the idle call
+     */
+    virtual void idle();
+};
diff --git a/libraries/plugins/src/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h
similarity index 100%
rename from libraries/plugins/src/PluginContainer.h
rename to libraries/plugins/src/plugins/PluginContainer.h
diff --git a/interface/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp
similarity index 100%
rename from interface/src/plugins/PluginManager.cpp
rename to libraries/plugins/src/plugins/PluginManager.cpp
diff --git a/interface/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h
similarity index 51%
rename from interface/src/plugins/PluginManager.h
rename to libraries/plugins/src/plugins/PluginManager.h
index 2526490eea..653c7a616a 100644
--- a/interface/src/plugins/PluginManager.h
+++ b/libraries/plugins/src/plugins/PluginManager.h
@@ -1,12 +1,10 @@
 #pragma once
 
-#include "plugins/Plugin.h"
-#include "plugins/display/DisplayPlugin.h"
+#include "Plugin.h"
 #include <QList>
 #include <QSharedPointer>
 
 class PluginManager : public QObject {
 public:
   static PluginManager * getInstance();
-  const QList<QSharedPointer<DisplayPlugin>> getDisplayPlugins();
 };