[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - 18 commits - include/vcl slideshow/opengl slideshow/Package_opengl.mk slideshow/source vcl/opengl vcl/source vcl/win

Tomaž Vajngerl tomaz.vajngerl at collabora.com
Sat Dec 12 00:33:53 PST 2015


 include/vcl/opengl/OpenGLHelper.hxx                                    |    5 
 slideshow/Package_opengl.mk                                            |    5 
 slideshow/opengl/basicVertexShader.glsl                                |   18 
 slideshow/opengl/glitterFragmentShader.glsl                            |   36 
 slideshow/opengl/glitterVertexShader.glsl                              |   79 +
 slideshow/opengl/honeycombFragmentShader.glsl                          |   63 +
 slideshow/opengl/honeycombGeometryShader.glsl                          |   64 +
 slideshow/opengl/honeycombVertexShader.glsl                            |   83 +
 slideshow/opengl/reflectionVertexShader.glsl                           |   18 
 slideshow/opengl/vortexFragmentShader.glsl                             |   12 
 slideshow/opengl/vortexVertexShader.glsl                               |   32 
 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx   |  620 ++++++----
 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx   |   39 
 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx |  101 -
 vcl/opengl/salbmp.cxx                                                  |  116 +
 vcl/source/opengl/OpenGLHelper.cxx                                     |   62 -
 vcl/win/source/gdi/salgdi2.cxx                                         |   32 
 17 files changed, 1022 insertions(+), 363 deletions(-)

New commits:
commit 1762a625db256758e23c7f9ec846b46af0ec145b
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date:   Fri Dec 11 13:42:52 2015 +0100

    slideshow: windows build fixes
    
    Change-Id: I9032af7583f0cf97664d2f84d5aead0cb1547c1a
    (cherry picked from commit 3b397f8a41ccc810ce5048d80b1e3dab827cb093)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 86cc2c7..ac7cf3b 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -1921,7 +1921,7 @@ void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlide
 
     // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
 
-    const float borderSize = 0.15;
+    const float borderSize = 0.15f;
 
     CHECK_GL_ERROR();
     glUniform1f(maSelectedTextureLocation, 0.0);
@@ -1956,7 +1956,7 @@ std::shared_ptr<OGLTransitionImpl> makeHoneycomb()
     const int NY = 21;
 
     TransitionSettings aSettings;
-    aSettings.mnRequiredGLVersion = 3.2;
+    aSettings.mnRequiredGLVersion = 3.2f;
 
     Primitives_t aSlide;
     Primitive aHexagon;
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index 2b9daa5..d8cbbfe 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -228,18 +228,18 @@ private:
     GLint m_nNormalLocation = -1;
     GLint m_nTexCoordLocation = -1;
 
-    GLuint m_nVertexArrayObject = -1;
+    GLuint m_nVertexArrayObject = 0u;
 
     std::vector<int> m_nFirstIndices;
 
 protected:
     /** GLSL program object
      */
-    GLuint m_nProgramObject = 0;
+    GLuint m_nProgramObject = 0u;
 
     /** VBO in which to put primitive data
      */
-    GLuint m_nVertexBufferObject = -1;
+    GLuint m_nVertexBufferObject = 0u;
 };
 
 
commit cc6d80170f9f008fc564e47a0af86a8c237c703f
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:35 2015 +0000

    slideshow: Improve the performances of the Glitter transition
    
    Change-Id: Iaf482b357577ff8a5511607844a69c90ea28d29f
    (cherry picked from commit d9116f2235e1a79c86446fc67231684edac49d82)

diff --git a/slideshow/Package_opengl.mk b/slideshow/Package_opengl.mk
index 5e9c8d3..bed17d9 100644
--- a/slideshow/Package_opengl.mk
+++ b/slideshow/Package_opengl.mk
@@ -15,6 +15,8 @@ $(eval $(call gb_Package_add_files,slideshow_opengl_shader,$(LIBO_ETC_FOLDER)/op
 		dissolveFragmentShader.glsl \
 		fadeBlackFragmentShader.glsl \
 		fadeFragmentShader.glsl \
+		glitterVertexShader.glsl \
+		glitterFragmentShader.glsl \
 		honeycombVertexShader.glsl \
 		honeycombGeometryShader.glsl \
 		honeycombFragmentShader.glsl \
diff --git a/slideshow/opengl/glitterFragmentShader.glsl b/slideshow/opengl/glitterFragmentShader.glsl
new file mode 100644
index 0000000..1bec201
--- /dev/null
+++ b/slideshow/opengl/glitterFragmentShader.glsl
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 130
+
+#define M_PI 3.1415926535897932384626433832795
+
+uniform sampler2D leavingSlideTexture;
+uniform sampler2D enteringSlideTexture;
+varying vec2 v_texturePosition;
+varying vec3 v_normal;
+
+uniform float time;
+varying float angle;
+
+void main() {
+    vec3 lightVector = vec3(0.0, 0.0, 1.0);
+    float light = dot(lightVector, v_normal);
+
+    vec4 fragment;
+    if (angle < M_PI)
+        fragment = texture2D(leavingSlideTexture, v_texturePosition);
+    else
+        fragment = texture2D(enteringSlideTexture, v_texturePosition);
+
+    vec4 black = vec4(0.0, 0.0, 0.0, fragment.a);
+    gl_FragColor = mix(black, fragment, max(light, 0.0));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/glitterVertexShader.glsl b/slideshow/opengl/glitterVertexShader.glsl
new file mode 100644
index 0000000..9fdaf29
--- /dev/null
+++ b/slideshow/opengl/glitterVertexShader.glsl
@@ -0,0 +1,79 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 130
+
+#define M_PI 3.1415926535897932384626433832795
+
+attribute vec3 a_position;
+attribute vec3 a_normal;
+
+uniform mat4 u_projectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform mat4 u_sceneTransformMatrix;
+uniform mat4 u_primitiveTransformMatrix;
+uniform mat4 u_operationsTransformMatrix;
+
+varying vec2 v_texturePosition;
+varying vec3 v_normal;
+
+attribute vec3 center;
+uniform float time;
+uniform ivec2 numTiles;
+uniform sampler2D permTexture;
+varying float angle;
+
+float snoise(vec2 p)
+{
+    return texture2D(permTexture, p).r;
+}
+
+mat4 translationMatrix(vec3 axis)
+{
+    return mat4(1.0,    0.0,    0.0,    0.0,
+                0.0,    1.0,    0.0,    0.0,
+                0.0,    0.0,    1.0,    0.0,
+                axis.x, axis.y, axis.z, 1.0);
+}
+
+mat4 rotationMatrix(vec3 axis, float angle)
+{
+    axis = normalize(axis);
+    float s = sin(angle);
+    float c = cos(angle);
+    float oc = 1.0 - c;
+
+    return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
+                oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
+                oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
+                0.0,                                0.0,                                0.0,                                1.0);
+}
+
+void main( void )
+{
+    // There are 18 vertices in an hexagon
+    int instanceID = gl_VertexID / 18;
+
+    vec2 pos = (center.xy + 1) / 2;
+    float fuzz = snoise(pos);
+    float startTime = pos.x * 0.5 + fuzz * 0.25;
+    float endTime = startTime + 0.25;
+    float actualTime = clamp((time - startTime) / (endTime - startTime), 0, 1);
+    angle = actualTime * M_PI * 2;
+
+    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat4 transformMatrix = translationMatrix(center) * rotationMatrix(vec3(0, 1, 0), angle) * translationMatrix(-center);
+
+    mat3 normalMatrix = mat3(transpose(inverse(transformMatrix)));
+    gl_Position = u_projectionMatrix * modelViewMatrix * transformMatrix * vec4(a_position, 1.0);
+    v_texturePosition = vec2((a_position.x + 1) / 2, (1 - a_position.y) / 2);
+    v_normal = normalize(normalMatrix * a_normal);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 36ee0e7..86cc2c7 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -1768,40 +1768,105 @@ void createHexagon(Primitive& aHexagon, const int x, const int y, const int NX,
     }
 }
 
-std::shared_ptr<OGLTransitionImpl> makeGlitter()
+namespace
 {
-    const int NX = 80;
-    const int NY = NX * 4 / 3;
 
-    Primitives_t aLeavingSlide;
-    Primitives_t aEnteringSlide;
-
-    for (int y = 0; y < NY+2; y+=2)
+class GlitterTransition : public PermTextureTransition
+{
+public:
+    GlitterTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
+        : PermTextureTransition(rScene, rSettings)
     {
-        for (int x = 0; x < NX+2; x+=2)
-        {
-            Primitive aHexagon;
-            createHexagon(aHexagon, x, y, NX, NY);
+    }
 
-            glm::vec3 aCenter = aHexagon.getVertex(2);
+private:
+    virtual GLuint makeShader() const override;
+    virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override;
+    virtual void finish( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) override;
 
-            float fRandom = comphelper::rng::uniform_real_distribution(-0.25, std::nextafter(0.2, DBL_MAX));
+    GLuint maBuffer = 0;
+};
 
-            double fDelta = 0.6 + fRandom;
-            double fHorizontal = fdiv(x, NX + 2) * fDelta;
+GLuint GlitterTransition::makeShader() const
+{
+    return OpenGLHelper::LoadShaders( "glitterVertexShader", "glitterFragmentShader" );
+}
 
-            double fStart = fHorizontal;
-            double fEnd   = fHorizontal + (1.0 - fDelta);
+struct ThreeFloats
+{
+    GLfloat x, y, z;
+};
 
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), aCenter, 180 , true, fStart, fEnd));
-            aLeavingSlide.push_back(aHexagon);
+void GlitterTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
+{
+    CHECK_GL_ERROR();
+    PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex );
+    CHECK_GL_ERROR();
 
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 1, 0), aCenter, 180 , false, fStart, fEnd));
-            aEnteringSlide.push_back(aHexagon);
-        }
+    GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
+    if (nNumTilesLocation != -1) {
+        glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(glm::ivec2(41, 41 * 4 / 3)));
+        CHECK_GL_ERROR();
     }
 
