From 22d133c71fb81cecb043c5e34aa64c375c3f61cd Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Thu, 11 Jan 2018 23:31:12 -0800
Subject: [PATCH] Allow GLES client on desktop builds

---
 CMakeLists.txt                    | 17 +++++-
 cmake/macros/TargetOpenGL.cmake   | 41 +++++++++-----
 interface/src/main.cpp            |  5 ++
 libraries/gl/src/gl/Config.cpp    |  4 +-
 libraries/gl/src/gl/Config.h      | 10 ++--
 libraries/gl/src/gl/Context.cpp   | 93 +++++++++++++++++--------------
 libraries/gl/src/gl/Context.h     |  5 +-
 libraries/gl/src/gl/ContextQt.cpp |  4 +-
 libraries/gl/src/gl/GLHelpers.cpp |  5 +-
 libraries/gl/src/gl/GLHelpers.h   |  2 +-
 plugins/oculus/CMakeLists.txt     |  2 +-
 plugins/openvr/CMakeLists.txt     |  2 +-
 12 files changed, 115 insertions(+), 75 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34ff672067..ddf57e00a3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,14 +39,26 @@ else()
     option(BUILD_TESTS "Build tests" ON)
 endif()
 
+
+
 if (ANDROID)
+  option(USE_GLES "Use OpenGL ES" ON)
   set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
-  set(PLATFORM_GL_BACKEND gpu-gles)
 else ()
+  option(USE_GLES "Use OpenGL ES" OFF)
   set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
-  set(PLATFORM_GL_BACKEND gpu-gl)
 endif ()
 
+set(PLATFORM_QT_GL OpenGL)
+
+if (USE_GLES)
+  add_definitions(-DUSE_GLES)
+  set(PLATFORM_GL_BACKEND gpu-gles)
+else()
+  set(PLATFORM_GL_BACKEND gpu-gl)
+endif()
+
+
 foreach(PLATFORM_QT_COMPONENT ${PLATFORM_QT_COMPONENTS})
   list(APPEND PLATFORM_QT_LIBRARIES "Qt5::${PLATFORM_QT_COMPONENT}")
 endforeach()
@@ -59,6 +71,7 @@ MESSAGE(STATUS "Build client:    " ${BUILD_CLIENT})
 MESSAGE(STATUS "Build tests:     " ${BUILD_TESTS})
 MESSAGE(STATUS "Build tools:     " ${BUILD_TOOLS})
 MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
+MESSAGE(STATUS "GL ES:           " ${USE_GLES})
 
 if (UNIX AND DEFINED ENV{HIFI_MEMORY_DEBUGGING})
     MESSAGE(STATUS "Memory debugging is enabled")
diff --git a/cmake/macros/TargetOpenGL.cmake b/cmake/macros/TargetOpenGL.cmake
index b9de4e6253..78b9e2909b 100644
--- a/cmake/macros/TargetOpenGL.cmake
+++ b/cmake/macros/TargetOpenGL.cmake
@@ -6,22 +6,33 @@
 #  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 # 
 macro(TARGET_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(ANDROID)
-      find_library(EGL EGL)
-      find_library(OpenGLES3 GLESv3)
-      list(APPEND IGNORE_COPY_LIBS ${OpenGLES3} ${OpenGLES2} ${EGL})
-      target_link_libraries(${TARGET_NAME} ${OpenGLES3} ${EGL})
+    if (ANDROID)
+        find_library(EGL EGL)
+        find_library(OpenGLES3 GLESv3)
+        list(APPEND IGNORE_COPY_LIBS ${OpenGLES3} ${OpenGLES2} ${EGL})
+        target_link_libraries(${TARGET_NAME} ${OpenGLES3} ${EGL})
+    elseif (USE_GLES)
+        set(ANGLE_INCLUDE_DIR "${QT_DIR}/include/QtANGLE")
+        set(ANGLE_LIB_DIR "${QT_DIR}/lib")
+        find_library(EGL_LIBRARY_RELEASE "libEGL" HINTS ${ANGLE_LIB_DIR})
+        find_library(EGL_LIBRARY_DEBUG "libEGLd" HINTS ${ANGLE_LIB_DIR})
+        find_library(GLES_LIBRARY_RELEASE "libGLESv2" HINTS ${ANGLE_LIB_DIR})
+        find_library(GLES_LIBRARY_DEBUG "libGLESv2d" HINTS ${ANGLE_LIB_DIR})
+        include(SelectLibraryConfigurations)
+        select_library_configurations(EGL)
+        select_library_configurations(GLES)
+        message("QQQ ${GLES_LIBRARIES}")
+        target_link_libraries(${TARGET_NAME} ${EGL_LIBRARIES})
+        target_link_libraries(${TARGET_NAME} ${GLES_LIBRARIES})
+        target_include_directories(${TARGET_NAME} PUBLIC "${ANGLE_INCLUDE_DIR}")
+    elseif (APPLE)
+        # link in required OS X frameworks and include the right GL headers
+        find_library(OpenGL OpenGL)
+        target_link_libraries(${TARGET_NAME} ${OpenGL})
     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})
