[Libreoffice-commits] core.git: 3 commits - slideshow/opengl slideshow/source vcl/opengl

Michael Meeks michael.meeks at collabora.com
Wed Feb 10 00:47:21 UTC 2016


 slideshow/opengl/honeycombFragmentShader.glsl                        |   11 
 slideshow/opengl/honeycombGeometryShader.glsl                        |   32 ++
 slideshow/opengl/honeycombVertexShader.glsl                          |   20 +
 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx |  125 +++++++++-
 vcl/opengl/salbmp.cxx                                                |   27 ++
 vcl/opengl/scale.cxx                                                 |    6 
 6 files changed, 203 insertions(+), 18 deletions(-)

New commits:
commit fea95da81260bc7eabe7ece595829009b2db3e62
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Feb 10 00:46:17 2016 +0000

    tdf#97700 - vcl: opengl - fix memory corrupting size mis-match.
    
    Change-Id: Iab49a20c85f9deb3e8c60a782050aa4c12b663ad

diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index 9ba7432..3f24807 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -68,6 +68,8 @@ bool OpenGLSalBitmap::ImplScaleFilter(
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
+    mnBufWidth = mnWidth;
+    mnBufHeight = mnHeight;
     maTexture = aNewTex;
 
     CHECK_GL_ERROR();
@@ -181,6 +183,8 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
+    mnBufWidth = mnWidth;
+    mnBufHeight = mnHeight;
 
     CHECK_GL_ERROR();
     return true;
@@ -256,6 +260,8 @@ bool OpenGLSalBitmap::ImplScaleArea( const rtl::Reference< OpenGLContext > &xCon
 
     mnWidth = nNewWidth;
     mnHeight = nNewHeight;
+    mnBufWidth = mnWidth;
+    mnBufHeight = mnHeight;
 
     CHECK_GL_ERROR();
     return true;
commit 13667e6576e3e5bc5b133764f77d71cef6c4687a
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Feb 10 00:06:32 2016 +0000

    tdf#97700 - vcl: opengl - add asserts for horrible size mismatch.
    
    We really need to be sure that our texture and its wrapper agree on
    the size of the texture, and particularly the buffer it is reading
    into to avoid DMA'ing junk over the heap.
    
    Add paranoid assertions, also add a canary at the end of the texture
    so we fail hard and fast in this case.
    
    Change-Id: Ibf4869fb5cba562aa117943ce0f2f3df21ca7036

diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 2c3ef26..be5f8f0 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -38,6 +38,10 @@
 
 #include "opengl/FixedTextureAtlas.hxx"
 
+#if OSL_DEBUG_LEVEL > 0
+#  define CANARY "tex-canary"
+#endif
+
 namespace
 {
 
@@ -147,6 +151,9 @@ bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long
     mbDirtyTexture = false;
     VCL_GL_INFO( "Created texture " << maTexture.Id() );
 
+    assert(mnWidth == maTexture.GetWidth() &&
+           mnHeight == maTexture.GetHeight());
+
     return true;
 }
 
@@ -258,7 +265,15 @@ bool OpenGLSalBitmap::AllocateUserData()
     {
         try
         {
-            mpUserBuffer = o3tl::make_shared_array<sal_uInt8>(static_cast<sal_uInt32>(mnBytesPerRow) * mnHeight);
+            size_t nToAllocate = static_cast<sal_uInt32>(mnBytesPerRow) * mnHeight;
+#if OSL_DEBUG_LEVEL > 0
+            nToAllocate += sizeof(CANARY);
+#endif
+            mpUserBuffer = o3tl::make_shared_array<sal_uInt8>(nToAllocate);
+#if OSL_DEBUG_LEVEL > 0
+            memcpy(mpUserBuffer.get() + nToAllocate - sizeof(CANARY),
+                   CANARY, sizeof(CANARY));
+#endif
             alloc = true;
         }
         catch (const std::bad_alloc &) {}
@@ -538,9 +553,19 @@ bool OpenGLSalBitmap::ReadTexture()
         // help valgrind & drmemory rescue us - touch last and first bits.
         pData[0] = 0;
         pData[mnBits/8*mnWidth*mnHeight-1] = 0;
+        // if this fails we can read too much into pData
+        assert(mnWidth == maTexture.GetWidth() &&
+               mnHeight == maTexture.GetHeight());
 #endif
 
         maTexture.Read(nFormat, nType, pData);
+
+#if OSL_DEBUG_LEVEL > 0
+        // If we read over the end of pData we have a real hidden memory
+        // corruption problem !
+        size_t nCanary = static_cast<sal_uInt32>(mnBytesPerRow) * mnHeight;
+        assert(!memcmp(pData + nCanary, CANARY, sizeof (CANARY)));
+#endif
         mnBufWidth = mnWidth;
         mnBufHeight = mnHeight;
         return true;
commit d323f2487d84fbd3909cd2166b98a2a875b71bf8
Author: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Date:   Tue Feb 9 23:59:16 2016 +0000

    slideshow: Add shadows to Honeycomb, using the same way as Vortex
    
    Change-Id: I1f8f11f900f281792b417c1efead272fe3e8432e

diff --git a/slideshow/opengl/honeycombFragmentShader.glsl b/slideshow/opengl/honeycombFragmentShader.glsl
index 7e52951..41b6738 100644
--- a/slideshow/opengl/honeycombFragmentShader.glsl
+++ b/slideshow/opengl/honeycombFragmentShader.glsl
@@ -13,8 +13,11 @@ in vec2 texturePosition;
 in float fuzz;
 in vec2 v_center;
 in vec3 normal;
+in vec4 shadowCoordinate;
 
 uniform sampler2D slideTexture;
+uniform sampler2D colorShadowTexture;
+uniform sampler2D depthShadowTexture;
 uniform float selectedTexture;
 uniform float time;
 uniform float hexagonSize;
@@ -70,8 +73,14 @@ void main()
             fragment.rgb *= actualTime;
         }
     }
+    float visibility = 1.0;
+    const float epsilon = 0.0001;
+    if (texture2D(depthShadowTexture, shadowCoordinate.xy).r < shadowCoordinate.z - epsilon)
+        visibility *= 0.7 + 0.3 * (1.0 - texture2D(colorShadowTexture, shadowCoordinate.xy).a);
     vec4 black = vec4(0.0, 0.0, 0.0, fragment.a);
-    gl_FragColor = mix(black, fragment, light);
+    if (fragment.a < 0.001)
+        discard;
+    gl_FragColor = mix(black, fragment, visibility * light);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/opengl/honeycombGeometryShader.glsl b/slideshow/opengl/honeycombGeometryShader.glsl
index f1c0c70..5269fad 100644
--- a/slideshow/opengl/honeycombGeometryShader.glsl
+++ b/slideshow/opengl/honeycombGeometryShader.glsl
@@ -12,7 +12,9 @@
 layout(triangles) in;
 layout(triangle_strip, max_vertices=27) out;
 
-in mat4 modelViewProjectionMatrix[];
+in mat4 projectionMatrix[];
+in mat4 modelViewMatrix[];
+in mat4 shadowMatrix[];
 
 uniform float hexagonSize;
 uniform sampler2D permTexture;
@@ -21,6 +23,7 @@ out vec2 texturePosition;
 out float fuzz;
 out vec2 v_center;
 out vec3 normal;
+out vec4 shadowCoordinate;
 
 const float expandFactor = 0.0318;
 
@@ -29,10 +32,35 @@ float snoise(vec2 p)
     return texture2D(permTexture, p).r;
 }
 
