From 6b67cfe63f4997969e8175f3ea5b415f14dcaedb Mon Sep 17 00:00:00 2001
From: whitequark <whitequark@whitequark.org>
Date: Fri, 13 Jan 2017 23:00:38 +0000
Subject: [PATCH] Except when using OpenGL ES 2, use OpenGL 3.2+ Core profile.

This is primarily done to lower the GTK version dependency below
GTK 3.22, since GTK 3.22 is unlikely to be widely availale any
time soon.
---
 CMakeLists.txt               |  2 +-
 res/CMakeLists.txt           |  1 +
 res/shaders/edge.frag        |  2 +-
 res/shaders/edge.vert        |  2 +-
 res/shaders/imesh.frag       |  2 +-
 res/shaders/imesh.vert       |  2 +-
 res/shaders/imesh_point.frag |  2 +-
 res/shaders/imesh_point.vert |  2 +-
 res/shaders/imesh_tex.frag   |  2 +-
 res/shaders/imesh_tex.vert   |  2 +-
 res/shaders/imesh_texa.frag  |  2 +-
 res/shaders/imesh_texr.frag  | 13 +++++++++++++
 res/shaders/mesh.frag        |  2 +-
 res/shaders/mesh.vert        |  2 +-
 res/shaders/mesh_fill.frag   |  2 +-
 res/shaders/mesh_fill.vert   |  2 +-
 res/shaders/outline.vert     |  2 +-
 src/platform/gtkmain.cpp     |  2 --
 src/render/gl2shader.cpp     | 22 ++++++++++++++++------
 src/render/gl2shader.h       | 14 +++++++++-----
 src/render/rendergl2.cpp     | 12 +++++++++++-
 21 files changed, 65 insertions(+), 29 deletions(-)
 create mode 100644 res/shaders/imesh_texr.frag

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 72429f2..1ff97f9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -191,7 +191,7 @@ else() # Linux and compatible systems
         find_package(OpenGL REQUIRED)
         pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
         pkg_check_modules(JSONC REQUIRED json-c)
-        pkg_check_modules(GTKMM REQUIRED gtkmm-3.0>=3.22 pangomm-1.4 x11)
+        pkg_check_modules(GTKMM REQUIRED gtkmm-3.0>=3.16 pangomm-1.4 x11)
     endif()
 endif()
 