-    return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
+    glGenBuffers(1, &maBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
+
+    // Upload the center of each hexagon.
+    const Primitive& primitive = getScene().getLeavingSlide()[0];
+    int nbVertices = primitive.getVerticesSize() / sizeof(Vertex);
+    std::vector<ThreeFloats> vertices;
+    for (int i = 2; i < nbVertices; i += 18) {
+        const glm::vec3& center = primitive.getVertex(i);
+        for (int j = 0; j < 18; ++j)
+            vertices.push_back({center.x, center.y, center.z});
+    }
+    glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
+
+    GLint location = glGetAttribLocation(m_nProgramObject, "center");
+    if (location != -1) {
+        glEnableVertexAttribArray(location);
+        glVertexAttribPointer( location, 3, GL_FLOAT, false, 0, NULL );
+        CHECK_GL_ERROR();
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void GlitterTransition::finish( double, double, double, double, double )
+{
+    CHECK_GL_ERROR();
+    glDeleteBuffers(1, &maBuffer);
+    CHECK_GL_ERROR();
+}
+
+std::shared_ptr<OGLTransitionImpl>
+makeGlitterTransition(const Primitives_t& rLeavingSlidePrimitives,
+                      const Primitives_t& rEnteringSlidePrimitives,
+                      const TransitionSettings& rSettings = TransitionSettings())
+{
+    return std::make_shared<GlitterTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
+                                               rSettings);
+}
+
+}
+
+std::shared_ptr<OGLTransitionImpl> makeGlitter()
+{
+    const int NX = 80;
+    const int NY = NX * 4 / 3;
+
+    Primitives_t aSlide;
+    Primitives_t aEmptySlide;
+    Primitive aHexagon;
+
+    for (int y = 0; y < NY+2; y+=2)
+        for (int x = 0; x < NX+2; x+=2)
+            createHexagon(aHexagon, x, y, NX, NY);
+
+    aSlide.push_back(aHexagon);
+
+    return makeGlitterTransition(aSlide, aEmptySlide);
 }
 
 namespace
commit d030595513dc15edbc01ecd26ecf6cc2f90d6b8f
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:34 2015 +0000

    slideshow: Improve the performances of the Honeycomb transition
    
    Change-Id: Iacddc7b84bf0be8bb112cba88cc7fd36f72e7ca0
    (cherry picked from commit c0b8c035db9afd6271e0382c4f10ad44d3aa0dbb)

diff --git a/slideshow/Package_opengl.mk b/slideshow/Package_opengl.mk
index 1293c05..5e9c8d3 100644
--- a/slideshow/Package_opengl.mk
+++ b/slideshow/Package_opengl.mk
@@ -15,6 +15,9 @@ $(eval $(call gb_Package_add_files,slideshow_opengl_shader,$(LIBO_ETC_FOLDER)/op
 		dissolveFragmentShader.glsl \
 		fadeBlackFragmentShader.glsl \
 		fadeFragmentShader.glsl \
+		honeycombVertexShader.glsl \
+		honeycombGeometryShader.glsl \
+		honeycombFragmentShader.glsl \
 		reflectionVertexShader.glsl \
 		reflectionFragmentShader.glsl \
 		staticFragmentShader.glsl \
diff --git a/slideshow/opengl/honeycombFragmentShader.glsl b/slideshow/opengl/honeycombFragmentShader.glsl
new file mode 100644
index 0000000..607e83d
--- /dev/null
+++ b/slideshow/opengl/honeycombFragmentShader.glsl
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 150
+
+in vec2 texturePosition;
+in float fuzz;
+in vec2 v_center;
+
+uniform sampler2D slideTexture;
+uniform float selectedTexture;
+uniform float time;
+uniform float hexagonSize;
+
+bool isBorder(vec2 point)
+{
+    return point.x < 0.02 || point.x > 0.98 || point.y < 0.02 || point.y > 0.98;
+}
+
+void main()
+{
+    gl_FragColor = texture2D(slideTexture, texturePosition);
+    if (hexagonSize > 1.0) {
+        // The space in-between hexagons.
+        if (selectedTexture > 0.5)
+            gl_FragColor.a = 1.0 - time * 8 + gl_FragCoord.x / 1024.;
+        else
+            gl_FragColor.a = time * 8 - 7.7 + gl_FragCoord.x / 1024.;
+    } else {
+        // The hexagons themselves.
+
+        float startTime;
+        float actualTime;
+        if (selectedTexture > 0.5) {
+            // Leaving slide.
+            if (isBorder(v_center))
+                // If the center is “outside” of the canvas, clear it first.
+                startTime = 0.15;
+            else
+                startTime = 0.15 + fuzz * 0.3;
+            float endTime = startTime + 0.05;
+            actualTime = 1.0 - clamp((time - startTime) / (endTime - startTime), 0, 1);
+        } else {
+            // Entering slide.
+            if (isBorder(v_center))
+                // If the center is “outside” of the canvas, clear it first.
+                startTime = 0.85;
+            else
+                startTime = 0.5 + fuzz * 0.3;
+            float endTime = startTime + 0.05;
+            actualTime = clamp((time - startTime) / (endTime - startTime), 0, 1);
+        }
+        gl_FragColor.a = actualTime;
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/honeycombGeometryShader.glsl b/slideshow/opengl/honeycombGeometryShader.glsl
new file mode 100644
index 0000000..bb2b1f3
--- /dev/null
+++ b/slideshow/opengl/honeycombGeometryShader.glsl
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 150
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=13) out;
+
+in mat4 modelViewProjectionMatrix[];
+
+uniform float hexagonSize;
+uniform sampler2D permTexture;
+
+out vec2 texturePosition;
+out float fuzz;
+out vec2 v_center;
+
+const float expandFactor = 0.0318;
+
+float snoise(vec2 p)
+{
+    return texture2D(permTexture, p).r;
+}
+
+void emitHexagonVertex(vec3 center, vec2 translation)
+{
+    vec4 pos = vec4(center + hexagonSize * expandFactor * vec3(translation, 0.0), 1.0);
+    gl_Position = modelViewProjectionMatrix[0] * pos;
+    texturePosition = vec2((pos.x + 1), (1 - pos.y)) / 2;
+    EmitVertex();
+}
+
+void main()
+{
+    vec2 translateVectors[6];
+    translateVectors[0] = vec2(-3, -2);
+    translateVectors[1] = vec2(0, -4);
+    translateVectors[2] = vec2(3, -2);
+    translateVectors[3] = vec2(3, 2);
+    translateVectors[4] = vec2(0, 4);
+    translateVectors[5] = vec2(-3, 2);
+
+    vec3 center = gl_in[0].gl_Position.xyz;
+
+    v_center = (1 + center.xy) / 2;
+    fuzz = snoise(center.xy);
+
+    emitHexagonVertex(center, translateVectors[5]);
+
+    for (int i = 0; i < 6; ++i) {
+        emitHexagonVertex(center, translateVectors[i]);
+        emitHexagonVertex(center, vec2(0, 0));
+    }
+
+    EndPrimitive();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/honeycombVertexShader.glsl b/slideshow/opengl/honeycombVertexShader.glsl
new file mode 100644
index 0000000..b54efbd
--- /dev/null
+++ b/slideshow/opengl/honeycombVertexShader.glsl
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#version 150
+
+#define M_PI 3.1415926535897932384626433832795
+
+in vec3 a_position;
+
+uniform mat4 u_projectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform mat4 u_sceneTransformMatrix;
+uniform mat4 u_primitiveTransformMatrix;
+uniform mat4 u_operationsTransformMatrix;
+
+uniform float time;
+uniform float selectedTexture;
+
+out mat4 modelViewProjectionMatrix;
+
+mat4 translationMatrix(vec3 axis)
+{
+    return mat4(1.0,    0.0,    0.0,    0.0,
+                0.0,    1.0,    0.0,    0.0,
+                0.0,    0.0,    1.0,    0.0,
+                axis.x, axis.y, axis.z, 1.0);
+}
+
+mat4 scaleMatrix(vec3 axis)
+{
+    return mat4(axis.x, 0.0,    0.0,    0.0,
+                0.0,    axis.y, 0.0,    0.0,
+                0.0,    0.0,    axis.z, 0.0,
+                0.0,    0.0,    0.0,    1.0);
+}
+
+mat4 rotationMatrix(vec3 axis, float angle)
+{
+    axis = normalize(axis);
+    float s = sin(angle);
+    float c = cos(angle);
+    float oc = 1.0 - c;
+
+    return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
+                oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
+                oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
+                0.0,                                0.0,                                0.0,                                1.0);
+}
+
+void main( void )
+{
+    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat4 transformMatrix;
+
+    // TODO: use the aspect ratio of the slide instead.
+    mat4 slideScaleMatrix = scaleMatrix(vec3(0.75, 1, 1));
+    mat4 invertSlideScaleMatrix = scaleMatrix(1.0 / vec3(0.75, 1, 1));
+
+    if (selectedTexture > 0.5) {
+        // Leaving texture
+        transformMatrix = translationMatrix(vec3(0, 0, 6 * time))
+            * scaleMatrix(vec3(1 + pow(2 * time, 2.1), 1 + pow(2 * time, 2.1), 0))
+            * slideScaleMatrix
+            * rotationMatrix(vec3(0.0, 0.0, 1.0), -pow(time, 3) * M_PI)
+            * invertSlideScaleMatrix;
+    } else {
+        // Entering texture
+        transformMatrix = translationMatrix(vec3(0, 0, 28 * (sqrt(time) - 1)))
+            * slideScaleMatrix
+            * rotationMatrix(vec3(0.0, 0.0, 1.0), pow(time - 1, 2) * M_PI)
+            * invertSlideScaleMatrix;
+    }
+    modelViewProjectionMatrix = u_projectionMatrix * modelViewMatrix * transformMatrix;
+    gl_Position = vec4(a_position, 1.0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index d432e72..36ee0e7 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -1804,70 +1804,103 @@ std::shared_ptr<OGLTransitionImpl> makeGlitter()
     return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
 }
 
-std::shared_ptr<OGLTransitionImpl> makeHoneycomb()
+namespace
 {
-    const int NX = 21;
-    const int NY = 21;
 
-    Primitives_t aLeavingSlide;
-    Primitives_t aEnteringSlide;
+class HoneycombTransition : public PermTextureTransition
+{
+public:
+    HoneycombTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
+        : PermTextureTransition(rScene, rSettings)
+    {
+    }
 
-    float fRandom = 0.0f;
+private:
+    virtual GLuint makeShader() const override;
+    virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override;
+    virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override;
 
-    int centerX = NX / 2;
-    int centerY = NY / 2;
+    GLint maHexagonSizeLocation = 0;
+    GLint maTimeLocation = 0;
+    GLint maSelectedTextureLocation = 0;
+};
 
-    for (int y = 0; y < NY+2; y+=2)
-    {
-        for (int x = 0; x < NX+2; x+=2)
-        {
-            Primitive aHexagon;
-            createHexagon(aHexagon, x, y, NX, NY);
+GLuint HoneycombTransition::makeShader() const
+{
+    return OpenGLHelper::LoadShaders( "honeycombVertexShader", "honeycombFragmentShader", "honeycombGeometryShader" );
+}
 
-            fRandom = comphelper::rng::uniform_real_distribution(0.2, std::nextafter(0.7, DBL_MAX));
+void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
+{
+    CHECK_GL_ERROR();
+    PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex );
 
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), 0 , false, -1, 0.1));
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), 90 , true, 0.2, 1.0));
-            if (x <= 0 || y <= 0 || x >= NX || y >= NY)
-            {
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 100), false, 0.1, 1.0));
-            }
-            else if ((centerX - 1 <= x && x <= centerX + 1 && centerY - 1 <= y && y <= centerY + 1 ))
-            {
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 7), true, 0.0, 1.0));
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 100), false, 0.1, 1.0));
-            }
-            else
-            {
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 7), true, 0.0, 1.0));
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 100), false, fRandom, 1.0));
-            }
+    CHECK_GL_ERROR();
+    maHexagonSizeLocation = glGetUniformLocation(m_nProgramObject, "hexagonSize");
+    maTimeLocation = glGetUniformLocation( m_nProgramObject, "time" );
+    maSelectedTextureLocation = glGetUniformLocation( m_nProgramObject, "selectedTexture" );
+    CHECK_GL_ERROR();
 
