8133348
From d1f6fc47af86a5db0a07effdefb10573f49928fb Mon Sep 17 00:00:00 2001
8133348
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
8133348
Date: Mon, 18 Dec 2017 17:39:31 +0100
8133348
Subject: [PATCH] Use QOpenGLFunctions for GL extensions, drop GLEW and
8133348
 obsolete GL stuff
8133348
MIME-Version: 1.0
8133348
Content-Type: text/plain; charset=UTF-8
8133348
Content-Transfer-Encoding: 8bit
8133348
8133348
Instead of relying on GLEW for resolution of GL extension function entry
8133348
points use QOpenGLFunctions, which provides the same, but also allows to
8133348
run on both OpenGL desktop and GLES platforms.
8133348
8133348
Also drop extension based shader support. Shaders are supported since
8133348
OpenGL 2.0, so ARB shaders are likely no longer used and make the code
8133348
harder to read. Assume PBOs are available, which is true since OpenGL 1.5.
8133348
8133348
Text rendering in the pixelview overlay was apparently broken (no text
8133348
drawn at all), switch to QPainter based text drawing, as
8133348
QGLWidget::renderText() is not supported by QOpenGLWidget.
8133348
8133348
Signed-off-by: Stefan BrĂ¼ns <stefan.bruens@rwth-aachen.de>
8133348
---
8133348
 CMakeLists.txt                   |   1 -
8133348
 INSTALL.md                       |   8 +-
8133348
 Makefile                         |   5 -
8133348
 src/cmake/externalpackages.cmake |  27 ----
8133348
 src/iv/CMakeLists.txt            |   9 +-
8133348
 src/iv/imageviewer.cpp           |  17 +-
8133348
 src/iv/imageviewer.h             |   1 -
8133348
 src/iv/ivgl.cpp                  | 336 +++++++++++++--------------------------
8133348
 src/iv/ivgl.h                    |  19 +--
8133348
 9 files changed, 128 insertions(+), 295 deletions(-)