+mat4 identityMatrix(void)
+{
+    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,
+                0.0, 0.0, 0.0, 1.0);
+}
+
+mat4 scaleMatrix(vec3 axis)
+{
+    mat4 matrix = identityMatrix();
+    matrix[0][0] = axis.x;
+    matrix[1][1] = axis.y;
+    matrix[2][2] = axis.z;
+    return matrix;
+}
+
+mat4 translationMatrix(vec3 axis)
+{
+    mat4 matrix = identityMatrix();
+    matrix[3] = vec4(axis, 1.0);
+    return matrix;
+}
+
 void emitHexagonVertex(vec3 center, vec2 translation)
 {
     vec4 pos = vec4(center + hexagonSize * expandFactor * vec3(translation, 0.0), 1.0);
-    gl_Position = modelViewProjectionMatrix[0] * pos;
+    gl_Position = projectionMatrix[0] * modelViewMatrix[0] * pos;
+    shadowCoordinate = translationMatrix(vec3(0.5, 0.5, 0.5)) * scaleMatrix(vec3(0.5, 0.5, 0.5)) * shadowMatrix[0] * modelViewMatrix[0] * pos;
     texturePosition = vec2((pos.x + 1), (1 - pos.y)) / 2;
     EmitVertex();
 }
diff --git a/slideshow/opengl/honeycombVertexShader.glsl b/slideshow/opengl/honeycombVertexShader.glsl
index d54783b..32fdece 100644
--- a/slideshow/opengl/honeycombVertexShader.glsl
+++ b/slideshow/opengl/honeycombVertexShader.glsl
@@ -21,8 +21,13 @@ uniform mat4 u_operationsTransformMatrix;
 
 uniform float time;
 uniform float selectedTexture;