-            aLeavingSlide.push_back(aHexagon);
+    // We want to see the entering slide behind the leaving one.
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    CHECK_GL_ERROR();
+}
 
-            aHexagon.Operations.clear();
+void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
+                                              double SlideWidthScale, double SlideHeightScale )
+{
+    CHECK_GL_ERROR();
+    applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+    glUniform1f( maTimeLocation, nTime );
 
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), -90 , false, -1, 0.0));
-            aHexagon.Operations.push_back(makeSRotate(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), 90 , true, 0.0, 0.8));
+    // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
 
-            aHexagon.Operations.push_back(makeSTranslate(glm::vec3(-100, 0, -20), false, -1, 0));
+    const float borderSize = 0.15;
 
-            if (x <= 0 || y <= 0 || x >= NX || y >= NY)
-            {
-                fRandom = comphelper::rng::uniform_real_distribution(0.85, std::nextafter(0.95, DBL_MAX));
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0), false, fRandom, 0.95));
-            }
-            else
-            {
-                fRandom = comphelper::rng::uniform_real_distribution(0.3, std::nextafter(0.8, DBL_MAX));
-                aHexagon.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0), false, fRandom, 0.9));
-            }
-            aHexagon.Operations.push_back(makeSTranslate(glm::vec3 (0, 0, 20), true, 0.1, 1.0));
-            aEnteringSlide.push_back(aHexagon);
-        }
-    }
+    CHECK_GL_ERROR();
+    glUniform1f(maSelectedTextureLocation, 0.0);
+    glUniform1f(maHexagonSizeLocation, 1.0 - borderSize);
+    displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
+    glUniform1f(maHexagonSizeLocation, 1.0 + borderSize);
+    displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
+    CHECK_GL_ERROR();
 
-    return makeSimpleTransition(aLeavingSlide, aEnteringSlide);
+    glUniform1f(maSelectedTextureLocation, 1.0);
+    glUniform1f(maHexagonSizeLocation, 1.0 - borderSize);
+    displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
+    glUniform1f(maHexagonSizeLocation, 1.0 + borderSize);
+    displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
+}
+
+std::shared_ptr<OGLTransitionImpl>
+makeHoneycombTransition(const Primitives_t& rLeavingSlidePrimitives,
+                        const Primitives_t& rEnteringSlidePrimitives,
+                        const TransitionSettings& rSettings = TransitionSettings())
+{
+    // The center point should be adjustable by the user, but we have no way to do that in the UI
+    return std::make_shared<HoneycombTransition>(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives),
+                                                 rSettings);
+}
+
+}
+
+std::shared_ptr<OGLTransitionImpl> makeHoneycomb()
+{
+    const int NX = 21;
+    const int NY = 21;
+
+    TransitionSettings aSettings;
+    aSettings.mnRequiredGLVersion = 3.2;
+
+    Primitives_t aSlide;
+    Primitive aHexagon;
+    for (int y = 0; y < NY+2; y+=2)
+        for (int x = 0; x < NX+2; x+=2)
+            aHexagon.pushTriangle(glm::vec2(y % 4 ? fdiv(x, NX) : fdiv(x + 1, NX), fdiv(y, NY)), glm::vec2(1, 0), glm::vec2(0, 0));
+    aSlide.push_back(aHexagon);
+
+    return makeHoneycombTransition(aSlide, aSlide, aSettings);
 }
 
 std::shared_ptr<OGLTransitionImpl> makeNewsflash()
commit 540b64d80f31df0529ad8269cf8b8da743188699
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:33 2015 +0000

    slideshow: Don’t upload matrices to inexistent uniforms
    
    Change-Id: I1572e101be0f5d9267dd48e96212689d80d1d023
    (cherry picked from commit c5228bd0e430c3e45383939cdbd3e6dc7ee9dca6)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 90c2695..d432e72 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -286,8 +286,10 @@ void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthS
     for(size_t i(0); i != rOverallOperations.size(); ++i)
         rOverallOperations[i]->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale);
     CHECK_GL_ERROR();
-    glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false, glm::value_ptr(matrix));
-    CHECK_GL_ERROR();
+    if (m_nOperationsTransformLocation != -1) {
+        glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false, glm::value_ptr(matrix));
+        CHECK_GL_ERROR();
+    }
 }
 
 static void displayPrimitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, std::vector<int>::const_iterator first)
@@ -305,8 +307,10 @@ OGLTransitionImpl::displaySlide(
     CHECK_GL_ERROR();
     glBindTexture(GL_TEXTURE_2D, glSlideTex);
     CHECK_GL_ERROR();
-    glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
-    CHECK_GL_ERROR();
+    if (m_nSceneTransformLocation != -1) {
+        glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
+        CHECK_GL_ERROR();
+    }
     displayPrimitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale, m_nFirstIndices.cbegin());
     CHECK_GL_ERROR();
 }
@@ -326,8 +330,10 @@ void Primitive::display(GLint primitiveTransformLocation, double nTime, double W
     applyOperations( matrix, nTime, WidthScale, HeightScale );
 
     CHECK_GL_ERROR();
-    glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
-    CHECK_GL_ERROR();
+    if (primitiveTransformLocation != -1) {
+        glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
+        CHECK_GL_ERROR();
+    }
     glDrawArrays( GL_TRIANGLES, first, Vertices.size() );
 
     CHECK_GL_ERROR();
@@ -350,8 +356,10 @@ void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransform
     else
         matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1));
     CHECK_GL_ERROR();
-    glUniformMatrix4fv(sceneTransformLocation, 1, false, glm::value_ptr(matrix));
-    CHECK_GL_ERROR();
+    if (sceneTransformLocation != -1) {
+        glUniformMatrix4fv(sceneTransformLocation, 1, false, glm::value_ptr(matrix));
+        CHECK_GL_ERROR();
+    }
     displayPrimitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1, maFirstIndices.cbegin());
     CHECK_GL_ERROR();
 }