8133348
8133348
--- a/CMakeLists.txt
8133348
+++ b/CMakeLists.txt
8133348
@@ -70,7 +70,6 @@ option (OIIO_BUILD_TOOLS "Build the comm
8133348
 option (OIIO_BUILD_TESTS "Build the unit tests" ON)
8133348
 option (USE_OPENGL "Include OpenGL support" ON)
8133348
 option (USE_QT "Include Qt support" ON)
8133348
-option (FORCE_OPENGL_1 "Force iv to use OpenGL's fixed pipeline")
8133348
 option (USE_PYTHON "Build the Python bindings" ON)
8133348
 set (PYTHON_VERSION "2.7" CACHE STRING "Target version of python to find")
8133348
 option (PYLIB_INCLUDE_SONAME "If ON, soname/soversion will be set for Python module library")
8133348
--- a/INSTALL.md
8133348
+++ b/INSTALL.md
8133348
@@ -43,8 +43,7 @@ Building OpenImageIO on Linux or OS X
8133348
 The following dependencies must be installed to build the core of
8133348
 OpenImageIO: Boost, libjpeg, libtiff, libpng and OpenEXR.  These can be
8133348
 installed using the standard package managers on your system.
8133348
-Optionally, to build the image viewing tools, you will need Qt, OpenGL,
8133348
-and GLEW.
8133348
+Optionally, to build the image viewing tools, you will need Qt and OpenGL.
8133348
 
8133348
 On OS X, these dependencies can be installed using Fink, MacPorts or
8133348
 Homebrew.  After installation of any of these package installers, use
8133348
@@ -99,7 +98,6 @@ Additionally, a few helpful modifiers al
8133348
 | make USE_OPENGL=0 ...     |  Skip anything that needs OpenGL
8133348
 | make USE_QT=0 ...         |  Skip anything that needs Qt
8133348
 | make MYCC=xx MYCXX=yy ... |  Use custom compilers
8133348
-| make FORCE_OPENGL_1=1 ... |  Force iv to use OpenGL's fixed pipeline
8133348
 | make USE_PYTHON=0 ...     |  Don't build the Python binding
8133348
 | make BUILDSTATIC=1 ...    |  Build static library instead of shared
8133348
 | make LINKSTATIC=1 ...     |  Link with static external libraries when possible
8133348
@@ -218,9 +216,6 @@ D:\OIIO\external\dist\windows\zlib-1.2.3
8133348
 ZLIB and PNG, add
8133348
 D:\OIIO\external\dist\windows\zlib-1.2.3;D:\OIIO\external\dist\windows\libpng-1.2.3.
8133348
 
8133348
-Also, if cmake won't find GLEW set up GLEW_INCLUDES and GLEW_LIBRARIES
8133348
-in cmake-gui. Don't add them (they are already added), just set them.
8133348
-
8133348
 
8133348
 Test Images
8133348
 -----------
8133348
--- a/Makefile
8133348
+++ b/Makefile
8133348
@@ -79,10 +79,6 @@ ifneq (${USE_QT},)
8133348
 MY_CMAKE_FLAGS += -DUSE_QT:BOOL=${USE_QT}
8133348
 endif
8133348
 
8133348
-ifneq (${FORCE_OPENGL_1},)
8133348
-MY_CMAKE_FLAGS += -DFORCE_OPENGL_1:BOOL=${FORCE_OPENGL_1}
8133348
-endif
8133348
-
8133348
 ifneq (${OIIO_THREAD_ALLOW_DCLP},)
8133348
 MY_CMAKE_FLAGS += -DOIIO_THREAD_ALLOW_DCLP:BOOL=${OIIO_THREAD_ALLOW_DCLP}
8133348
 endif
8133348
@@ -473,7 +469,6 @@ help:
8133348
 	@echo "      USE_EXTERNAL_PUGIXML=1   Use the system PugiXML, not the one in OIIO"
8133348
 	@echo "      USE_QT=0                 Skip anything that needs Qt"
8133348
 	@echo "      USE_OPENGL=0             Skip anything that needs OpenGL"
8133348
-	@echo "      FORCE_OPENGL_1=1         Force iv to use OpenGL's fixed pipeline"
8133348
 	@echo "      USE_PYTHON=0             Don't build the Python binding"
8133348
 	@echo "      USE_PYTHON3=1            If 1, try to build against Python3, not 2.x"
8133348
 	@echo "      PYTHON_VERSION=2.6       Specify the Python version"
8133348
--- a/src/cmake/externalpackages.cmake
8133348
+++ b/src/cmake/externalpackages.cmake
8133348
@@ -9,7 +9,6 @@ if (NOT VERBOSE)
8133348
     set (Field3D_FIND_QUIETLY true)
8133348
     set (Freetype_FIND_QUIETLY true)
8133348
     set (GIF_FIND_QUIETLY true)
8133348
-    set (GLEW_FIND_QUIETLY true)
8133348
     set (HDF5_FIND_QUIETLY true)
8133348
     set (IlmBase_FIND_QUIETLY true)
8133348
     set (JPEG_FIND_QUIETLY true)
8133348
@@ -209,32 +208,6 @@ endif ()
8133348
 # end Qt setup
8133348
 ###########################################################################
8133348
 
8133348
-###########################################################################
8133348
-# GL Extension Wrangler library setup
8133348
-
8133348
-if (USE_OPENGL)
8133348
-    set (GLEW_VERSION 1.5.1)
8133348
-    find_library (GLEW_LIBRARIES
8133348
-                  NAMES GLEW glew32)
8133348
-    find_path (GLEW_INCLUDES
8133348
-               NAMES glew.h
8133348
-               PATH_SUFFIXES GL)
8133348
-    if (GLEW_INCLUDES AND GLEW_LIBRARIES)
8133348
-        set (GLEW_FOUND TRUE)
8133348
-        if (NOT GLEW_FIND_QUIETLY)
8133348
-            message (STATUS "GLEW includes = ${GLEW_INCLUDES}")
8133348
-            message (STATUS "GLEW library = ${GLEW_LIBRARIES}")
8133348
-        endif ()
8133348
-    else ()
8133348
-        message (STATUS "GLEW not found")
8133348
-    endif ()
8133348
-else ()
8133348
-    message (STATUS "USE_OPENGL=0, skipping components that need OpenGL")
8133348
-endif (USE_OPENGL)
8133348
-
8133348
-# end GL Extension Wrangler library setup
8133348
-###########################################################################
8133348
-
8133348
 
8133348
 ###########################################################################
8133348
 # BZIP2 - used by ffmped and freetype
8133348
--- a/src/iv/CMakeLists.txt
8133348
+++ b/src/iv/CMakeLists.txt
8133348
@@ -1,9 +1,9 @@
8133348
-if (Qt5_FOUND AND OPENGL_FOUND AND GLEW_FOUND)
8133348
+if (Qt5_FOUND AND OPENGL_FOUND)
8133348
     set (CMAKE_AUTOMOC ON)
8133348
 	if (Qt5_POSITION_INDEPENDENT_CODE)
8133348
         set (CMAKE_POSITION_INDEPENDENT_CODE ON)
8133348
 	endif()
8133348
-    include_directories (${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDES})
8133348
+    include_directories (${OPENGL_INCLUDE_DIR})
8133348
     set (iv_srcs imageviewer.cpp ivimage.cpp ivgl.cpp ivinfowin.cpp 
8133348
                  ivpref.cpp ivmain.cpp)
8133348
     if (FORCE_OPENGL_1)
8133348
@@ -14,10 +14,9 @@ if (Qt5_FOUND AND OPENGL_FOUND AND GLEW_
8133348
     target_link_libraries (iv OpenImageIO
8133348
                                Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL
8133348
                                ${OPENGL_LIBRARIES}
8133348
-                               ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}
8133348
-                               ${GLEW_LIBRARIES})
8133348
+                               ${Boost_LIBRARIES} ${CMAKE_DL_LIBS})
8133348
     oiio_install_targets (iv)
8133348
 
8133348
 else ()
8133348
-    message (STATUS "\n\n   WARNING: Qt, OpenGL, or GLEW not found -- 'iv' will not be built!\n")
8133348
+    message (STATUS "\n\n   WARNING: Qt or OpenGL not found -- 'iv' will not be built!\n")
8133348
 endif ()
8133348
--- a/src/iv/imageviewer.cpp
8133348
+++ b/src/iv/imageviewer.cpp
8133348
@@ -1025,8 +1025,7 @@ ImageViewer::displayCurrentImage (bool u
8133348
         }
8133348
     } else {
8133348
         m_current_image = m_last_image = -1;
8133348
-        repaint(); // add repaint event to Qt queue
8133348
-        glwin->trigger_redraw(); // then make sure GL canvas is cleared
8133348
+        ((QOpenGLWidget*)(glwin))->update ();
8133348
     }
8133348
 
8133348
     if (update) {
8133348
@@ -1795,8 +1794,10 @@ void ImageViewer::zoomIn()
8133348
         float z = Imath::lerp (oldzoom, newzoom, a);
8133348
         float zoomratio = z / oldzoom;
8133348
         view (xm + xoffset/zoomratio, ym + yoffset/zoomratio, z, false);
8133348
-        if (i != nsteps)
8133348
+        if (i != nsteps) {
8133348
+            QApplication::processEvents();
8133348
             Sysutil::usleep (1000000 / 4 / nsteps);
8133348
+        }
8133348
     }