diff --git a/res/CMakeLists.txt b/res/CMakeLists.txt
index b91f216..1913c06 100644
--- a/res/CMakeLists.txt
+++ b/res/CMakeLists.txt
@@ -211,6 +211,7 @@ add_resources(
     shaders/imesh_point.vert
     shaders/imesh_tex.frag
     shaders/imesh_texa.frag
+    shaders/imesh_texr.frag
     shaders/imesh_tex.vert
     shaders/mesh.frag
     shaders/mesh.vert
diff --git a/res/shaders/edge.frag b/res/shaders/edge.frag
index 87951e2..979dca4 100644
--- a/res/shaders/edge.frag
+++ b/res/shaders/edge.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Edge rendering shader
+// Edge rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/edge.vert b/res/shaders/edge.vert
index 902bf03..2217ee8 100644
--- a/res/shaders/edge.vert
+++ b/res/shaders/edge.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Edge rendering shader
+// Edge rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh.frag b/res/shaders/imesh.frag
index d4a4160..872bb48 100644
--- a/res/shaders/imesh.frag
+++ b/res/shaders/imesh.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Indexed Mesh rendering shader
+// Indexed Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh.vert b/res/shaders/imesh.vert
index 0c6742d..5e3e59a 100644
--- a/res/shaders/imesh.vert
+++ b/res/shaders/imesh.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Indexed Mesh rendering shader
+// Indexed Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_point.frag b/res/shaders/imesh_point.frag
index 799bfba..ca887f7 100644
--- a/res/shaders/imesh_point.frag
+++ b/res/shaders/imesh_point.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Point rendering shader
+// Point rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_point.vert b/res/shaders/imesh_point.vert
index f32f24d..bc92045 100644
--- a/res/shaders/imesh_point.vert
+++ b/res/shaders/imesh_point.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Point rendering shader
+// Point rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_tex.frag b/res/shaders/imesh_tex.frag
index bb34784..79adcec 100644
--- a/res/shaders/imesh_tex.frag
+++ b/res/shaders/imesh_tex.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Indexed Mesh rendering shader
+// Indexed Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_tex.vert b/res/shaders/imesh_tex.vert
index d40dd95..e048759 100644
--- a/res/shaders/imesh_tex.vert
+++ b/res/shaders/imesh_tex.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Indexed Mesh rendering shader
+// Indexed Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_texa.frag b/res/shaders/imesh_texa.frag
index 85359ee..db2934e 100644
--- a/res/shaders/imesh_texa.frag
+++ b/res/shaders/imesh_texa.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Indexed Mesh rendering shader
+// Indexed Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/imesh_texr.frag b/res/shaders/imesh_texr.frag
new file mode 100644
index 0000000..5d7bc68
--- /dev/null
+++ b/res/shaders/imesh_texr.frag
@@ -0,0 +1,13 @@
+//-----------------------------------------------------------------------------
+// Indexed Mesh rendering shader
+//
+// Copyright 2016 Aleksey Egorov
+//-----------------------------------------------------------------------------
+uniform vec4 color;
+uniform sampler2D texture;
+
+varying vec2 fragTex;
+
+void main() {
+    gl_FragColor = vec4(color.rgb, color.a * texture2D(texture, fragTex).r);
+}
diff --git a/res/shaders/mesh.frag b/res/shaders/mesh.frag
index bfd78bf..8cb32c2 100644
--- a/res/shaders/mesh.frag
+++ b/res/shaders/mesh.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Mesh rendering shader
+// Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/mesh.vert b/res/shaders/mesh.vert
index 7aa8efb..c310ffc 100644
--- a/res/shaders/mesh.vert
+++ b/res/shaders/mesh.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Mesh rendering shader
+// Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/mesh_fill.frag b/res/shaders/mesh_fill.frag
index 1a05f16..4521ca9 100644
--- a/res/shaders/mesh_fill.frag
+++ b/res/shaders/mesh_fill.frag
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Mesh rendering shader
+// Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/mesh_fill.vert b/res/shaders/mesh_fill.vert
index e7ebc25..935efa6 100644
--- a/res/shaders/mesh_fill.vert
+++ b/res/shaders/mesh_fill.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Mesh rendering shader
+// Mesh rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/res/shaders/outline.vert b/res/shaders/outline.vert
index 4de3e87..6bf1dfc 100644
--- a/res/shaders/outline.vert
+++ b/res/shaders/outline.vert
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// SolveSpace Outline rendering shader
+// Outline rendering shader
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
diff --git a/src/platform/gtkmain.cpp b/src/platform/gtkmain.cpp
index 249db3a..faa2ac1 100644
--- a/src/platform/gtkmain.cpp
+++ b/src/platform/gtkmain.cpp
@@ -338,7 +338,6 @@ public:
                    Gdk::LEAVE_NOTIFY_MASK);
         set_has_alpha(true);
         set_has_depth_buffer(true);
-        set_use_es(true);
     }
 
 protected:
@@ -1109,7 +1108,6 @@ public:
                    Gdk::LEAVE_NOTIFY_MASK);
         set_has_alpha(true);
         set_has_depth_buffer(true);