commit 0ab9db174ada1268283dca37004eead82876b308
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:32 2015 +0000

    slideshow: Use GL_CLAMP_TO_BORDER for texture wrap
    
    No transition makes use of repeat, and it could lead to some artifacts
    when writing transitions.
    
    Change-Id: Icf6f4f0eb74c28d8c75991e717b6b4ffe9df5060
    (cherry picked from commit b4383be80b0f24ebee670eec558d0963404d40d4)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index 387e96e..6aa726b 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -574,8 +574,8 @@ void OGLTransitionerImpl::createTexture( GLuint* texID,
     glDeleteTextures( 1, texID );
     glGenTextures( 1, texID );
     glBindTexture( GL_TEXTURE_2D, *texID );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
-    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
     CHECK_GL_ERROR();
 
 #if defined( GLX_EXT_texture_from_pixmap )
commit fe9bcdc5a5989f5f56488d75809b040c3f484202
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:31 2015 +0000

    opengl: Add Geometry Shader support to OpenGLHelper
    
    This is the ground work for some later transitions in slideshow.
    
    Change-Id: Ib200cf7fabd579256a5255b0fb5d8c4accf7d24b
    (cherry picked from commit facfbeb5cbff191da956827bc37df7bc74ed0b81)

diff --git a/include/vcl/opengl/OpenGLHelper.hxx b/include/vcl/opengl/OpenGLHelper.hxx
index 1e27411..a7f139c 100644
--- a/include/vcl/opengl/OpenGLHelper.hxx
+++ b/include/vcl/opengl/OpenGLHelper.hxx
@@ -43,7 +43,10 @@ public:
 
     static rtl::OString GetDigest(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const rtl::OString& preamble = "" );
 
-    static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const rtl::OString& preamble = "", const rtl::OString& rDigest = "" );
+    static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const OUString& rGeometryShaderName, const rtl::OString& preamble, const rtl::OString& rDigest );
+    static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const rtl::OString& preamble, const rtl::OString& rDigest );
+    static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName, const OUString& rGeometryShaderName);
+    static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName);
 
     /**
      * The caller is responsible for allocate the memory for the RGBA buffer, before call
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index 9bd4476..387e96e 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -366,10 +366,12 @@ bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presenta
     aDeviceParams[1] >>= aVal;
 
     mpContext = OpenGLContext::Create();
-    mpContext->requestLegacyContext();
 
-    if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) )
-        return false;
+    if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) ) {
+        mpContext->requestLegacyContext();
+        if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) )
+            return false;
+    }
     SAL_INFO("slideshow", "created the context");
 
     CHECK_GL_ERROR();
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index c7cbfa3..f1e1660 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -302,12 +302,15 @@ namespace
 
     OString createFileName( const OUString& rVertexShaderName,
                             const OUString& rFragmentShaderName,
+                            const OUString& rGeometryShaderName,
                             const OString& rDigest )
     {
         OString aFileName;
         aFileName += getCacheFolder();
         aFileName += rtl::OUStringToOString( rVertexShaderName, RTL_TEXTENCODING_UTF8 ) + "-";
         aFileName += rtl::OUStringToOString( rFragmentShaderName, RTL_TEXTENCODING_UTF8 ) + "-";
+        if (!rGeometryShaderName.isEmpty())
+            aFileName += rtl::OUStringToOString( rGeometryShaderName, RTL_TEXTENCODING_UTF8 ) + "-";
         aFileName += rDigest + ".bin";
         return aFileName;
     }
@@ -376,6 +379,7 @@ rtl::OString OpenGLHelper::GetDigest( const OUString& rVertexShaderName,
 
 GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
                                 const OUString& rFragmentShaderName,
+                                const OUString& rGeometryShaderName,
                                 const OString& preamble,
                                 const OString& rDigest)
 {
@@ -383,18 +387,23 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
 
     gbInShaderCompile = true;
 
+    bool bHasGeometryShader = !rGeometryShaderName.isEmpty();
+
     // create the program object
     GLint ProgramID = glCreateProgram();
 
     // read shaders from file
     OString aVertexShaderSource = getShaderSource(rVertexShaderName);
     OString aFragmentShaderSource = getShaderSource(rFragmentShaderName);
+    OString aGeometryShaderSource;
+    if (bHasGeometryShader)
+        aGeometryShaderSource = getShaderSource(rGeometryShaderName);
 
     GLint bBinaryResult = GL_FALSE;
     if( GLEW_ARB_get_program_binary && !rDigest.isEmpty() )
     {
         OString aFileName =
-                createFileName(rVertexShaderName, rFragmentShaderName, rDigest);
+                createFileName(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, rDigest);
         bBinaryResult = loadProgramBinary(ProgramID, aFileName);
         VCL_GL_INFO("Load binary shader from '" << aFileName << "'" << bBinaryResult);
         CHECK_GL_ERROR();
@@ -403,10 +412,16 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
     if( bBinaryResult != GL_FALSE )
         return ProgramID;
 
-    VCL_GL_INFO("Load shader: vertex " << rVertexShaderName << " fragment " << rFragmentShaderName);
+    if (bHasGeometryShader)
+        VCL_GL_INFO("Load shader: vertex " << rVertexShaderName << " fragment " << rFragmentShaderName << " geometry " << rGeometryShaderName);
+    else
+        VCL_GL_INFO("Load shader: vertex " << rVertexShaderName << " fragment " << rFragmentShaderName);
     // Create the shaders
     GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
     GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
+    GLuint GeometryShaderID = 0;
+    if (bHasGeometryShader)
+        GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
 
     GLint Result = GL_FALSE;
 
@@ -436,9 +451,27 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
         return LogCompilerError(FragmentShaderID, "fragment",
                                 rFragmentShaderName, true);
 
+    if (bHasGeometryShader)
+    {
+        // Compile Geometry Shader
+        if( !preamble.isEmpty())
+            addPreamble( aGeometryShaderSource, preamble );
+        char const * GeometrySourcePointer = aGeometryShaderSource.getStr();
+        glShaderSource(GeometryShaderID, 1, &GeometrySourcePointer , nullptr);
+        glCompileShader(GeometryShaderID);
+
+        // Check Geometry Shader
+        glGetShaderiv(GeometryShaderID, GL_COMPILE_STATUS, &Result);
+        if (!Result)
+            return LogCompilerError(GeometryShaderID, "geometry",
+                                    rGeometryShaderName, true);
+    }
+
     // Link the program
     glAttachShader(ProgramID, VertexShaderID);
     glAttachShader(ProgramID, FragmentShaderID);
+    if (bHasGeometryShader)
+        glAttachShader(ProgramID, GeometryShaderID);
 
     if( GLEW_ARB_get_program_binary && !rDigest.isEmpty() )
     {
@@ -451,7 +484,7 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
             return LogCompilerError(ProgramID, "program", "<both>", false);
         }
         OString aFileName =
-                createFileName(rVertexShaderName, rFragmentShaderName, rDigest);
+                createFileName(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, rDigest);
         saveProgramBinary(ProgramID, aFileName);
     }
     else
@@ -461,6 +494,8 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
 
     glDeleteShader(VertexShaderID);
     glDeleteShader(FragmentShaderID);
+    if (bHasGeometryShader)
+        glDeleteShader(GeometryShaderID);
 
     // Check the program
     glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
@@ -476,6 +511,27 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
     return ProgramID;
 }
 
+GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
+                                const OUString& rFragmentShaderName,
+                                const OString& preamble,
+                                const OString& rDigest)
+{
+    return LoadShaders(rVertexShaderName, rFragmentShaderName, OUString(), preamble, rDigest);
+}
+
+GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
+                                const OUString& rFragmentShaderName,
+                                const OUString& rGeometryShaderName)
+{
+    return LoadShaders(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, OString(), OString());
+}
+
+GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
+                                const OUString& rFragmentShaderName)
+{
+    return LoadShaders(rVertexShaderName, rFragmentShaderName, OUString(), "", "");
+}
+
 void OpenGLHelper::ConvertBitmapExToRGBATextureBuffer(const BitmapEx& rBitmapEx, sal_uInt8* o_pRGBABuffer, const bool bFlip)
 {
     long nBmpWidth = rBitmapEx.GetSizePixel().Width();
commit 1a4ce718c884a0a4568fb157617bc5fd5f71b9cd
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:30 2015 +0000

    slideshow: Remove extraneous checks for the program object.
    
    Change-Id: Ice61bfbd75aafd4197584c34ef7fbed80c20c184
    (cherry picked from commit 129b8b85c945091665ad3ae1c4fa3b6d9a157d25)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index e7065c8..90c2695 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -143,67 +143,65 @@ bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
     if (!m_nProgramObject)
         return false;
 
+    CHECK_GL_ERROR();
+    glUseProgram( m_nProgramObject );
+    CHECK_GL_ERROR();
+
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
     for(size_t i(0); i != rSceneObjects.size(); ++i) {
         rSceneObjects[i]->prepare(m_nProgramObject);
     }
 
-    CHECK_GL_ERROR();
-    if( m_nProgramObject ) {
-        glUseProgram( m_nProgramObject );
+    GLint location = glGetUniformLocation( m_nProgramObject, "leavingSlideTexture" );
+    if( location != -1 ) {
+        glUniform1i( location, 0 );  // texture unit 0
         CHECK_GL_ERROR();
+    }
 
-        GLint location = glGetUniformLocation( m_nProgramObject, "leavingSlideTexture" );
-        if( location != -1 ) {
-            glUniform1i( location, 0 );  // texture unit 0
-            CHECK_GL_ERROR();
-        }
-
-        location = glGetUniformLocation( m_nProgramObject, "enteringSlideTexture" );
-        if( location != -1 ) {
-            glUniform1i( location, 2 );  // texture unit 2
-            CHECK_GL_ERROR();
-        }
-
-        uploadModelViewProjectionMatrices();
+    location = glGetUniformLocation( m_nProgramObject, "enteringSlideTexture" );
+    if( location != -1 ) {
+        glUniform1i( location, 2 );  // texture unit 2
+        CHECK_GL_ERROR();
+    }
 
-        m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
-        m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
-        m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
+    uploadModelViewProjectionMatrices();
 
-        glGenVertexArrays(1, &m_nVertexArrayObject);
-        glBindVertexArray(m_nVertexArrayObject);
+    m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
+    m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
+    m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
 
-        glGenBuffers(1, &m_nVertexBufferObject);
-        glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
+    glGenVertexArrays(1, &m_nVertexArrayObject);
+    glBindVertexArray(m_nVertexArrayObject);
 
-        // In practice both leaving and entering slides share the same primitives.
-        m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
+    glGenBuffers(1, &m_nVertexBufferObject);
+    glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
 
-        // Attribute bindings
-        m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
-        if (m_nPositionLocation != -1) {
-            glEnableVertexAttribArray(m_nPositionLocation);
-            glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
-            CHECK_GL_ERROR();
-        }
+    // In practice both leaving and entering slides share the same primitives.
+    m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
 
-        m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal");
-        if (m_nNormalLocation != -1) {
-            glEnableVertexAttribArray(m_nNormalLocation);
-            glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
-            CHECK_GL_ERROR();
-        }
+    // Attribute bindings
+    m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
+    if (m_nPositionLocation != -1) {
+        glEnableVertexAttribArray(m_nPositionLocation);
+        glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
+        CHECK_GL_ERROR();
+    }
 
-        m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord");
-        if (m_nTexCoordLocation != -1) {
-            glEnableVertexAttribArray(m_nTexCoordLocation);
-            glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
-            CHECK_GL_ERROR();
-        }
+    m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal");
+    if (m_nNormalLocation != -1) {
+        glEnableVertexAttribArray(m_nNormalLocation);
+        glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
+        CHECK_GL_ERROR();
+    }
 
-        glBindBuffer(GL_ARRAY_BUFFER, 0);
+    m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord");
+    if (m_nTexCoordLocation != -1) {
+        glEnableVertexAttribArray(m_nTexCoordLocation);
+        glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
+        CHECK_GL_ERROR();
     }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
     CHECK_GL_ERROR();
 
     prepareTransition( glLeavingSlideTex, glEnteringSlideTex );
@@ -252,12 +250,9 @@ void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTe
     CHECK_GL_ERROR();
     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
 
-    if( m_nProgramObject ) {
-        GLint location = glGetUniformLocation( m_nProgramObject, "time" );
-        if( location != -1 ) {
-            glUniform1f( location, nTime );
-        }
-    }
+    GLint location = glGetUniformLocation( m_nProgramObject, "time" );
+    if( location != -1 )
+        glUniform1f( location, nTime );
 
     glActiveTexture( GL_TEXTURE2 );
     glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
@@ -1418,20 +1413,18 @@ static void initPermTexture(GLuint *texID)
 void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32 )
 {
     CHECK_GL_ERROR();
-    if( m_nProgramObject ) {
-        GLint location = glGetUniformLocation( m_nProgramObject, "permTexture" );
-        if( location != -1 ) {
-            glActiveTexture(GL_TEXTURE1);
-            CHECK_GL_ERROR();
-            if( !m_nHelperTexture )
-                initPermTexture( &m_nHelperTexture );
-
-            glActiveTexture(GL_TEXTURE0);
-            CHECK_GL_ERROR();
-
-            glUniform1i( location, 1 );  // texture unit 1
-            CHECK_GL_ERROR();
-        }
+    GLint location = glGetUniformLocation( m_nProgramObject, "permTexture" );
+    if( location != -1 ) {
+        glActiveTexture(GL_TEXTURE1);
+        CHECK_GL_ERROR();
+        if( !m_nHelperTexture )
+            initPermTexture( &m_nHelperTexture );
+
+        glActiveTexture(GL_TEXTURE0);
+        CHECK_GL_ERROR();
+
+        glUniform1i( location, 1 );  // texture unit 1
+        CHECK_GL_ERROR();
     }
     CHECK_GL_ERROR();
 }
@@ -1601,20 +1594,14 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32
     PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex );
     CHECK_GL_ERROR();
 
-    if (m_nProgramObject)
-    {
-        mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo");
-        CHECK_GL_ERROR();
-
-        glUseProgram(m_nProgramObject);
-        CHECK_GL_ERROR();
+    mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo");
+    CHECK_GL_ERROR();
 
-        GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
-        CHECK_GL_ERROR();
+    GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles");
+    CHECK_GL_ERROR();
 
-        glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
-        CHECK_GL_ERROR();
-    }
+    glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles));
+    CHECK_GL_ERROR();
 
     glGenBuffers(1, &mnTileInfoBuffer);
     CHECK_GL_ERROR();
@@ -1712,17 +1699,11 @@ GLuint RippleTransition::makeShader() const
 
 void RippleTransition::prepareTransition( sal_Int32, sal_Int32 )
 {
-    if (m_nProgramObject)
-    {
-        glUseProgram(m_nProgramObject);
-        CHECK_GL_ERROR();
-
-        GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center");
-        CHECK_GL_ERROR();
+    GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center");
+    CHECK_GL_ERROR();
 
-        glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter));
-        CHECK_GL_ERROR();
-    }
+    glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter));
+    CHECK_GL_ERROR();
 }
 
 std::shared_ptr<OGLTransitionImpl>
commit c319cb0023ae4ab496b7d03f72c9f19864f29b57
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:29 2015 +0000

    slideshow: Don’t crash when a transition fails to initialize.
    
    Instead replace it with no transition at all.
    
    Change-Id: If7085e2ecd79eda80097f96bebbb2f9d11161c22
    (cherry picked from commit 9e991f43e57d7a74fa2db10a46021cbe2218ac5a)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index d277aa2..e7065c8 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -137,9 +137,11 @@ static std::vector<int> uploadPrimitives(const Primitives_t& primitives)
     return indices;
 }
 
-void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
+bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
 {
     m_nProgramObject = makeShader();
+    if (!m_nProgramObject)
+        return false;
 
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
     for(size_t i(0); i != rSceneObjects.size(); ++i) {
@@ -205,6 +207,7 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
     CHECK_GL_ERROR();
 
     prepareTransition( glLeavingSlideTex, glEnteringSlideTex );
+    return true;
 }
 
 void OGLTransitionImpl::finish()
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index f339685..2b9daa5 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -140,7 +140,7 @@ public:
 
     /** Prepare transition.
       */