8133348
 
8133348
     fitImageToWindowAct->setChecked (false);
8133348
@@ -1827,8 +1828,10 @@ void ImageViewer::zoomOut()
8133348
         float z = Imath::lerp (oldzoom, newzoom, a);
8133348
         float zoomratio = z / oldzoom;
8133348
         view (xmpel + xoffset/zoomratio, ympel + yoffset/zoomratio, z, false);
8133348
-        if (i != nsteps)
8133348
+        if (i != nsteps) {
8133348
+            QApplication::processEvents();
8133348
             Sysutil::usleep (1000000 / 4 / nsteps);
8133348
+        }
8133348
     }
8133348
 
8133348
     fitImageToWindowAct->setChecked (false);
8133348
@@ -2037,8 +2040,10 @@ ImageViewer::view (float xcenter, float
8133348
         m_zoom = Imath::lerp (oldzoom, newzoom, a);
8133348
 
8133348
         glwin->view (xc, yc, m_zoom, redraw);  // Triggers redraw automatically
8133348
-        if (i != nsteps)
8133348
+        if (i != nsteps) {
8133348
+            QApplication::processEvents();
8133348
             Sysutil::usleep (1000000 / 4 / nsteps);
8133348
+        }
8133348
     }
8133348
 
8133348
     if (img->auto_subimage ()) {
8133348
@@ -2090,7 +2095,7 @@ ImageViewer::showInfoWindow ()
8133348
 void
8133348
 ImageViewer::showPixelviewWindow ()
8133348
 {
8133348
-    glwin->trigger_redraw ();
8133348
+    ((QOpenGLWidget*)(glwin))->update ();
8133348
 }
8133348
 
8133348
 
8133348
--- a/src/iv/imageviewer.h
8133348
+++ b/src/iv/imageviewer.h
8133348
@@ -46,7 +46,6 @@
8133348
 
8133348
 #include <vector>
8133348
 
8133348
-#include <glew.h>
8133348
 #include <QGLWidget>
8133348
 #include <QAction>
8133348
 #include <QCheckBox>
8133348
--- a/src/iv/ivgl.cpp
8133348
+++ b/src/iv/ivgl.cpp
8133348
@@ -40,7 +40,6 @@
8133348
 #include <QLabel>
8133348
 #include <QMouseEvent>
8133348
 #include <QProgressBar>
8133348
-#include <QGLFormat>
8133348
 
8133348
 #include "ivutils.h"
8133348
 #include <OpenImageIO/strutil.h>
8133348
@@ -71,12 +70,12 @@ gl_err_to_string (GLenum err)
8133348
 
8133348
 
8133348
 IvGL::IvGL (QWidget *parent, ImageViewer &viewer)
8133348
-    : QGLWidget(parent), m_viewer(viewer), 
8133348
+    : QOpenGLWidget(parent), m_viewer(viewer),
8133348
       m_shaders_created(false), m_tex_created(false),
8133348
       m_zoom(1.0), m_centerx(0), m_centery(0), m_dragging(false),
8133348
-      m_use_shaders(false), m_shaders_using_extensions(false), 
8133348
+      m_use_shaders(false),
8133348
       m_use_halffloat(false), m_use_float(false),
8133348
-      m_use_srgb(false), m_use_pbo(false), 
8133348
+      m_use_srgb(false),
8133348
       m_texture_width(1), m_texture_height(1), m_last_pbo_used(0), 
8133348
       m_current_image(NULL), m_pixelview_left_corner(true),
8133348
       m_last_texbuf_used(0)
8133348
@@ -106,20 +105,13 @@ IvGL::~IvGL ()
8133348
 void
8133348
 IvGL::initializeGL ()
8133348
 {
8133348
-    GLenum glew_error = glewInit ();
8133348
-    if (glew_error != GLEW_OK) {
8133348
-        std::cerr << "GLEW init error " << glewGetErrorString (glew_error) << "\n";
8133348
-    }
8133348
+    initializeOpenGLFunctions();
8133348
 
8133348
     glClearColor (0.05f, 0.05f, 0.05f, 1.0f);
8133348
-    glShadeModel (GL_FLAT);
8133348
-    glEnable (GL_DEPTH_TEST);
8133348
-    glDisable (GL_CULL_FACE);
8133348
     glEnable (GL_BLEND);
8133348
     glEnable (GL_TEXTURE_2D);
8133348
     // glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8133348
     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
8133348
-    glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
8133348
     // Make sure initial matrix is identity (returning to this stack level loads
8133348
     // back this matrix).
8133348
     glLoadIdentity();
8133348
@@ -202,12 +194,10 @@ IvGL::create_textures (void)
8133348
     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8133348
     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8133348
 
8133348
-    if (m_use_pbo) {
8133348
-        glGenBuffersARB(2, m_pbo_objects);
8133348
-        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo_objects[0]);
8133348
-        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, m_pbo_objects[1]);
8133348
-        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
8133348
-    }
8133348
+    glGenBuffers (2, m_pbo_objects);
8133348
+    glBindBuffer (GL_PIXEL_UNPACK_BUFFER, m_pbo_objects[0]);
8133348
+    glBindBuffer (GL_PIXEL_UNPACK_BUFFER, m_pbo_objects[1]);
8133348
+    glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
8133348
 
8133348
     m_tex_created = true;
8133348
 }
8133348
@@ -349,90 +339,50 @@ IvGL::create_shaders (void)
8133348
     // entry points (which is actually done by GLEW) and then call them. So