+        find_package(OpenGL REQUIRED)
+        target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}")
+        target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
     endif()
     target_nsight()
     target_glew()
diff --git a/interface/src/main.cpp b/interface/src/main.cpp
index 5c07bebc23..86fb43cc9a 100644
--- a/interface/src/main.cpp
+++ b/interface/src/main.cpp
@@ -49,6 +49,11 @@ int main(int argc, const char* argv[]) {
     CrashReporter crashReporter { BUG_SPLAT_DATABASE, BUG_SPLAT_APPLICATION_NAME, BuildInfo::VERSION };
 #endif
 
+#if USE_GLES
+    qputenv("QT_ANGLE_PLATFORM", "d3d11");
+    QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
+#endif
+
 #ifdef Q_OS_LINUX
     QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
 #endif
diff --git a/libraries/gl/src/gl/Config.cpp b/libraries/gl/src/gl/Config.cpp
index d862149a44..eff278511d 100644
--- a/libraries/gl/src/gl/Config.cpp
+++ b/libraries/gl/src/gl/Config.cpp
@@ -13,7 +13,7 @@
 
 #include <mutex>
 
-#if defined(Q_OS_ANDROID)
+#if defined(HIFI_GLES)
 PFNGLQUERYCOUNTEREXTPROC __glQueryCounterEXT = NULL;
 PFNGLGETQUERYOBJECTUI64VEXTPROC __glGetQueryObjectui64vEXT = NULL;
 PFNGLFRAMEBUFFERTEXTUREEXTPROC __glFramebufferTextureEXT = NULL;
@@ -22,7 +22,7 @@ PFNGLFRAMEBUFFERTEXTUREEXTPROC __glFramebufferTextureEXT = NULL;
 void gl::initModuleGl() {
     static std::once_flag once;
     std::call_once(once, [] {
-#if defined(Q_OS_ANDROID)
+#if defined(HIFI_GLES)
         glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC)eglGetProcAddress("glQueryCounterEXT");
         glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)eglGetProcAddress("glGetQueryObjectui64vEXT");
         glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC)eglGetProcAddress("glFramebufferTextureEXT");
diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h
index 6dc95cb1b1..0258f573f6 100644
--- a/libraries/gl/src/gl/Config.h
+++ b/libraries/gl/src/gl/Config.h
@@ -14,7 +14,7 @@
 
 #include <QtCore/QtGlobal>
 
-#if defined(Q_OS_ANDROID)
+#if defined(USE_GLES)
 #define HIFI_GLES
 #define HIFI_EGL
 #endif
@@ -36,11 +36,11 @@
 #define MINIMUM_GL_VERSION ((GL_MIN_VERSION_MAJOR << 8) | GL_MIN_VERSION_MINOR)
 
 #if defined(HIFI_GLES)
+#define GL_GLEXT_PROTOTYPES
 #include <EGL/egl.h>
-#endif
-
-#if defined(HIFI_GLES)
-#include <GLES3/gl32.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#include <GLES3/gl3platform.h>
 
 #define GL_DEPTH_COMPONENT32_OES          0x81A7
 #define GL_TIME_ELAPSED_EXT               0x88BF
diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp
index f7e08e607b..b7a63d7036 100644
--- a/libraries/gl/src/gl/Context.cpp
+++ b/libraries/gl/src/gl/Context.cpp
@@ -69,7 +69,7 @@ Context::Context(QWindow* window) {
     setWindow(window);
 }
 
-#ifdef Q_OS_WIN
+#ifdef GL_CUSTOM_CONTEXT
 void Context::destroyWin32Context(HGLRC hglrc) {
     wglDeleteContext(hglrc);
 }
@@ -77,7 +77,7 @@ void Context::destroyWin32Context(HGLRC hglrc) {
 
 void Context::release() {
     doneCurrent();
-#ifdef Q_OS_WIN
+#ifdef GL_CUSTOM_CONTEXT
     if (_wrappedContext) {
         destroyContext(_wrappedContext);
         _wrappedContext = nullptr;
@@ -123,14 +123,37 @@ void Context::setWindow(QWindow* window) {
     release();
     _window = window;
 
-#ifdef Q_OS_WIN
+#ifdef GL_CUSTOM_CONTEXT
     _hwnd = (HWND)window->winId();
 #endif
 
     updateSwapchainMemoryCounter();
 }
 
-#ifdef Q_OS_WIN
+
+#ifndef GLAPIENTRY 
+#define GLAPIENTRY GL_APIENTRY
+#endif
+
+void GLAPIENTRY debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
+    //if (GL_DEBUG_SEVERITY_NOTIFICATION == severity) {
+    //    return;
+    //}
+    qCDebug(glLogging) << "OpenGL: " << message;
+
+    // For high severity errors, force a sync to the log, since we might crash 
+    // before the log file was flushed otherwise.  Performance hit here
+    //if (GL_DEBUG_SEVERITY_HIGH == severity) {
+    //    AbstractLoggerInterface* logger = AbstractLoggerInterface::get();
+    //    if (logger) {
+    //        // FIXME find a way to force the log file to sync that doesn't lead to a deadlock
+    //        // logger->sync();
+    //    }
+    //}
+}
+
+
+#if defined(GL_CUSTOM_CONTEXT)
 
 bool Context::makeCurrent() {
     BOOL result = wglMakeCurrent(_hdc, _hglrc);
@@ -148,47 +171,30 @@ void Context::doneCurrent() {
     wglMakeCurrent(0, 0);
 }
 
-void GLAPIENTRY debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
-    if (GL_DEBUG_SEVERITY_NOTIFICATION == severity) {
-        return;
-    }
-    qCDebug(glLogging) << "OpenGL: " << message;
-    
-    // For high severity errors, force a sync to the log, since we might crash 
-    // before the log file was flushed otherwise.  Performance hit here
-    if (GL_DEBUG_SEVERITY_HIGH == severity) {
-        AbstractLoggerInterface* logger = AbstractLoggerInterface::get();
-        if (logger) {
-            // FIXME find a way to force the log file to sync that doesn't lead to a deadlock
-            // logger->sync();
-        }
-    }
-}
-
-// FIXME build the PFD based on the 
-static const PIXELFORMATDESCRIPTOR pfd =    // pfd Tells Windows How We Want Things To Be
-{
-    sizeof(PIXELFORMATDESCRIPTOR),         // Size Of This Pixel Format Descriptor
-    1,                                      // Version Number
-    PFD_DRAW_TO_WINDOW |                    // Format Must Support Window
-    PFD_SUPPORT_OPENGL |                    // Format Must Support OpenGL
-    PFD_DOUBLEBUFFER,                       // Must Support Double Buffering
-    PFD_TYPE_RGBA,                          // Request An RGBA Format
-    24,                                     // Select Our Color Depth
-    0, 0, 0, 0, 0, 0,                       // Color Bits Ignored
-    1,                                      // Alpha Buffer
-    0,                                      // Shift Bit Ignored
-    0,                                      // No Accumulation Buffer
-    0, 0, 0, 0,                             // Accumulation Bits Ignored
-    24,                                     // 24 Bit Z-Buffer (Depth Buffer)  
-    8,                                      // 8 Bit Stencil Buffer
-    0,                                      // No Auxiliary Buffer
-    PFD_MAIN_PLANE,                         // Main Drawing Layer
-    0,                                      // Reserved
-    0, 0, 0                                 // Layer Masks Ignored
-};
 
 void setupPixelFormatSimple(HDC hdc) {
+    // FIXME build the PFD based on the 
+    static const PIXELFORMATDESCRIPTOR pfd =    // pfd Tells Windows How We Want Things To Be
+    {
+        sizeof(PIXELFORMATDESCRIPTOR),         // Size Of This Pixel Format Descriptor
+        1,                                      // Version Number
+        PFD_DRAW_TO_WINDOW |                    // Format Must Support Window
+        PFD_SUPPORT_OPENGL |                    // Format Must Support OpenGL
+        PFD_DOUBLEBUFFER,                       // Must Support Double Buffering
+        PFD_TYPE_RGBA,                          // Request An RGBA Format
+        24,                                     // Select Our Color Depth
+        0, 0, 0, 0, 0, 0,                       // Color Bits Ignored
+        1,                                      // Alpha Buffer
+        0,                                      // Shift Bit Ignored
+        0,                                      // No Accumulation Buffer
+        0, 0, 0, 0,                             // Accumulation Bits Ignored
+        24,                                     // 24 Bit Z-Buffer (Depth Buffer)  
+        8,                                      // 8 Bit Stencil Buffer
+        0,                                      // No Auxiliary Buffer
+        PFD_MAIN_PLANE,                         // Main Drawing Layer
+        0,                                      // Reserved
+        0, 0, 0                                 // Layer Masks Ignored
+    };
     auto pixelFormat = ChoosePixelFormat(hdc, &pfd);
     if (pixelFormat == 0) {
         throw std::runtime_error("Unable to create initial context");
@@ -314,6 +320,7 @@ void Context::create() {
         doneCurrent();
     }
 }
+
 #endif
 
 void Context::clear() {
diff --git a/libraries/gl/src/gl/Context.h b/libraries/gl/src/gl/Context.h
index d1b0d53631..0a2d13bb5f 100644
--- a/libraries/gl/src/gl/Context.h
+++ b/libraries/gl/src/gl/Context.h
@@ -22,6 +22,9 @@ class QWindow;
 class QOpenGLContext;
 class QThread;
 
+#if defined(Q_OS_WIN) && !defined(USE_GLES)
+#define GL_CUSTOM_CONTEXT
+#endif
 namespace gl {
 
     class Context {
@@ -29,7 +32,7 @@ namespace gl {
         QWindow* _window { nullptr };
         static Context* PRIMARY;
         static void destroyContext(QOpenGLContext* context);
-#if defined(Q_OS_WIN)
+#if defined(GL_CUSTOM_CONTEXT)
         uint32_t _version { 0x0401 };
         HWND _hwnd { 0 };
         HDC _hdc { 0 };
diff --git a/libraries/gl/src/gl/ContextQt.cpp b/libraries/gl/src/gl/ContextQt.cpp
index 4d5d2c4e9f..cf07f5ccd5 100644
--- a/libraries/gl/src/gl/ContextQt.cpp
+++ b/libraries/gl/src/gl/ContextQt.cpp
@@ -28,7 +28,7 @@ void Context::makeCurrent(QOpenGLContext* context, QSurface* surface) {
 }
 
 QOpenGLContext* Context::qglContext() {
-#ifdef Q_OS_WIN
+#ifdef GL_CUSTOM_CONTEXT
     if (!_wrappedContext) {
         _wrappedContext = new QOpenGLContext();
         _wrappedContext->setNativeHandle(QVariant::fromValue(QWGLNativeContext(_hglrc, _hwnd)));
@@ -45,7 +45,7 @@ void Context::moveToThread(QThread* thread) {
     qglContext()->moveToThread(thread);
 }
 
-#ifndef Q_OS_WIN
+#ifndef GL_CUSTOM_CONTEXT
 bool Context::makeCurrent() {
     updateSwapchainMemoryCounter();
     return _context->makeCurrent(_window);
diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp
index 722253c26f..8413942301 100644
--- a/libraries/gl/src/gl/GLHelpers.cpp
+++ b/libraries/gl/src/gl/GLHelpers.cpp
@@ -28,18 +28,19 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
     static QSurfaceFormat format;
     static std::once_flag once;
     std::call_once(once, [] {
-#if defined(HIFI_GLES)
+#if defined(USE_GLES)
         format.setRenderableType(QSurfaceFormat::OpenGLES);
         format.setRedBufferSize(8);
         format.setGreenBufferSize(8);
         format.setBlueBufferSize(8);
         format.setAlphaBufferSize(8);
+#else
+        format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
 #endif
         // Qt Quick may need a depth and stencil buffer. Always make sure these are available.
         format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
         format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
         setGLFormatVersion(format);
-        format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
         QSurfaceFormat::setDefaultFormat(format);
     });
     return format;
diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h
index 73319e2e6d..581bb09360 100644
--- a/libraries/gl/src/gl/GLHelpers.h
+++ b/libraries/gl/src/gl/GLHelpers.h
@@ -26,7 +26,7 @@ class QGLFormat;
 
 template<class F>
 // https://bugreports.qt.io/browse/QTBUG-64703 prevents us from using "defined(QT_OPENGL_ES_3_1)"
-#if defined(Q_OS_ANDROID)
+#if defined(USE_GLES)
 void setGLFormatVersion(F& format, int major = 3, int minor = 2)
 #else
 void setGLFormatVersion(F& format, int major = 4, int minor = 5) 
diff --git a/plugins/oculus/CMakeLists.txt b/plugins/oculus/CMakeLists.txt
index 55eb9c7b85..c77a1f30e6 100644
--- a/plugins/oculus/CMakeLists.txt
+++ b/plugins/oculus/CMakeLists.txt
@@ -6,7 +6,7 @@
 #  See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
 #
 
-if (WIN32)
+if (WIN32 AND (NOT USE_GLES))
 
   # we're using static GLEW, so define GLEW_STATIC
   add_definitions(-DGLEW_STATIC)
diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt
index 7878ae2d7e..3d63a7ba9f 100644
--- a/plugins/openvr/CMakeLists.txt
+++ b/plugins/openvr/CMakeLists.txt
@@ -6,7 +6,7 @@
 #  See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
 #
 
-if (WIN32)
+if (WIN32 AND (NOT USE_GLES))
     # we're using static GLEW, so define GLEW_STATIC
     add_definitions(-DGLEW_STATIC)
     set(TARGET_NAME openvr)