-    void prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex );
+    bool prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex );
     /** Display a step of the transition.
       */
     void display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight );
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index 5788a0c..9bd4476 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -175,7 +175,7 @@ class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable,
 {
 public:
     OGLTransitionerImpl();
-    void setTransition( std::shared_ptr<OGLTransitionImpl> pOGLTransition );
+    bool setTransition( std::shared_ptr<OGLTransitionImpl> pOGLTransition );
     bool initialize( const Reference< presentation::XSlideShowView >& xView,
             const Reference< rendering::XBitmap >& xLeavingSlide,
             const Reference< rendering::XBitmap >& xEnteringSlide );
@@ -224,7 +224,7 @@ private:
     */
     void GLInitSlides();
 
-    void impl_prepareTransition();
+    bool impl_prepareTransition();
     void impl_finishTransition();
 
 private:
@@ -529,10 +529,11 @@ void OGLTransitionerImpl::impl_prepareSlides()
 #endif
 }
 
-void OGLTransitionerImpl::impl_prepareTransition()
+bool OGLTransitionerImpl::impl_prepareTransition()
 {
     if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
-        mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL );
+        return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL );
+    return false;
 }
 
 void OGLTransitionerImpl::impl_finishTransition()
@@ -541,15 +542,21 @@ void OGLTransitionerImpl::impl_finishTransition()
         mpTransition->finish();
 }
 
-void OGLTransitionerImpl::setTransition( std::shared_ptr<OGLTransitionImpl> pTransition )
+bool OGLTransitionerImpl::setTransition( std::shared_ptr<OGLTransitionImpl> pTransition )
 {
     if ( mpTransition ) // already initialized
-        return;
+        return true;
 
     mpTransition = pTransition;
 
+    bool succeeded = impl_prepareTransition();
+    if (!succeeded) {
+        mpTransition = nullptr;
+        return false;
+    }
+
     impl_prepareSlides();
-    impl_prepareTransition();
+    return true;
 }
 
 void OGLTransitionerImpl::createTexture( GLuint* texID,
@@ -1138,7 +1145,7 @@ void OGLTransitionerImpl::GLInitSlides()
 {
     osl::MutexGuard const guard( m_aMutex );
 
-    if (isDisposed() || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
+    if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
         return;
 
 #if OSL_DEBUG_LEVEL > 1
@@ -1187,7 +1194,7 @@ void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeExc
 #endif
     osl::MutexGuard const guard( m_aMutex );
 
-    if (isDisposed() || !mbValidOpenGLContext || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
+    if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
         return;
 
     mpContext->makeCurrent();
@@ -1197,14 +1204,11 @@ void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeExc
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     CHECK_GL_ERROR();
 
-    if(mpTransition)
-    {
-        const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
-        mpTransition->display( nTime, maLeavingSlideGL, maEnteringSlideGL,
-                              maSlideSize.Width, maSlideSize.Height,
-                              static_cast<double>(rGLWindow.Width),
-                              static_cast<double>(rGLWindow.Height) );
-    }
+    const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
+    mpTransition->display( nTime, maLeavingSlideGL, maEnteringSlideGL,
+                          maSlideSize.Width, maSlideSize.Height,
+                          static_cast<double>(rGLWindow.Width),
+                          static_cast<double>(rGLWindow.Height) );
 
     mpContext->swapBuffers();
 
@@ -1502,11 +1506,9 @@ public:
             pTransition = makeNewsflash();
         }
 
-        if ( !pTransition )
+        if ( !pTransition || !xRes->setTransition(pTransition) )
             return uno::Reference< presentation::XTransition >();
 
-        xRes->setTransition( pTransition );
-
         return uno::Reference<presentation::XTransition>(xRes.get());
     }
 };
commit 130c85b54928c025d18bc19a2a155eb85b742675
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:28 2015 +0000

    slideshow: Only upload vertex data on prepare
    
    Change-Id: If87f441607adf2ed0aa31023352774e7372b7edb
    (cherry picked from commit 463739f44e75798dbdb1239c7374ed5254a9e9d4)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 649190a..d277aa2 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -111,15 +111,41 @@ void OGLTransitionImpl::uploadModelViewProjectionMatrices()
     }
 }
 
+static std::vector<int> uploadPrimitives(const Primitives_t& primitives)
+{
+    int size = 0;
+    for (const Primitive& primitive: primitives)
+        size += primitive.getVerticesSize();
+
+    CHECK_GL_ERROR();
+    glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
+    CHECK_GL_ERROR();
+    Vertex *buf = static_cast<Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
+
+    std::vector<int> indices;
+    int last_pos = 0;
+    for (const Primitive& primitive: primitives) {
+        indices.push_back(last_pos);
+        int num = primitive.writeVertices(buf);
+        buf += num;
+        last_pos += num;
+    }
+
+    CHECK_GL_ERROR();
+    glUnmapBuffer(GL_ARRAY_BUFFER);
+    CHECK_GL_ERROR();
+    return indices;
+}
+
 void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
 {
+    m_nProgramObject = makeShader();
+
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
     for(size_t i(0); i != rSceneObjects.size(); ++i) {
-        rSceneObjects[i]->prepare();
+        rSceneObjects[i]->prepare(m_nProgramObject);
     }
 
-    m_nProgramObject = makeShader();
-
     CHECK_GL_ERROR();
     if( m_nProgramObject ) {
         glUseProgram( m_nProgramObject );
@@ -149,6 +175,9 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
         glGenBuffers(1, &m_nVertexBufferObject);
         glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
 
+        // In practice both leaving and entering slides share the same primitives.
+        m_nFirstIndices = uploadPrimitives(getScene().getLeavingSlide());
+
         // Attribute bindings
         m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
         if (m_nPositionLocation != -1) {
@@ -170,6 +199,8 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
             glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
             CHECK_GL_ERROR();
         }
+
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
     }
     CHECK_GL_ERROR();
 
@@ -240,6 +271,7 @@ void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_
     const double SlideHeightScale = SlideHeight/DispHeight;
 
     CHECK_GL_ERROR();
+    glBindVertexArray(m_nVertexArrayObject);
     prepare( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
 
     CHECK_GL_ERROR();
@@ -260,30 +292,8 @@ void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthS
     CHECK_GL_ERROR();
 }
 
-static void display_primitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale)
+static void displayPrimitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, std::vector<int>::const_iterator first)
 {
-    int size = 0;
-    for (const Primitive& primitive: primitives)
-        size += primitive.getVerticesSize();
-
-    CHECK_GL_ERROR();
-    glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STREAM_DRAW);
-    CHECK_GL_ERROR();
-    Vertex *buf = static_cast<Vertex*>(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
-
-    std::vector<int> first_elements;
-    int last_pos = 0;
-    for (const Primitive& primitive: primitives) {
-        first_elements.push_back(last_pos);
-        int num = primitive.writeVertices(buf);
-        buf += num;
-        last_pos += num;
-    }
-    auto first = first_elements.begin();
-
-    CHECK_GL_ERROR();
-    glUnmapBuffer(GL_ARRAY_BUFFER);
-
     for (const Primitive& primitive: primitives)
         primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
 }