8133348
     // we have to get the functions through the right symbols otherwise
8133348
     // extension-based shaders won't work.
8133348
-    if (m_shaders_using_extensions) {
8133348
-        m_shader_program = glCreateProgramObjectARB ();
8133348
-    }
8133348
-    else {
8133348
-        m_shader_program = glCreateProgram ();
8133348
-    }
8133348
+    m_shader_program = glCreateProgram ();
8133348
+
8133348
     GLERRPRINT ("create progam");
8133348
 
8133348
     // This holds the compilation status
8133348
     GLint status;
8133348
 
8133348
-    if (m_shaders_using_extensions) {
8133348
-        m_vertex_shader = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
8133348
-        glShaderSourceARB (m_vertex_shader, 1, &vertex_source, NULL);
8133348
-        glCompileShaderARB (m_vertex_shader);
8133348
-        glGetObjectParameterivARB (m_vertex_shader,
8133348
-                GL_OBJECT_COMPILE_STATUS_ARB, &status);
8133348
-    } else {
8133348
-        m_vertex_shader = glCreateShader (GL_VERTEX_SHADER);
8133348
-        glShaderSource (m_vertex_shader, 1, &vertex_source, NULL);
8133348
-        glCompileShader (m_vertex_shader);
8133348
-        glGetShaderiv (m_vertex_shader, GL_COMPILE_STATUS, &status);
8133348
-    }
8133348
+    m_vertex_shader = glCreateShader (GL_VERTEX_SHADER);
8133348
+    glShaderSource (m_vertex_shader, 1, &vertex_source, NULL);
8133348
+    glCompileShader (m_vertex_shader);
8133348
+    glGetShaderiv (m_vertex_shader, GL_COMPILE_STATUS, &status);
8133348
+
8133348
     if (! status) {
8133348
         std::cerr << "vertex shader compile status: " << status << "\n";
8133348
         print_shader_log (std::cerr, m_vertex_shader);
8133348
         create_shaders_abort ();
8133348
         return;
8133348
     }
8133348
-    if (m_shaders_using_extensions) {
8133348
-        glAttachObjectARB (m_shader_program, m_vertex_shader);
8133348
-    } else {
8133348
-        glAttachShader (m_shader_program, m_vertex_shader);
8133348
-    }
8133348
+    glAttachShader (m_shader_program, m_vertex_shader);
8133348
     GLERRPRINT ("After attach vertex shader.");
8133348
 
8133348
-    if (m_shaders_using_extensions) {
8133348
-        m_fragment_shader = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
8133348
-        glShaderSourceARB (m_fragment_shader, 1, &fragment_source, NULL);
8133348
-        glCompileShaderARB (m_fragment_shader);
8133348
-        glGetObjectParameterivARB (m_fragment_shader,
8133348
-                GL_OBJECT_COMPILE_STATUS_ARB, &status);
8133348
-    } else {
8133348
-        m_fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
8133348
-        glShaderSource (m_fragment_shader, 1, &fragment_source, NULL);
8133348
-        glCompileShader (m_fragment_shader);
8133348
-        glGetShaderiv (m_fragment_shader, GL_COMPILE_STATUS, &status);
8133348
-    }
8133348
+    m_fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
8133348
+    glShaderSource (m_fragment_shader, 1, &fragment_source, NULL);
8133348
+    glCompileShader (m_fragment_shader);
8133348
+    glGetShaderiv (m_fragment_shader, GL_COMPILE_STATUS, &status);
8133348
     if (! status) {
8133348
         std::cerr << "fragment shader compile status: " << status << "\n";
8133348
         print_shader_log(std::cerr, m_fragment_shader);
8133348
         create_shaders_abort ();
8133348
         return;
8133348
     }
8133348
-    if (m_shaders_using_extensions) {
8133348
-        glAttachObjectARB (m_shader_program, m_fragment_shader);
8133348
-    } else {
8133348
-        glAttachShader (m_shader_program, m_fragment_shader);
8133348
-    }
8133348
+    glAttachShader (m_shader_program, m_fragment_shader);
8133348
     GLERRPRINT ("After attach fragment shader");
8133348
 
8133348
-    if (m_shaders_using_extensions) {
8133348
-        glLinkProgramARB (m_shader_program);
8133348
-    } else {
8133348
-        glLinkProgram (m_shader_program);
8133348
-    }
8133348
+    glLinkProgram (m_shader_program);
8133348
     GLERRPRINT ("link");
8133348
     GLint linked;