+uniform float shadow;
+uniform mat4 orthoProjectionMatrix;
+uniform mat4 orthoViewMatrix;
 
-out mat4 modelViewProjectionMatrix;
+out mat4 projectionMatrix;
+out mat4 modelViewMatrix;
+out mat4 shadowMatrix;
 
 mat4 translationMatrix(vec3 axis)
 {
@@ -55,7 +60,7 @@ mat4 rotationMatrix(vec3 axis, float angle)
 
 void main( void )
 {
-    mat4 modelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
+    mat4 nmodelViewMatrix = u_modelViewMatrix * u_operationsTransformMatrix * u_sceneTransformMatrix * u_primitiveTransformMatrix;
     mat4 transformMatrix;
 
     // TODO: use the aspect ratio of the slide instead.
@@ -76,7 +81,16 @@ void main( void )
             * rotationMatrix(vec3(0.0, 0.0, 1.0), pow(0.8 * (time - 1.0), 2.0) * M_PI)
             * invertSlideScaleMatrix;
     }
-    modelViewProjectionMatrix = u_projectionMatrix * modelViewMatrix * transformMatrix;
+
+    if (shadow < 0.5) {
+        projectionMatrix = u_projectionMatrix;
+        shadowMatrix = orthoProjectionMatrix * orthoViewMatrix;
+    } else {
+        projectionMatrix = orthoProjectionMatrix * orthoViewMatrix;
+        shadowMatrix = mat4(0.0);
+    }
+
+    modelViewMatrix = nmodelViewMatrix * transformMatrix;
     gl_Position = vec4(a_position, 1.0);
 }
 
diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
index b764dd7..5a42031 100644
--- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx
@@ -2011,17 +2011,42 @@ public:
     HoneycombTransition(const TransitionScene& rScene, const TransitionSettings& rSettings)
         : PermTextureTransition(rScene, rSettings)
     {
+        mnDepthTextures[0] = 0;
+        mnDepthTextures[1] = 0;
     }
 
 private:
+    virtual void finishTransition() override;
     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;
 
     GLint maHexagonSizeLocation = -1;
     GLint maSelectedTextureLocation = -1;
+    GLint mnShadowLocation = -1;
+    GLuint mnFramebuffer = 0u;
+    std::array<GLuint, 2> mnDepthTextures;
 };
 