@@ -299,7 +309,7 @@ OGLTransitionImpl::displaySlide(
     CHECK_GL_ERROR();
     glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
     CHECK_GL_ERROR();
-    display_primitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale);
+    displayPrimitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale, m_nFirstIndices.cbegin());
     CHECK_GL_ERROR();
 }
 
@@ -344,7 +354,7 @@ void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransform
     CHECK_GL_ERROR();
     glUniformMatrix4fv(sceneTransformLocation, 1, false, glm::value_ptr(matrix));
     CHECK_GL_ERROR();
-    display_primitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1);
+    displayPrimitives(maPrimitives, primitiveTransformLocation, nTime, 1, 1, maFirstIndices.cbegin());
     CHECK_GL_ERROR();
 }
 
@@ -370,22 +380,26 @@ class Iris : public SceneObject
 public:
     Iris() = default;
 
-    virtual void prepare() override;
+    virtual void prepare(GLuint program) override;
     virtual void display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight) const override;
     virtual void finish() override;
 
 private:
     GLuint maTexture = 0;
+    GLuint maBuffer = 0;
+    GLuint maVertexArray = 0;
 };
 
 void Iris::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) const
 {
+    glBindVertexArray(maVertexArray);
+    CHECK_GL_ERROR();
     glBindTexture(GL_TEXTURE_2D, maTexture);
     CHECK_GL_ERROR();
     SceneObject::display(sceneTransformLocation, primitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
 }
 
-void Iris::prepare()
+void Iris::prepare(GLuint program)
 {
     CHECK_GL_ERROR();
     static const GLubyte img[3] = { 80, 80, 80 };
@@ -395,14 +409,49 @@ void Iris::prepare()
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
     CHECK_GL_ERROR();
+
+    glGenVertexArrays(1, &maVertexArray);
+    glBindVertexArray(maVertexArray);
+
+    glGenBuffers(1, &maBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, maBuffer);
+    maFirstIndices = uploadPrimitives(maPrimitives);
+
+    // Attribute bindings
+    GLint location = glGetAttribLocation(program, "a_position");
+    if (location != -1) {
+        glEnableVertexAttribArray(location);
+        glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
+        CHECK_GL_ERROR();
+    }
+
+    location = glGetAttribLocation(program, "a_normal");
+    if (location != -1) {
+        glEnableVertexAttribArray(location);
+        glVertexAttribPointer( location, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
+        CHECK_GL_ERROR();
+    }
+
+    location = glGetAttribLocation(program, "a_texCoord");
+    if (location != -1) {
+        glEnableVertexAttribArray(location);
+        glVertexAttribPointer( location, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
+        CHECK_GL_ERROR();
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
 void Iris::finish()
 {
     CHECK_GL_ERROR();
+    glDeleteBuffers(1, &maBuffer);
+    CHECK_GL_ERROR();
+    glDeleteVertexArrays(1, &maVertexArray);
+    CHECK_GL_ERROR();
     glDeleteTextures(1, &maTexture);
     CHECK_GL_ERROR();
 }
@@ -1529,7 +1578,7 @@ void VortexTransition::prepare( double, double, double, double, double )
     glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
     CHECK_GL_ERROR();
 
-    glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
     CHECK_GL_ERROR();
 }
 
@@ -1592,7 +1641,7 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32
     glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW);
     CHECK_GL_ERROR();
 
-    glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
     CHECK_GL_ERROR();
 }
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index 7568006..f339685 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -230,6 +230,8 @@ private:
 
     GLuint m_nVertexArrayObject = -1;
 
+    std::vector<int> m_nFirstIndices;
+
 protected:
     /** GLSL program object
      */
@@ -273,7 +275,7 @@ public:
     SceneObject();
     virtual ~SceneObject();
 
-    virtual void prepare() {}
+    virtual void prepare(GLuint /* program */) {}
     virtual void display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) const;
     virtual void finish() {}
 
@@ -283,6 +285,7 @@ protected:
     /** All the surrounding scene primitives
     */
     Primitives_t maPrimitives;
+    std::vector<int> maFirstIndices;
 };
 
 struct Vertex
commit acf1765797a558bf6c903f9620b669a98454e06e
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:27 2015 +0000

    slideshow: Fix what was remaining to be able to use a core context
    
    Change-Id: Ifb22c75c77d6bb5d3f144a1ed92bbcdf8d1112fd
    (cherry picked from commit c831e4851f35ddef5ef45062ba291d07dda4b1b4)

diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 09ccc6d..649190a 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -143,6 +143,9 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
         m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
         m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
 
+        glGenVertexArrays(1, &m_nVertexArrayObject);
+        glBindVertexArray(m_nVertexArrayObject);
+
         glGenBuffers(1, &m_nVertexBufferObject);
         glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
 
@@ -186,6 +189,8 @@ void OGLTransitionImpl::finish()
     if( m_nProgramObject ) {
         glDeleteBuffers(1, &m_nVertexBufferObject);
         m_nVertexBufferObject = 0;
+        glDeleteVertexArrays(1, &m_nVertexArrayObject);
+        m_nVertexArrayObject = 0;
         glDeleteProgram( m_nProgramObject );
         m_nProgramObject = 0;
     }
@@ -220,7 +225,6 @@ void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTe
         }
     }
 
-    glEnable(GL_TEXTURE_2D);
     glActiveTexture( GL_TEXTURE2 );
     glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
     glActiveTexture( GL_TEXTURE0 );
@@ -301,9 +305,8 @@ OGLTransitionImpl::displaySlide(
 
 void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
 {
-    CHECK_GL_ERROR();
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
-    glEnable(GL_TEXTURE_2D);
+    CHECK_GL_ERROR();
     for(size_t i(0); i != rSceneObjects.size(); ++i)
         rSceneObjects[i]->display(m_nSceneTransformLocation, m_nPrimitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
     CHECK_GL_ERROR();
@@ -389,7 +392,7 @@ void Iris::prepare()
 
     glGenTextures(1, &maTexture);
     glBindTexture(GL_TEXTURE_2D, maTexture);
-    glTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
@@ -749,8 +752,6 @@ void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTe
 {
     applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
 
-    glEnable(GL_TEXTURE_2D);
-
     if( nTime > .5) {
         displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
         displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
@@ -1528,7 +1529,7 @@ void VortexTransition::prepare( double, double, double, double, double )
     glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
     CHECK_GL_ERROR();
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
     CHECK_GL_ERROR();
 }
 
@@ -1591,7 +1592,7 @@ void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32
     glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW);
     CHECK_GL_ERROR();
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
     CHECK_GL_ERROR();
 }
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index 0bd15d6..7568006 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -228,12 +228,16 @@ private:
     GLint m_nNormalLocation = -1;
     GLint m_nTexCoordLocation = -1;
 
-    GLuint m_nVertexBufferObject = -1;
+    GLuint m_nVertexArrayObject = -1;
 
 protected:
     /** GLSL program object
      */
     GLuint m_nProgramObject = 0;
+
+    /** VBO in which to put primitive data
+     */
+    GLuint m_nVertexBufferObject = -1;
 };
 
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index 5d6a855..5788a0c 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -984,7 +984,7 @@ void OGLTransitionerImpl::impl_createTexture(
             maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
                 data,
                 getOGLColorSpace()));