8133348
-    if (m_shaders_using_extensions) {
8133348
-        glGetObjectParameterivARB (m_shader_program,
8133348
-                GL_OBJECT_LINK_STATUS_ARB, &linked);
8133348
-    } else {
8133348
-        glGetProgramiv (m_shader_program, GL_LINK_STATUS, &linked);
8133348
-    }
8133348
+    glGetProgramiv (m_shader_program, GL_LINK_STATUS, &linked);
8133348
     if (! linked) {
8133348
         std::cerr << "NOT LINKED\n";
8133348
         char buf[10000];
8133348
         buf[0] = 0;
8133348
         GLsizei len;
8133348
-        if (m_shaders_using_extensions) {
8133348
-            glGetInfoLogARB (m_shader_program, sizeof(buf), &len, buf);
8133348
-        } else {
8133348
-            glGetProgramInfoLog (m_shader_program, sizeof(buf), &len, buf);
8133348
-        }
8133348
+        glGetProgramInfoLog (m_shader_program, sizeof(buf), &len, buf);
8133348
         std::cerr << "link log:\n" << buf << "---\n";
8133348
         create_shaders_abort ();
8133348
         return;
8133348
@@ -446,25 +396,13 @@ IvGL::create_shaders (void)
8133348
 void
8133348
 IvGL::create_shaders_abort (void)
8133348
 {
8133348
-    if (m_shaders_using_extensions) {
8133348
-        glUseProgramObjectARB (0);
8133348
-        if (m_shader_program)
8133348
-            //this will also detach related shaders
8133348
-            glDeleteObjectARB (m_shader_program);
8133348
-        if (m_vertex_shader)
8133348
-            glDeleteObjectARB (m_vertex_shader);
8133348
-        if (m_fragment_shader)
8133348
-            glDeleteObjectARB (m_fragment_shader);
8133348
-    }
8133348
-    else {
8133348
-        glUseProgram (0);        
8133348
-        if (m_shader_program)
8133348
-            glDeleteProgram (m_shader_program);
8133348
-        if (m_vertex_shader)
8133348
-            glDeleteShader (m_vertex_shader);
8133348
-        if (m_fragment_shader)
8133348
-            glDeleteShader (m_fragment_shader);
8133348
-    }
8133348
+    glUseProgram (0);
8133348
+    if (m_shader_program)
8133348
+        glDeleteProgram (m_shader_program);
8133348
+    if (m_vertex_shader)
8133348
+        glDeleteShader (m_vertex_shader);
8133348
+    if (m_fragment_shader)
8133348
+        glDeleteShader (m_fragment_shader);
8133348
     
8133348
     GLERRPRINT ("After delete shaders");    
8133348
     m_use_shaders = false;
8133348
@@ -697,16 +635,23 @@ void
8133348
 IvGL::shadowed_text (float x, float y, float z, const std::string &s,
8133348
                      const QFont &font)
8133348
 {
8133348
-    QString q (s.c_str());
8133348
-#if 0
8133348
-    glColor4f (0, 0, 0, 1);
8133348
-    const int b = 2;  // blur size
8133348
-    for (int i = -b;  i <= b;  ++i)
8133348
-        for (int j = -b;  j <= b;  ++j)
8133348
-            renderText (x+i, y+j, q, font);
8133348
-#endif
8133348
-    glColor4f (1, 1, 1, 1);
8133348
-    renderText (x, y, z, q, font);
8133348
+    /*
8133348
+     * Paint on intermediate QImage, AA text on QOpenGLWidget based
8133348
+     * QPaintDevice requires MSAA
8133348
+     */
8133348
+    QImage t(size(), QImage::Format_ARGB32_Premultiplied);
8133348
+    t.fill(qRgba(0, 0, 0, 0));
8133348
+    {
8133348
+        QPainter painter(&t);
8133348
+        painter.setRenderHint(QPainter::TextAntialiasing, true);
8133348
+
8133348
+        painter.setFont(font);
8133348
+
8133348
+        painter.setPen(QPen(Qt::white, 1.0));
8133348
+        painter.drawText(QPointF(x, y), QString(s.c_str()));
8133348
+    }
8133348
+    QPainter painter(this);
8133348
+    painter.drawImage(rect(), t);
8133348
 }
8133348
 
8133348
 
8133348
@@ -837,9 +782,7 @@ IvGL::paint_pixelview ()
8133348
         GLenum glformat, gltype, glinternalformat;
8133348
         typespec_to_opengl (spec, nchannels, gltype, glformat, glinternalformat);
8133348
         // Use pixelview's own texture, and upload the corresponding image patch.
8133348
-        if (m_use_pbo) {
8133348
-            glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
8133348
-        }
8133348
+        glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
8133348
         glBindTexture (GL_TEXTURE_2D, m_pixelview_tex);
8133348
         glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 
8133348
                          xend-xbegin, yend-ybegin,
8133348
@@ -880,7 +823,7 @@ IvGL::paint_pixelview ()
8133348
     glDisable (GL_TEXTURE_2D);
8133348
     if (m_use_shaders) {
8133348
         // Disable shaders for this.
8133348
-        gl_use_program (0);
8133348
+        glUseProgram (0);
8133348
     }
8133348
     float extraspace = yspacing * (1 + spec.nchannels) + 4;
8133348
     glColor4f (0.1f, 0.1f, 0.1f, 0.5f);
8133348
@@ -893,11 +836,11 @@ IvGL::paint_pixelview ()
8133348
         QFont font;
8133348
         font.setFixedPitch (true);
8133348
         float *fpixel = (float *) alloca (spec.nchannels*sizeof(float));
8133348
-        int textx = - closeupsize/2 + 4;
8133348
-        int texty = - closeupsize/2 - yspacing;
8133348
+        int textx = xw - closeupsize/2 + 4;
8133348
+        int texty = yw + closeupsize/2 + yspacing;
8133348
         std::string s = Strutil::format ("(%d, %d)", (int) real_xp+spec.x, (int) real_yp+spec.y);
8133348
         shadowed_text (textx, texty, 0.0f, s, font);
8133348
-        texty -= yspacing;
8133348
+        texty += yspacing;
8133348
         img->getpixel ((int) real_xp+spec.x, (int) real_yp+spec.y, fpixel);
8133348
         for (int i = 0;  i < spec.nchannels;  ++i) {
8133348
             switch (spec.format.basetype) {
8133348
@@ -920,7 +863,7 @@ IvGL::paint_pixelview ()
8133348
                                      spec.channelnames[i].c_str(), fpixel[i]);
8133348
             }
8133348
             shadowed_text (textx, texty, 0.0f, s, font);
8133348
-            texty -= yspacing;
8133348
+            texty += yspacing;
8133348
         }
8133348
     }
8133348
 