-        set_use_es(true);
     }
 
     void set_cursor_hand(bool is_hand) {
diff --git a/src/render/gl2shader.cpp b/src/render/gl2shader.cpp
index b86c5ec..786a6a9 100644
--- a/src/render/gl2shader.cpp
+++ b/src/render/gl2shader.cpp
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// OpenGL 2 shader interface.
+// OpenGL ES 2.0 and OpenGL 3.0 shader interface.
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
@@ -67,12 +67,17 @@ static GLuint CompileShader(const std::string &res, GLenum type) {
     // GLES2+ depending on whether we run on X11 or Wayland, and OS X supports either a legacy
     // profile or a GL3.2 core profile or (on 10.9+) a GL4.1 core profile.
     // The platforms barely have a common subset of features:
-    //  * Linux Mesa/NVidia accept basically everything thrown at it;
     //  * mobile+web and Windows (D3D9 through ANGLE) are strictly GLES2/GLSL1.0;
     //  * OS X legacy compatibility profile has GLSL1.2 only shaders, and GL3.2 core profile
     //    that has GLSL1.0 shaders compatible with GLES2 makes mandatory the use of vertex array
     //    objects, which cannot be used in GLES2 at all; similarly GL3.2 core has GL_RED but not
     //    GL_ALPHA whereas GLES2 has GL_ALPHA but not GL_RED.
+    //  * GTK does not work on anything prior to GL3.0/GLES2.0; it does not permit explicitly
+    //    asking for a compatibility profile, i.e. you can only ask for 3.2+; and it does not
+    //    permit asking for a GLES profile prior to GTK 3.22, which will get into Ubuntu
+    //    no earlier than late 2017. This is despite the fact that if only GTK defaulted
+    //    to the compatibility profile, everything would have just worked as Mesa is
+    //    very permissive.
     // While we're at it, let's remember that GLES2 has *only* glDepthRangef, GL3.2 has *only*
     // glDepthRange, and GL4.1+ has both glDepthRangef and glDepthRange. Also, that GLSL1.0
     // makes `precision highp float;` mandatory in fragment shaders, and GLSL1.2 removes
@@ -80,10 +85,10 @@ static GLuint CompileShader(const std::string &res, GLenum type) {
     // Christ, what a trash fire.
 
     std::string src(resData, size);
-#ifdef __APPLE__
-    src = "#version 120\n" + src;
-#else
+#if defined(HAVE_GLES)
     src = "#version 100\nprecision highp float;\n" + src;
+#else
+    src = "#version 120\n" + src;
 #endif
 
     GLuint shader = glCreateShader(type);
@@ -924,7 +929,12 @@ void IndexedMeshRenderer::Init() {
         }
     );
     texaShader.Init(
-        "shaders/imesh_tex.vert", "shaders/imesh_texa.frag",
+        "shaders/imesh_tex.vert",
+#if defined(HAVE_GLES)
+        "shaders/imesh_texa.frag",
+#else
+        "shaders/imesh_texr.frag",
+#endif
         {
             { ATTRIB_POS, "pos" },
             { ATTRIB_TEX, "tex" }
diff --git a/src/render/gl2shader.h b/src/render/gl2shader.h
index 94c476f..ab7138f 100644
--- a/src/render/gl2shader.h
+++ b/src/render/gl2shader.h
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// OpenGL 2 shader interface.
+// OpenGL ES 2.0 and OpenGL 3.0 shader interface.
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
@@ -11,18 +11,22 @@
 #   define GL_GLEXT_PROTOTYPES
 #   include <GLES2/gl2.h>
 #   include <GLES2/gl2ext.h>
+#   define HAVE_GLES
 #elif __APPLE__
 #   include <OpenGL/gl.h>
-// glDepthRange is in GL1+ but not GLES2, glDepthRangef is in GL4.1+ and GLES2.
-// Consistency!
-#   define glClearDepthf glClearDepth
-#   define glDepthRangef glDepthRange
 #else
 #   define GL_GLEXT_PROTOTYPES
 #   include <GL/gl.h>
 #   include <GL/glext.h>
 #endif
 
+#if !defined(HAVE_GLES)
+// glDepthRange is in GL1+ but not GLES2, glDepthRangef is in GL4.1+ and GLES2.
+// Consistency!
+#   define glClearDepthf glClearDepth
+#   define glDepthRangef glDepthRange
+#endif
+
 namespace SolveSpace {
 
 //-----------------------------------------------------------------------------
diff --git a/src/render/rendergl2.cpp b/src/render/rendergl2.cpp
index 20a7816..aae81d8 100644
--- a/src/render/rendergl2.cpp
+++ b/src/render/rendergl2.cpp
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// OpenGL 2 based rendering interface.
+// OpenGL ES 2.0 and OpenGL 3.0 based rendering interface.
 //
 // Copyright 2016 Aleksey Egorov
 //-----------------------------------------------------------------------------
@@ -271,7 +271,11 @@ void OpenGl2Renderer::InvalidatePixmap(std::shared_ptr<const Pixmap> pm) {
     switch(pm->format) {
         case Pixmap::Format::RGBA: format = GL_RGBA;  break;
         case Pixmap::Format::RGB:  format = GL_RGB;   break;
+#if defined(HAVE_GLES)
         case Pixmap::Format::A:    format = GL_ALPHA; break;
+#else
+        case Pixmap::Format::A:    format = GL_RED;   break;
+#endif
         case Pixmap::Format::BGRA:
         case Pixmap::Format::BGR:
             ssassert(false, "Unexpected pixmap format");
@@ -423,6 +427,12 @@ void OpenGl2Renderer::Init() {
     outlineRenderer.Init(&atlas);
     meshRenderer.Init();
     imeshRenderer.Init();
+
+#if !defined(HAVE_GLES) && !defined(__APPLE__)
+    GLuint array;
+    glGenVertexArrays(1, &array);
+    glBindVertexArray(array);
+#endif
 }
 
 void OpenGl2Renderer::DrawLine(const Vector &a, const Vector &b, hStroke hcs) {