-        buildMipmaps(     4,
+        buildMipmaps(     GL_RGBA,
                           maSlideSize.Width,
                           maSlideSize.Height,
                           GL_RGBA,
commit c670b677024aed17a5d5a96388be734754f99449
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:26 2015 +0000

    slideshow: Fix lighting in the Vortex transition
    
    Change-Id: I870ef7885fe569c89bde63a70ef038c4133ffbfd
    (cherry picked from commit 859e64aa730fa380ecaab92527e2cfe97c299a4f)

diff --git a/slideshow/opengl/vortexFragmentShader.glsl b/slideshow/opengl/vortexFragmentShader.glsl
index 9b7741a..3e104b2 100755
--- a/slideshow/opengl/vortexFragmentShader.glsl
+++ b/slideshow/opengl/vortexFragmentShader.glsl
@@ -14,19 +14,27 @@ uniform sampler2D enteringSlideTexture;
 uniform float time;
 varying vec2 v_texturePosition;
 varying float v_textureSelect;
+varying vec3 v_normal;
 
 void main()
 {
+    vec3 lightVector = vec3(0.0, 0.0, 1.0);
+    float light = abs(dot(lightVector, v_normal));
+    vec4 fragment;
+
     if (v_textureSelect == 0)
     {
-        gl_FragColor = texture2D(leavingSlideTexture, v_texturePosition);
+        fragment = texture2D(leavingSlideTexture, v_texturePosition);
     }
     else
     {
         vec2 pos = v_texturePosition;
         pos.x = 1 - pos.x;
-        gl_FragColor = texture2D(enteringSlideTexture, pos);
+        fragment = texture2D(enteringSlideTexture, pos);
     }
+
+    vec4 black = vec4(0.0, 0.0, 0.0, fragment.a);
+    gl_FragColor = mix(black, fragment, light);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/vortexVertexShader.glsl b/slideshow/opengl/vortexVertexShader.glsl
index ff86546..b2f94c5 100755
--- a/slideshow/opengl/vortexVertexShader.glsl
+++ b/slideshow/opengl/vortexVertexShader.glsl
@@ -11,11 +11,23 @@
 
 #define M_PI 3.1415926535897932384626433832795
 
+attribute vec3 a_position;
+attribute vec3 a_normal;
+attribute vec2 a_texCoord;
+
+uniform mat4 u_projectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform mat4 u_sceneTransformMatrix;
+uniform mat4 u_primitiveTransformMatrix;
+uniform mat4 u_operationsTransformMatrix;
+
+varying vec2 v_texturePosition;
+varying vec3 v_normal;
+
 uniform float time;
 uniform ivec2 numTiles;
 uniform sampler2D permTexture;
 attribute float tileInfo;
-varying vec2 v_texturePosition;
 varying float v_textureSelect;
 
 float snoise(vec2 p)
@@ -38,7 +50,8 @@ mat4 rotationMatrix(vec3 axis, float angle)
 
 void main( void )
 {
-    vec4 v = gl_Vertex;
+    vec4 v = vec4(a_position, 1.0);
+    vec4 normal = vec4(a_normal, 1.0);
 
     // Not sure it this is like what it should eventually be; just
     // experimenting to get at least something.
@@ -82,7 +95,9 @@ void main( void )
         float rotation = direction * (time - startTime) / (endTime - startTime);
 
         // Avoid z fighting
-        v = rotationMatrix(vec3(0, 1, 0), max(min(rotation, ALMOST_ONE), -ALMOST_ONE)*M_PI) * v;
+        mat4 matrix = rotationMatrix(vec3(0, 1, 0), max(min(rotation, ALMOST_ONE), -ALMOST_ONE)*M_PI);
+        v = matrix * v;
+        normal = matrix * normal;
 
         v_textureSelect = float(rotation > 0.5 || rotation < -0.5);
     }
@@ -91,14 +106,19 @@ void main( void )
         // At end location. Tile is 180 degrees rotated
 
         // Avoid z fighting
-        v = rotationMatrix(vec3(0, 1, 0), direction*ALMOST_ONE*M_PI) * v;
+        mat4 matrix = rotationMatrix(vec3(0, 1, 0), direction*ALMOST_ONE*M_PI);
+        v = matrix * v;
+        normal = matrix * normal;
 
         v_textureSelect = 1;
     }
 
-    gl_Position = gl_ModelViewProjectionMatrix * v;
+    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
+    gl_Position = u_projectionMatrix * modelViewMatrix * v;
 
-    v_texturePosition = gl_MultiTexCoord0.xy;
+    v_texturePosition = a_texCoord;
+    v_normal = normalize(normalMatrix * vec3(normal));
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 2ad7c8f76e29d9c7dfc3c6840cc383ef74d22310
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:25 2015 +0000

    slideshow: Remove the last legacy uniforms
    
    Change-Id: If5f7368bf53dd59e66e990e4f2c57b6ee2cba44b
    (cherry picked from commit a74e8ab7841a67ae353c537d449d27a931ba67d8)

diff --git a/slideshow/opengl/basicVertexShader.glsl b/slideshow/opengl/basicVertexShader.glsl
index ebd5dbc..cd68b16 100644
--- a/slideshow/opengl/basicVertexShader.glsl
+++ b/slideshow/opengl/basicVertexShader.glsl
@@ -28,6 +28,10 @@
 
 #version 120
 
+attribute vec3 a_position;
+attribute vec3 a_normal;
+attribute vec2 a_texCoord;
+
 uniform mat4 u_projectionMatrix;
 uniform mat4 u_modelViewMatrix;
 uniform mat4 u_sceneTransformMatrix;
@@ -41,9 +45,9 @@ void main( void )
 {
     mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
     mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
-    gl_Position = u_projectionMatrix * modelViewMatrix * gl_Vertex;
-    v_texturePosition = gl_MultiTexCoord0.xy;
-    v_normal = normalize(normalMatrix * gl_Normal);
+    gl_Position = u_projectionMatrix * modelViewMatrix * vec4(a_position, 1.0);
+    v_texturePosition = a_texCoord;
+    v_normal = normalize(normalMatrix * a_normal);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/reflectionVertexShader.glsl b/slideshow/opengl/reflectionVertexShader.glsl
index 566eafa..9674888 100644
--- a/slideshow/opengl/reflectionVertexShader.glsl
+++ b/slideshow/opengl/reflectionVertexShader.glsl
@@ -28,6 +28,10 @@
 
 #version 130
 
+attribute vec3 a_position;
+attribute vec3 a_normal;
+attribute vec2 a_texCoord;
+
 uniform mat4 u_projectionMatrix;
 uniform mat4 u_modelViewMatrix;
 uniform mat4 u_sceneTransformMatrix;
@@ -42,9 +46,9 @@ void main( void )
 {
     mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
     mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
-    gl_Position = u_projectionMatrix * modelViewMatrix * gl_Vertex;
-    v_texturePosition = gl_MultiTexCoord0.xy;
-    v_normal = normalize(normalMatrix * gl_Normal);
+    gl_Position = u_projectionMatrix * modelViewMatrix * vec4(a_position, 1.0);
+    v_texturePosition = a_texCoord;
+    v_normal = normalize(normalMatrix * a_normal);
     v_isShadow = float(gl_VertexID >= 6);
 }
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 025c980..09ccc6d 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -142,6 +142,31 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
         m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
         m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
         m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
+
+        glGenBuffers(1, &m_nVertexBufferObject);
+        glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject);
+
+        // Attribute bindings
+        m_nPositionLocation = glGetAttribLocation(m_nProgramObject, "a_position");
+        if (m_nPositionLocation != -1) {
+            glEnableVertexAttribArray(m_nPositionLocation);
+            glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
+            CHECK_GL_ERROR();
+        }
+
+        m_nNormalLocation = glGetAttribLocation(m_nProgramObject, "a_normal");
+        if (m_nNormalLocation != -1) {
+            glEnableVertexAttribArray(m_nNormalLocation);
+            glVertexAttribPointer( m_nNormalLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, normal)) );
+            CHECK_GL_ERROR();
+        }
+
+        m_nTexCoordLocation = glGetAttribLocation(m_nProgramObject, "a_texCoord");
+        if (m_nTexCoordLocation != -1) {
+            glEnableVertexAttribArray(m_nTexCoordLocation);
+            glVertexAttribPointer( m_nTexCoordLocation, 2, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
+            CHECK_GL_ERROR();
+        }
     }
     CHECK_GL_ERROR();
 
@@ -159,6 +184,8 @@ void OGLTransitionImpl::finish()
 
     CHECK_GL_ERROR();
     if( m_nProgramObject ) {
+        glDeleteBuffers(1, &m_nVertexBufferObject);
+        m_nVertexBufferObject = 0;
         glDeleteProgram( m_nProgramObject );
         m_nProgramObject = 0;
     }
@@ -231,12 +258,6 @@ void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthS
 
 static void display_primitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale)
 {
-    CHECK_GL_ERROR();
-    GLuint buffer;
-    glGenBuffers(1, &buffer);
-    CHECK_GL_ERROR();
-    glBindBuffer(GL_ARRAY_BUFFER, buffer);
-
     int size = 0;
     for (const Primitive& primitive: primitives)
         size += primitive.getVerticesSize();
@@ -259,26 +280,8 @@ static void display_primitives(const Primitives_t& primitives, GLint primitiveTr
     CHECK_GL_ERROR();
     glUnmapBuffer(GL_ARRAY_BUFFER);
 
-    // State initialization
-    // TODO: move that elsewhere.
-    CHECK_GL_ERROR();
-    glEnableClientState( GL_VERTEX_ARRAY );
-    CHECK_GL_ERROR();
-    glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)) );
-    CHECK_GL_ERROR();
-    glEnableClientState( GL_NORMAL_ARRAY );
-    CHECK_GL_ERROR();
-    glNormalPointer( GL_FLOAT , sizeof(Vertex) , reinterpret_cast<void*>(offsetof(Vertex, normal)) );
-    CHECK_GL_ERROR();
-    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-    CHECK_GL_ERROR();
-    glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
-
     for (const Primitive& primitive: primitives)
         primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
-
-    CHECK_GL_ERROR();
-    glDeleteBuffers(1, &buffer);
 }
 
 void
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index c972ff3..0bd15d6 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -216,17 +216,19 @@ private:
      */
     void uploadModelViewProjectionMatrices();
 
-    /** Uniform location for primitive transform
+    /** Uniform locations for transform matrices
      */
     GLint m_nPrimitiveTransformLocation = -1;
-
-    /** Uniform location for scene transform
-     */
     GLint m_nSceneTransformLocation = -1;
+    GLint m_nOperationsTransformLocation = -1;
 
-    /** Uniform location for operations transform
+    /** Per-vertex attribute locations
      */
-    GLint m_nOperationsTransformLocation = -1;
+    GLint m_nPositionLocation = -1;
+    GLint m_nNormalLocation = -1;
+    GLint m_nTexCoordLocation = -1;
+
+    GLuint m_nVertexBufferObject = -1;
 
 protected:
     /** GLSL program object
commit 793c0050e0da1c196381a019250333e889cbc68d
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:24 2015 +0000

    slideshow: Upload the projection and modelview matrices as uniforms
    
    Change-Id: I9d6c3ad0d2cc2f691afb2c8622471286f8a5e1c7
    (cherry picked from commit 7d1c123a55d222868e27673685c25d62b1e96cd5)

diff --git a/slideshow/opengl/basicVertexShader.glsl b/slideshow/opengl/basicVertexShader.glsl
index a4b258c..ebd5dbc 100644
--- a/slideshow/opengl/basicVertexShader.glsl
+++ b/slideshow/opengl/basicVertexShader.glsl
@@ -28,6 +28,8 @@
 
 #version 120
 
+uniform mat4 u_projectionMatrix;
+uniform mat4 u_modelViewMatrix;
 uniform mat4 u_sceneTransformMatrix;
 uniform mat4 u_primitiveTransformMatrix;
 uniform mat4 u_operationsTransformMatrix;
@@ -37,9 +39,9 @@ varying vec3 v_normal;
 
 void main( void )
 {
-    mat4 modelViewMatrix = gl_ModelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
     mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
-    gl_Position = gl_ProjectionMatrix * modelViewMatrix * gl_Vertex;
+    gl_Position = u_projectionMatrix * modelViewMatrix * gl_Vertex;
     v_texturePosition = gl_MultiTexCoord0.xy;
     v_normal = normalize(normalMatrix * gl_Normal);
 }
diff --git a/slideshow/opengl/reflectionVertexShader.glsl b/slideshow/opengl/reflectionVertexShader.glsl
index ad9b033..566eafa 100644
--- a/slideshow/opengl/reflectionVertexShader.glsl
+++ b/slideshow/opengl/reflectionVertexShader.glsl
@@ -28,6 +28,8 @@
 
 #version 130
 
+uniform mat4 u_projectionMatrix;
+uniform mat4 u_modelViewMatrix;
 uniform mat4 u_sceneTransformMatrix;
 uniform mat4 u_primitiveTransformMatrix;
 uniform mat4 u_operationsTransformMatrix;
@@ -38,9 +40,9 @@ varying float v_isShadow;
 
 void main( void )
 {
-    mat4 modelViewMatrix = gl_ModelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
     mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
-    gl_Position = gl_ProjectionMatrix * modelViewMatrix * gl_Vertex;
+    gl_Position = u_projectionMatrix * modelViewMatrix * gl_Vertex;
     v_texturePosition = gl_MultiTexCoord0.xy;
     v_normal = normalize(normalMatrix * gl_Normal);
     v_isShadow = float(gl_VertexID >= 6);
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index aab8508..025c980 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -74,6 +74,43 @@ void OGLTransitionImpl::setScene(TransitionScene const& rScene)
     maScene = rScene;
 }
 
+void OGLTransitionImpl::uploadModelViewProjectionMatrices()
+{
+    double EyePos(10.0);
+    double RealF(1.0);
+    double RealN(-1.0);
+    double RealL(-1.0);
+    double RealR(1.0);
+    double RealB(-1.0);
+    double RealT(1.0);
+    double ClipN(EyePos+5.0*RealN);
+    double ClipF(EyePos+15.0*RealF);
+    double ClipL(RealL*8.0);
+    double ClipR(RealR*8.0);
+    double ClipB(RealB*8.0);
+    double ClipT(RealT*8.0);
+
+    glm::mat4 projection = glm::frustum<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
+    //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
+    glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
+                    1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
+                    1.0);
+    projection = glm::scale(projection, scale);
+    glm::mat4 modelview = glm::translate(glm::mat4(), glm::vec3(0, 0, -EyePos));
+
+    GLint location = glGetUniformLocation( m_nProgramObject, "u_projectionMatrix" );
+    if( location != -1 ) {
+        glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection));
+        CHECK_GL_ERROR();
+    }
+
+    location = glGetUniformLocation( m_nProgramObject, "u_modelViewMatrix" );
+    if( location != -1 ) {
+        glUniformMatrix4fv(location, 1, false, glm::value_ptr(modelview));
+        CHECK_GL_ERROR();
+    }
+}
+
 void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex )
 {
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
@@ -100,6 +137,8 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
             CHECK_GL_ERROR();
         }
 
+        uploadModelViewProjectionMatrices();
+
         m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
         m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
         m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
index 61aed6d..c972ff3 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx
@@ -212,6 +212,10 @@ private:
     TransitionScene maScene;
     const TransitionSettings maSettings;
 
+    /** Calculates the projection and model/view matrices, and upload them.
+     */
+    void uploadModelViewProjectionMatrices();
+
     /** Uniform location for primitive transform
      */
     GLint m_nPrimitiveTransformLocation = -1;
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
index f808a1f..5d6a855 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx
@@ -207,7 +207,6 @@ protected:
             bool useMipmap,
             uno::Sequence<sal_Int8>& data,
             const OGLFormat* pFormat );