8133348
@@ -955,47 +898,47 @@ IvGL::useshader (int tex_width, int tex_
8133348
 
8133348
     const ImageSpec &spec (img->spec());
8133348
 
8133348
-    gl_use_program (m_shader_program);
8133348
+    glUseProgram (m_shader_program);
8133348
     GLERRPRINT ("After use program");
8133348
 
8133348
     GLint loc;
8133348
 
8133348
-    loc = gl_get_uniform_location ("startchannel");
8133348
+    loc = glGetUniformLocation (m_shader_program, "startchannel");
8133348
     if (m_viewer.current_channel()>=spec.nchannels) {
8133348
-        gl_uniform (loc, -1);
8133348
+        glUniform1i (loc, -1);
8133348
         return;
8133348
     }
8133348
-    gl_uniform (loc, 0);
8133348
+    glUniform1i (loc, 0);
8133348
 
8133348
-    loc = gl_get_uniform_location ("imgtex");
8133348
+    loc = glGetUniformLocation (m_shader_program, "imgtex");
8133348
     // This is the texture unit, not the texture object
8133348
-    gl_uniform (loc, 0);
8133348
+    glUniform1i (loc, 0);
8133348
 
8133348
-    loc = gl_get_uniform_location ("gain");
8133348
+    loc = glGetUniformLocation (m_shader_program, "gain");
8133348
 
8133348
     float gain = powf (2.0, img->exposure ());
8133348
-    gl_uniform (loc, gain);
8133348
+    glUniform1f (loc, gain);
8133348
 
8133348
-    loc = gl_get_uniform_location ("gamma");
8133348
-    gl_uniform (loc, img->gamma ());
8133348
+    loc = glGetUniformLocation (m_shader_program, "gamma");
8133348
+    glUniform1f (loc, img->gamma ());
8133348
 
8133348
-    loc = gl_get_uniform_location ("colormode");
8133348
-    gl_uniform (loc, m_viewer.current_color_mode());
8133348
+    loc = glGetUniformLocation (m_shader_program, "colormode");
8133348
+    glUniform1i (loc, m_viewer.current_color_mode());
8133348
 
8133348
-    loc = gl_get_uniform_location ("imgchannels");
8133348
-    gl_uniform (loc, spec.nchannels);
8133348
+    loc = glGetUniformLocation (m_shader_program, "imgchannels");
8133348
+    glUniform1i (loc, spec.nchannels);
8133348
 
8133348
-    loc = gl_get_uniform_location ("pixelview");
8133348
-    gl_uniform (loc, pixelview);
8133348
+    loc = glGetUniformLocation (m_shader_program, "pixelview");
8133348
+    glUniform1i (loc, pixelview);
8133348
 
8133348
-    loc = gl_get_uniform_location ("linearinterp");
8133348
-    gl_uniform (loc, m_viewer.linearInterpolation ());
8133348
+    loc = glGetUniformLocation (m_shader_program, "linearinterp");
8133348
+    glUniform1i (loc, m_viewer.linearInterpolation ());
8133348
 
8133348
-    loc = gl_get_uniform_location ("width");
8133348
-    gl_uniform (loc, tex_width);
8133348
+    loc = glGetUniformLocation (m_shader_program, "width");
8133348
+    glUniform1i (loc, tex_width);
8133348
 
8133348
-    loc = gl_get_uniform_location ("height");
8133348
-    gl_uniform (loc, tex_height);
8133348
+    loc = glGetUniformLocation (m_shader_program, "height");
8133348
+    glUniform1i (loc, tex_height);
8133348
     GLERRPRINT ("After settting uniforms");
8133348
 }
8133348
 
8133348
@@ -1032,11 +975,7 @@ IvGL::update ()
8133348
     m_texture_width = clamp (pow2roundup(spec.width), 1, m_max_texture_size);
8133348
     m_texture_height= clamp (pow2roundup(spec.height), 1, m_max_texture_size);
8133348
 
8133348
-    if (m_use_pbo) {
8133348
-        // Otherwise OpenGL will confuse the NULL with an index into one of
8133348
-        // the PBOs.
8133348
-        glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
8133348
-    }
8133348
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
8133348
 
8133348
     for (auto&& tb : m_texbufs) {
8133348
         tb.width = 0;
8133348
@@ -1073,7 +1012,7 @@ IvGL::view (float xcenter, float ycenter
8133348
     m_zoom = zoom;
8133348
 
8133348
     if (redraw)
8133348
-        trigger_redraw ();
8133348
+        parent_t::update();
8133348
 }
8133348
 
8133348
 
8133348
@@ -1256,7 +1195,7 @@ IvGL::mouseMoveEvent (QMouseEvent *event
8133348
     }
8133348
     remember_mouse (pos);
8133348
     if (m_viewer.pixelviewOn())
8133348
-        trigger_redraw ();
8133348
+        parent_t::update();
8133348
     parent_t::mouseMoveEvent (event);
8133348
 }
8133348
 
8133348
@@ -1332,63 +1271,14 @@ IvGL::get_focus_image_pixel (int &x, int
8133348
 }
8133348
 
8133348
 