+void HoneycombTransition::finishTransition()
+{
+    PermTextureTransition::finishTransition();
+
+    CHECK_GL_ERROR();
+    glActiveTexture( GL_TEXTURE2 );
+    glBindTexture( GL_TEXTURE_2D, 0 );
+    glActiveTexture( GL_TEXTURE3 );
+    glBindTexture( GL_TEXTURE_2D, 0 );
+    glActiveTexture( GL_TEXTURE0 );
+    CHECK_GL_ERROR();
+    glDeleteTextures(2, mnDepthTextures.data());
+    mnDepthTextures = {0u, 0u};
+    CHECK_GL_ERROR();
+    glDeleteFramebuffers(1, &mnFramebuffer);
+    mnFramebuffer = 0u;
+    CHECK_GL_ERROR();
+}
+
 GLuint HoneycombTransition::makeShader() const
 {
     return OpenGLHelper::LoadShaders( "honeycombVertexShader", "honeycombFragmentShader", "honeycombGeometryShader" );
@@ -2035,38 +2060,116 @@ void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_In
     CHECK_GL_ERROR();
     maHexagonSizeLocation = glGetUniformLocation(m_nProgramObject, "hexagonSize");
     maSelectedTextureLocation = glGetUniformLocation( m_nProgramObject, "selectedTexture" );
+    mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow");
+    GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix");
+    GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix");
+    GLint location = glGetUniformLocation(m_nProgramObject, "colorShadowTexture");
+    glUniform1i(location, 2);
+    location = glGetUniformLocation(m_nProgramObject, "depthShadowTexture");
+    glUniform1i(location, 3);
     CHECK_GL_ERROR();
 
     // 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();
+
+    double EyePos(10.0);
+    double RealF(1.0);
+    double RealN(-1.0);
+    double RealL(-4.0);
+    double RealR(4.0);
+    double RealB(-4.0);
+    double RealT(4.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::ortho<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);
+    glUniformMatrix4fv(nOrthoProjectionMatrix, 1, false, glm::value_ptr(projection));
+
+    glm::mat4 view = lookAt(glm::vec3(0, 0, EyePos), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
+    glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view));
+
+    // Generate the framebuffer and textures for the shadows.
+    glGenTextures(2, mnDepthTextures.data());
+    glActiveTexture(GL_TEXTURE2);
+    glBindTexture(GL_TEXTURE_2D, mnDepthTextures[0]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2048, 2048, 0, GL_RGBA, GL_FLOAT, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glActiveTexture(GL_TEXTURE3);
+    glBindTexture(GL_TEXTURE_2D, mnDepthTextures[1]);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glActiveTexture(GL_TEXTURE0);
+    glGenFramebuffers(1, &mnFramebuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
+    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mnDepthTextures[0], 0);
+    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[1], 0);
+
+    // Always check that our framebuffer is ok
+    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+        SAL_WARN("slideshow.opengl", "Wrong framebuffer!");
+        return;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
 void HoneycombTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex,
                                               double SlideWidthScale, double SlideHeightScale )
 {
     CHECK_GL_ERROR();
-    applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
-    glUniform1f( m_nTimeLocation, nTime );
-
-    // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
+    applyOverallOperations(nTime, SlideWidthScale, SlideHeightScale);
+    glUniform1f(m_nTimeLocation, nTime);
+    glUniform1f(mnShadowLocation, 1.0);
+    CHECK_GL_ERROR();
 
     const float borderSize = 0.15f;
 
-    CHECK_GL_ERROR();
-    glUniform1f(maSelectedTextureLocation, 0.0);
+    std::array<GLint, 4> viewport;
+    glGetIntegerv(GL_VIEWPORT, viewport.data());
+    glViewport(0, 0, 2048, 2048);
+    glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffer);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glUniform1f(mnShadowLocation, 1.0);
+    glUniform1f(maSelectedTextureLocation, 1.0);
     glUniform1f(maHexagonSizeLocation, 1.0 - borderSize);
-    displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
+    displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
     glUniform1f(maHexagonSizeLocation, 1.0 + borderSize);
-    displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale );
-    CHECK_GL_ERROR();
+    displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
 
+    // The back (entering) slide needs to be drawn before the front (leaving) one in order for blending to work.
+    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glUniform1f(mnShadowLocation, 0.0);
+    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);
     glUniform1f(maSelectedTextureLocation, 1.0);
     glUniform1f(maHexagonSizeLocation, 1.0 - borderSize);
-    displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
+    displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
     glUniform1f(maHexagonSizeLocation, 1.0 + borderSize);
-    displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale );
+    displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale);
+    CHECK_GL_ERROR();
 }
 
 std::shared_ptr<OGLTransitionImpl>


More information about the Libreoffice-commits mailing list