-    static void prepareEnvironment();
     const OGLFormat* chooseFormats();
 
 private:
@@ -532,7 +531,6 @@ void OGLTransitionerImpl::impl_prepareSlides()
 
 void OGLTransitionerImpl::impl_prepareTransition()
 {
-    prepareEnvironment();
     if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
         mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL );
 }
@@ -1014,41 +1012,6 @@ void OGLTransitionerImpl::impl_createTexture(
     CHECK_GL_ERROR();
 }
 
-void OGLTransitionerImpl::prepareEnvironment()
-{
-    double EyePos(10.0);
-    double RealF(1.0);
-    double RealN(-1.0);
-    double RealL(-1.0);
-    double RealR(1.0);
-    double RealB(-1.0);
-    double RealT(1.0);
-    double ClipN(EyePos+5.0*RealN);
-    double ClipF(EyePos+15.0*RealF);
-    double ClipL(RealL*8.0);
-    double ClipR(RealR*8.0);
-    double ClipB(RealB*8.0);
-    double ClipT(RealT*8.0);
-
-    CHECK_GL_ERROR();
-    glMatrixMode(GL_PROJECTION);
-    glm::mat4 projection = glm::frustum<float>(ClipL, ClipR, ClipB, ClipT, ClipN, ClipF);
-    //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
-    glm::vec3 scale(1.0 / (((RealR * 2.0 * ClipN) / (EyePos * (ClipR - ClipL))) - ((ClipR + ClipL) / (ClipR - ClipL))),
-                    1.0 / (((RealT * 2.0 * ClipN) / (EyePos * (ClipT - ClipB))) - ((ClipT + ClipB) / (ClipT - ClipB))),
-                    1.0);
-    projection = glm::scale(projection, scale);
-    CHECK_GL_ERROR();
-    glLoadMatrixf(glm::value_ptr(projection));
-
-    CHECK_GL_ERROR();
-    glMatrixMode(GL_MODELVIEW);
-    glm::mat4 modelview = glm::translate(glm::mat4(), glm::vec3(0, 0, -EyePos));
-    CHECK_GL_ERROR();
-    glLoadMatrixf(glm::value_ptr(modelview));
-    CHECK_GL_ERROR();
-}
-
 const OGLFormat* OGLTransitionerImpl::chooseFormats()
 {
     const OGLFormat* pDetectedFormat=nullptr;
commit 63f8cb0117d45f523de5b5e06b698327521cc89c
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Wed Dec 9 21:39:23 2015 +0000

    slideshow: upload the transform matrices as uniforms
    
    Change-Id: I2380fc7f8462514e6c032b18b44df51fbaaccb9f
    (cherry picked from commit 566eca14481ea70c83aef30824da911ccf834b41)

diff --git a/slideshow/opengl/basicVertexShader.glsl b/slideshow/opengl/basicVertexShader.glsl
index 020616f..a4b258c 100644
--- a/slideshow/opengl/basicVertexShader.glsl
+++ b/slideshow/opengl/basicVertexShader.glsl
@@ -28,14 +28,20 @@
 
 #version 120
 
+uniform mat4 u_sceneTransformMatrix;
+uniform mat4 u_primitiveTransformMatrix;
+uniform mat4 u_operationsTransformMatrix;
+
 varying vec2 v_texturePosition;
 varying vec3 v_normal;
 
 void main( void )
 {
-    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+    mat4 modelViewMatrix = gl_ModelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
+    gl_Position = gl_ProjectionMatrix * modelViewMatrix * gl_Vertex;
     v_texturePosition = gl_MultiTexCoord0.xy;
-    v_normal = normalize(gl_NormalMatrix * gl_Normal);
+    v_normal = normalize(normalMatrix * gl_Normal);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/reflectionVertexShader.glsl b/slideshow/opengl/reflectionVertexShader.glsl
index 5087b98..ad9b033 100644
--- a/slideshow/opengl/reflectionVertexShader.glsl
+++ b/slideshow/opengl/reflectionVertexShader.glsl
@@ -28,15 +28,21 @@
 
 #version 130
 
+uniform mat4 u_sceneTransformMatrix;
+uniform mat4 u_primitiveTransformMatrix;
+uniform mat4 u_operationsTransformMatrix;
+
 varying vec2 v_texturePosition;
 varying vec3 v_normal;
 varying float v_isShadow;
 
 void main( void )
 {
-    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+    mat4 modelViewMatrix = gl_ModelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat3 normalMatrix = mat3(transpose(inverse(modelViewMatrix)));
+    gl_Position = gl_ProjectionMatrix * modelViewMatrix * gl_Vertex;
     v_texturePosition = gl_MultiTexCoord0.xy;
-    v_normal = normalize(gl_NormalMatrix * gl_Normal);
+    v_normal = normalize(normalMatrix * gl_Normal);
     v_isShadow = float(gl_VertexID >= 6);
 }
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index 94ded57..aab8508 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -99,6 +99,10 @@ void OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteri
             glUniform1i( location, 2 );  // texture unit 2
             CHECK_GL_ERROR();
         }
+
+        m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" );
+        m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" );
+        m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" );
     }
     CHECK_GL_ERROR();
 
@@ -169,14 +173,10 @@ void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_
     prepare( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
 
     CHECK_GL_ERROR();
-    glPushMatrix();
-    CHECK_GL_ERROR();
     displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale );
     CHECK_GL_ERROR();
     displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
     CHECK_GL_ERROR();
-    glPopMatrix();
-    CHECK_GL_ERROR();
 }
 
 void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale )
@@ -186,11 +186,11 @@ void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthS
     for(size_t i(0); i != rOverallOperations.size(); ++i)
         rOverallOperations[i]->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale);
     CHECK_GL_ERROR();
-    glMultMatrixf(glm::value_ptr(matrix));
+    glUniformMatrix4fv(m_nOperationsTransformLocation, 1, false, glm::value_ptr(matrix));
     CHECK_GL_ERROR();
 }
 
-static void display_primitives(const Primitives_t& primitives, double nTime, double WidthScale, double HeightScale)
+static void display_primitives(const Primitives_t& primitives, GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale)
 {
     CHECK_GL_ERROR();
     GLuint buffer;
@@ -236,7 +236,7 @@ static void display_primitives(const Primitives_t& primitives, double nTime, dou
     glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, texcoord)) );
 
     for (const Primitive& primitive: primitives)
-        primitive.display(nTime, WidthScale, HeightScale, *first++);
+        primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++);
 
     CHECK_GL_ERROR();
     glDeleteBuffers(1, &buffer);
@@ -251,7 +251,9 @@ OGLTransitionImpl::displaySlide(
     CHECK_GL_ERROR();
     glBindTexture(GL_TEXTURE_2D, glSlideTex);
     CHECK_GL_ERROR();
-    display_primitives(primitives, nTime, SlideWidthScale, SlideHeightScale);
+    glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4()));
+    CHECK_GL_ERROR();
+    display_primitives(primitives, m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale);
     CHECK_GL_ERROR();
 }
 
@@ -261,55 +263,43 @@ void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double Sl
     const SceneObjects_t& rSceneObjects(maScene.getSceneObjects());
     glEnable(GL_TEXTURE_2D);
     for(size_t i(0); i != rSceneObjects.size(); ++i)
-        rSceneObjects[i]->display(nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
+        rSceneObjects[i]->display(m_nSceneTransformLocation, m_nPrimitiveTransformLocation, nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
     CHECK_GL_ERROR();
 }
 
-void Primitive::display(double nTime, double WidthScale, double HeightScale, int first) const
+void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const
 {
-    CHECK_GL_ERROR();
-    glPushMatrix();
+    glm::mat4 matrix;
+    applyOperations( matrix, nTime, WidthScale, HeightScale );
 
     CHECK_GL_ERROR();
-    applyOperations( nTime, WidthScale, HeightScale );
-
+    glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix));
     CHECK_GL_ERROR();
     glDrawArrays( GL_TRIANGLES, first, Vertices.size() );
 
     CHECK_GL_ERROR();
-    glPopMatrix();
-    CHECK_GL_ERROR();
 }
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list