8133348
-
8133348
-inline void
8133348
-IvGL::gl_use_program (int program)
8133348
-{
8133348
-    if (m_shaders_using_extensions) 
8133348
-        glUseProgramObjectARB (program);
8133348
-    else
8133348
-        glUseProgram (program);
8133348
-}
8133348
-
8133348
-
8133348
-
8133348
-inline GLint
8133348
-IvGL::gl_get_uniform_location (const char *uniform)
8133348
-{
8133348
-    if (m_shaders_using_extensions)
8133348
-        return glGetUniformLocationARB (m_shader_program, uniform);
8133348
-    else
8133348
-        return glGetUniformLocation (m_shader_program, uniform);
8133348
-}
8133348
-
8133348
-
8133348
-
8133348
-inline void
8133348
-IvGL::gl_uniform (GLint location, float value)
8133348
-{
8133348
-    if (m_shaders_using_extensions)
8133348
-        glUniform1fARB (location, value);
8133348
-    else
8133348
-        glUniform1f (location, value);
8133348
-}
8133348
-
8133348
-
8133348
-
8133348
-inline void
8133348
-IvGL::gl_uniform (GLint location, int value)
8133348
-{
8133348
-    if (m_shaders_using_extensions)
8133348
-        glUniform1iARB (location, value);
8133348
-    else
8133348
-        glUniform1i (location, value);
8133348
-}
8133348
-
8133348
-
8133348
-
8133348
 void
8133348
-IvGL::print_shader_log (std::ostream& out, const GLuint shader_id) const
8133348
+IvGL::print_shader_log (std::ostream& out, const GLuint shader_id)
8133348
 {
8133348
     GLint size = 0;
8133348
     glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &size);
8133348
     if (size > 0) {    
8133348
         GLchar* log = new GLchar[size];
8133348
-        if (m_shaders_using_extensions) {
8133348
-            glGetInfoLogARB (shader_id, size, NULL, log);
8133348
-        } else {
8133348
-            glGetShaderInfoLog (shader_id, size, NULL, log);
8133348
-        }
8133348
+        glGetShaderInfoLog (shader_id, size, NULL, log);
8133348
         out << "compile log:\n" << log << "---\n";
8133348
         delete[] log;
8133348
     }
8133348
@@ -1399,32 +1289,26 @@ IvGL::print_shader_log (std::ostream& ou
8133348
 void
8133348
 IvGL::check_gl_extensions (void)
8133348
 {
8133348
-#ifndef FORCE_OPENGL_1
8133348
-    m_use_shaders = glewIsSupported("GL_VERSION_2_0");
8133348
+    m_use_shaders = hasOpenGLFeature(QOpenGLFunctions::Shaders);
8133348
 
8133348
-    if (!m_use_shaders && glewIsSupported("GL_ARB_shader_objects "
8133348
-                                          "GL_ARB_vertex_shader "
8133348
-                                          "GL_ARB_fragment_shader")) {
8133348
-        m_use_shaders = true;
8133348
-        m_shaders_using_extensions = true;
8133348
-    }
8133348
-
8133348
-    m_use_srgb = glewIsSupported("GL_VERSION_2_1") ||
8133348
-                 glewIsSupported("GL_EXT_texture_sRGB");
8133348
-
8133348
-    m_use_halffloat = glewIsSupported("GL_VERSION_3_0") ||
8133348
-                      glewIsSupported("GL_ARB_half_float_pixel") ||
8133348
-                      glewIsSupported("GL_NV_half_float_pixel");
8133348
-
8133348
-    m_use_float = glewIsSupported("GL_VERSION_3_0") ||
8133348
-                  glewIsSupported("GL_ARB_texture_float") ||
8133348
-                  glewIsSupported("GL_ATI_texture_float");
8133348
-
8133348
-    m_use_pbo = glewIsSupported("GL_VERSION_1_5") ||
8133348
-                glewIsSupported("GL_ARB_pixel_buffer_object");
8133348
-#else
8133348
-    std::cerr << "Not checking GL extensions\n";
8133348
-#endif
8133348
+    QOpenGLContext* context = QOpenGLContext::currentContext();
8133348
+    QSurfaceFormat format = context->format();
8133348
+    bool isGLES = format.renderableType() == QSurfaceFormat::OpenGLES;
8133348
+
8133348
+    m_use_srgb = (isGLES && format.majorVersion() >= 3) ||
8133348
+                 (!isGLES && format.version() >= qMakePair(2, 1)) ||
8133348
+                 context->hasExtension("GL_EXT_texture_sRGB") ||
8133348
+                 context->hasExtension("GL_EXT_sRGB");
8133348
+
8133348
+    m_use_halffloat = (!isGLES && format.version() >= qMakePair(3, 0)) ||
8133348
+                      context->hasExtension("GL_ARB_half_float_pixel") ||
8133348
+                      context->hasExtension("GL_NV_half_float_pixel") ||
8133348
+                      context->hasExtension("GL_OES_texture_half_float");
8133348
+
8133348
+    m_use_float = (!isGLES && format.version() >= qMakePair(3, 0)) ||
8133348
+                  context->hasExtension("GL_ARB_texture_float") ||
8133348
+                  context->hasExtension("GL_ATI_texture_float") ||
8133348
+                  context->hasExtension("GL_OES_texture_float");
8133348
 
8133348
     m_max_texture_size = 0;
8133348
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_max_texture_size);
8133348
@@ -1436,13 +1320,9 @@ IvGL::check_gl_extensions (void)
8133348
 #ifndef NDEBUG
8133348
     // Report back...
8133348
     std::cerr << "OpenGL Shading Language supported: " << m_use_shaders << "\n";
8133348
-    if (m_shaders_using_extensions) {
8133348
-        std::cerr << "\t(with extensions)\n";
8133348
-    }
8133348
     std::cerr << "OpenGL sRGB color space textures supported: " << m_use_srgb << "\n";
8133348
     std::cerr << "OpenGL half-float pixels supported: " << m_use_halffloat << "\n";
8133348
     std::cerr << "OpenGL float texture storage supported: " << m_use_float << "\n";
8133348
-    std::cerr << "OpenGL pixel buffer object supported: " << m_use_pbo << "\n";
8133348
     std::cerr << "OpenGL max texture dimension: " << m_max_texture_size << "\n";
8133348
 #endif
8133348
 }
8133348
@@ -1603,21 +1483,18 @@ IvGL::load_texture (int x, int y, int wi
8133348
                                           m_viewer.current_channel() + nchannels),
8133348
                                      spec.format, &m_tex_buffer[0]);
8133348
     }
8133348
-    if (m_use_pbo) {
8133348
-        glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 
8133348
-                         m_pbo_objects[m_last_pbo_used]);
8133348
-        glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, 
8133348
-                         width * height * spec.pixel_bytes(),
8133348
-                         &m_tex_buffer[0],
8133348
-                         GL_STREAM_DRAW_ARB);
8133348
-        GLERRPRINT ("After buffer data");
8133348
-        m_last_pbo_used = (m_last_pbo_used + 1) & 1;
8133348
-    }
8133348
+
8133348
+    glBindBuffer (GL_PIXEL_UNPACK_BUFFER,
8133348
+                     m_pbo_objects[m_last_pbo_used]);
8133348
+    glBufferData (GL_PIXEL_UNPACK_BUFFER,
8133348
+                     width * height * spec.pixel_bytes(),
8133348
+                     &m_tex_buffer[0],
8133348
+                     GL_STREAM_DRAW);
8133348
+    GLERRPRINT ("After buffer data");
8133348
+    m_last_pbo_used = (m_last_pbo_used + 1) & 1;
8133348
 
8133348
     // When using PBO this is the offset within the buffer.
8133348
     void *data = 0;
8133348
-    if (! m_use_pbo)
8133348
-        data = &m_tex_buffer[0];
8133348
 
8133348
     glBindTexture (GL_TEXTURE_2D, tb.tex_object);
8133348
     GLERRPRINT ("After bind texture");
8133348
@@ -1628,6 +1505,7 @@ IvGL::load_texture (int x, int y, int wi
8133348
                      data);
8133348
     GLERRPRINT ("After loading sub image");
8133348
     m_last_texbuf_used = (m_last_texbuf_used + 1) % m_texbufs.size();
8133348
+    glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
8133348
 }
8133348
 
8133348
 
8133348
--- a/src/iv/ivgl.h
8133348
+++ b/src/iv/ivgl.h
8133348
@@ -46,7 +46,8 @@
8133348
 
8133348
 #include <vector>
8133348
 
8133348
-#include <QGLWidget>
8133348
+#include <QOpenGLWidget>
8133348
+#include <QOpenGLFunctions>
8133348
 
8133348
 #include <OpenImageIO/imageio.h>
8133348
 #include <OpenImageIO/imagebuf.h>
8133348
@@ -58,7 +59,7 @@ class ImageViewer;
8133348
 
8133348
 
8133348
 
8133348
-class IvGL : public QGLWidget
8133348
+class IvGL : public QOpenGLWidget, protected QOpenGLFunctions
8133348
 {
8133348
 Q_OBJECT
8133348
 public:
8133348
@@ -103,8 +104,6 @@ public:
8133348
     /// widget boundaries)
8133348
     void get_focus_window_pixel (int &x, int &y);
8133348
 
8133348
-    void trigger_redraw (void) { glDraw(); }
8133348
-
8133348
     /// Returns true if OpenGL is capable of loading textures in the sRGB color
8133348
     /// space.
8133348
     bool is_srgb_capable (void) const { return m_use_srgb; }
8133348
@@ -137,12 +136,10 @@ protected:
8133348
     int m_mousex, m_mousey;           ///< Last mouse position
8133348
     Qt::MouseButton m_drag_button;    ///< Button on when dragging
8133348
     bool m_use_shaders;               ///< Are shaders supported?
8133348
-    bool m_shaders_using_extensions;  ///< Are we using ARB_*_shader?
8133348
     bool m_use_halffloat;             ///< Are half-float textures supported?
8133348
     bool m_use_float;                 ///< Are float textures supported?
8133348
     bool m_use_srgb;                  ///< Are sRGB-space textures supported?
8133348
     bool m_use_npot_texture;          ///< Can we handle NPOT textures?
8133348
-    bool m_use_pbo;                   ///< Can we use PBO to upload the texture?
8133348
     GLint m_max_texture_size;         ///< Maximum allowed texture dimension.
8133348
     GLsizei m_texture_width;
8133348
     GLsizei m_texture_height;
8133348
@@ -190,7 +187,7 @@ protected:
8133348
                         const QFont &font);
8133348
 
8133348
 private:
8133348
-    typedef QGLWidget parent_t;
8133348
+    typedef QOpenGLWidget parent_t;
8133348
     /// ncloseuppixels is the number of big pixels (in each direction)
8133348
     /// visible in our closeup window.
8133348
     const static int ncloseuppixels = 9;
8133348
@@ -207,19 +204,13 @@ private:
8133348
 
8133348
     void clamp_view_to_window ();
8133348
 
8133348
-    // Small wrappers to handle ARB shaders.
8133348
-    void gl_use_program (int program);
8133348
-    GLint gl_get_uniform_location (const char*);
8133348
-    void gl_uniform (GLint location, float value);
8133348
-    void gl_uniform (GLint location, int value);
8133348
-
8133348
     /// checks what OpenGL extensions we have
8133348
     ///
8133348
     void check_gl_extensions (void);
8133348
 
8133348
     /// print shader info to out stream
8133348
     ///
8133348
-    void print_shader_log (std::ostream& out, const GLuint shader_id) const;
8133348
+    void print_shader_log (std::ostream& out, const GLuint shader_id);
8133348
 
8133348
     /// Loads the given patch of the image, but first figures if it's already
8133348
     /// been loaded.