From c5423234f329225036dc4360a02fec3e35fe733f Mon Sep 17 00:00:00 2001 From: David Tardon Date: Tue, 25 Oct 2016 11:52:39 +0200 Subject: remove unnecessary dir and name prefix Change-Id: I57b8d8b187fe7b8a99f2f90d696cd8c97b8a07b6 --- slideshow/Library_OGLTrans.mk | 6 +- slideshow/source/engine/OGLTrans/Operation.cxx | 223 ++ slideshow/source/engine/OGLTrans/Operation.hxx | 272 +++ .../source/engine/OGLTrans/TransitionImpl.cxx | 2283 ++++++++++++++++++++ .../source/engine/OGLTrans/TransitionImpl.hxx | 371 ++++ .../source/engine/OGLTrans/TransitionerImpl.cxx | 1339 ++++++++++++ .../engine/OGLTrans/generic/OGLTrans_Operation.cxx | 223 -- .../engine/OGLTrans/generic/OGLTrans_Operation.hxx | 272 --- .../OGLTrans/generic/OGLTrans_TransitionImpl.cxx | 2283 -------------------- .../OGLTrans/generic/OGLTrans_TransitionImpl.hxx | 371 ---- .../OGLTrans/generic/OGLTrans_TransitionerImpl.cxx | 1339 ------------ 11 files changed, 4491 insertions(+), 4491 deletions(-) create mode 100644 slideshow/source/engine/OGLTrans/Operation.cxx create mode 100644 slideshow/source/engine/OGLTrans/Operation.hxx create mode 100644 slideshow/source/engine/OGLTrans/TransitionImpl.cxx create mode 100644 slideshow/source/engine/OGLTrans/TransitionImpl.hxx create mode 100644 slideshow/source/engine/OGLTrans/TransitionerImpl.cxx delete mode 100644 slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.cxx delete mode 100644 slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.hxx delete mode 100644 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx delete mode 100644 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx delete mode 100644 slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx (limited to 'slideshow') diff --git a/slideshow/Library_OGLTrans.mk b/slideshow/Library_OGLTrans.mk index 78d7188da09b..612f6defad28 100644 --- a/slideshow/Library_OGLTrans.mk +++ b/slideshow/Library_OGLTrans.mk @@ -62,9 +62,9 @@ $(eval $(call gb_Library_add_libs,OGLTrans,\ endif $(eval $(call gb_Library_add_exception_objects,OGLTrans,\ - slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl \ - slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl \ - slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation \ + slideshow/source/engine/OGLTrans/TransitionerImpl \ + slideshow/source/engine/OGLTrans/TransitionImpl \ + slideshow/source/engine/OGLTrans/Operation \ )) # vim: set noet sw=4 ts=4: diff --git a/slideshow/source/engine/OGLTrans/Operation.cxx b/slideshow/source/engine/OGLTrans/Operation.cxx new file mode 100644 index 000000000000..0888d6ae39bb --- /dev/null +++ b/slideshow/source/engine/OGLTrans/Operation.cxx @@ -0,0 +1,223 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2015 by Collabora, Ltd. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include + +#include +#include + +#include "Operation.hxx" + +SRotate::SRotate(const glm::vec3& Axis, const glm::vec3& Origin, + double Angle, bool bInter, double T0, double T1): + Operation(bInter, T0, T1), + axis(Axis), + origin(Origin), + angle(Angle) +{ +} + +SScale::SScale(const glm::vec3& Scale, const glm::vec3& Origin, + bool bInter, double T0, double T1): + Operation(bInter, T0, T1), + scale(Scale), + origin(Origin) +{ +} + +RotateAndScaleDepthByWidth::RotateAndScaleDepthByWidth(const glm::vec3& Axis, + const glm::vec3& Origin, double Angle, bool bScale, bool bInter, double T0, double T1): + Operation(bInter, T0, T1), + axis(Axis), + origin(Origin), + angle(Angle), + scale(bScale) +{ +} + +RotateAndScaleDepthByHeight::RotateAndScaleDepthByHeight(const glm::vec3& Axis, + const glm::vec3& Origin, double Angle, bool bScale, bool bInter, double T0, double T1): + Operation(bInter, T0, T1), + axis(Axis), + origin(Origin), + angle(Angle), + scale(bScale) +{ +} + + +STranslate::STranslate(const glm::vec3& Vector, bool bInter, double T0, double T1): + Operation(bInter, T0, T1), + vector(Vector) +{ +} + +std::shared_ptr +makeSRotate(const glm::vec3& Axis,const glm::vec3& Origin,double Angle,bool bInter, double T0, double T1) +{ + return std::make_shared(Axis, Origin, Angle, bInter, T0, T1); +} + +std::shared_ptr +makeSScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1) +{ + return std::make_shared(Scale, Origin, bInter, T0, T1); +} + +std::shared_ptr +makeSTranslate(const glm::vec3& Vector,bool bInter, double T0, double T1) +{ + return std::make_shared(Vector, bInter, T0, T1); +} + +std::shared_ptr +makeSEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1) +{ + return std::make_shared(dWidth, dHeight, dStartPosition, dEndPosition, bInter, T0, T1); +} + +std::shared_ptr +makeRotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1) +{ + return std::make_shared(Axis, Origin, Angle, bScale, bInter, T0, T1); +} + +std::shared_ptr +makeRotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle,bool bScale, bool bInter, double T0, double T1) +{ + return std::make_shared(Axis, Origin, Angle, bScale, bInter, T0, T1); +} + +inline double intervalInter(double t, double T0, double T1) +{ + return ( t - T0 ) / ( T1 - T0 ); +} + +void STranslate::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + matrix = glm::translate(matrix, glm::vec3(SlideWidthScale*t*vector.x, SlideHeightScale*t*vector.y, t*vector.z)); +} + +void SRotate::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, origin.z); + glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); + matrix = glm::translate(matrix, translation_vector); + matrix = glm::scale(matrix, scale_vector); + matrix = glm::rotate(matrix, static_cast(t*angle), axis); + matrix = glm::scale(matrix, 1.f / scale_vector); + matrix = glm::translate(matrix, -translation_vector); +} + +void SScale::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, origin.z); + matrix = glm::translate(matrix, translation_vector); + matrix = glm::scale(matrix, static_cast(1 - t) + static_cast(t) * scale); + matrix = glm::translate(matrix, -translation_vector); +} + +void RotateAndScaleDepthByWidth::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, SlideWidthScale*origin.z); + glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); + matrix = glm::translate(matrix, translation_vector); + if (scale) + matrix = glm::scale(matrix, scale_vector); + matrix = glm::rotate(matrix, static_cast(t*angle), axis); + if (scale) + matrix = glm::scale(matrix, 1.f / scale_vector); + matrix = glm::translate(matrix, -translation_vector); +} + +void RotateAndScaleDepthByHeight::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, SlideHeightScale*origin.z); + glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); + matrix = glm::translate(matrix, translation_vector); + if (scale) + matrix = glm::scale(matrix, scale_vector); + matrix = glm::rotate(matrix, static_cast(t*angle), axis); + if (scale) + matrix = glm::scale(matrix, 1.f / scale_vector); + matrix = glm::translate(matrix, -translation_vector); +} + +SEllipseTranslate::SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, + double dEndPosition, bool bInter, double T0, double T1): + Operation(bInter, T0, T1) +{ + width = dWidth; + height = dHeight; + startPosition = dStartPosition; + endPosition = dEndPosition; +} + +void SEllipseTranslate::interpolate(glm::mat4& matrix, double t, double /* SlideWidthScale */, double /* SlideHeightScale */) const +{ + if(t <= mnT0) + return; + if(!mbInterpolate || t > mnT1) + t = mnT1; + t = intervalInter(t,mnT0,mnT1); + + double a1, a2, x, y; + a1 = startPosition*2*M_PI; + a2 = (startPosition + t*(endPosition - startPosition))*2*M_PI; + x = width*(cos (a2) - cos (a1))/2; + y = height*(sin (a2) - sin (a1))/2; + + matrix = glm::translate(matrix, glm::vec3(x, 0, y)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/Operation.hxx b/slideshow/source/engine/OGLTrans/Operation.hxx new file mode 100644 index 000000000000..12d0a4842278 --- /dev/null +++ b/slideshow/source/engine/OGLTrans/Operation.hxx @@ -0,0 +1,272 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2015 by Collabora, Ltd. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef INCLUDED_OGLTRANS_OPERATIONS_HXX_ +#define INCLUDED_OGLTRANS_OPERATIONS_HXX_ + +#include +#include + +#include + +/** This class is to be derived to make any operation (transform) you may need in order to construct your transitions +*/ +class Operation +{ +public: + virtual ~Operation(){} + Operation(const Operation&) = delete; + Operation& operator=(const Operation&) = delete; + +protected: + /** Should this operation be interpolated . If TRUE, the transform will smoothly move from making no difference from t = 0.0 to mnT0 to being completely transformed from t = mnT1 to 1. If FALSE, the transform will be ineffectual from t = 0 to mnT0, and completely transformed from t = mnT0 to 1. + */ + bool mbInterpolate; + + /** time to begin the transformation + */ + double mnT0; + + /** time to finish the transformation + */ + double mnT1; +public: + /** this is the function that is called to give the Operation to OpenGL. + + @param t + time from t = 0 to t = 1 + + @param SlideWidthScale + width of slide divided by width of window + + @param SlideHeightScale + height of slide divided by height of window + + */ + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const = 0; + +protected: + Operation(bool bInterpolate, double nT0, double nT1): + mbInterpolate(bInterpolate), mnT0(nT0), mnT1(nT1){} +}; + +/** this class is a generic CounterClockWise(CCW) rotation with an axis angle +*/ +class SRotate: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + /** Constructor + + @param Axis + axis to rotate about + + @param Origin + position that rotation axis runs through + + @param Angle + angle in radians of CCW rotation + + @param bInter + see Operation + + @param T0 + transformation starting time + + @param T1 + transformation ending time + + */ + SRotate(const glm::vec3& Axis, const glm::vec3& Origin, double Angle, + bool bInter, double T0, double T1); + virtual ~SRotate() override {} +private: + /** axis to rotate CCW about + */ + glm::vec3 axis; + + /** position that rotation axis runs through + */ + glm::vec3 origin; + + /** angle in radians of CCW rotation + */ + double angle; +}; + +std::shared_ptr +makeSRotate(const glm::vec3& Axis, const glm::vec3& Origin, double Angle, + bool bInter, double T0, double T1); + +/** scaling transformation +*/ +class SScale: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + /** Constructor + + @param Scale + amount to scale by + + @param Origin + position that rotation axis runs through + + @param bInter + see Operation + + @param T0 + transformation starting time + + @param T1 + transformation ending time + + */ + SScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1); + virtual ~SScale() override {} +private: + glm::vec3 scale; + glm::vec3 origin; +}; + +std::shared_ptr +makeSScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1); + +/** translation transformation +*/ +class STranslate: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + /** Constructor + + @param Vector + vector to translate + + @param bInter + see Operation + + @param T0 + transformation starting time + + @param T1 + transformation ending time + + */ + STranslate(const glm::vec3& Vector,bool bInter, double T0, double T1); + virtual ~STranslate() override {} +private: + /** vector to translate by + */ + glm::vec3 vector; +}; + +std::shared_ptr +makeSTranslate(const glm::vec3& Vector,bool bInter, double T0, double T1); + +/** translation transformation +*/ +class SEllipseTranslate: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + /** Constructor + + @param Vector + vector to translate + + @param bInter + see Operation + + @param T0 + transformation starting time + + @param T1 + transformation ending time + + */ + SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1); + virtual ~SEllipseTranslate() override {} +private: + /** width and length of the ellipse + */ + double width, height; + + /** start and end position on the ellipse <0,1> + */ + double startPosition; + double endPosition; +}; + +std::shared_ptr +makeSEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1); + +/** Same as SRotate, except the depth is scaled by the width of the slide divided by the width of the window. +*/ +class RotateAndScaleDepthByWidth: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + RotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); + virtual ~RotateAndScaleDepthByWidth() override {} +private: + glm::vec3 axis; + glm::vec3 origin; + double angle; + bool scale; +}; + +std::shared_ptr +makeRotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); + +/** Same as SRotate, except the depth is scaled by the width of the slide divided by the height of the window. +*/ +class RotateAndScaleDepthByHeight: public Operation +{ +public: + virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; + + RotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); + virtual ~RotateAndScaleDepthByHeight() override {} +private: + glm::vec3 axis; + glm::vec3 origin; + double angle; + bool scale; +}; + +std::shared_ptr +makeRotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); + +#endif // INCLUDED_SLIDESHOW_OPERATIONS_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/TransitionImpl.cxx new file mode 100644 index 000000000000..33e7f4ba0f43 --- /dev/null +++ b/slideshow/source/engine/OGLTrans/TransitionImpl.cxx @@ -0,0 +1,2283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "TransitionImpl.hxx" +#include "Operation.hxx" +#include + +TransitionScene::TransitionScene(TransitionScene const& rOther) + : maLeavingSlidePrimitives(rOther.maLeavingSlidePrimitives) + , maEnteringSlidePrimitives(rOther.maEnteringSlidePrimitives) + , maOverallOperations(rOther.maOverallOperations) + , maSceneObjects(rOther.maSceneObjects) +{ +} + +TransitionScene& TransitionScene::operator=(const TransitionScene& rOther) +{ + TransitionScene aTmp(rOther); + swap(aTmp); + return *this; +} + +void TransitionScene::swap(TransitionScene& rOther) +{ + using std::swap; + + swap(maLeavingSlidePrimitives, rOther.maLeavingSlidePrimitives); + swap(maEnteringSlidePrimitives, rOther.maEnteringSlidePrimitives); + swap(maOverallOperations, rOther.maOverallOperations); + swap(maSceneObjects, rOther.maSceneObjects); +} + +OGLTransitionImpl::~OGLTransitionImpl() +{ +} + +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(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(); + } +} + +static std::vector 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(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)); + + std::vector 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; +} + +bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) +{ + m_nProgramObject = makeShader(); + 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); + } + + 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(); + + m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" ); + m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" ); + m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" ); + m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" ); + + glGenVertexArrays(1, &m_nVertexArrayObject); + glBindVertexArray(m_nVertexArrayObject); + + 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) { + glEnableVertexAttribArray(m_nPositionLocation); + glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast(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(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(offsetof(Vertex, texcoord)) ); + CHECK_GL_ERROR(); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); + + prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); + return true; +} + +void OGLTransitionImpl::finish() +{ + const SceneObjects_t& rSceneObjects(maScene.getSceneObjects()); + for(size_t i(0); i != rSceneObjects.size(); ++i) { + rSceneObjects[i]->finish(); + } + + finishTransition(); + + CHECK_GL_ERROR(); + if( m_nProgramObject ) { + glDeleteBuffers(1, &m_nVertexBufferObject); + m_nVertexBufferObject = 0; + glDeleteVertexArrays(1, &m_nVertexArrayObject); + m_nVertexArrayObject = 0; + glDeleteProgram( m_nProgramObject ); + m_nProgramObject = 0; + } + CHECK_GL_ERROR(); +} + +void OGLTransitionImpl::prepare( double, double, double, double, double ) +{ +} + +void OGLTransitionImpl::finish( double, double, double, double, double ) +{ +} + +void OGLTransitionImpl::prepareTransition( sal_Int32, sal_Int32 ) +{ +} + +void OGLTransitionImpl::finishTransition() +{ +} + +void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + + glUniform1f( m_nTimeLocation, nTime ); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex ); + glActiveTexture( GL_TEXTURE0 ); + + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); +} + +void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, + double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) +{ + const double SlideWidthScale = SlideWidth/DispWidth; + const double SlideHeightScale = SlideHeight/DispHeight; + + CHECK_GL_ERROR(); + glBindVertexArray(m_nVertexArrayObject); + prepare( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight ); + + CHECK_GL_ERROR(); + displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); + displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight ); + CHECK_GL_ERROR(); +} + +void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale ) +{ + const Operations_t& rOverallOperations(maScene.getOperations()); + glm::mat4 matrix; + for(size_t i(0); i != rOverallOperations.size(); ++i) + rOverallOperations[i]->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale); + 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::const_iterator first) +{ + for (const Primitive& primitive: primitives) + primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++); +} + +void +OGLTransitionImpl::displaySlide( + const double nTime, + const sal_Int32 glSlideTex, const Primitives_t& primitives, + double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + glBindTexture(GL_TEXTURE_2D, glSlideTex); + 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(); +} + +void +OGLTransitionImpl::displayUnbufferedSlide( + const double nTime, + const sal_Int32 glSlideTex, const Primitives_t& primitives, + double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + glPushMatrix(); + CHECK_GL_ERROR(); + glBindTexture(GL_TEXTURE_2D, glSlideTex); + CHECK_GL_ERROR(); + glBindVertexArray(0); + CHECK_GL_ERROR(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); + if (m_nSceneTransformLocation != -1) { + glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4())); + CHECK_GL_ERROR(); + } + for (const Primitive& primitive: primitives) + primitive.display(m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale); + CHECK_GL_ERROR(); + glBindVertexArray(m_nVertexArrayObject); + CHECK_GL_ERROR(); + glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject); + CHECK_GL_ERROR(); + glPopMatrix(); + CHECK_GL_ERROR(); +} + +void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) +{ + const SceneObjects_t& rSceneObjects(maScene.getSceneObjects()); + 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(); +} + +void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const +{ + glm::mat4 matrix; + applyOperations( matrix, nTime, WidthScale, HeightScale ); + + CHECK_GL_ERROR(); + if (primitiveTransformLocation != -1) { + glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix)); + CHECK_GL_ERROR(); + } + + glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + CHECK_GL_ERROR(); + glEnableClientState( GL_VERTEX_ARRAY ); + CHECK_GL_ERROR(); + glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &Vertices[0] ); + CHECK_GL_ERROR(); + glDrawArrays( GL_TRIANGLES, 0, getVerticesSize() ); + CHECK_GL_ERROR(); + glPopClientAttrib(); + + CHECK_GL_ERROR(); +} + +void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const +{ + glm::mat4 matrix; + applyOperations( matrix, nTime, WidthScale, HeightScale ); + + 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(); +} + +void Primitive::applyOperations(glm::mat4& matrix, double nTime, double WidthScale, double HeightScale) const +{ + for(const auto & rOperation : Operations) + rOperation->interpolate(matrix, nTime, WidthScale, HeightScale); + matrix = glm::scale(matrix, glm::vec3(WidthScale, HeightScale, 1)); +} + +void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const +{ + // fixme: allow various model spaces, now we make it so that + // it is regular -1,-1 to 1,1, where the whole display fits in + glm::mat4 matrix; + if (DispHeight > DispWidth) + matrix = glm::scale(matrix, glm::vec3(DispHeight/DispWidth, 1, 1)); + else + matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1)); + 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(); +} + +void SceneObject::pushPrimitive(const Primitive &p) +{ + maPrimitives.push_back(p); +} + +SceneObject::SceneObject() + : maPrimitives() +{ +} + +SceneObject::~SceneObject() +{ +} + +namespace +{ + +class Iris : public SceneObject +{ +public: + Iris() = default; + + 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(GLuint program) +{ + CHECK_GL_ERROR(); + static const GLubyte img[3] = { 80, 80, 80 }; + + glGenTextures(1, &maTexture); + glBindTexture(GL_TEXTURE_2D, maTexture); + 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_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(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(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(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(); +} + +} + +namespace +{ + +class ReflectionTransition : public OGLTransitionImpl +{ +public: + ReflectionTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : OGLTransitionImpl(rScene, rSettings) + {} + +private: + virtual GLuint makeShader() const override; + virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; + + virtual void prepareTransition( sal_Int32, sal_Int32 ) override { + glDisable(GL_CULL_FACE); + } + + virtual void finishTransition() override { + glEnable(GL_CULL_FACE); + } +}; + +GLuint ReflectionTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "reflectionVertexShader", "reflectionFragmentShader" ); +} + +void ReflectionTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, + double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + + sal_Int32 texture; + Primitives_t slide; + if (nTime < 0.5) { + texture = glLeavingSlideTex; + slide = getScene().getLeavingSlide(); + } else { + texture = glEnteringSlideTex; + slide = getScene().getEnteringSlide(); + } + + displaySlide( nTime, texture, slide, SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); +} + +std::shared_ptr +makeReflectionTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const Operations_t& rOverallOperations, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t()), + rSettings); +} + +} + +namespace +{ + +class SimpleTransition : public OGLTransitionImpl +{ +public: + SimpleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : OGLTransitionImpl(rScene, rSettings) + { + } + +private: + virtual GLuint makeShader() const override; + + virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; +}; + +GLuint SimpleTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "basicVertexShader", "basicFragmentShader" ); +} + +void SimpleTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, + double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + + CHECK_GL_ERROR(); + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); +} + +std::shared_ptr +makeSimpleTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const Operations_t& rOverallOperations, + const SceneObjects_t& rSceneObjects, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, rSceneObjects), + rSettings); +} + +std::shared_ptr +makeSimpleTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const Operations_t& rOverallOperations, + const TransitionSettings& rSettings = TransitionSettings()) +{ + return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t(), rSettings); +} + +std::shared_ptr +makeSimpleTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const SceneObjects_t& rSceneObjects, + const TransitionSettings& rSettings) +{ + return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), rSceneObjects, rSettings); +} + +std::shared_ptr +makeSimpleTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings = TransitionSettings()) +{ + return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), SceneObjects_t(), rSettings); +} + +} + +std::shared_ptr makeOutsideCubeFaceToLeft() +{ + Primitive Slide; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),90,false,false,0.0,1.0)); + + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back(Slide); + + Operations_t aOperations; + aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),-90,false,true,0.0,1.0)); + + return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations); +} + +std::shared_ptr makeInsideCubeFaceToLeft() +{ + Primitive Slide; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),-90,false,false,0.0,1.0)); + + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back(Slide); + + Operations_t aOperations; + aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),90,false,true,0.0,1.0)); + + return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations); +} + +std::shared_ptr makeFallLeaving() +{ + Primitive Slide; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(1,0,0),glm::vec3(0,-1,0), 90,true,true,0.0,1.0)); + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back(Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapEntering = false; + + return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings); +} + +std::shared_ptr makeTurnAround() +{ + Primitive Slide; + TransitionSettings aSettings; + aSettings.mnRequiredGLVersion = 3.0; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); + aLeavingPrimitives.push_back(Slide); + + Slide.Operations.clear(); + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0),-180,true,false,0.0,1.0)); + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); + aEnteringPrimitives.push_back(Slide); + + Operations_t aOperations; + aOperations.push_back(makeSTranslate(glm::vec3(0, 0, -1.5),true, 0, 0.5)); + aOperations.push_back(makeSTranslate(glm::vec3(0, 0, 1.5), true, 0.5, 1)); + aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0),glm::vec3(0, 0, 0), -180, true, true, 0.0, 1.0)); + + return makeReflectionTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations, aSettings); +} + +std::shared_ptr makeTurnDown() +{ + Primitive Slide; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back(Slide); + + Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 0.0001), false, -1.0, 0.0)); + Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), -90, true, 0.0, 1.0)); + Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), 90, false, -1.0, 0.0)); + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back(Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = false; + + return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings); +} + +std::shared_ptr makeIris() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aEnteringPrimitives; + aEnteringPrimitives.push_back (Slide); + + Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.000001), false, -1, 0)); + Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, -0.000002), false, 0.5, 1)); + Primitives_t aLeavingPrimitives; + aLeavingPrimitives.push_back (Slide); + + + Primitive irisPart, part; + int i, nSteps = 24, nParts = 7; + double t = 1.0/nSteps, lx = 1, ly = 0, of=2.2, f=1.42; + + for (i=1; i<=nSteps; i++) { + double x = cos ((3*2*M_PI*t)/nParts); + double y = -sin ((3*2*M_PI*t)/nParts); + double cx = (f*x + 1)/2; + double cy = (f*y + 1)/2; + double lcx = (f*lx + 1)/2; + double lcy = (f*ly + 1)/2; + double cxo = (of*x + 1)/2; + double cyo = (of*y + 1)/2; + double lcxo = (of*lx + 1)/2; + double lcyo = (of*ly + 1)/2; + irisPart.pushTriangle (glm::vec2 (lcx, lcy), + glm::vec2 (lcxo, lcyo), + glm::vec2 (cx, cy)); + irisPart.pushTriangle (glm::vec2 (cx, cy), + glm::vec2 (lcxo, lcyo), + glm::vec2 (cxo, cyo)); + lx = x; + ly = y; + t += 1.0/nSteps; + } + + std::shared_ptr pIris = std::make_shared(); + double angle = 87; + + for (i = 0; i < nParts; i++) { + irisPart.Operations.clear (); + double rx, ry; + + rx = cos ((2*M_PI*i)/nParts); + ry = sin ((2*M_PI*i)/nParts); + irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), angle, true, 0.0, 0.5)); + irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), -angle, true, 0.5, 1)); + if (i > 0) { + irisPart.Operations.push_back (makeSTranslate (glm::vec3(rx, ry, 0), false, -1, 0)); + irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), i*360.0/nParts, false, -1, 0)); + irisPart.Operations.push_back (makeSTranslate (glm::vec3(-1, 0, 0), false, -1, 0)); + } + irisPart.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 1), false, -2, 0.0)); + irisPart.Operations.push_back (makeSRotate (glm::vec3(1, .5, 0), glm::vec3(1, 0, 0), -30, false, -1, 0)); + pIris->pushPrimitive (irisPart); + } + + SceneObjects_t aSceneObjects; + aSceneObjects.push_back (pIris); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSceneObjects, aSettings); +} + +namespace +{ + +class RochadeTransition : public ReflectionTransition +{ +public: + RochadeTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : ReflectionTransition(rScene, rSettings) + {} + +private: + virtual void displaySlides_(double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale) override; +}; + +void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) +{ + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + + if( nTime > .5) { + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + } else { + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + } +} + +std::shared_ptr +makeRochadeTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings) + ; + +} +} + +std::shared_ptr makeRochade() +{ + Primitive Slide; + TransitionSettings aSettings; + aSettings.mnRequiredGLVersion = 3.0; + + double w, h; + + w = 2.2; + h = 10; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + + Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.25, -0.25, true, 0, 1)); + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back(Slide); + + Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); + aLeavingSlide.push_back(Slide); + + Slide.Operations.clear(); + Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.75, 0.25, true, 0, 1)); + Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, -h), false, -1, 0)); + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1)); + Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), 45, true, false, -1, 0)); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back(Slide); + + Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); + aEnteringSlide.push_back(Slide); + + return makeRochadeTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +inline double randFromNeg1to1() +{ + return comphelper::rng::uniform_real_distribution(-1.0, std::nextafter(1.0, DBL_MAX)); +} + +// TODO(Q3): extract to basegfx +inline glm::vec3 randNormVectorInXYPlane() +{ + glm::vec3 toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0); + return glm::normalize(toReturn); +} + +template +T clamp(const T& rIn) +{ + return glm::clamp(rIn, T(-1.0), T(1.0)); +} + +std::shared_ptr makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles ) +{ + double dAngle(2*3.1415926/static_cast( nPointsOnCircles )); + if(nCircles < 2 || nPointsOnCircles < 4) + return makeNByMTileFlip(1,1); + float Radius(1.0/static_cast( nCircles )); + float dRadius(Radius); + float LastRadius(0.0); + float NextRadius(2*Radius); + + /// now we know there is at least two circles + /// the first will always be a full circle + /// the last will always be the outer shell of the slide with a circle hole + + //add the full circle + std::vector unScaledTexCoords; + float TempAngle(0.0); + for(unsigned int Point(0); Point < nPointsOnCircles; ++Point) + { + unScaledTexCoords.push_back( glm::vec2( cos(TempAngle - 3.1415926/2.0) , sin(TempAngle- 3.1415926/2.0) ) ); + + TempAngle += dAngle; + } + + Primitives_t aLeavingSlide; + Primitives_t aEnteringSlide; + { + Primitive EnteringSlide; + Primitive LeavingSlide; + for(int Point(0); Point + 1 < nPointsOnCircles; ++Point) + { + EnteringSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5 , 0.5 ) ); + LeavingSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5, 0.5) ); + } + EnteringSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius * unScaledTexCoords[ 0 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ nPointsOnCircles - 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) ); + LeavingSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) ); + + glm::vec3 axis(randNormVectorInXYPlane()); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); + LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); + + aEnteringSlide.push_back(EnteringSlide); + aLeavingSlide.push_back(LeavingSlide); + LastRadius = Radius; + Radius = NextRadius; + NextRadius += dRadius; + } + + for(int i(1); i < nCircles - 1; ++i) + { + Primitive LeavingSlide; + Primitive EnteringSlide; + for(int Side(0); Side < nPointsOnCircles - 1; ++Side) + { + EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + + LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + } + + EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + + LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + + glm::vec3 axis(randNormVectorInXYPlane()); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); + LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); + + aEnteringSlide.push_back(EnteringSlide); + aLeavingSlide.push_back(LeavingSlide); + + LastRadius = Radius; + Radius = NextRadius; + NextRadius += dRadius; + } + { + Radius = sqrt(2.0); + Primitive LeavingSlide; + Primitive EnteringSlide; + for(int Side(0); Side < nPointsOnCircles - 1; ++Side) + { + + EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) ); + + LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); + LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) ); + } + + EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) ); + + LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); + LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) ); + + glm::vec3 axis(randNormVectorInXYPlane()); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) ); + LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) ); + EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); + + aEnteringSlide.push_back(EnteringSlide); + aLeavingSlide.push_back(LeavingSlide); + } + + return makeSimpleTransition(aLeavingSlide, aEnteringSlide); +} + +std::shared_ptr makeHelix( sal_uInt16 nRows ) +{ + double invN(1.0/static_cast(nRows)); + double iDn = 0.0; + double iPDn = invN; + Primitives_t aLeavingSlide; + Primitives_t aEnteringSlide; + for(unsigned int i(0); i < nRows; ++i) + { + Primitive Tile; + + Tile.pushTriangle(glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iDn ) , glm::vec2( 0.0 , iPDn )); + + Tile.pushTriangle(glm::vec2( 1.0 , iPDn ) , glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iPDn )); + + Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , 180 , + true, std::min(std::max(static_cast(i - nRows/2.0)*invN/2.0,0.0),1.0), + std::min(std::max(static_cast(i + nRows/2.0)*invN/2.0,0.0),1.0) ) ); + + aLeavingSlide.push_back(Tile); + + Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , -180 , false,0.0,1.0) ); + + aEnteringSlide.push_back(Tile); + + iDn += invN; + iPDn += invN; + } + + return makeSimpleTransition(aLeavingSlide, aEnteringSlide); +} + +float fdiv(int a, int b) +{ + return static_cast(a)/b; +} + +glm::vec2 vec(float x, float y, float nx, float ny) +{ + x = x < 0.0 ? 0.0 : x; + x = x > nx ? nx : x; + y = y < 0.0 ? 0.0 : y; + y = y > ny ? ny : y; + return glm::vec2(fdiv(x, nx), fdiv(y, ny)); +} + +std::shared_ptr makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m ) +{ + Primitives_t aLeavingSlide; + Primitives_t aEnteringSlide; + + for (int x = 0; x < n; x++) + { + for (int y = 0; y < n; y++) + { + Primitive aTile; + glm::vec2 x11 = vec(x, y, n, m); + glm::vec2 x12 = vec(x, y+1, n, m); + glm::vec2 x21 = vec(x+1, y, n, m); + glm::vec2 x22 = vec(x+1, y+1, n, m); + + aTile.pushTriangle(x21, x11, x12); + aTile.pushTriangle(x22, x21, x12); + + aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, 180 , true, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f)); + aLeavingSlide.push_back(aTile); + + aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, -180, false, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f)); + aEnteringSlide.push_back(aTile); + } + } + + return makeSimpleTransition(aLeavingSlide, aEnteringSlide); +} + +Primitive& Primitive::operator=(const Primitive& rvalue) +{ + Primitive aTmp(rvalue); + swap(aTmp); + return *this; +} + +Primitive::Primitive(const Primitive& rvalue) + : Operations(rvalue.Operations) + , Vertices(rvalue.Vertices) +{ +} + +void Primitive::swap(Primitive& rOther) +{ + using std::swap; + + swap(Operations, rOther.Operations); + swap(Vertices, rOther.Vertices); +} + +void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2) +{ + std::vector Verts; + std::vector Texs; + Verts.reserve(3); + Texs.reserve(3); + + Verts.push_back(glm::vec3( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 )); + Verts.push_back(glm::vec3( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 )); + Verts.push_back(glm::vec3( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 )); + + //figure out if they're facing the correct way, and make them face the correct way. + glm::vec3 Normal( glm::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) ); + if(Normal.z >= 0.0)//if the normal is facing us + { + Texs.push_back(SlideLocation0); + Texs.push_back(SlideLocation1); + Texs.push_back(SlideLocation2); + } + else // if the normal is facing away from us, make it face us + { + Texs.push_back(SlideLocation0); + Texs.push_back(SlideLocation2); + Texs.push_back(SlideLocation1); + Verts.clear(); + Verts.push_back(glm::vec3( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 )); + Verts.push_back(glm::vec3( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 )); + Verts.push_back(glm::vec3( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 )); + } + + Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed. + Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed. + Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed. +} + +namespace +{ + +class DiamondTransition : public SimpleTransition +{ +public: + DiamondTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : SimpleTransition(rScene, rSettings) + {} + +private: + virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; +}; + +Primitives_t makeLeavingSlide(double nTime) +{ + Primitive Slide2; + if( nTime >= 0.5 ) { + double m = 1 - nTime; + + Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (m,0), glm::vec2 (0,m)); + Slide2.pushTriangle (glm::vec2 (nTime,0), glm::vec2 (1,0), glm::vec2 (1,m)); + Slide2.pushTriangle (glm::vec2 (1,nTime), glm::vec2 (1,1), glm::vec2 (nTime,1)); + Slide2.pushTriangle (glm::vec2 (0,nTime), glm::vec2 (m,1), glm::vec2 (0,1)); + } else { + double l = 0.5 - nTime; + double h = 0.5 + nTime; + + Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0.5,l)); + Slide2.pushTriangle (glm::vec2 (0.5,l), glm::vec2 (1,0), glm::vec2 (h,0.5)); + Slide2.pushTriangle (glm::vec2 (1,0), glm::vec2 (1,1), glm::vec2 (h,0.5)); + Slide2.pushTriangle (glm::vec2 (h,0.5), glm::vec2 (1,1), glm::vec2 (0.5,h)); + Slide2.pushTriangle (glm::vec2 (0.5,h), glm::vec2 (1,1), glm::vec2 (0,1)); + Slide2.pushTriangle (glm::vec2 (l,0.5), glm::vec2 (0.5,h), glm::vec2 (0,1)); + Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (l,0.5), glm::vec2 (0,1)); + Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (0.5,l), glm::vec2 (l,0.5)); + } + Slide2.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.00000001), false, -1, 0)); + Primitives_t aLeavingSlidePrimitives; + aLeavingSlidePrimitives.push_back (Slide2); + + return aLeavingSlidePrimitives; +} + +void DiamondTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, + double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + + CHECK_GL_ERROR(); + displayUnbufferedSlide( nTime, glLeavingSlideTex, makeLeavingSlide(nTime), SlideWidthScale, SlideHeightScale ); + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); +} + +std::shared_ptr +makeDiamondTransition(const TransitionSettings& rSettings) +{ + Primitive Slide1; + Slide1.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide1.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aEnteringSlidePrimitives; + aEnteringSlidePrimitives.push_back (Slide1); + Primitives_t aLeavingSlidePrimitives; + aLeavingSlidePrimitives.push_back (Slide1); + return std::make_shared(TransitionScene(aLeavingSlidePrimitives, aEnteringSlidePrimitives), rSettings); +} + +} + +std::shared_ptr makeDiamond() +{ + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeDiamondTransition(aSettings); +} + +std::shared_ptr makeVenetianBlinds( bool vertical, int parts ) +{ + static double t30 = tan( M_PI/6.0 ); + double ln = 0; + double p = 1.0/parts; + + Primitives_t aLeavingSlide; + Primitives_t aEnteringSlide; + for( int i=0; i +makeFadeSmoothlyTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings) + ; +} + +} + +std::shared_ptr makeFadeSmoothly() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeFadeSmoothlyTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +namespace +{ + +class FadeThroughBlackTransition : public OGLTransitionImpl +{ +public: + FadeThroughBlackTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : OGLTransitionImpl(rScene, rSettings) + {} + +private: + virtual GLuint makeShader() const override; +}; + +GLuint FadeThroughBlackTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "basicVertexShader", "fadeBlackFragmentShader" ); +} + +std::shared_ptr +makeFadeThroughBlackTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings) + ; +} + +} + +std::shared_ptr makeFadeThroughBlack() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeFadeThroughBlackTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +namespace +{ + +class PermTextureTransition : public OGLTransitionImpl +{ +protected: + PermTextureTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : OGLTransitionImpl(rScene, rSettings) + , m_nHelperTexture(0) + {} + + virtual void finishTransition() override; + virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override; + +private: + /** various data */ + GLuint m_nHelperTexture; +}; + +void PermTextureTransition::finishTransition() +{ + CHECK_GL_ERROR(); + if ( m_nHelperTexture ) + { + glDeleteTextures( 1, &m_nHelperTexture ); + m_nHelperTexture = 0; + } + CHECK_GL_ERROR(); +} + +int permutation256 [256]= { +215, 100, 200, 204, 233, 50, 85, 196, + 71, 141, 122, 160, 93, 131, 243, 234, +162, 183, 36, 155, 4, 62, 35, 205, + 40, 102, 33, 27, 255, 55, 214, 156, + 75, 163, 134, 126, 249, 74, 197, 228, + 72, 90, 206, 235, 17, 22, 49, 169, +227, 89, 16, 5, 117, 60, 248, 230, +217, 68, 138, 96, 194, 170, 136, 10, +112, 238, 184, 189, 176, 42, 225, 212, + 84, 58, 175, 244, 150, 168, 219, 236, +101, 208, 123, 37, 164, 110, 158, 201, + 78, 114, 57, 48, 70, 142, 106, 43, +232, 26, 32, 252, 239, 98, 191, 94, + 59, 149, 39, 187, 203, 190, 19, 13, +133, 45, 61, 247, 23, 34, 20, 52, +118, 209, 146, 193, 222, 18, 1, 152, + 46, 41, 91, 148, 115, 25, 135, 77, +254, 147, 224, 161, 9, 213, 223, 250, +231, 251, 127, 166, 63, 179, 81, 130, +139, 28, 120, 151, 241, 86, 111, 0, + 88, 153, 172, 182, 159, 105, 178, 47, + 51, 167, 65, 66, 92, 73, 198, 211, +245, 195, 31, 220, 140, 76, 221, 186, +154, 185, 56, 83, 38, 165, 109, 67, +124, 226, 132, 53, 229, 29, 12, 181, +121, 24, 207, 199, 177, 113, 30, 80, + 3, 97, 188, 79, 216, 173, 8, 145, + 87, 128, 180, 237, 240, 137, 125, 104, + 15, 242, 119, 246, 103, 143, 95, 144, + 2, 44, 69, 157, 192, 174, 14, 54, +218, 82, 64, 210, 11, 6, 129, 21, +116, 171, 99, 202, 7, 107, 253, 108 +}; + +void initPermTexture(GLuint *texID) +{ + CHECK_GL_ERROR(); + glGenTextures(1, texID); + glBindTexture(GL_TEXTURE_2D, *texID); + + static bool initialized = false; + static unsigned char permutation2D[256*256*4]; + if( !initialized ) { + int x, y; + + for( y=0; y < 256; y++ ) + for( x=0; x < 256; x++ ) + permutation2D[x*4 + y*1024] = permutation256[(y + permutation256[x]) & 0xff]; + + initialized = true; + } + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, permutation2D ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + CHECK_GL_ERROR(); +} + +void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32 ) +{ + 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(); +} + +} + +namespace +{ + +class StaticNoiseTransition : public PermTextureTransition +{ +public: + StaticNoiseTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : PermTextureTransition(rScene, rSettings) + {} + +private: + virtual GLuint makeShader() const override; +}; + +GLuint StaticNoiseTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "basicVertexShader", "staticFragmentShader" ); +} + +std::shared_ptr +makeStaticNoiseTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings) + ; +} + +} + +std::shared_ptr makeStatic() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeStaticNoiseTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +namespace +{ + +class DissolveTransition : public PermTextureTransition +{ +public: + DissolveTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : PermTextureTransition(rScene, rSettings) + {} + +private: + virtual GLuint makeShader() const override; +}; + +GLuint DissolveTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "basicVertexShader", "dissolveFragmentShader" ); +} + +std::shared_ptr +makeDissolveTransition( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared( + TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings) + ; +} + +} + +std::shared_ptr makeDissolve() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeDissolveTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +namespace +{ + +class VortexTransition : public PermTextureTransition +{ +public: + VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY) + : PermTextureTransition(rScene, rSettings) + , maNumTiles(nNX,nNY) + { + mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y); + mnFramebuffers[0] = 0; + mnFramebuffers[1] = 0; + 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 mnSlideLocation = -1; + GLint mnTileInfoLocation = -1; + GLuint mnTileInfoBuffer = 0u; + GLint mnShadowLocation = -1; + std::array mnFramebuffers; + std::array mnDepthTextures; + + glm::ivec2 maNumTiles; + + std::vector mvTileInfo; +}; + +void VortexTransition::finishTransition() +{ + PermTextureTransition::finishTransition(); + + CHECK_GL_ERROR(); + glDeleteTextures(2, mnDepthTextures.data()); + mnDepthTextures = {0u, 0u}; + CHECK_GL_ERROR(); + glDeleteFramebuffers(2, mnFramebuffers.data()); + mnFramebuffers = {0u, 0u}; + glDeleteBuffers(1, &mnTileInfoBuffer); + mnTileInfoBuffer = 0u; + mnSlideLocation = -1; + mnTileInfoLocation = -1; + mnShadowLocation = -1; + CHECK_GL_ERROR(); +} + +GLuint VortexTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader" ); +} + +glm::mat4 lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up) { + glm::vec3 f = glm::normalize(center - eye); + glm::vec3 u = glm::normalize(up); + glm::vec3 s = glm::normalize(glm::cross(f, u)); + u = glm::cross(s, f); + + return glm::mat4(s.x, u.x, -f.x, 0, + s.y, u.y, -f.y, 0, + s.z, u.z, -f.z, 0, + -glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1); +} + +void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) +{ + CHECK_GL_ERROR(); + PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); + CHECK_GL_ERROR(); + + mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide"); + mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo"); + GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles"); + mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow"); + GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix"); + GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix"); + GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture"); + glUniform1i(location, 2); + location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture"); + glUniform1i(location, 3); + CHECK_GL_ERROR(); + + glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles)); + CHECK_GL_ERROR(); + + glGenBuffers(1, &mnTileInfoBuffer); + CHECK_GL_ERROR(); + + // We store the (x,y) indexes of the tile each vertex belongs to in a float, so they must fit. + assert(maNumTiles.x < 256); + assert(maNumTiles.y < 256); + + // Two triangles, i.e. six vertices, per tile + { + int n = 0; + for (int x = 0; x < maNumTiles.x; x++) + { + for (int y = 0; y < maNumTiles.y; y++) + { + for (int v = 0; v < 6; v++) + { + mvTileInfo[n] = x + (y << 8) + (v << 16); + n++; + } + } + } + } + + glBindBuffer(GL_ARRAY_BUFFER, mnTileInfoBuffer); + CHECK_GL_ERROR(); + glEnableVertexAttribArray(mnTileInfoLocation); + CHECK_GL_ERROR(); + glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr); + CHECK_GL_ERROR(); + glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW); + CHECK_GL_ERROR(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); + + double EyePos(10.0); + double RealF(1.0); + double RealN(-1.0); + double RealL(-2.0); + double RealR(2.0); + double RealB(-2.0); + double RealT(2.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(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(-1, 1, EyePos), glm::vec3(-0.5, 0.5, 0), glm::vec3(0, 1, 0)); + glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view)); + + // Generate the framebuffers and textures for the shadows. + glGenTextures(2, mnDepthTextures.data()); + glGenFramebuffers(2, mnFramebuffers.data()); + + for (int i : {0, 1}) { + glBindTexture(GL_TEXTURE_2D, mnDepthTextures[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + 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_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[i]); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[i], 0); + glDrawBuffer(GL_NONE); // No color buffer is drawn to. + + // 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); + glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, mnDepthTextures[0] ); + glActiveTexture( GL_TEXTURE3 ); + glBindTexture( GL_TEXTURE_2D, mnDepthTextures[1] ); + glActiveTexture( GL_TEXTURE0 ); +} + +void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) +{ + CHECK_GL_ERROR(); + applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); + glUniform1f( m_nTimeLocation, nTime ); + glUniform1f( mnShadowLocation, 1.0 ); + + std::array viewport; + glGetIntegerv(GL_VIEWPORT, viewport.data()); + glViewport(0, 0, 2048, 2048); + + glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[0]); + glClear(GL_DEPTH_BUFFER_BIT); + glUniform1f( mnSlideLocation, 0.0 ); + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + + glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[1]); + glClear(GL_DEPTH_BUFFER_BIT); + glUniform1f( mnSlideLocation, 1.0 ); + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glUniform1f( mnShadowLocation, 0.0 ); + glUniform1f( mnSlideLocation, 0.0 ); + displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); + glUniform1f( mnSlideLocation, 1.0 ); + displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); + CHECK_GL_ERROR(); +} + +std::shared_ptr +makeVortexTransition(const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings, + int NX, + int NY) +{ + return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings, + NX, NY); +} + +} + +std::shared_ptr makeVortex() +{ + const int NX = 96, NY = 96; + Primitive Slide; + + for (int x = 0; x < NX; x++) + { + for (int y = 0; y < NY; y++) + { + Slide.pushTriangle (glm::vec2 (fdiv(x,NX),fdiv(y,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY))); + Slide.pushTriangle (glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y+1,NY))); + } + } + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + aSettings.mnRequiredGLVersion = 3.2f; + + return makeVortexTransition(aLeavingSlide, aEnteringSlide, aSettings, NX, NY); +} + +namespace +{ + +class RippleTransition : public OGLTransitionImpl +{ +public: + RippleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, const glm::vec2& rCenter) + : OGLTransitionImpl(rScene, rSettings), + maCenter(rCenter) + { + } + +private: + virtual GLuint makeShader() const override; + virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override; + virtual void prepare( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) override; + + glm::vec2 maCenter; + GLint maSlideRatioLocation = -1; +}; + +GLuint RippleTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "basicVertexShader", "rippleFragmentShader" ); +} + +void RippleTransition::prepareTransition( sal_Int32, sal_Int32 ) +{ + GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center"); + CHECK_GL_ERROR(); + + glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter)); + CHECK_GL_ERROR(); + + maSlideRatioLocation = glGetUniformLocation(m_nProgramObject, "slideRatio"); + CHECK_GL_ERROR(); +} + +void RippleTransition::prepare( double /* nTime */, double SlideWidth, double SlideHeight, double /* DispWidth */, double /* DispHeight */ ) +{ + if( maSlideRatioLocation != -1 ) + glUniform1f( maSlideRatioLocation, SlideWidth / SlideHeight ); +} + +std::shared_ptr +makeRippleTransition(const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + // The center point should be adjustable by the user, but we have no way to do that in the UI + return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings, + glm::vec2(0.5, 0.5)); +} + +} + +std::shared_ptr makeRipple() +{ + Primitive Slide; + + Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); + Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); + + Primitives_t aLeavingSlide; + aLeavingSlide.push_back (Slide); + + Primitives_t aEnteringSlide; + aEnteringSlide.push_back (Slide); + + TransitionSettings aSettings; + aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; + + return makeRippleTransition(aLeavingSlide, aEnteringSlide, aSettings); +} + +void createHexagon(Primitive& aHexagon, const int x, const int y, const int NX, const int NY) +{ + if (y % 4 == 0) + { + aHexagon.pushTriangle(vec(x-1, y-1, NX, NY), vec(x, y-2, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x, y-2, NX, NY), vec(x+1, y-1, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x+1, y-1, NX, NY), vec(x+1, y, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x+1, y, NX, NY), vec(x, y+1, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x, y+1, NX, NY), vec(x-1, y, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x-1, y, NX, NY), vec(x-1, y-1, NX, NY), vec(x, y+0.5, NX, NY)); + } + else + { + aHexagon.pushTriangle(vec(x-2, y-1, NX, NY), vec(x-1, y-2, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x-1, y-2, NX, NY), vec(x, y-1, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x, y-1, NX, NY), vec(x, y, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x, y, NX, NY), vec(x-1, y+1, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x-1, y+1, NX, NY), vec(x-2, y, NX, NY), vec(x, y+0.5, NX, NY)); + aHexagon.pushTriangle(vec(x-2, y, NX, NY), vec(x-2, y-1, NX, NY), vec(x, y+0.5, NX, NY)); + } +} + +namespace +{ + +class GlitterTransition : public PermTextureTransition +{ +public: + GlitterTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) + : PermTextureTransition(rScene, rSettings) + { + } + +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; + + GLuint maBuffer = 0; +}; + +GLuint GlitterTransition::makeShader() const +{ + return OpenGLHelper::LoadShaders( "glitterVertexShader", "glitterFragmentShader" ); +} + +struct ThreeFloats +{ + GLfloat x, y, z; +}; + +void GlitterTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) +{ + CHECK_GL_ERROR(); + PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); + CHECK_GL_ERROR(); + + GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles"); + if (nNumTilesLocation != -1) { + glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(glm::ivec2(41, 41 * 4 / 3))); + CHECK_GL_ERROR(); + } + + 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 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, nullptr ); + 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 +makeGlitterTransition(const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings); +} + +} + +std::shared_ptr 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, TransitionSettings()); +} + +namespace +{ + +class HoneycombTransition : public PermTextureTransition +{ +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 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" ); +} + +void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) +{ + CHECK_GL_ERROR(); + PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); + + 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(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, nullptr); + 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_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, nullptr); + 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_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); + glUniform1f(mnShadowLocation, 1.0); + CHECK_GL_ERROR(); + + const float borderSize = 0.15f; + + std::array 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.0f - borderSize); + displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); + glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); + 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.0f - borderSize); + displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale); + glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); + displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale); + glUniform1f(maSelectedTextureLocation, 1.0); + glUniform1f(maHexagonSizeLocation, 1.0f - borderSize); + displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); + glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); + displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); + CHECK_GL_ERROR(); +} + +std::shared_ptr +makeHoneycombTransition(const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const TransitionSettings& rSettings) +{ + // The center point should be adjustable by the user, but we have no way to do that in the UI + return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), + rSettings); +} + +} + +std::shared_ptr makeHoneycomb() +{ + const int NX = 21; + const int NY = 21; + + TransitionSettings aSettings; + aSettings.mnRequiredGLVersion = 3.2f; + + 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 makeNewsflash() +{ + Primitive Slide; + + Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); + Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); + Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),3000,true,0,0.5)); + Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),true,0,0.5)); + Slide.Operations.push_back(makeSTranslate(glm::vec3(-10000, 0, 0),false, 0.5, 2)); + Primitives_t aLeavingSlide; + aLeavingSlide.push_back(Slide); + + Slide.Operations.clear(); + Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),-3000,true,0.5,1)); + Slide.Operations.push_back(makeSTranslate(glm::vec3(-100, 0, 0),false, -1, 1)); + Slide.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0),false, 0.5, 1)); + Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),false,-1,1)); + Slide.Operations.push_back(makeSScale(glm::vec3(100,100,100),glm::vec3(0,0,0),true,0.5,1)); + Primitives_t aEnteringSlide; + aEnteringSlide.push_back(Slide); + + Operations_t aOverallOperations; + aOverallOperations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0.2,0.2,0),1080,true,0,1)); + + return makeSimpleTransition(aLeavingSlide, aEnteringSlide, aOverallOperations); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/TransitionImpl.hxx new file mode 100644 index 000000000000..66ecb6b61a0c --- /dev/null +++ b/slideshow/source/engine/OGLTrans/TransitionImpl.hxx @@ -0,0 +1,371 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_ +#define INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_ + +#include +#include + +#include + +#include +#include + +class Primitive; +class Operation; +class SceneObject; +class TransitionData; + +struct TransitionSettings +{ + TransitionSettings() : + mbUseMipMapLeaving( true ), + mbUseMipMapEntering( true ), + mnRequiredGLVersion( 2.1f ) + { + } + + /** Whether to use mipmaping for slides textures + */ + bool mbUseMipMapLeaving; + bool mbUseMipMapEntering; + + /** which GL version does the transition require + */ + float mnRequiredGLVersion; +}; + +typedef std::vector Primitives_t; +typedef std::vector > SceneObjects_t; +typedef std::vector > Operations_t; + +class TransitionScene +{ +public: + TransitionScene( + const Primitives_t& rLeavingSlidePrimitives, + const Primitives_t& rEnteringSlidePrimitives, + const Operations_t& rOverallOperations = Operations_t(), + const SceneObjects_t& rSceneObjects = SceneObjects_t() + ) + : maLeavingSlidePrimitives(rLeavingSlidePrimitives) + , maEnteringSlidePrimitives(rEnteringSlidePrimitives) + , maOverallOperations(rOverallOperations) + , maSceneObjects(rSceneObjects) + { + } + + TransitionScene(TransitionScene const& rOther); + TransitionScene& operator=(const TransitionScene& rOther); + + void swap(TransitionScene& rOther); + + const Primitives_t& getLeavingSlide() const + { + return maLeavingSlidePrimitives; + } + + const Primitives_t& getEnteringSlide() const + { + return maEnteringSlidePrimitives; + } + + const Operations_t& getOperations() const + { + return maOverallOperations; + } + + const SceneObjects_t& getSceneObjects() const + { + return maSceneObjects; + } + +private: + /** All the primitives that use the leaving slide texture + */ + Primitives_t maLeavingSlidePrimitives; + + /** All the primitives that use the leaving slide texture + */ + Primitives_t maEnteringSlidePrimitives; + + /** All the operations that should be applied to both leaving and entering slide primitives. These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back. + */ + Operations_t maOverallOperations; + + /** All the surrounding scene objects + */ + SceneObjects_t maSceneObjects; +}; + +/** OpenGL 3D Transition class. It implicitly is constructed from XOGLTransition + + It holds Primitives and Operations on those primitives. +*/ +class OGLTransitionImpl +{ +public: + virtual ~OGLTransitionImpl(); + + OGLTransitionImpl(const OGLTransitionImpl&) = delete; + OGLTransitionImpl& operator=(const OGLTransitionImpl&) = delete; + + /** Prepare transition. + */ + 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 ); + /** Clean up after transition. + */ + void finish(); + + TransitionSettings const& getSettings() const + { + return maSettings; + } + +protected: + OGLTransitionImpl(const TransitionScene& rScene, const TransitionSettings& rSettings) + : maScene(rScene) + , maSettings(rSettings) + {} + + TransitionScene const& getScene() const + { + return maScene; + } + + void displaySlide( double nTime, sal_Int32 glSlideTex, const Primitives_t& primitives, double SlideWidthScale, double SlideHeightScale ); + void displayUnbufferedSlide( double nTime, sal_Int32 glSlideTex, const Primitives_t& primitives, double SlideWidthScale, double SlideHeightScale ); + void displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight); + void applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale ); + +private: + /** This function is called in display method to prepare the slides, scene, etc. + * + * Default implementation does nothing. + */ + virtual void prepare( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ); + + /** This function is called in display method to prepare the slides, scene, etc. + * + * Default implementation does nothing. + */ + virtual void finish( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ); + + /** This function is called after glx context is ready to let the transition prepare GL related things, like GLSL program. + * + * Default implementation does nothing. + */ + virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ); + + /** This function is called when the transition needs to clear after itself, like delete own textures etc. + * + * Default implementation does nothing. + */ + virtual void finishTransition(); + + /** This function is called in display method to display the slides. + * + * Default implementation applies overall operations and then + * displays both slides. + */ + virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ); + + /** This function is called in prepare method to create the GL program. + * + * It is a pure virtual to make sure no class will use a default one. + */ + virtual GLuint makeShader() const = 0; + +private: + const TransitionScene maScene; + const TransitionSettings maSettings; + + /** Calculates the projection and model/view matrices, and upload them. + */ + void uploadModelViewProjectionMatrices(); + + /** Uniform locations for transform matrices + */ + GLint m_nPrimitiveTransformLocation = -1; + GLint m_nSceneTransformLocation = -1; + GLint m_nOperationsTransformLocation = -1; + + /** Per-vertex attribute locations + */ + GLint m_nPositionLocation = -1; + GLint m_nNormalLocation = -1; + GLint m_nTexCoordLocation = -1; + + GLuint m_nVertexArrayObject = 0u; + + std::vector m_nFirstIndices; + +protected: + /** GLSL program object + */ + GLuint m_nProgramObject = 0u; + + /** VBO in which to put primitive data + */ + GLuint m_nVertexBufferObject = 0u; + + /** Location of the "time" uniform + */ + GLint m_nTimeLocation = -1; +}; + + +// "Constructors" of available transitions +std::shared_ptr makeOutsideCubeFaceToLeft(); +std::shared_ptr makeInsideCubeFaceToLeft(); +std::shared_ptr makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m ); +std::shared_ptr makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles ); +std::shared_ptr makeHelix( sal_uInt16 nRows ); +std::shared_ptr makeFallLeaving(); +std::shared_ptr makeTurnAround(); +std::shared_ptr makeTurnDown(); +std::shared_ptr makeIris(); +std::shared_ptr makeRochade(); +std::shared_ptr makeVenetianBlinds( bool vertical, int parts ); +std::shared_ptr makeStatic(); +std::shared_ptr makeDissolve(); +std::shared_ptr makeVortex(); +std::shared_ptr makeRipple(); +std::shared_ptr makeGlitter(); +std::shared_ptr makeHoneycomb(); +std::shared_ptr makeNewsflash(); + +/** 2D replacements */ + +std::shared_ptr makeDiamond(); +std::shared_ptr makeFadeSmoothly(); +std::shared_ptr makeFadeThroughBlack(); + +class SceneObject +{ +public: + SceneObject(); + virtual ~SceneObject(); + SceneObject(const SceneObject&) = delete; + SceneObject& operator=(const SceneObject&) = delete; + + 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() {} + + void pushPrimitive (const Primitive &p); + +protected: + /** All the surrounding scene primitives + */ + Primitives_t maPrimitives; + std::vector maFirstIndices; +}; + +struct Vertex +{ + glm::vec3 position; + glm::vec3 normal; + glm::vec2 texcoord; +}; +static_assert(sizeof(Vertex) == (3 + 3 + 2) * 4, "Vertex struct has wrong size/alignment"); + +/** This class is a list of Triangles that will share Operations, and could possibly share +*/ +class Primitive +{ +public: + Primitive() {} + // making copy constructor explicit makes the class un-suitable for use with stl containers + Primitive(const Primitive& rvalue); + Primitive& operator=(const Primitive& rvalue); + + void swap(Primitive& rOther); + + void applyOperations(glm::mat4& matrix, double nTime, double SlideWidthScale, double SlideHeightScale) const; + void display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const; + void display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const; + + /** PushBack a vertex,normal, and tex coord. Each SlideLocation is where on the slide is mapped to this location ( from (0,0) to (1,1) ). This will make sure the correct aspect ratio is used, and helps to make slides begin and end at the correct position. (0,0) is the top left of the slide, and (1,1) is the bottom right. + + @param SlideLocation0 + Location of first Vertex on slide + + @param SlideLocation1 + Location of second Vertex on slide + + @param SlideLocation2 + Location of third Vertex on slide + + */ + void pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2); + + /** guards against directly changing the vertices + + @return + the list of vertices + */ + const glm::vec3& getVertex(int n) const {return Vertices[n].position;} + + /** accessor for the size of the vertices data + + @return + the size in bytes of the Vertices data + */ + int getVerticesSize() const {return Vertices.size() * sizeof(Vertex);} + + /** copies all vertices to the C array passed + + @return + the number of written vertices + */ + int writeVertices(Vertex *location) const { + std::copy(Vertices.begin(), Vertices.end(), location); + return Vertices.size(); + } + + /** list of Operations to be performed on this primitive.These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back. + + @return + the list of Operations + + */ + Operations_t Operations; + +private: + /** list of vertices + */ + std::vector Vertices; +}; + +#endif // INCLUDED_SLIDESHOW_TRANSITION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/TransitionerImpl.cxx new file mode 100644 index 000000000000..6e2f5a98a055 --- /dev/null +++ b/slideshow/source/engine/OGLTrans/TransitionerImpl.cxx @@ -0,0 +1,1339 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#undef IN +#undef OUT +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include "TransitionImpl.hxx" + +#include + +#if OSL_DEBUG_LEVEL > 0 +#include +#endif + +using namespace ::com::sun::star; +using ::com::sun::star::beans::XFastPropertySet; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; + +namespace +{ + +typedef cppu::WeakComponentImplHelper OGLTransitionerImplBase; + +#if OSL_DEBUG_LEVEL > 0 +class TimerContext +{ +public: + explicit TimerContext(OUString const& rWhat) + : m_aWhat(rWhat) + , m_StartTime(std::chrono::steady_clock::now()) + { + } + ~TimerContext() + { + auto const aDuration(std::chrono::steady_clock::now() - m_StartTime); + SAL_INFO("slideshow.opengl", m_aWhat << " took: " << std::chrono::duration_cast(aDuration).count()); + } +private: + OUString const m_aWhat; + std::chrono::steady_clock::time_point const m_StartTime; +}; +#endif + +struct OGLFormat +{ + GLint nInternalFormat; + GLenum eFormat; + GLenum eType; +}; + +/* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr) + */ +int calcComponentOrderIndex(const uno::Sequence& rTags) +{ + using namespace rendering::ColorComponentTag; + + static const sal_Int8 aOrderTable[] = + { + RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA, + RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA, + ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE, + ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED, + }; + + const sal_Int32 nNumComps(rTags.getLength()); + const sal_Int8* pLine=aOrderTable; + for(int i=0; i<4; ++i) + { + int j=0; + while( j<4 && j& pOGLTransition ); + bool initialize( const Reference< presentation::XSlideShowView >& xView, + const Reference< rendering::XBitmap >& xLeavingSlide, + const Reference< rendering::XBitmap >& xEnteringSlide ); + + // XTransition + virtual void SAL_CALL update( double nTime ) + throw (uno::RuntimeException, std::exception) override; + virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView, + const Reference< rendering::XBitmap >& rLeavingBitmap, + const Reference< rendering::XBitmap >& rEnteringBitmap ) + throw (uno::RuntimeException, std::exception) override; + +protected: + void disposeTextures(); + + // WeakComponentImplHelperBase + virtual void SAL_CALL disposing() override; + + bool isDisposed() const + { + return (rBHelper.bDisposed || rBHelper.bInDispose); + } + + void createTexture( GLuint* texID, + bool useMipmap, + uno::Sequence& data, + const OGLFormat* pFormat ); + const OGLFormat* chooseFormats(); + +private: + void impl_initializeFlags( bool const bGLXPresent ); + + void impl_dispose(); + + void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide ); + void impl_prepareSlides(); + + void impl_createTexture( bool useMipmap, uno::Sequence& data, const OGLFormat* pFormat ); + + bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView ); + /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL. + */ + void GLInitSlides(); + + bool impl_prepareTransition(); + void impl_finishTransition(); + +private: + rtl::Reference mpContext; + + /** OpenGL handle to the leaving slide's texture + */ + GLuint maLeavingSlideGL; + /** OpenGL handle to the entering slide's texture + */ + GLuint maEnteringSlideGL; + + Reference< presentation::XSlideShowView > mxView; + Reference< rendering::XIntegerBitmap > mxLeavingBitmap; + Reference< rendering::XIntegerBitmap > mxEnteringBitmap; + + /** raw bytes of the entering bitmap + */ + uno::Sequence maEnteringBytes; + + /** raw bytes of the leaving bitmap + */ + uno::Sequence maLeavingBytes; + + bool mbRestoreSync; + + /** the form the raw bytes are in for the bitmaps + */ + rendering::IntegerBitmapLayout maSlideBitmapLayout; + + /** the size of the slides + */ + geometry::IntegerSize2D maSlideSize; + + /** Our Transition to be used. + */ + std::shared_ptr mpTransition; + +public: + /** whether we are running on ATI fglrx with bug related to textures + */ + bool mbBrokenTexturesATI; + + /** GL version + */ + float mnGLVersion; + + /** + Whether the display has GLX extension on X11, always true otherwise (?) + */ + bool mbValidOpenGLContext; + +#if OSL_DEBUG_LEVEL > 0 + std::chrono::steady_clock::time_point m_UpdateStartTime; + std::chrono::steady_clock::time_point m_UpdateEndTime; + std::chrono::steady_clock::time_point m_StartTime; + std::chrono::steady_clock::time_point m_EndTime; + std::chrono::steady_clock::duration m_TotalUpdateDuration; + int mnFrameCount; +#endif +}; + +bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView, + const Reference< rendering::XBitmap >& xLeavingSlide, + const Reference< rendering::XBitmap >& xEnteringSlide ) +{ + bool const bValidContext( initWindowFromSlideShowView( xView ) ); + impl_initializeFlags( bValidContext ); + + setSlides( xLeavingSlide, xEnteringSlide ); + + CHECK_GL_ERROR(); + return mbValidOpenGLContext; +} + +void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext ) +{ + CHECK_GL_ERROR(); + mbValidOpenGLContext = bValidContext; + if ( bValidContext ) { + mnGLVersion = OpenGLHelper::getGLVersion(); + SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion << "" ); + +#if defined( UNX ) && !defined( MACOSX ) + const GLubyte* vendor = glGetString( GL_VENDOR ); + /* TODO: check for version once the bug in fglrx driver is fixed */ + mbBrokenTexturesATI = (vendor && strcmp( reinterpret_cast(vendor), "ATI Technologies Inc." ) == 0 ); +#endif + } + CHECK_GL_ERROR(); +} + +bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView ) +{ + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed()) + return false; + + mxView.set( xView, UNO_QUERY ); + if( !mxView.is() ) + return false; + +#if OSL_DEBUG_LEVEL > 0 + TimerContext aTimerContext("initWindowFromSlideShowView"); +#endif + + /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx + uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW); + uno::Sequence< uno::Any > aDeviceParams; + ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ); + + OUString aImplName; + aDeviceParams[ 0 ] >>= aImplName; + + sal_Int64 aVal = 0; + aDeviceParams[1] >>= aVal; + + mpContext = OpenGLContext::Create(); + + 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"); + + mpContext->makeCurrent(); + CHECK_GL_ERROR(); + + awt::Rectangle aCanvasArea = mxView->getCanvasArea(); + mpContext->setWinPosAndSize(Point(aCanvasArea.X, aCanvasArea.Y), Size(aCanvasArea.Width, aCanvasArea.Height)); + SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height); + + CHECK_GL_ERROR(); + glEnable(GL_CULL_FACE); + CHECK_GL_ERROR(); + glCullFace(GL_BACK); + CHECK_GL_ERROR(); + glClearColor (0, 0, 0, 0); + CHECK_GL_ERROR(); + glClear(GL_COLOR_BUFFER_BIT); + CHECK_GL_ERROR(); + + mpContext->swapBuffers(); + + glViewport(0, 0, aCanvasArea.Width, aCanvasArea.Height); + CHECK_GL_ERROR(); + + return true; +} + +void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide, + const uno::Reference< rendering::XBitmap >& xEnteringSlide ) +{ + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed()) + return; + + mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW ); + mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW ); + + maSlideSize = mxLeavingBitmap->getSize(); + SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height); + maSlideSize = mxEnteringBitmap->getSize(); + SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height); +} + + +void OGLTransitionerImpl::impl_prepareSlides() +{ + Reference< XFastPropertySet > xLeavingSet( mxLeavingBitmap , UNO_QUERY ); + Reference< XFastPropertySet > xEnteringSet( mxEnteringBitmap , UNO_QUERY ); + + geometry::IntegerRectangle2D aSlideRect; + aSlideRect.X1 = 0; + aSlideRect.X2 = maSlideSize.Width; + aSlideRect.Y1 = 0; + aSlideRect.Y2 = maSlideSize.Height; + + CHECK_GL_ERROR(); + mpContext->sync(); + CHECK_GL_ERROR(); + + maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect); + maEnteringBytes = mxEnteringBitmap->getData(maSlideBitmapLayout, aSlideRect); + + CHECK_GL_ERROR(); + GLInitSlides(); + + SAL_WARN_IF(maSlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now"); + + mpContext->sync(); + + CHECK_GL_ERROR(); + + // synchronized X still gives us much smoother play + // I suspect some issues in above code in slideshow + // synchronize whole transition for now + const GLWindow& rGLWindow(mpContext->getOpenGLWindow()); + mbRestoreSync = rGLWindow.Synchronize(true); +} + +bool OGLTransitionerImpl::impl_prepareTransition() +{ + if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion ) + return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL ); + return false; +} + +void OGLTransitionerImpl::impl_finishTransition() +{ + if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion ) + mpTransition->finish(); +} + +bool OGLTransitionerImpl::setTransition( const std::shared_ptr& pTransition ) +{ + if ( mpTransition ) // already initialized + return true; + + mpTransition = pTransition; + + mpContext->makeCurrent(); + CHECK_GL_ERROR(); + + bool succeeded = impl_prepareTransition(); + if (!succeeded) { + mpTransition = nullptr; + return false; + } + + impl_prepareSlides(); + return true; +} + +void OGLTransitionerImpl::createTexture( GLuint* texID, + bool useMipmap, + uno::Sequence& data, + const OGLFormat* pFormat ) +{ + CHECK_GL_ERROR(); + glDeleteTextures( 1, texID ); + glGenTextures( 1, texID ); + glBindTexture( GL_TEXTURE_2D, *texID ); + 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(); + + impl_createTexture( useMipmap, data, pFormat ); + + SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL"); + CHECK_GL_ERROR(); +} + +namespace +{ + class OGLColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace > + { + private: + uno::Sequence< sal_Int8 > maComponentTags; + uno::Sequence< sal_Int32 > maBitCounts; + + virtual sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) override + { + return rendering::ColorSpaceType::RGB; + } + virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) override + { + return maComponentTags; + } + virtual sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) override + { + return rendering::RenderingIntent::PERCEPTUAL; + } + virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) override + { + return uno::Sequence< beans::PropertyValue >(); + } + virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException, std::exception) override + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const double* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const double* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const double* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( std::size_t i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = 1.0; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( std::size_t i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( std::size_t i=0; iRed/pIn->Alpha; + *pColors++ = pIn->Green/pIn->Alpha; + *pColors++ = pIn->Blue/pIn->Alpha; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + + // XIntegerBitmapColorSpace + virtual sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) override + { + return 32; + } + virtual uno::Sequence< sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) override + { + return maBitCounts; + } + virtual sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) override + { + return util::Endianness::LITTLE; + } + virtual uno::Sequence SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException, std::exception) override + { + if( dynamic_cast(targetColorSpace.get()) ) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence aRes(nLen); + double* pOut( aRes.getArray() ); + for( std::size_t i=0; i aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + } + virtual uno::Sequence< sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor, + const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException, std::exception) override + { + if( dynamic_cast(targetColorSpace.get()) ) + { + // it's us, so simply pass-through the data + return deviceColor; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertIntegerFromARGB(aIntermediate); + } + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertIntegerToARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertIntegerToPARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const std::size_t nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( std::size_t i=0; i SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( std::size_t i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = -1; + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( std::size_t i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const std::size_t nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( std::size_t i=0; iRed/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); + ++pIn; + } + return aRes; + } + + public: + OGLColorSpace() : + maComponentTags(4), + maBitCounts(4) + { + sal_Int8* pTags = maComponentTags.getArray(); + sal_Int32* pBitCounts = maBitCounts.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_RED; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_BLUE; + pTags[3] = rendering::ColorComponentTag::ALPHA; + + pBitCounts[0] = + pBitCounts[1] = + pBitCounts[2] = + pBitCounts[3] = 8; + } + }; + + struct OGLColorSpaceHolder : public rtl::StaticWithInit, OGLColorSpaceHolder> + { + uno::Reference operator()() + { + return new OGLColorSpace(); + } + }; + + uno::Reference + getOGLColorSpace() + { + return OGLColorSpaceHolder::get(); + } +} + +namespace { + +void buildMipmaps( + GLint internalFormat, GLsizei width, GLsizei height, GLenum format, + GLenum type, const void * data) +{ + if (GLEW_ARB_framebuffer_object) { + glTexImage2D( + GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, + data); + glGenerateMipmap(GL_TEXTURE_2D); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glTexImage2D( + GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, + data); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri( + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); +} + +} + +void OGLTransitionerImpl::impl_createTexture( + bool useMipmap, + uno::Sequence& data, + const OGLFormat* pFormat ) +{ + if( !pFormat ) + { + CHECK_GL_ERROR(); + // force-convert color to ARGB8888 int color space + uno::Sequence tempBytes( + maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace( + data, + getOGLColorSpace())); + buildMipmaps( GL_RGBA, + maSlideSize.Width, + maSlideSize.Height, + GL_RGBA, + GL_UNSIGNED_BYTE, + &tempBytes[0]); + + //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) + GLfloat largest_supported_anisotropy; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy); + } else { + if( mpTransition && !mbBrokenTexturesATI && !useMipmap) { + glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] ); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + } else { + buildMipmaps( pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] ); + + //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) + GLfloat largest_supported_anisotropy; + glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy ); + } + } + CHECK_GL_ERROR(); +} + +const OGLFormat* OGLTransitionerImpl::chooseFormats() +{ + const OGLFormat* pDetectedFormat=nullptr; + uno::Reference xIntColorSpace( + maSlideBitmapLayout.ColorSpace); + + if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB || + xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) ) + { + /* table for canvas->OGL format mapping. outer index is number + of color components (0:3, 1:4), then comes bits per pixel + (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra, + 2:argb, 3:abgr) + */ + static const OGLFormat lcl_RGB24[] = + { + // 24 bit RGB + {3, GL_BGR, GL_UNSIGNED_BYTE}, + {3, GL_RGB, GL_UNSIGNED_BYTE}, + {3, GL_BGR, GL_UNSIGNED_BYTE}, + {3, GL_RGB, GL_UNSIGNED_BYTE} + }; + +#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3) + // more format constants available + static const OGLFormat lcl_RGB16[] = + { + // 16 bit RGB + {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, + {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, + {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, + {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5} + }; + + static const OGLFormat lcl_ARGB16_4[] = + { + // 16 bit ARGB + {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, + {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, + {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4}, + {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4} + }; + + static const OGLFormat lcl_ARGB16_5[] = + { + // 16 bit ARGB + {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, + {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, + {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1}, + {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1} + }; + + static const OGLFormat lcl_ARGB32[] = + { + // 32 bit ARGB + {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, + {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, + {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8}, + {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8} + }; + + const uno::Sequence aComponentTags( + xIntColorSpace->getComponentTags()); + const uno::Sequence aComponentBitcounts( + xIntColorSpace->getComponentBitCounts()); + const sal_Int32 nNumComponents( aComponentBitcounts.getLength() ); + const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() ); + + // supported component ordering? + const int nComponentOrderIndex( + calcComponentOrderIndex(aComponentTags)); + if( nComponentOrderIndex != -1 ) + { + switch( nBitsPerPixel ) + { + case 16: + if( nNumComponents == 3 ) + { + pDetectedFormat = &lcl_RGB16[nComponentOrderIndex]; + } + else if( nNumComponents == 4 ) + { + if( aComponentBitcounts[1] == 4 ) + { + pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex]; + } + else if( aComponentBitcounts[1] == 5 ) + { + pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex]; + } + } + break; + case 24: + if( nNumComponents == 3 ) + { + pDetectedFormat = &lcl_RGB24[nComponentOrderIndex]; + } + break; + case 32: + if ( nNumComponents == 4 ) + { + pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex]; + } + break; + } + } +#else + const uno::Sequence aComponentTags( + xIntColorSpace->getComponentTags()); + const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags)); + if( aComponentTags.getLength() == 3 && + nComponentOrderIndex != -1 && + xIntColorSpace->getBitsPerPixel() == 24 ) + { + pDetectedFormat = &lcl_RGB24[nComponentOrderIndex]; + } +#endif + } + + return pDetectedFormat; +} + +void OGLTransitionerImpl::GLInitSlides() +{ + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion) + return; + +#if OSL_DEBUG_LEVEL > 0 + TimerContext aTimerContext("texture creation"); +#endif + + mpContext->makeCurrent(); + + const OGLFormat* pFormat = chooseFormats(); + + CHECK_GL_ERROR(); + createTexture( &maLeavingSlideGL, + mpTransition->getSettings().mbUseMipMapLeaving, + maLeavingBytes, + pFormat ); + + createTexture( &maEnteringSlideGL, + mpTransition->getSettings().mbUseMipMapEntering, + maEnteringBytes, + pFormat ); + + CHECK_GL_ERROR(); + mpContext->sync(); + CHECK_GL_ERROR(); +} + +void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException, std::exception) +{ +#if OSL_DEBUG_LEVEL > 0 + mnFrameCount ++; + m_UpdateStartTime = std::chrono::steady_clock::now(); + if( mnFrameCount == 1 ) { + m_StartTime = m_UpdateStartTime; + m_TotalUpdateDuration = std::chrono::seconds(0); + } +#endif + osl::MutexGuard const guard( m_aMutex ); + + if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion) + return; + + mpContext->makeCurrent(); + CHECK_GL_ERROR(); + + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + CHECK_GL_ERROR(); + + const GLWindow& rGLWindow(mpContext->getOpenGLWindow()); + mpTransition->display( nTime, maLeavingSlideGL, maEnteringSlideGL, + maSlideSize.Width, maSlideSize.Height, + static_cast(rGLWindow.Width), + static_cast(rGLWindow.Height) ); + + mpContext->swapBuffers(); + + mpContext->show(); + mpContext->sync(); + CHECK_GL_ERROR(); + +#if OSL_DEBUG_LEVEL > 0 + m_UpdateEndTime = std::chrono::steady_clock::now(); + + SAL_INFO("slideshow.opengl", "update time: " << nTime); + SAL_INFO("slideshow.opengl", "update took: " << std::chrono::duration_cast(m_UpdateEndTime - m_UpdateStartTime).count()); + m_TotalUpdateDuration += (m_UpdateEndTime - m_UpdateStartTime); +#endif +} + +void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView, + const Reference< rendering::XBitmap >& rLeavingBitmap, + const Reference< rendering::XBitmap >& rEnteringBitmap ) + throw (uno::RuntimeException, std::exception) +{ + SAL_INFO("slideshow.opengl", "transitioner: view changed"); + + impl_dispose(); + + initWindowFromSlideShowView( rView ); + setSlides( rLeavingBitmap, rEnteringBitmap ); + impl_prepareSlides(); + impl_prepareTransition(); +} + +void OGLTransitionerImpl::disposeTextures() +{ + mpContext->makeCurrent(); + CHECK_GL_ERROR(); + + glDeleteTextures(1,&maLeavingSlideGL); + maLeavingSlideGL = 0; + glDeleteTextures(1,&maEnteringSlideGL); + maEnteringSlideGL = 0; + + CHECK_GL_ERROR(); +} + +void OGLTransitionerImpl::impl_dispose() +{ + mpContext->makeCurrent(); + CHECK_GL_ERROR(); + + impl_finishTransition(); + disposeTextures(); + if( mpContext.is() ) + mpContext->dispose(); + mpContext.clear(); +} + +// we are about to be disposed (someone call dispose() on us) +void OGLTransitionerImpl::disposing() +{ + osl::MutexGuard const guard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + SAL_INFO("slideshow.opengl", "dispose " << this); + if( mnFrameCount ) { + m_EndTime = std::chrono::steady_clock::now(); + auto const duration = m_EndTime - m_StartTime; + SAL_INFO("slideshow.opengl", + "whole transition (frames: " << mnFrameCount + << ") took: " << std::chrono::duration_cast(duration).count() + << " fps: " + << (((double)mnFrameCount*1000000000.0)/std::chrono::duration_cast(duration).count()) + << " time spent in updates: " << std::chrono::duration_cast(m_TotalUpdateDuration).count() + << " percentage of transition time: " + << (100*(((double)std::chrono::duration_cast(m_TotalUpdateDuration).count())/((double)std::chrono::duration_cast(duration).count()))) + << '%' + ); + } +#endif + + if (mbRestoreSync && bool(mpContext.is())) { + // try to reestablish synchronize state + const char* sal_synchronize = getenv("SAL_SYNCHRONIZE"); + mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' ); + } + + impl_dispose(); + + mpTransition.reset(); + + mxLeavingBitmap.clear(); + mxEnteringBitmap.clear(); + mxView.clear(); +} + +OGLTransitionerImpl::OGLTransitionerImpl() + : OGLTransitionerImplBase(m_aMutex) + , mpContext() + , maLeavingSlideGL(0) + , maEnteringSlideGL(0) + , mxView() + , maEnteringBytes() + , maLeavingBytes() + , mbRestoreSync(false) + , maSlideBitmapLayout() + , maSlideSize() + , mbBrokenTexturesATI(false) + , mnGLVersion(0) + , mbValidOpenGLContext(false) +#if OSL_DEBUG_LEVEL > 0 + , mnFrameCount(0) +#endif +{ +} + +typedef cppu::WeakComponentImplHelper OGLTransitionFactoryImplBase; + +class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase +{ +public: + explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) : + OGLTransitionFactoryImplBase(m_aMutex) + {} + + // XTransitionFactory + virtual sal_Bool SAL_CALL hasTransition( sal_Int16 transitionType, sal_Int16 transitionSubType ) throw (uno::RuntimeException, std::exception) override + { + // A set of css::animation::TransitionSubType that don't have any meaning (in the SMIL 2.0 + // standard) for MISCSHAPEWIPE have been chosen to refer to some of these "fancy" optional + // transitions. (The only subtypes of 'miscShapeWipe' defined in the standard are 'heart' + // and 'keyhole'.) The set of subtypes used seems to be a bit random; it starts from the + // beginning of the list (in the order (numeric) in our TransitionSubType set of constants) + // but then jumps a bit randomly. The numeric values as such have no meaning, but still. + + if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) { + switch( transitionSubType ) + { + case animations::TransitionSubType::LEFTTORIGHT: // 1 + case animations::TransitionSubType::TOPTOBOTTOM: // 2 + case animations::TransitionSubType::TOPLEFT: // 3 + case animations::TransitionSubType::TOPRIGHT: // 4 + case animations::TransitionSubType::BOTTOMRIGHT: // 5 + case animations::TransitionSubType::BOTTOMLEFT: // 6 + case animations::TransitionSubType::TOPCENTER: // 7 + case animations::TransitionSubType::RIGHTCENTER: // 8 + case animations::TransitionSubType::BOTTOMCENTER: // 9 + case animations::TransitionSubType::CORNERSIN: // 11 + case animations::TransitionSubType::CORNERSOUT: // 12 + case animations::TransitionSubType::VERTICAL: // 13 + case animations::TransitionSubType::HORIZONTAL: // 14 + case animations::TransitionSubType::DIAMOND: // 26 + case animations::TransitionSubType::CIRCLE: // 27 + case animations::TransitionSubType::HEART: // 31 + case animations::TransitionSubType::FANOUTHORIZONTAL: // 55 + case animations::TransitionSubType::ACROSS: // 108 + return true; + + default: + return false; + } + } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) { + return true; + } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) { + return true; + } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) { + return true; + } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) { + return true; + } else + return false; + } + + virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition( + sal_Int16 transitionType, + sal_Int16 transitionSubType, + const uno::Reference< presentation::XSlideShowView >& view, + const uno::Reference< rendering::XBitmap >& leavingBitmap, + const uno::Reference< rendering::XBitmap >& enteringBitmap ) + throw (uno::RuntimeException, std::exception) override + { + if( !hasTransition( transitionType, transitionSubType ) ) + return uno::Reference< presentation::XTransition >(); + + rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() ); + if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) ) + return uno::Reference< presentation::XTransition >(); + + std::shared_ptr pTransition; + + if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) { + switch( transitionSubType ) + { + case animations::TransitionSubType::LEFTTORIGHT: + pTransition = makeFallLeaving(); + break; + case animations::TransitionSubType::TOPTOBOTTOM: + pTransition = makeTurnAround(); + break; + case animations::TransitionSubType::TOPLEFT: + pTransition = makeIris(); + break; + case animations::TransitionSubType::TOPRIGHT: + pTransition = makeTurnDown(); + break; + case animations::TransitionSubType::BOTTOMRIGHT: + pTransition = makeRochade(); + break; + case animations::TransitionSubType::BOTTOMLEFT: + pTransition = makeVenetianBlinds( true, 8 ); + break; + case animations::TransitionSubType::TOPCENTER: + pTransition = makeVenetianBlinds( false, 6 ); + break; + case animations::TransitionSubType::RIGHTCENTER: + pTransition = makeStatic(); + break; + case animations::TransitionSubType::BOTTOMCENTER: + pTransition = makeDissolve(); + break; + case animations::TransitionSubType::CORNERSIN: + pTransition = makeInsideCubeFaceToLeft(); + break; + case animations::TransitionSubType::CORNERSOUT: + pTransition = makeOutsideCubeFaceToLeft(); + break; + case animations::TransitionSubType::VERTICAL: + pTransition = makeVortex(); + break; + case animations::TransitionSubType::HORIZONTAL: + pTransition = makeRipple(); + break; + case animations::TransitionSubType::CIRCLE: + pTransition = makeRevolvingCircles(8,128); + break; + case animations::TransitionSubType::FANOUTHORIZONTAL: + pTransition = makeHelix(20); + break; + case animations::TransitionSubType::ACROSS: + pTransition = makeNByMTileFlip(8,6); + break; + case animations::TransitionSubType::DIAMOND: + pTransition = makeGlitter(); + break; + case animations::TransitionSubType::HEART: + pTransition = makeHoneycomb(); + break; + } + } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) { + pTransition = makeFadeSmoothly(); + } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) { + pTransition = makeFadeThroughBlack(); + } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) { + pTransition = makeDiamond(); + } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) { + pTransition = makeNewsflash(); + } + + if ( !pTransition || !xRes->setTransition(pTransition) ) + return uno::Reference< presentation::XTransition >(); + + return uno::Reference(xRes.get()); + } +}; + +} + +namespace sdecl = comphelper::service_decl; + const sdecl::ServiceDecl OGLTransitionFactoryDecl( + sdecl::class_(), + "com.sun.star.comp.presentation.OGLTransitionFactory", + "com.sun.star.presentation.TransitionFactory" ); + +// The C shared lib entry points +extern "C" +SAL_DLLPUBLIC_EXPORT void* SAL_CALL ogltrans_component_getFactory( sal_Char const* pImplName, + void*, void* ) +{ + return sdecl::component_getFactoryHelper( pImplName, {&OGLTransitionFactoryDecl} ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.cxx deleted file mode 100644 index c61209fea3e0..000000000000 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.cxx +++ /dev/null @@ -1,223 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2015 by Collabora, Ltd. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include - -#include -#include - -#include "OGLTrans_Operation.hxx" - -SRotate::SRotate(const glm::vec3& Axis, const glm::vec3& Origin, - double Angle, bool bInter, double T0, double T1): - Operation(bInter, T0, T1), - axis(Axis), - origin(Origin), - angle(Angle) -{ -} - -SScale::SScale(const glm::vec3& Scale, const glm::vec3& Origin, - bool bInter, double T0, double T1): - Operation(bInter, T0, T1), - scale(Scale), - origin(Origin) -{ -} - -RotateAndScaleDepthByWidth::RotateAndScaleDepthByWidth(const glm::vec3& Axis, - const glm::vec3& Origin, double Angle, bool bScale, bool bInter, double T0, double T1): - Operation(bInter, T0, T1), - axis(Axis), - origin(Origin), - angle(Angle), - scale(bScale) -{ -} - -RotateAndScaleDepthByHeight::RotateAndScaleDepthByHeight(const glm::vec3& Axis, - const glm::vec3& Origin, double Angle, bool bScale, bool bInter, double T0, double T1): - Operation(bInter, T0, T1), - axis(Axis), - origin(Origin), - angle(Angle), - scale(bScale) -{ -} - - -STranslate::STranslate(const glm::vec3& Vector, bool bInter, double T0, double T1): - Operation(bInter, T0, T1), - vector(Vector) -{ -} - -std::shared_ptr -makeSRotate(const glm::vec3& Axis,const glm::vec3& Origin,double Angle,bool bInter, double T0, double T1) -{ - return std::make_shared(Axis, Origin, Angle, bInter, T0, T1); -} - -std::shared_ptr -makeSScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1) -{ - return std::make_shared(Scale, Origin, bInter, T0, T1); -} - -std::shared_ptr -makeSTranslate(const glm::vec3& Vector,bool bInter, double T0, double T1) -{ - return std::make_shared(Vector, bInter, T0, T1); -} - -std::shared_ptr -makeSEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1) -{ - return std::make_shared(dWidth, dHeight, dStartPosition, dEndPosition, bInter, T0, T1); -} - -std::shared_ptr -makeRotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1) -{ - return std::make_shared(Axis, Origin, Angle, bScale, bInter, T0, T1); -} - -std::shared_ptr -makeRotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle,bool bScale, bool bInter, double T0, double T1) -{ - return std::make_shared(Axis, Origin, Angle, bScale, bInter, T0, T1); -} - -inline double intervalInter(double t, double T0, double T1) -{ - return ( t - T0 ) / ( T1 - T0 ); -} - -void STranslate::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - matrix = glm::translate(matrix, glm::vec3(SlideWidthScale*t*vector.x, SlideHeightScale*t*vector.y, t*vector.z)); -} - -void SRotate::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, origin.z); - glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); - matrix = glm::translate(matrix, translation_vector); - matrix = glm::scale(matrix, scale_vector); - matrix = glm::rotate(matrix, static_cast(t*angle), axis); - matrix = glm::scale(matrix, 1.f / scale_vector); - matrix = glm::translate(matrix, -translation_vector); -} - -void SScale::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, origin.z); - matrix = glm::translate(matrix, translation_vector); - matrix = glm::scale(matrix, static_cast(1 - t) + static_cast(t) * scale); - matrix = glm::translate(matrix, -translation_vector); -} - -void RotateAndScaleDepthByWidth::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, SlideWidthScale*origin.z); - glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); - matrix = glm::translate(matrix, translation_vector); - if (scale) - matrix = glm::scale(matrix, scale_vector); - matrix = glm::rotate(matrix, static_cast(t*angle), axis); - if (scale) - matrix = glm::scale(matrix, 1.f / scale_vector); - matrix = glm::translate(matrix, -translation_vector); -} - -void RotateAndScaleDepthByHeight::interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - glm::vec3 translation_vector(SlideWidthScale*origin.x, SlideHeightScale*origin.y, SlideHeightScale*origin.z); - glm::vec3 scale_vector(SlideWidthScale * SlideWidthScale, SlideHeightScale * SlideHeightScale, 1); - matrix = glm::translate(matrix, translation_vector); - if (scale) - matrix = glm::scale(matrix, scale_vector); - matrix = glm::rotate(matrix, static_cast(t*angle), axis); - if (scale) - matrix = glm::scale(matrix, 1.f / scale_vector); - matrix = glm::translate(matrix, -translation_vector); -} - -SEllipseTranslate::SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, - double dEndPosition, bool bInter, double T0, double T1): - Operation(bInter, T0, T1) -{ - width = dWidth; - height = dHeight; - startPosition = dStartPosition; - endPosition = dEndPosition; -} - -void SEllipseTranslate::interpolate(glm::mat4& matrix, double t, double /* SlideWidthScale */, double /* SlideHeightScale */) const -{ - if(t <= mnT0) - return; - if(!mbInterpolate || t > mnT1) - t = mnT1; - t = intervalInter(t,mnT0,mnT1); - - double a1, a2, x, y; - a1 = startPosition*2*M_PI; - a2 = (startPosition + t*(endPosition - startPosition))*2*M_PI; - x = width*(cos (a2) - cos (a1))/2; - y = height*(sin (a2) - sin (a1))/2; - - matrix = glm::translate(matrix, glm::vec3(x, 0, y)); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.hxx deleted file mode 100644 index 12d0a4842278..000000000000 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_Operation.hxx +++ /dev/null @@ -1,272 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2015 by Collabora, Ltd. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef INCLUDED_OGLTRANS_OPERATIONS_HXX_ -#define INCLUDED_OGLTRANS_OPERATIONS_HXX_ - -#include -#include - -#include - -/** This class is to be derived to make any operation (transform) you may need in order to construct your transitions -*/ -class Operation -{ -public: - virtual ~Operation(){} - Operation(const Operation&) = delete; - Operation& operator=(const Operation&) = delete; - -protected: - /** Should this operation be interpolated . If TRUE, the transform will smoothly move from making no difference from t = 0.0 to mnT0 to being completely transformed from t = mnT1 to 1. If FALSE, the transform will be ineffectual from t = 0 to mnT0, and completely transformed from t = mnT0 to 1. - */ - bool mbInterpolate; - - /** time to begin the transformation - */ - double mnT0; - - /** time to finish the transformation - */ - double mnT1; -public: - /** this is the function that is called to give the Operation to OpenGL. - - @param t - time from t = 0 to t = 1 - - @param SlideWidthScale - width of slide divided by width of window - - @param SlideHeightScale - height of slide divided by height of window - - */ - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const = 0; - -protected: - Operation(bool bInterpolate, double nT0, double nT1): - mbInterpolate(bInterpolate), mnT0(nT0), mnT1(nT1){} -}; - -/** this class is a generic CounterClockWise(CCW) rotation with an axis angle -*/ -class SRotate: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - /** Constructor - - @param Axis - axis to rotate about - - @param Origin - position that rotation axis runs through - - @param Angle - angle in radians of CCW rotation - - @param bInter - see Operation - - @param T0 - transformation starting time - - @param T1 - transformation ending time - - */ - SRotate(const glm::vec3& Axis, const glm::vec3& Origin, double Angle, - bool bInter, double T0, double T1); - virtual ~SRotate() override {} -private: - /** axis to rotate CCW about - */ - glm::vec3 axis; - - /** position that rotation axis runs through - */ - glm::vec3 origin; - - /** angle in radians of CCW rotation - */ - double angle; -}; - -std::shared_ptr -makeSRotate(const glm::vec3& Axis, const glm::vec3& Origin, double Angle, - bool bInter, double T0, double T1); - -/** scaling transformation -*/ -class SScale: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - /** Constructor - - @param Scale - amount to scale by - - @param Origin - position that rotation axis runs through - - @param bInter - see Operation - - @param T0 - transformation starting time - - @param T1 - transformation ending time - - */ - SScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1); - virtual ~SScale() override {} -private: - glm::vec3 scale; - glm::vec3 origin; -}; - -std::shared_ptr -makeSScale(const glm::vec3& Scale, const glm::vec3& Origin,bool bInter, double T0, double T1); - -/** translation transformation -*/ -class STranslate: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - /** Constructor - - @param Vector - vector to translate - - @param bInter - see Operation - - @param T0 - transformation starting time - - @param T1 - transformation ending time - - */ - STranslate(const glm::vec3& Vector,bool bInter, double T0, double T1); - virtual ~STranslate() override {} -private: - /** vector to translate by - */ - glm::vec3 vector; -}; - -std::shared_ptr -makeSTranslate(const glm::vec3& Vector,bool bInter, double T0, double T1); - -/** translation transformation -*/ -class SEllipseTranslate: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - /** Constructor - - @param Vector - vector to translate - - @param bInter - see Operation - - @param T0 - transformation starting time - - @param T1 - transformation ending time - - */ - SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1); - virtual ~SEllipseTranslate() override {} -private: - /** width and length of the ellipse - */ - double width, height; - - /** start and end position on the ellipse <0,1> - */ - double startPosition; - double endPosition; -}; - -std::shared_ptr -makeSEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1); - -/** Same as SRotate, except the depth is scaled by the width of the slide divided by the width of the window. -*/ -class RotateAndScaleDepthByWidth: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - RotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); - virtual ~RotateAndScaleDepthByWidth() override {} -private: - glm::vec3 axis; - glm::vec3 origin; - double angle; - bool scale; -}; - -std::shared_ptr -makeRotateAndScaleDepthByWidth(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); - -/** Same as SRotate, except the depth is scaled by the width of the slide divided by the height of the window. -*/ -class RotateAndScaleDepthByHeight: public Operation -{ -public: - virtual void interpolate(glm::mat4& matrix, double t, double SlideWidthScale, double SlideHeightScale) const override; - - RotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); - virtual ~RotateAndScaleDepthByHeight() override {} -private: - glm::vec3 axis; - glm::vec3 origin; - double angle; - bool scale; -}; - -std::shared_ptr -makeRotateAndScaleDepthByHeight(const glm::vec3& Axis,const glm::vec3& Origin,double Angle, bool bScale, bool bInter, double T0, double T1); - -#endif // INCLUDED_SLIDESHOW_OPERATIONS_HXX_ - -/* 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 deleted file mode 100644 index a7e398f8221e..000000000000 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.cxx +++ /dev/null @@ -1,2283 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "OGLTrans_TransitionImpl.hxx" -#include "OGLTrans_Operation.hxx" -#include - -TransitionScene::TransitionScene(TransitionScene const& rOther) - : maLeavingSlidePrimitives(rOther.maLeavingSlidePrimitives) - , maEnteringSlidePrimitives(rOther.maEnteringSlidePrimitives) - , maOverallOperations(rOther.maOverallOperations) - , maSceneObjects(rOther.maSceneObjects) -{ -} - -TransitionScene& TransitionScene::operator=(const TransitionScene& rOther) -{ - TransitionScene aTmp(rOther); - swap(aTmp); - return *this; -} - -void TransitionScene::swap(TransitionScene& rOther) -{ - using std::swap; - - swap(maLeavingSlidePrimitives, rOther.maLeavingSlidePrimitives); - swap(maEnteringSlidePrimitives, rOther.maEnteringSlidePrimitives); - swap(maOverallOperations, rOther.maOverallOperations); - swap(maSceneObjects, rOther.maSceneObjects); -} - -OGLTransitionImpl::~OGLTransitionImpl() -{ -} - -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(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(); - } -} - -static std::vector 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(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY)); - - std::vector 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; -} - -bool OGLTransitionImpl::prepare( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) -{ - m_nProgramObject = makeShader(); - 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); - } - - 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(); - - m_nPrimitiveTransformLocation = glGetUniformLocation( m_nProgramObject, "u_primitiveTransformMatrix" ); - m_nSceneTransformLocation = glGetUniformLocation( m_nProgramObject, "u_sceneTransformMatrix" ); - m_nOperationsTransformLocation = glGetUniformLocation( m_nProgramObject, "u_operationsTransformMatrix" ); - m_nTimeLocation = glGetUniformLocation( m_nProgramObject, "time" ); - - glGenVertexArrays(1, &m_nVertexArrayObject); - glBindVertexArray(m_nVertexArrayObject); - - 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) { - glEnableVertexAttribArray(m_nPositionLocation); - glVertexAttribPointer( m_nPositionLocation, 3, GL_FLOAT, false, sizeof(Vertex), reinterpret_cast(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(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(offsetof(Vertex, texcoord)) ); - CHECK_GL_ERROR(); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); - - prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); - return true; -} - -void OGLTransitionImpl::finish() -{ - const SceneObjects_t& rSceneObjects(maScene.getSceneObjects()); - for(size_t i(0); i != rSceneObjects.size(); ++i) { - rSceneObjects[i]->finish(); - } - - finishTransition(); - - CHECK_GL_ERROR(); - if( m_nProgramObject ) { - glDeleteBuffers(1, &m_nVertexBufferObject); - m_nVertexBufferObject = 0; - glDeleteVertexArrays(1, &m_nVertexArrayObject); - m_nVertexArrayObject = 0; - glDeleteProgram( m_nProgramObject ); - m_nProgramObject = 0; - } - CHECK_GL_ERROR(); -} - -void OGLTransitionImpl::prepare( double, double, double, double, double ) -{ -} - -void OGLTransitionImpl::finish( double, double, double, double, double ) -{ -} - -void OGLTransitionImpl::prepareTransition( sal_Int32, sal_Int32 ) -{ -} - -void OGLTransitionImpl::finishTransition() -{ -} - -void OGLTransitionImpl::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - - glUniform1f( m_nTimeLocation, nTime ); - - glActiveTexture( GL_TEXTURE2 ); - glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex ); - glActiveTexture( GL_TEXTURE0 ); - - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); -} - -void OGLTransitionImpl::display( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, - double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) -{ - const double SlideWidthScale = SlideWidth/DispWidth; - const double SlideHeightScale = SlideHeight/DispHeight; - - CHECK_GL_ERROR(); - glBindVertexArray(m_nVertexArrayObject); - prepare( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight ); - - CHECK_GL_ERROR(); - displaySlides_( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); - displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight ); - CHECK_GL_ERROR(); -} - -void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale ) -{ - const Operations_t& rOverallOperations(maScene.getOperations()); - glm::mat4 matrix; - for(size_t i(0); i != rOverallOperations.size(); ++i) - rOverallOperations[i]->interpolate(matrix, nTime, SlideWidthScale, SlideHeightScale); - 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::const_iterator first) -{ - for (const Primitive& primitive: primitives) - primitive.display(primitiveTransformLocation, nTime, WidthScale, HeightScale, *first++); -} - -void -OGLTransitionImpl::displaySlide( - const double nTime, - const sal_Int32 glSlideTex, const Primitives_t& primitives, - double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - glBindTexture(GL_TEXTURE_2D, glSlideTex); - 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(); -} - -void -OGLTransitionImpl::displayUnbufferedSlide( - const double nTime, - const sal_Int32 glSlideTex, const Primitives_t& primitives, - double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - glPushMatrix(); - CHECK_GL_ERROR(); - glBindTexture(GL_TEXTURE_2D, glSlideTex); - CHECK_GL_ERROR(); - glBindVertexArray(0); - CHECK_GL_ERROR(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); - if (m_nSceneTransformLocation != -1) { - glUniformMatrix4fv(m_nSceneTransformLocation, 1, false, glm::value_ptr(glm::mat4())); - CHECK_GL_ERROR(); - } - for (const Primitive& primitive: primitives) - primitive.display(m_nPrimitiveTransformLocation, nTime, SlideWidthScale, SlideHeightScale); - CHECK_GL_ERROR(); - glBindVertexArray(m_nVertexArrayObject); - CHECK_GL_ERROR(); - glBindBuffer(GL_ARRAY_BUFFER, m_nVertexBufferObject); - CHECK_GL_ERROR(); - glPopMatrix(); - CHECK_GL_ERROR(); -} - -void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) -{ - const SceneObjects_t& rSceneObjects(maScene.getSceneObjects()); - 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(); -} - -void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const -{ - glm::mat4 matrix; - applyOperations( matrix, nTime, WidthScale, HeightScale ); - - CHECK_GL_ERROR(); - if (primitiveTransformLocation != -1) { - glUniformMatrix4fv(primitiveTransformLocation, 1, false, glm::value_ptr(matrix)); - CHECK_GL_ERROR(); - } - - glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - CHECK_GL_ERROR(); - glEnableClientState( GL_VERTEX_ARRAY ); - CHECK_GL_ERROR(); - glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &Vertices[0] ); - CHECK_GL_ERROR(); - glDrawArrays( GL_TRIANGLES, 0, getVerticesSize() ); - CHECK_GL_ERROR(); - glPopClientAttrib(); - - CHECK_GL_ERROR(); -} - -void Primitive::display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const -{ - glm::mat4 matrix; - applyOperations( matrix, nTime, WidthScale, HeightScale ); - - 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(); -} - -void Primitive::applyOperations(glm::mat4& matrix, double nTime, double WidthScale, double HeightScale) const -{ - for(const auto & rOperation : Operations) - rOperation->interpolate(matrix, nTime, WidthScale, HeightScale); - matrix = glm::scale(matrix, glm::vec3(WidthScale, HeightScale, 1)); -} - -void SceneObject::display(GLint sceneTransformLocation, GLint primitiveTransformLocation, double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight ) const -{ - // fixme: allow various model spaces, now we make it so that - // it is regular -1,-1 to 1,1, where the whole display fits in - glm::mat4 matrix; - if (DispHeight > DispWidth) - matrix = glm::scale(matrix, glm::vec3(DispHeight/DispWidth, 1, 1)); - else - matrix = glm::scale(matrix, glm::vec3(1, DispWidth/DispHeight, 1)); - 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(); -} - -void SceneObject::pushPrimitive(const Primitive &p) -{ - maPrimitives.push_back(p); -} - -SceneObject::SceneObject() - : maPrimitives() -{ -} - -SceneObject::~SceneObject() -{ -} - -namespace -{ - -class Iris : public SceneObject -{ -public: - Iris() = default; - - 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(GLuint program) -{ - CHECK_GL_ERROR(); - static const GLubyte img[3] = { 80, 80, 80 }; - - glGenTextures(1, &maTexture); - glBindTexture(GL_TEXTURE_2D, maTexture); - 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_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(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(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(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(); -} - -} - -namespace -{ - -class ReflectionTransition : public OGLTransitionImpl -{ -public: - ReflectionTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : OGLTransitionImpl(rScene, rSettings) - {} - -private: - virtual GLuint makeShader() const override; - virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; - - virtual void prepareTransition( sal_Int32, sal_Int32 ) override { - glDisable(GL_CULL_FACE); - } - - virtual void finishTransition() override { - glEnable(GL_CULL_FACE); - } -}; - -GLuint ReflectionTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "reflectionVertexShader", "reflectionFragmentShader" ); -} - -void ReflectionTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, - double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - - sal_Int32 texture; - Primitives_t slide; - if (nTime < 0.5) { - texture = glLeavingSlideTex; - slide = getScene().getLeavingSlide(); - } else { - texture = glEnteringSlideTex; - slide = getScene().getEnteringSlide(); - } - - displaySlide( nTime, texture, slide, SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); -} - -std::shared_ptr -makeReflectionTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const Operations_t& rOverallOperations, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t()), - rSettings); -} - -} - -namespace -{ - -class SimpleTransition : public OGLTransitionImpl -{ -public: - SimpleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : OGLTransitionImpl(rScene, rSettings) - { - } - -private: - virtual GLuint makeShader() const override; - - virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; -}; - -GLuint SimpleTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "basicVertexShader", "basicFragmentShader" ); -} - -void SimpleTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, - double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - - CHECK_GL_ERROR(); - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); -} - -std::shared_ptr -makeSimpleTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const Operations_t& rOverallOperations, - const SceneObjects_t& rSceneObjects, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, rSceneObjects), - rSettings); -} - -std::shared_ptr -makeSimpleTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const Operations_t& rOverallOperations, - const TransitionSettings& rSettings = TransitionSettings()) -{ - return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, rOverallOperations, SceneObjects_t(), rSettings); -} - -std::shared_ptr -makeSimpleTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const SceneObjects_t& rSceneObjects, - const TransitionSettings& rSettings) -{ - return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), rSceneObjects, rSettings); -} - -std::shared_ptr -makeSimpleTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings = TransitionSettings()) -{ - return makeSimpleTransition(rLeavingSlidePrimitives, rEnteringSlidePrimitives, Operations_t(), SceneObjects_t(), rSettings); -} - -} - -std::shared_ptr makeOutsideCubeFaceToLeft() -{ - Primitive Slide; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),90,false,false,0.0,1.0)); - - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back(Slide); - - Operations_t aOperations; - aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,-1),-90,false,true,0.0,1.0)); - - return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations); -} - -std::shared_ptr makeInsideCubeFaceToLeft() -{ - Primitive Slide; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),-90,false,false,0.0,1.0)); - - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back(Slide); - - Operations_t aOperations; - aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,1),90,false,true,0.0,1.0)); - - return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations); -} - -std::shared_ptr makeFallLeaving() -{ - Primitive Slide; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(1,0,0),glm::vec3(0,-1,0), 90,true,true,0.0,1.0)); - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back(Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapEntering = false; - - return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings); -} - -std::shared_ptr makeTurnAround() -{ - Primitive Slide; - TransitionSettings aSettings; - aSettings.mnRequiredGLVersion = 3.0; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); - aLeavingPrimitives.push_back(Slide); - - Slide.Operations.clear(); - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0),-180,true,false,0.0,1.0)); - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); - aEnteringPrimitives.push_back(Slide); - - Operations_t aOperations; - aOperations.push_back(makeSTranslate(glm::vec3(0, 0, -1.5),true, 0, 0.5)); - aOperations.push_back(makeSTranslate(glm::vec3(0, 0, 1.5), true, 0.5, 1)); - aOperations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0, 1, 0),glm::vec3(0, 0, 0), -180, true, true, 0.0, 1.0)); - - return makeReflectionTransition(aLeavingPrimitives, aEnteringPrimitives, aOperations, aSettings); -} - -std::shared_ptr makeTurnDown() -{ - Primitive Slide; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back(Slide); - - Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 0.0001), false, -1.0, 0.0)); - Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), -90, true, 0.0, 1.0)); - Slide.Operations.push_back(makeSRotate (glm::vec3(0, 0, 1), glm::vec3(-1, 1, 0), 90, false, -1.0, 0.0)); - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back(Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = false; - - return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSettings); -} - -std::shared_ptr makeIris() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aEnteringPrimitives; - aEnteringPrimitives.push_back (Slide); - - Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.000001), false, -1, 0)); - Slide.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, -0.000002), false, 0.5, 1)); - Primitives_t aLeavingPrimitives; - aLeavingPrimitives.push_back (Slide); - - - Primitive irisPart, part; - int i, nSteps = 24, nParts = 7; - double t = 1.0/nSteps, lx = 1, ly = 0, of=2.2, f=1.42; - - for (i=1; i<=nSteps; i++) { - double x = cos ((3*2*M_PI*t)/nParts); - double y = -sin ((3*2*M_PI*t)/nParts); - double cx = (f*x + 1)/2; - double cy = (f*y + 1)/2; - double lcx = (f*lx + 1)/2; - double lcy = (f*ly + 1)/2; - double cxo = (of*x + 1)/2; - double cyo = (of*y + 1)/2; - double lcxo = (of*lx + 1)/2; - double lcyo = (of*ly + 1)/2; - irisPart.pushTriangle (glm::vec2 (lcx, lcy), - glm::vec2 (lcxo, lcyo), - glm::vec2 (cx, cy)); - irisPart.pushTriangle (glm::vec2 (cx, cy), - glm::vec2 (lcxo, lcyo), - glm::vec2 (cxo, cyo)); - lx = x; - ly = y; - t += 1.0/nSteps; - } - - std::shared_ptr pIris = std::make_shared(); - double angle = 87; - - for (i = 0; i < nParts; i++) { - irisPart.Operations.clear (); - double rx, ry; - - rx = cos ((2*M_PI*i)/nParts); - ry = sin ((2*M_PI*i)/nParts); - irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), angle, true, 0.0, 0.5)); - irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(rx, ry, 0), -angle, true, 0.5, 1)); - if (i > 0) { - irisPart.Operations.push_back (makeSTranslate (glm::vec3(rx, ry, 0), false, -1, 0)); - irisPart.Operations.push_back (makeSRotate (glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), i*360.0/nParts, false, -1, 0)); - irisPart.Operations.push_back (makeSTranslate (glm::vec3(-1, 0, 0), false, -1, 0)); - } - irisPart.Operations.push_back(makeSTranslate(glm::vec3(0, 0, 1), false, -2, 0.0)); - irisPart.Operations.push_back (makeSRotate (glm::vec3(1, .5, 0), glm::vec3(1, 0, 0), -30, false, -1, 0)); - pIris->pushPrimitive (irisPart); - } - - SceneObjects_t aSceneObjects; - aSceneObjects.push_back (pIris); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeSimpleTransition(aLeavingPrimitives, aEnteringPrimitives, aSceneObjects, aSettings); -} - -namespace -{ - -class RochadeTransition : public ReflectionTransition -{ -public: - RochadeTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : ReflectionTransition(rScene, rSettings) - {} - -private: - virtual void displaySlides_(double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale) override; -}; - -void RochadeTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) -{ - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - - if( nTime > .5) { - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - } else { - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - } -} - -std::shared_ptr -makeRochadeTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings) - ; - -} -} - -std::shared_ptr makeRochade() -{ - Primitive Slide; - TransitionSettings aSettings; - aSettings.mnRequiredGLVersion = 3.0; - - double w, h; - - w = 2.2; - h = 10; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - - Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.25, -0.25, true, 0, 1)); - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back(Slide); - - Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); - aLeavingSlide.push_back(Slide); - - Slide.Operations.clear(); - Slide.Operations.push_back(makeSEllipseTranslate(w, h, 0.75, 0.25, true, 0, 1)); - Slide.Operations.push_back(makeSTranslate(glm::vec3(0, 0, -h), false, -1, 0)); - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), -45, true, true, 0, 1)); - Slide.Operations.push_back(makeRotateAndScaleDepthByWidth(glm::vec3(0,1,0),glm::vec3(0,0,0), 45, true, false, -1, 0)); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back(Slide); - - Slide.Operations.push_back(makeSScale(glm::vec3(1, -1, 1), glm::vec3(0, -1.02, 0), false, -1, 0)); - aEnteringSlide.push_back(Slide); - - return makeRochadeTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -inline double randFromNeg1to1() -{ - return comphelper::rng::uniform_real_distribution(-1.0, std::nextafter(1.0, DBL_MAX)); -} - -// TODO(Q3): extract to basegfx -inline glm::vec3 randNormVectorInXYPlane() -{ - glm::vec3 toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0); - return glm::normalize(toReturn); -} - -template -T clamp(const T& rIn) -{ - return glm::clamp(rIn, T(-1.0), T(1.0)); -} - -std::shared_ptr makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles ) -{ - double dAngle(2*3.1415926/static_cast( nPointsOnCircles )); - if(nCircles < 2 || nPointsOnCircles < 4) - return makeNByMTileFlip(1,1); - float Radius(1.0/static_cast( nCircles )); - float dRadius(Radius); - float LastRadius(0.0); - float NextRadius(2*Radius); - - /// now we know there is at least two circles - /// the first will always be a full circle - /// the last will always be the outer shell of the slide with a circle hole - - //add the full circle - std::vector unScaledTexCoords; - float TempAngle(0.0); - for(unsigned int Point(0); Point < nPointsOnCircles; ++Point) - { - unScaledTexCoords.push_back( glm::vec2( cos(TempAngle - 3.1415926/2.0) , sin(TempAngle- 3.1415926/2.0) ) ); - - TempAngle += dAngle; - } - - Primitives_t aLeavingSlide; - Primitives_t aEnteringSlide; - { - Primitive EnteringSlide; - Primitive LeavingSlide; - for(int Point(0); Point + 1 < nPointsOnCircles; ++Point) - { - EnteringSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5 , 0.5 ) ); - LeavingSlide.pushTriangle( glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0f + glm::vec2( 0.5, 0.5) ); - } - EnteringSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius * unScaledTexCoords[ 0 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ nPointsOnCircles - 1 ] / 2.0f + glm::vec2( 0.5 , 0.5 ) ); - LeavingSlide.pushTriangle( glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) ); - - glm::vec3 axis(randNormVectorInXYPlane()); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); - LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); - - aEnteringSlide.push_back(EnteringSlide); - aLeavingSlide.push_back(LeavingSlide); - LastRadius = Radius; - Radius = NextRadius; - NextRadius += dRadius; - } - - for(int i(1); i < nCircles - 1; ++i) - { - Primitive LeavingSlide; - Primitive EnteringSlide; - for(int Side(0); Side < nPointsOnCircles - 1; ++Side) - { - EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - - LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - } - - EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - - LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - - glm::vec3 axis(randNormVectorInXYPlane()); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); - LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) ); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); - - aEnteringSlide.push_back(EnteringSlide); - aLeavingSlide.push_back(LeavingSlide); - - LastRadius = Radius; - Radius = NextRadius; - NextRadius += dRadius; - } - { - Radius = sqrt(2.0); - Primitive LeavingSlide; - Primitive EnteringSlide; - for(int Side(0); Side < nPointsOnCircles - 1; ++Side) - { - - EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) ); - - LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) ); - LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0f + glm::vec2(0.5,0.5) ); - } - - EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) ); - - LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) ); - LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0f + glm::vec2(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0f + glm::vec2(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0f + glm::vec2(0.5,0.5) ); - - glm::vec3 axis(randNormVectorInXYPlane()); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) ); - LeavingSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) ); - EnteringSlide.Operations.push_back( makeSRotate( axis , glm::vec3(0,0,0) , -180, false,0.0,1.0) ); - - aEnteringSlide.push_back(EnteringSlide); - aLeavingSlide.push_back(LeavingSlide); - } - - return makeSimpleTransition(aLeavingSlide, aEnteringSlide); -} - -std::shared_ptr makeHelix( sal_uInt16 nRows ) -{ - double invN(1.0/static_cast(nRows)); - double iDn = 0.0; - double iPDn = invN; - Primitives_t aLeavingSlide; - Primitives_t aEnteringSlide; - for(unsigned int i(0); i < nRows; ++i) - { - Primitive Tile; - - Tile.pushTriangle(glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iDn ) , glm::vec2( 0.0 , iPDn )); - - Tile.pushTriangle(glm::vec2( 1.0 , iPDn ) , glm::vec2( 1.0 , iDn ) , glm::vec2( 0.0 , iPDn )); - - Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , 180 , - true, std::min(std::max(static_cast(i - nRows/2.0)*invN/2.0,0.0),1.0), - std::min(std::max(static_cast(i + nRows/2.0)*invN/2.0,0.0),1.0) ) ); - - aLeavingSlide.push_back(Tile); - - Tile.Operations.push_back( makeSRotate( glm::vec3( 0 , 1 , 0 ) , ( Tile.getVertex(1) + Tile.getVertex(3) )/2.0f , -180 , false,0.0,1.0) ); - - aEnteringSlide.push_back(Tile); - - iDn += invN; - iPDn += invN; - } - - return makeSimpleTransition(aLeavingSlide, aEnteringSlide); -} - -float fdiv(int a, int b) -{ - return static_cast(a)/b; -} - -glm::vec2 vec(float x, float y, float nx, float ny) -{ - x = x < 0.0 ? 0.0 : x; - x = x > nx ? nx : x; - y = y < 0.0 ? 0.0 : y; - y = y > ny ? ny : y; - return glm::vec2(fdiv(x, nx), fdiv(y, ny)); -} - -std::shared_ptr makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m ) -{ - Primitives_t aLeavingSlide; - Primitives_t aEnteringSlide; - - for (int x = 0; x < n; x++) - { - for (int y = 0; y < n; y++) - { - Primitive aTile; - glm::vec2 x11 = vec(x, y, n, m); - glm::vec2 x12 = vec(x, y+1, n, m); - glm::vec2 x21 = vec(x+1, y, n, m); - glm::vec2 x22 = vec(x+1, y+1, n, m); - - aTile.pushTriangle(x21, x11, x12); - aTile.pushTriangle(x22, x21, x12); - - aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, 180 , true, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f)); - aLeavingSlide.push_back(aTile); - - aTile.Operations.push_back(makeSRotate( glm::vec3(0 , 1, 0), (aTile.getVertex(1) + aTile.getVertex(3)) / 2.0f, -180, false, x11.x * x11.y / 2.0f , ((x22.x * x22.y) + 1.0f) / 2.0f)); - aEnteringSlide.push_back(aTile); - } - } - - return makeSimpleTransition(aLeavingSlide, aEnteringSlide); -} - -Primitive& Primitive::operator=(const Primitive& rvalue) -{ - Primitive aTmp(rvalue); - swap(aTmp); - return *this; -} - -Primitive::Primitive(const Primitive& rvalue) - : Operations(rvalue.Operations) - , Vertices(rvalue.Vertices) -{ -} - -void Primitive::swap(Primitive& rOther) -{ - using std::swap; - - swap(Operations, rOther.Operations); - swap(Vertices, rOther.Vertices); -} - -void Primitive::pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2) -{ - std::vector Verts; - std::vector Texs; - Verts.reserve(3); - Texs.reserve(3); - - Verts.push_back(glm::vec3( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 )); - Verts.push_back(glm::vec3( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 )); - Verts.push_back(glm::vec3( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 )); - - //figure out if they're facing the correct way, and make them face the correct way. - glm::vec3 Normal( glm::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) ); - if(Normal.z >= 0.0)//if the normal is facing us - { - Texs.push_back(SlideLocation0); - Texs.push_back(SlideLocation1); - Texs.push_back(SlideLocation2); - } - else // if the normal is facing away from us, make it face us - { - Texs.push_back(SlideLocation0); - Texs.push_back(SlideLocation2); - Texs.push_back(SlideLocation1); - Verts.clear(); - Verts.push_back(glm::vec3( 2*SlideLocation0.x - 1, -2*SlideLocation0.y + 1 , 0.0 )); - Verts.push_back(glm::vec3( 2*SlideLocation2.x - 1, -2*SlideLocation2.y + 1 , 0.0 )); - Verts.push_back(glm::vec3( 2*SlideLocation1.x - 1, -2*SlideLocation1.y + 1 , 0.0 )); - } - - Vertices.push_back({Verts[0], glm::vec3(0, 0, 1), Texs[0]}); //all normals always face the screen when untransformed. - Vertices.push_back({Verts[1], glm::vec3(0, 0, 1), Texs[1]}); //all normals always face the screen when untransformed. - Vertices.push_back({Verts[2], glm::vec3(0, 0, 1), Texs[2]}); //all normals always face the screen when untransformed. -} - -namespace -{ - -class DiamondTransition : public SimpleTransition -{ -public: - DiamondTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : SimpleTransition(rScene, rSettings) - {} - -private: - virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) override; -}; - -Primitives_t makeLeavingSlide(double nTime) -{ - Primitive Slide2; - if( nTime >= 0.5 ) { - double m = 1 - nTime; - - Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (m,0), glm::vec2 (0,m)); - Slide2.pushTriangle (glm::vec2 (nTime,0), glm::vec2 (1,0), glm::vec2 (1,m)); - Slide2.pushTriangle (glm::vec2 (1,nTime), glm::vec2 (1,1), glm::vec2 (nTime,1)); - Slide2.pushTriangle (glm::vec2 (0,nTime), glm::vec2 (m,1), glm::vec2 (0,1)); - } else { - double l = 0.5 - nTime; - double h = 0.5 + nTime; - - Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0.5,l)); - Slide2.pushTriangle (glm::vec2 (0.5,l), glm::vec2 (1,0), glm::vec2 (h,0.5)); - Slide2.pushTriangle (glm::vec2 (1,0), glm::vec2 (1,1), glm::vec2 (h,0.5)); - Slide2.pushTriangle (glm::vec2 (h,0.5), glm::vec2 (1,1), glm::vec2 (0.5,h)); - Slide2.pushTriangle (glm::vec2 (0.5,h), glm::vec2 (1,1), glm::vec2 (0,1)); - Slide2.pushTriangle (glm::vec2 (l,0.5), glm::vec2 (0.5,h), glm::vec2 (0,1)); - Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (l,0.5), glm::vec2 (0,1)); - Slide2.pushTriangle (glm::vec2 (0,0), glm::vec2 (0.5,l), glm::vec2 (l,0.5)); - } - Slide2.Operations.push_back (makeSTranslate (glm::vec3 (0, 0, 0.00000001), false, -1, 0)); - Primitives_t aLeavingSlidePrimitives; - aLeavingSlidePrimitives.push_back (Slide2); - - return aLeavingSlidePrimitives; -} - -void DiamondTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, - double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - - CHECK_GL_ERROR(); - displayUnbufferedSlide( nTime, glLeavingSlideTex, makeLeavingSlide(nTime), SlideWidthScale, SlideHeightScale ); - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); -} - -std::shared_ptr -makeDiamondTransition(const TransitionSettings& rSettings) -{ - Primitive Slide1; - Slide1.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide1.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aEnteringSlidePrimitives; - aEnteringSlidePrimitives.push_back (Slide1); - Primitives_t aLeavingSlidePrimitives; - aLeavingSlidePrimitives.push_back (Slide1); - return std::make_shared(TransitionScene(aLeavingSlidePrimitives, aEnteringSlidePrimitives), rSettings); -} - -} - -std::shared_ptr makeDiamond() -{ - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeDiamondTransition(aSettings); -} - -std::shared_ptr makeVenetianBlinds( bool vertical, int parts ) -{ - static double t30 = tan( M_PI/6.0 ); - double ln = 0; - double p = 1.0/parts; - - Primitives_t aLeavingSlide; - Primitives_t aEnteringSlide; - for( int i=0; i -makeFadeSmoothlyTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings) - ; -} - -} - -std::shared_ptr makeFadeSmoothly() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeFadeSmoothlyTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -namespace -{ - -class FadeThroughBlackTransition : public OGLTransitionImpl -{ -public: - FadeThroughBlackTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : OGLTransitionImpl(rScene, rSettings) - {} - -private: - virtual GLuint makeShader() const override; -}; - -GLuint FadeThroughBlackTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "basicVertexShader", "fadeBlackFragmentShader" ); -} - -std::shared_ptr -makeFadeThroughBlackTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings) - ; -} - -} - -std::shared_ptr makeFadeThroughBlack() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeFadeThroughBlackTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -namespace -{ - -class PermTextureTransition : public OGLTransitionImpl -{ -protected: - PermTextureTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : OGLTransitionImpl(rScene, rSettings) - , m_nHelperTexture(0) - {} - - virtual void finishTransition() override; - virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override; - -private: - /** various data */ - GLuint m_nHelperTexture; -}; - -void PermTextureTransition::finishTransition() -{ - CHECK_GL_ERROR(); - if ( m_nHelperTexture ) - { - glDeleteTextures( 1, &m_nHelperTexture ); - m_nHelperTexture = 0; - } - CHECK_GL_ERROR(); -} - -int permutation256 [256]= { -215, 100, 200, 204, 233, 50, 85, 196, - 71, 141, 122, 160, 93, 131, 243, 234, -162, 183, 36, 155, 4, 62, 35, 205, - 40, 102, 33, 27, 255, 55, 214, 156, - 75, 163, 134, 126, 249, 74, 197, 228, - 72, 90, 206, 235, 17, 22, 49, 169, -227, 89, 16, 5, 117, 60, 248, 230, -217, 68, 138, 96, 194, 170, 136, 10, -112, 238, 184, 189, 176, 42, 225, 212, - 84, 58, 175, 244, 150, 168, 219, 236, -101, 208, 123, 37, 164, 110, 158, 201, - 78, 114, 57, 48, 70, 142, 106, 43, -232, 26, 32, 252, 239, 98, 191, 94, - 59, 149, 39, 187, 203, 190, 19, 13, -133, 45, 61, 247, 23, 34, 20, 52, -118, 209, 146, 193, 222, 18, 1, 152, - 46, 41, 91, 148, 115, 25, 135, 77, -254, 147, 224, 161, 9, 213, 223, 250, -231, 251, 127, 166, 63, 179, 81, 130, -139, 28, 120, 151, 241, 86, 111, 0, - 88, 153, 172, 182, 159, 105, 178, 47, - 51, 167, 65, 66, 92, 73, 198, 211, -245, 195, 31, 220, 140, 76, 221, 186, -154, 185, 56, 83, 38, 165, 109, 67, -124, 226, 132, 53, 229, 29, 12, 181, -121, 24, 207, 199, 177, 113, 30, 80, - 3, 97, 188, 79, 216, 173, 8, 145, - 87, 128, 180, 237, 240, 137, 125, 104, - 15, 242, 119, 246, 103, 143, 95, 144, - 2, 44, 69, 157, 192, 174, 14, 54, -218, 82, 64, 210, 11, 6, 129, 21, -116, 171, 99, 202, 7, 107, 253, 108 -}; - -void initPermTexture(GLuint *texID) -{ - CHECK_GL_ERROR(); - glGenTextures(1, texID); - glBindTexture(GL_TEXTURE_2D, *texID); - - static bool initialized = false; - static unsigned char permutation2D[256*256*4]; - if( !initialized ) { - int x, y; - - for( y=0; y < 256; y++ ) - for( x=0; x < 256; x++ ) - permutation2D[x*4 + y*1024] = permutation256[(y + permutation256[x]) & 0xff]; - - initialized = true; - } - - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, permutation2D ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - CHECK_GL_ERROR(); -} - -void PermTextureTransition::prepareTransition( sal_Int32, sal_Int32 ) -{ - 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(); -} - -} - -namespace -{ - -class StaticNoiseTransition : public PermTextureTransition -{ -public: - StaticNoiseTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : PermTextureTransition(rScene, rSettings) - {} - -private: - virtual GLuint makeShader() const override; -}; - -GLuint StaticNoiseTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "basicVertexShader", "staticFragmentShader" ); -} - -std::shared_ptr -makeStaticNoiseTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings) - ; -} - -} - -std::shared_ptr makeStatic() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeStaticNoiseTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -namespace -{ - -class DissolveTransition : public PermTextureTransition -{ -public: - DissolveTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : PermTextureTransition(rScene, rSettings) - {} - -private: - virtual GLuint makeShader() const override; -}; - -GLuint DissolveTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "basicVertexShader", "dissolveFragmentShader" ); -} - -std::shared_ptr -makeDissolveTransition( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared( - TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings) - ; -} - -} - -std::shared_ptr makeDissolve() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeDissolveTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -namespace -{ - -class VortexTransition : public PermTextureTransition -{ -public: - VortexTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, int nNX, int nNY) - : PermTextureTransition(rScene, rSettings) - , maNumTiles(nNX,nNY) - { - mvTileInfo.resize(6*maNumTiles.x*maNumTiles.y); - mnFramebuffers[0] = 0; - mnFramebuffers[1] = 0; - 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 mnSlideLocation = -1; - GLint mnTileInfoLocation = -1; - GLuint mnTileInfoBuffer = 0u; - GLint mnShadowLocation = -1; - std::array mnFramebuffers; - std::array mnDepthTextures; - - glm::ivec2 maNumTiles; - - std::vector mvTileInfo; -}; - -void VortexTransition::finishTransition() -{ - PermTextureTransition::finishTransition(); - - CHECK_GL_ERROR(); - glDeleteTextures(2, mnDepthTextures.data()); - mnDepthTextures = {0u, 0u}; - CHECK_GL_ERROR(); - glDeleteFramebuffers(2, mnFramebuffers.data()); - mnFramebuffers = {0u, 0u}; - glDeleteBuffers(1, &mnTileInfoBuffer); - mnTileInfoBuffer = 0u; - mnSlideLocation = -1; - mnTileInfoLocation = -1; - mnShadowLocation = -1; - CHECK_GL_ERROR(); -} - -GLuint VortexTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader" ); -} - -glm::mat4 lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up) { - glm::vec3 f = glm::normalize(center - eye); - glm::vec3 u = glm::normalize(up); - glm::vec3 s = glm::normalize(glm::cross(f, u)); - u = glm::cross(s, f); - - return glm::mat4(s.x, u.x, -f.x, 0, - s.y, u.y, -f.y, 0, - s.z, u.z, -f.z, 0, - -glm::dot(s, eye), -glm::dot(u, eye), glm::dot(f, eye), 1); -} - -void VortexTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) -{ - CHECK_GL_ERROR(); - PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); - CHECK_GL_ERROR(); - - mnSlideLocation = glGetUniformLocation(m_nProgramObject, "slide"); - mnTileInfoLocation = glGetAttribLocation(m_nProgramObject, "tileInfo"); - GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles"); - mnShadowLocation = glGetUniformLocation(m_nProgramObject, "shadow"); - GLint nOrthoProjectionMatrix = glGetUniformLocation(m_nProgramObject, "orthoProjectionMatrix"); - GLint nOrthoViewMatrix = glGetUniformLocation(m_nProgramObject, "orthoViewMatrix"); - GLint location = glGetUniformLocation(m_nProgramObject, "leavingShadowTexture"); - glUniform1i(location, 2); - location = glGetUniformLocation(m_nProgramObject, "enteringShadowTexture"); - glUniform1i(location, 3); - CHECK_GL_ERROR(); - - glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(maNumTiles)); - CHECK_GL_ERROR(); - - glGenBuffers(1, &mnTileInfoBuffer); - CHECK_GL_ERROR(); - - // We store the (x,y) indexes of the tile each vertex belongs to in a float, so they must fit. - assert(maNumTiles.x < 256); - assert(maNumTiles.y < 256); - - // Two triangles, i.e. six vertices, per tile - { - int n = 0; - for (int x = 0; x < maNumTiles.x; x++) - { - for (int y = 0; y < maNumTiles.y; y++) - { - for (int v = 0; v < 6; v++) - { - mvTileInfo[n] = x + (y << 8) + (v << 16); - n++; - } - } - } - } - - glBindBuffer(GL_ARRAY_BUFFER, mnTileInfoBuffer); - CHECK_GL_ERROR(); - glEnableVertexAttribArray(mnTileInfoLocation); - CHECK_GL_ERROR(); - glVertexAttribPointer(mnTileInfoLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr); - CHECK_GL_ERROR(); - glBufferData(GL_ARRAY_BUFFER, mvTileInfo.size()*sizeof(GLfloat), mvTileInfo.data(), GL_STATIC_DRAW); - CHECK_GL_ERROR(); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); - - double EyePos(10.0); - double RealF(1.0); - double RealN(-1.0); - double RealL(-2.0); - double RealR(2.0); - double RealB(-2.0); - double RealT(2.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(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(-1, 1, EyePos), glm::vec3(-0.5, 0.5, 0), glm::vec3(0, 1, 0)); - glUniformMatrix4fv(nOrthoViewMatrix, 1, false, glm::value_ptr(view)); - - // Generate the framebuffers and textures for the shadows. - glGenTextures(2, mnDepthTextures.data()); - glGenFramebuffers(2, mnFramebuffers.data()); - - for (int i : {0, 1}) { - glBindTexture(GL_TEXTURE_2D, mnDepthTextures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 2048, 2048, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); - 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_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[i]); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mnDepthTextures[i], 0); - glDrawBuffer(GL_NONE); // No color buffer is drawn to. - - // 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); - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture( GL_TEXTURE2 ); - glBindTexture( GL_TEXTURE_2D, mnDepthTextures[0] ); - glActiveTexture( GL_TEXTURE3 ); - glBindTexture( GL_TEXTURE_2D, mnDepthTextures[1] ); - glActiveTexture( GL_TEXTURE0 ); -} - -void VortexTransition::displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ) -{ - CHECK_GL_ERROR(); - applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale ); - glUniform1f( m_nTimeLocation, nTime ); - glUniform1f( mnShadowLocation, 1.0 ); - - std::array viewport; - glGetIntegerv(GL_VIEWPORT, viewport.data()); - glViewport(0, 0, 2048, 2048); - - glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[0]); - glClear(GL_DEPTH_BUFFER_BIT); - glUniform1f( mnSlideLocation, 0.0 ); - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - - glBindFramebuffer(GL_FRAMEBUFFER, mnFramebuffers[1]); - glClear(GL_DEPTH_BUFFER_BIT); - glUniform1f( mnSlideLocation, 1.0 ); - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glUniform1f( mnShadowLocation, 0.0 ); - glUniform1f( mnSlideLocation, 0.0 ); - displaySlide( nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale ); - glUniform1f( mnSlideLocation, 1.0 ); - displaySlide( nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale ); - CHECK_GL_ERROR(); -} - -std::shared_ptr -makeVortexTransition(const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings, - int NX, - int NY) -{ - return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings, - NX, NY); -} - -} - -std::shared_ptr makeVortex() -{ - const int NX = 96, NY = 96; - Primitive Slide; - - for (int x = 0; x < NX; x++) - { - for (int y = 0; y < NY; y++) - { - Slide.pushTriangle (glm::vec2 (fdiv(x,NX),fdiv(y,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY))); - Slide.pushTriangle (glm::vec2 (fdiv(x+1,NX),fdiv(y,NY)), glm::vec2 (fdiv(x,NX),fdiv(y+1,NY)), glm::vec2 (fdiv(x+1,NX),fdiv(y+1,NY))); - } - } - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - aSettings.mnRequiredGLVersion = 3.2f; - - return makeVortexTransition(aLeavingSlide, aEnteringSlide, aSettings, NX, NY); -} - -namespace -{ - -class RippleTransition : public OGLTransitionImpl -{ -public: - RippleTransition(const TransitionScene& rScene, const TransitionSettings& rSettings, const glm::vec2& rCenter) - : OGLTransitionImpl(rScene, rSettings), - maCenter(rCenter) - { - } - -private: - virtual GLuint makeShader() const override; - virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) override; - virtual void prepare( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ) override; - - glm::vec2 maCenter; - GLint maSlideRatioLocation = -1; -}; - -GLuint RippleTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "basicVertexShader", "rippleFragmentShader" ); -} - -void RippleTransition::prepareTransition( sal_Int32, sal_Int32 ) -{ - GLint nCenterLocation = glGetUniformLocation(m_nProgramObject, "center"); - CHECK_GL_ERROR(); - - glUniform2fv(nCenterLocation, 1, glm::value_ptr(maCenter)); - CHECK_GL_ERROR(); - - maSlideRatioLocation = glGetUniformLocation(m_nProgramObject, "slideRatio"); - CHECK_GL_ERROR(); -} - -void RippleTransition::prepare( double /* nTime */, double SlideWidth, double SlideHeight, double /* DispWidth */, double /* DispHeight */ ) -{ - if( maSlideRatioLocation != -1 ) - glUniform1f( maSlideRatioLocation, SlideWidth / SlideHeight ); -} - -std::shared_ptr -makeRippleTransition(const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - // The center point should be adjustable by the user, but we have no way to do that in the UI - return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings, - glm::vec2(0.5, 0.5)); -} - -} - -std::shared_ptr makeRipple() -{ - Primitive Slide; - - Slide.pushTriangle (glm::vec2 (0,0), glm::vec2 (1,0), glm::vec2 (0,1)); - Slide.pushTriangle (glm::vec2 (1,0), glm::vec2 (0,1), glm::vec2 (1,1)); - - Primitives_t aLeavingSlide; - aLeavingSlide.push_back (Slide); - - Primitives_t aEnteringSlide; - aEnteringSlide.push_back (Slide); - - TransitionSettings aSettings; - aSettings.mbUseMipMapLeaving = aSettings.mbUseMipMapEntering = false; - - return makeRippleTransition(aLeavingSlide, aEnteringSlide, aSettings); -} - -void createHexagon(Primitive& aHexagon, const int x, const int y, const int NX, const int NY) -{ - if (y % 4 == 0) - { - aHexagon.pushTriangle(vec(x-1, y-1, NX, NY), vec(x, y-2, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x, y-2, NX, NY), vec(x+1, y-1, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x+1, y-1, NX, NY), vec(x+1, y, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x+1, y, NX, NY), vec(x, y+1, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x, y+1, NX, NY), vec(x-1, y, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x-1, y, NX, NY), vec(x-1, y-1, NX, NY), vec(x, y+0.5, NX, NY)); - } - else - { - aHexagon.pushTriangle(vec(x-2, y-1, NX, NY), vec(x-1, y-2, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x-1, y-2, NX, NY), vec(x, y-1, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x, y-1, NX, NY), vec(x, y, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x, y, NX, NY), vec(x-1, y+1, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x-1, y+1, NX, NY), vec(x-2, y, NX, NY), vec(x, y+0.5, NX, NY)); - aHexagon.pushTriangle(vec(x-2, y, NX, NY), vec(x-2, y-1, NX, NY), vec(x, y+0.5, NX, NY)); - } -} - -namespace -{ - -class GlitterTransition : public PermTextureTransition -{ -public: - GlitterTransition(const TransitionScene& rScene, const TransitionSettings& rSettings) - : PermTextureTransition(rScene, rSettings) - { - } - -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; - - GLuint maBuffer = 0; -}; - -GLuint GlitterTransition::makeShader() const -{ - return OpenGLHelper::LoadShaders( "glitterVertexShader", "glitterFragmentShader" ); -} - -struct ThreeFloats -{ - GLfloat x, y, z; -}; - -void GlitterTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) -{ - CHECK_GL_ERROR(); - PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); - CHECK_GL_ERROR(); - - GLint nNumTilesLocation = glGetUniformLocation(m_nProgramObject, "numTiles"); - if (nNumTilesLocation != -1) { - glUniform2iv(nNumTilesLocation, 1, glm::value_ptr(glm::ivec2(41, 41 * 4 / 3))); - CHECK_GL_ERROR(); - } - - 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 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, nullptr ); - 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 -makeGlitterTransition(const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings); -} - -} - -std::shared_ptr 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, TransitionSettings()); -} - -namespace -{ - -class HoneycombTransition : public PermTextureTransition -{ -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 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" ); -} - -void HoneycombTransition::prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ) -{ - CHECK_GL_ERROR(); - PermTextureTransition::prepareTransition( glLeavingSlideTex, glEnteringSlideTex ); - - 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(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, nullptr); - 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_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, nullptr); - 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_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); - glUniform1f(mnShadowLocation, 1.0); - CHECK_GL_ERROR(); - - const float borderSize = 0.15f; - - std::array 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.0f - borderSize); - displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); - glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); - 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.0f - borderSize); - displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale); - glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); - displaySlide(nTime, glEnteringSlideTex, getScene().getEnteringSlide(), SlideWidthScale, SlideHeightScale); - glUniform1f(maSelectedTextureLocation, 1.0); - glUniform1f(maHexagonSizeLocation, 1.0f - borderSize); - displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); - glUniform1f(maHexagonSizeLocation, 1.0f + borderSize); - displaySlide(nTime, glLeavingSlideTex, getScene().getLeavingSlide(), SlideWidthScale, SlideHeightScale); - CHECK_GL_ERROR(); -} - -std::shared_ptr -makeHoneycombTransition(const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const TransitionSettings& rSettings) -{ - // The center point should be adjustable by the user, but we have no way to do that in the UI - return std::make_shared(TransitionScene(rLeavingSlidePrimitives, rEnteringSlidePrimitives), - rSettings); -} - -} - -std::shared_ptr makeHoneycomb() -{ - const int NX = 21; - const int NY = 21; - - TransitionSettings aSettings; - aSettings.mnRequiredGLVersion = 3.2f; - - 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 makeNewsflash() -{ - Primitive Slide; - - Slide.pushTriangle(glm::vec2(0,0),glm::vec2(1,0),glm::vec2(0,1)); - Slide.pushTriangle(glm::vec2(1,0),glm::vec2(0,1),glm::vec2(1,1)); - Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),3000,true,0,0.5)); - Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),true,0,0.5)); - Slide.Operations.push_back(makeSTranslate(glm::vec3(-10000, 0, 0),false, 0.5, 2)); - Primitives_t aLeavingSlide; - aLeavingSlide.push_back(Slide); - - Slide.Operations.clear(); - Slide.Operations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0,0,0),-3000,true,0.5,1)); - Slide.Operations.push_back(makeSTranslate(glm::vec3(-100, 0, 0),false, -1, 1)); - Slide.Operations.push_back(makeSTranslate(glm::vec3(100, 0, 0),false, 0.5, 1)); - Slide.Operations.push_back(makeSScale(glm::vec3(0.01,0.01,0.01),glm::vec3(0,0,0),false,-1,1)); - Slide.Operations.push_back(makeSScale(glm::vec3(100,100,100),glm::vec3(0,0,0),true,0.5,1)); - Primitives_t aEnteringSlide; - aEnteringSlide.push_back(Slide); - - Operations_t aOverallOperations; - aOverallOperations.push_back(makeSRotate(glm::vec3(0,0,1),glm::vec3(0.2,0.2,0),1080,true,0,1)); - - return makeSimpleTransition(aLeavingSlide, aEnteringSlide, aOverallOperations); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx deleted file mode 100644 index 66ecb6b61a0c..000000000000 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionImpl.hxx +++ /dev/null @@ -1,371 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_ -#define INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_ - -#include -#include - -#include - -#include -#include - -class Primitive; -class Operation; -class SceneObject; -class TransitionData; - -struct TransitionSettings -{ - TransitionSettings() : - mbUseMipMapLeaving( true ), - mbUseMipMapEntering( true ), - mnRequiredGLVersion( 2.1f ) - { - } - - /** Whether to use mipmaping for slides textures - */ - bool mbUseMipMapLeaving; - bool mbUseMipMapEntering; - - /** which GL version does the transition require - */ - float mnRequiredGLVersion; -}; - -typedef std::vector Primitives_t; -typedef std::vector > SceneObjects_t; -typedef std::vector > Operations_t; - -class TransitionScene -{ -public: - TransitionScene( - const Primitives_t& rLeavingSlidePrimitives, - const Primitives_t& rEnteringSlidePrimitives, - const Operations_t& rOverallOperations = Operations_t(), - const SceneObjects_t& rSceneObjects = SceneObjects_t() - ) - : maLeavingSlidePrimitives(rLeavingSlidePrimitives) - , maEnteringSlidePrimitives(rEnteringSlidePrimitives) - , maOverallOperations(rOverallOperations) - , maSceneObjects(rSceneObjects) - { - } - - TransitionScene(TransitionScene const& rOther); - TransitionScene& operator=(const TransitionScene& rOther); - - void swap(TransitionScene& rOther); - - const Primitives_t& getLeavingSlide() const - { - return maLeavingSlidePrimitives; - } - - const Primitives_t& getEnteringSlide() const - { - return maEnteringSlidePrimitives; - } - - const Operations_t& getOperations() const - { - return maOverallOperations; - } - - const SceneObjects_t& getSceneObjects() const - { - return maSceneObjects; - } - -private: - /** All the primitives that use the leaving slide texture - */ - Primitives_t maLeavingSlidePrimitives; - - /** All the primitives that use the leaving slide texture - */ - Primitives_t maEnteringSlidePrimitives; - - /** All the operations that should be applied to both leaving and entering slide primitives. These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back. - */ - Operations_t maOverallOperations; - - /** All the surrounding scene objects - */ - SceneObjects_t maSceneObjects; -}; - -/** OpenGL 3D Transition class. It implicitly is constructed from XOGLTransition - - It holds Primitives and Operations on those primitives. -*/ -class OGLTransitionImpl -{ -public: - virtual ~OGLTransitionImpl(); - - OGLTransitionImpl(const OGLTransitionImpl&) = delete; - OGLTransitionImpl& operator=(const OGLTransitionImpl&) = delete; - - /** Prepare transition. - */ - 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 ); - /** Clean up after transition. - */ - void finish(); - - TransitionSettings const& getSettings() const - { - return maSettings; - } - -protected: - OGLTransitionImpl(const TransitionScene& rScene, const TransitionSettings& rSettings) - : maScene(rScene) - , maSettings(rSettings) - {} - - TransitionScene const& getScene() const - { - return maScene; - } - - void displaySlide( double nTime, sal_Int32 glSlideTex, const Primitives_t& primitives, double SlideWidthScale, double SlideHeightScale ); - void displayUnbufferedSlide( double nTime, sal_Int32 glSlideTex, const Primitives_t& primitives, double SlideWidthScale, double SlideHeightScale ); - void displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight); - void applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale ); - -private: - /** This function is called in display method to prepare the slides, scene, etc. - * - * Default implementation does nothing. - */ - virtual void prepare( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ); - - /** This function is called in display method to prepare the slides, scene, etc. - * - * Default implementation does nothing. - */ - virtual void finish( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight ); - - /** This function is called after glx context is ready to let the transition prepare GL related things, like GLSL program. - * - * Default implementation does nothing. - */ - virtual void prepareTransition( sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex ); - - /** This function is called when the transition needs to clear after itself, like delete own textures etc. - * - * Default implementation does nothing. - */ - virtual void finishTransition(); - - /** This function is called in display method to display the slides. - * - * Default implementation applies overall operations and then - * displays both slides. - */ - virtual void displaySlides_( double nTime, sal_Int32 glLeavingSlideTex, sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale ); - - /** This function is called in prepare method to create the GL program. - * - * It is a pure virtual to make sure no class will use a default one. - */ - virtual GLuint makeShader() const = 0; - -private: - const TransitionScene maScene; - const TransitionSettings maSettings; - - /** Calculates the projection and model/view matrices, and upload them. - */ - void uploadModelViewProjectionMatrices(); - - /** Uniform locations for transform matrices - */ - GLint m_nPrimitiveTransformLocation = -1; - GLint m_nSceneTransformLocation = -1; - GLint m_nOperationsTransformLocation = -1; - - /** Per-vertex attribute locations - */ - GLint m_nPositionLocation = -1; - GLint m_nNormalLocation = -1; - GLint m_nTexCoordLocation = -1; - - GLuint m_nVertexArrayObject = 0u; - - std::vector m_nFirstIndices; - -protected: - /** GLSL program object - */ - GLuint m_nProgramObject = 0u; - - /** VBO in which to put primitive data - */ - GLuint m_nVertexBufferObject = 0u; - - /** Location of the "time" uniform - */ - GLint m_nTimeLocation = -1; -}; - - -// "Constructors" of available transitions -std::shared_ptr makeOutsideCubeFaceToLeft(); -std::shared_ptr makeInsideCubeFaceToLeft(); -std::shared_ptr makeNByMTileFlip( sal_uInt16 n, sal_uInt16 m ); -std::shared_ptr makeRevolvingCircles( sal_uInt16 nCircles , sal_uInt16 nPointsOnCircles ); -std::shared_ptr makeHelix( sal_uInt16 nRows ); -std::shared_ptr makeFallLeaving(); -std::shared_ptr makeTurnAround(); -std::shared_ptr makeTurnDown(); -std::shared_ptr makeIris(); -std::shared_ptr makeRochade(); -std::shared_ptr makeVenetianBlinds( bool vertical, int parts ); -std::shared_ptr makeStatic(); -std::shared_ptr makeDissolve(); -std::shared_ptr makeVortex(); -std::shared_ptr makeRipple(); -std::shared_ptr makeGlitter(); -std::shared_ptr makeHoneycomb(); -std::shared_ptr makeNewsflash(); - -/** 2D replacements */ - -std::shared_ptr makeDiamond(); -std::shared_ptr makeFadeSmoothly(); -std::shared_ptr makeFadeThroughBlack(); - -class SceneObject -{ -public: - SceneObject(); - virtual ~SceneObject(); - SceneObject(const SceneObject&) = delete; - SceneObject& operator=(const SceneObject&) = delete; - - 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() {} - - void pushPrimitive (const Primitive &p); - -protected: - /** All the surrounding scene primitives - */ - Primitives_t maPrimitives; - std::vector maFirstIndices; -}; - -struct Vertex -{ - glm::vec3 position; - glm::vec3 normal; - glm::vec2 texcoord; -}; -static_assert(sizeof(Vertex) == (3 + 3 + 2) * 4, "Vertex struct has wrong size/alignment"); - -/** This class is a list of Triangles that will share Operations, and could possibly share -*/ -class Primitive -{ -public: - Primitive() {} - // making copy constructor explicit makes the class un-suitable for use with stl containers - Primitive(const Primitive& rvalue); - Primitive& operator=(const Primitive& rvalue); - - void swap(Primitive& rOther); - - void applyOperations(glm::mat4& matrix, double nTime, double SlideWidthScale, double SlideHeightScale) const; - void display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale) const; - void display(GLint primitiveTransformLocation, double nTime, double WidthScale, double HeightScale, int first) const; - - /** PushBack a vertex,normal, and tex coord. Each SlideLocation is where on the slide is mapped to this location ( from (0,0) to (1,1) ). This will make sure the correct aspect ratio is used, and helps to make slides begin and end at the correct position. (0,0) is the top left of the slide, and (1,1) is the bottom right. - - @param SlideLocation0 - Location of first Vertex on slide - - @param SlideLocation1 - Location of second Vertex on slide - - @param SlideLocation2 - Location of third Vertex on slide - - */ - void pushTriangle(const glm::vec2& SlideLocation0,const glm::vec2& SlideLocation1,const glm::vec2& SlideLocation2); - - /** guards against directly changing the vertices - - @return - the list of vertices - */ - const glm::vec3& getVertex(int n) const {return Vertices[n].position;} - - /** accessor for the size of the vertices data - - @return - the size in bytes of the Vertices data - */ - int getVerticesSize() const {return Vertices.size() * sizeof(Vertex);} - - /** copies all vertices to the C array passed - - @return - the number of written vertices - */ - int writeVertices(Vertex *location) const { - std::copy(Vertices.begin(), Vertices.end(), location); - return Vertices.size(); - } - - /** list of Operations to be performed on this primitive.These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back. - - @return - the list of Operations - - */ - Operations_t Operations; - -private: - /** list of vertices - */ - std::vector Vertices; -}; - -#endif // INCLUDED_SLIDESHOW_TRANSITION_HXX_ - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx deleted file mode 100644 index 55859d28a30c..000000000000 --- a/slideshow/source/engine/OGLTrans/generic/OGLTrans_TransitionerImpl.cxx +++ /dev/null @@ -1,1339 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#undef IN -#undef OUT -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -#include "OGLTrans_TransitionImpl.hxx" - -#include - -#if OSL_DEBUG_LEVEL > 0 -#include -#endif - -using namespace ::com::sun::star; -using ::com::sun::star::beans::XFastPropertySet; -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::uno::UNO_QUERY_THROW; - -namespace -{ - -typedef cppu::WeakComponentImplHelper OGLTransitionerImplBase; - -#if OSL_DEBUG_LEVEL > 0 -class TimerContext -{ -public: - explicit TimerContext(OUString const& rWhat) - : m_aWhat(rWhat) - , m_StartTime(std::chrono::steady_clock::now()) - { - } - ~TimerContext() - { - auto const aDuration(std::chrono::steady_clock::now() - m_StartTime); - SAL_INFO("slideshow.opengl", m_aWhat << " took: " << std::chrono::duration_cast(aDuration).count()); - } -private: - OUString const m_aWhat; - std::chrono::steady_clock::time_point const m_StartTime; -}; -#endif - -struct OGLFormat -{ - GLint nInternalFormat; - GLenum eFormat; - GLenum eType; -}; - -/* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr) - */ -int calcComponentOrderIndex(const uno::Sequence& rTags) -{ - using namespace rendering::ColorComponentTag; - - static const sal_Int8 aOrderTable[] = - { - RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA, - RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA, - ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE, - ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED, - }; - - const sal_Int32 nNumComps(rTags.getLength()); - const sal_Int8* pLine=aOrderTable; - for(int i=0; i<4; ++i) - { - int j=0; - while( j<4 && j& pOGLTransition ); - bool initialize( const Reference< presentation::XSlideShowView >& xView, - const Reference< rendering::XBitmap >& xLeavingSlide, - const Reference< rendering::XBitmap >& xEnteringSlide ); - - // XTransition - virtual void SAL_CALL update( double nTime ) - throw (uno::RuntimeException, std::exception) override; - virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView, - const Reference< rendering::XBitmap >& rLeavingBitmap, - const Reference< rendering::XBitmap >& rEnteringBitmap ) - throw (uno::RuntimeException, std::exception) override; - -protected: - void disposeTextures(); - - // WeakComponentImplHelperBase - virtual void SAL_CALL disposing() override; - - bool isDisposed() const - { - return (rBHelper.bDisposed || rBHelper.bInDispose); - } - - void createTexture( GLuint* texID, - bool useMipmap, - uno::Sequence& data, - const OGLFormat* pFormat ); - const OGLFormat* chooseFormats(); - -private: - void impl_initializeFlags( bool const bGLXPresent ); - - void impl_dispose(); - - void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide ); - void impl_prepareSlides(); - - void impl_createTexture( bool useMipmap, uno::Sequence& data, const OGLFormat* pFormat ); - - bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView ); - /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL. - */ - void GLInitSlides(); - - bool impl_prepareTransition(); - void impl_finishTransition(); - -private: - rtl::Reference mpContext; - - /** OpenGL handle to the leaving slide's texture - */ - GLuint maLeavingSlideGL; - /** OpenGL handle to the entering slide's texture - */ - GLuint maEnteringSlideGL; - - Reference< presentation::XSlideShowView > mxView; - Reference< rendering::XIntegerBitmap > mxLeavingBitmap; - Reference< rendering::XIntegerBitmap > mxEnteringBitmap; - - /** raw bytes of the entering bitmap - */ - uno::Sequence maEnteringBytes; - - /** raw bytes of the leaving bitmap - */ - uno::Sequence maLeavingBytes; - - bool mbRestoreSync; - - /** the form the raw bytes are in for the bitmaps - */ - rendering::IntegerBitmapLayout maSlideBitmapLayout; - - /** the size of the slides - */ - geometry::IntegerSize2D maSlideSize; - - /** Our Transition to be used. - */ - std::shared_ptr mpTransition; - -public: - /** whether we are running on ATI fglrx with bug related to textures - */ - bool mbBrokenTexturesATI; - - /** GL version - */ - float mnGLVersion; - - /** - Whether the display has GLX extension on X11, always true otherwise (?) - */ - bool mbValidOpenGLContext; - -#if OSL_DEBUG_LEVEL > 0 - std::chrono::steady_clock::time_point m_UpdateStartTime; - std::chrono::steady_clock::time_point m_UpdateEndTime; - std::chrono::steady_clock::time_point m_StartTime; - std::chrono::steady_clock::time_point m_EndTime; - std::chrono::steady_clock::duration m_TotalUpdateDuration; - int mnFrameCount; -#endif -}; - -bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView, - const Reference< rendering::XBitmap >& xLeavingSlide, - const Reference< rendering::XBitmap >& xEnteringSlide ) -{ - bool const bValidContext( initWindowFromSlideShowView( xView ) ); - impl_initializeFlags( bValidContext ); - - setSlides( xLeavingSlide, xEnteringSlide ); - - CHECK_GL_ERROR(); - return mbValidOpenGLContext; -} - -void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext ) -{ - CHECK_GL_ERROR(); - mbValidOpenGLContext = bValidContext; - if ( bValidContext ) { - mnGLVersion = OpenGLHelper::getGLVersion(); - SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion << "" ); - -#if defined( UNX ) && !defined( MACOSX ) - const GLubyte* vendor = glGetString( GL_VENDOR ); - /* TODO: check for version once the bug in fglrx driver is fixed */ - mbBrokenTexturesATI = (vendor && strcmp( reinterpret_cast(vendor), "ATI Technologies Inc." ) == 0 ); -#endif - } - CHECK_GL_ERROR(); -} - -bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView ) -{ - osl::MutexGuard const guard( m_aMutex ); - - if (isDisposed()) - return false; - - mxView.set( xView, UNO_QUERY ); - if( !mxView.is() ) - return false; - -#if OSL_DEBUG_LEVEL > 0 - TimerContext aTimerContext("initWindowFromSlideShowView"); -#endif - - /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx - uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW); - uno::Sequence< uno::Any > aDeviceParams; - ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ); - - OUString aImplName; - aDeviceParams[ 0 ] >>= aImplName; - - sal_Int64 aVal = 0; - aDeviceParams[1] >>= aVal; - - mpContext = OpenGLContext::Create(); - - 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"); - - mpContext->makeCurrent(); - CHECK_GL_ERROR(); - - awt::Rectangle aCanvasArea = mxView->getCanvasArea(); - mpContext->setWinPosAndSize(Point(aCanvasArea.X, aCanvasArea.Y), Size(aCanvasArea.Width, aCanvasArea.Height)); - SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height); - - CHECK_GL_ERROR(); - glEnable(GL_CULL_FACE); - CHECK_GL_ERROR(); - glCullFace(GL_BACK); - CHECK_GL_ERROR(); - glClearColor (0, 0, 0, 0); - CHECK_GL_ERROR(); - glClear(GL_COLOR_BUFFER_BIT); - CHECK_GL_ERROR(); - - mpContext->swapBuffers(); - - glViewport(0, 0, aCanvasArea.Width, aCanvasArea.Height); - CHECK_GL_ERROR(); - - return true; -} - -void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide, - const uno::Reference< rendering::XBitmap >& xEnteringSlide ) -{ - osl::MutexGuard const guard( m_aMutex ); - - if (isDisposed()) - return; - - mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW ); - mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW ); - - maSlideSize = mxLeavingBitmap->getSize(); - SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height); - maSlideSize = mxEnteringBitmap->getSize(); - SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height); -} - - -void OGLTransitionerImpl::impl_prepareSlides() -{ - Reference< XFastPropertySet > xLeavingSet( mxLeavingBitmap , UNO_QUERY ); - Reference< XFastPropertySet > xEnteringSet( mxEnteringBitmap , UNO_QUERY ); - - geometry::IntegerRectangle2D aSlideRect; - aSlideRect.X1 = 0; - aSlideRect.X2 = maSlideSize.Width; - aSlideRect.Y1 = 0; - aSlideRect.Y2 = maSlideSize.Height; - - CHECK_GL_ERROR(); - mpContext->sync(); - CHECK_GL_ERROR(); - - maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect); - maEnteringBytes = mxEnteringBitmap->getData(maSlideBitmapLayout, aSlideRect); - - CHECK_GL_ERROR(); - GLInitSlides(); - - SAL_WARN_IF(maSlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now"); - - mpContext->sync(); - - CHECK_GL_ERROR(); - - // synchronized X still gives us much smoother play - // I suspect some issues in above code in slideshow - // synchronize whole transition for now - const GLWindow& rGLWindow(mpContext->getOpenGLWindow()); - mbRestoreSync = rGLWindow.Synchronize(true); -} - -bool OGLTransitionerImpl::impl_prepareTransition() -{ - if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion ) - return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL ); - return false; -} - -void OGLTransitionerImpl::impl_finishTransition() -{ - if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion ) - mpTransition->finish(); -} - -bool OGLTransitionerImpl::setTransition( const std::shared_ptr& pTransition ) -{ - if ( mpTransition ) // already initialized - return true; - - mpTransition = pTransition; - - mpContext->makeCurrent(); - CHECK_GL_ERROR(); - - bool succeeded = impl_prepareTransition(); - if (!succeeded) { - mpTransition = nullptr; - return false; - } - - impl_prepareSlides(); - return true; -} - -void OGLTransitionerImpl::createTexture( GLuint* texID, - bool useMipmap, - uno::Sequence& data, - const OGLFormat* pFormat ) -{ - CHECK_GL_ERROR(); - glDeleteTextures( 1, texID ); - glGenTextures( 1, texID ); - glBindTexture( GL_TEXTURE_2D, *texID ); - 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(); - - impl_createTexture( useMipmap, data, pFormat ); - - SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL"); - CHECK_GL_ERROR(); -} - -namespace -{ - class OGLColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace > - { - private: - uno::Sequence< sal_Int8 > maComponentTags; - uno::Sequence< sal_Int32 > maBitCounts; - - virtual sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) override - { - return rendering::ColorSpaceType::RGB; - } - virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) override - { - return maComponentTags; - } - virtual sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) override - { - return rendering::RenderingIntent::PERCEPTUAL; - } - virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) override - { - return uno::Sequence< beans::PropertyValue >(); - } - virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, - const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, - uno::RuntimeException, std::exception) override - { - // TODO(P3): if we know anything about target - // colorspace, this can be greatly sped up - uno::Sequence aIntermediate( - convertToARGB(deviceColor)); - return targetColorSpace->convertFromARGB(aIntermediate); - } - virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const double* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::RGBColor > aRes(nLen/4); - rendering::RGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const double* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::ARGBColor > aRes(nLen/4); - rendering::ARGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const double* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::ARGBColor > aRes(nLen/4); - rendering::ARGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::RGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< double > aRes(nLen*4); - double* pColors=aRes.getArray(); - for( std::size_t i=0; iRed; - *pColors++ = pIn->Green; - *pColors++ = pIn->Blue; - *pColors++ = 1.0; - ++pIn; - } - return aRes; - } - virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< double > aRes(nLen*4); - double* pColors=aRes.getArray(); - for( std::size_t i=0; iRed; - *pColors++ = pIn->Green; - *pColors++ = pIn->Blue; - *pColors++ = pIn->Alpha; - ++pIn; - } - return aRes; - } - virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< double > aRes(nLen*4); - double* pColors=aRes.getArray(); - for( std::size_t i=0; iRed/pIn->Alpha; - *pColors++ = pIn->Green/pIn->Alpha; - *pColors++ = pIn->Blue/pIn->Alpha; - *pColors++ = pIn->Alpha; - ++pIn; - } - return aRes; - } - - // XIntegerBitmapColorSpace - virtual sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) override - { - return 32; - } - virtual uno::Sequence< sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) override - { - return maBitCounts; - } - virtual sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) override - { - return util::Endianness::LITTLE; - } - virtual uno::Sequence SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor, - const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, - uno::RuntimeException, std::exception) override - { - if( dynamic_cast(targetColorSpace.get()) ) - { - const sal_Int8* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence aRes(nLen); - double* pOut( aRes.getArray() ); - for( std::size_t i=0; i aIntermediate( - convertIntegerToARGB(deviceColor)); - return targetColorSpace->convertFromARGB(aIntermediate); - } - } - virtual uno::Sequence< sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor, - const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, - uno::RuntimeException, std::exception) override - { - if( dynamic_cast(targetColorSpace.get()) ) - { - // it's us, so simply pass-through the data - return deviceColor; - } - else - { - // TODO(P3): if we know anything about target - // colorspace, this can be greatly sped up - uno::Sequence aIntermediate( - convertIntegerToARGB(deviceColor)); - return targetColorSpace->convertIntegerFromARGB(aIntermediate); - } - } - virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const sal_Int8* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::RGBColor > aRes(nLen/4); - rendering::RGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertIntegerToARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const sal_Int8* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::ARGBColor > aRes(nLen/4); - rendering::ARGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertIntegerToPARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const sal_Int8* pIn( deviceColor.getConstArray() ); - const std::size_t nLen( deviceColor.getLength() ); - ENSURE_ARG_OR_THROW2(nLen%4==0, - "number of channels no multiple of 4", - static_cast(this), 0); - - uno::Sequence< rendering::ARGBColor > aRes(nLen/4); - rendering::ARGBColor* pOut( aRes.getArray() ); - for( std::size_t i=0; i SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::RGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< sal_Int8 > aRes(nLen*4); - sal_Int8* pColors=aRes.getArray(); - for( std::size_t i=0; iRed); - *pColors++ = vcl::unotools::toByteColor(pIn->Green); - *pColors++ = vcl::unotools::toByteColor(pIn->Blue); - *pColors++ = -1; - ++pIn; - } - return aRes; - } - - virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< sal_Int8 > aRes(nLen*4); - sal_Int8* pColors=aRes.getArray(); - for( std::size_t i=0; iRed); - *pColors++ = vcl::unotools::toByteColor(pIn->Green); - *pColors++ = vcl::unotools::toByteColor(pIn->Blue); - *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); - ++pIn; - } - return aRes; - } - - virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override - { - const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); - const std::size_t nLen( rgbColor.getLength() ); - - uno::Sequence< sal_Int8 > aRes(nLen*4); - sal_Int8* pColors=aRes.getArray(); - for( std::size_t i=0; iRed/pIn->Alpha); - *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha); - *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha); - *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); - ++pIn; - } - return aRes; - } - - public: - OGLColorSpace() : - maComponentTags(4), - maBitCounts(4) - { - sal_Int8* pTags = maComponentTags.getArray(); - sal_Int32* pBitCounts = maBitCounts.getArray(); - pTags[0] = rendering::ColorComponentTag::RGB_RED; - pTags[1] = rendering::ColorComponentTag::RGB_GREEN; - pTags[2] = rendering::ColorComponentTag::RGB_BLUE; - pTags[3] = rendering::ColorComponentTag::ALPHA; - - pBitCounts[0] = - pBitCounts[1] = - pBitCounts[2] = - pBitCounts[3] = 8; - } - }; - - struct OGLColorSpaceHolder : public rtl::StaticWithInit, OGLColorSpaceHolder> - { - uno::Reference operator()() - { - return new OGLColorSpace(); - } - }; - - uno::Reference - getOGLColorSpace() - { - return OGLColorSpaceHolder::get(); - } -} - -namespace { - -void buildMipmaps( - GLint internalFormat, GLsizei width, GLsizei height, GLenum format, - GLenum type, const void * data) -{ - if (GLEW_ARB_framebuffer_object) { - glTexImage2D( - GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, - data); - glGenerateMipmap(GL_TEXTURE_2D); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - glTexImage2D( - GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, - data); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); -} - -} - -void OGLTransitionerImpl::impl_createTexture( - bool useMipmap, - uno::Sequence& data, - const OGLFormat* pFormat ) -{ - if( !pFormat ) - { - CHECK_GL_ERROR(); - // force-convert color to ARGB8888 int color space - uno::Sequence tempBytes( - maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace( - data, - getOGLColorSpace())); - buildMipmaps( GL_RGBA, - maSlideSize.Width, - maSlideSize.Height, - GL_RGBA, - GL_UNSIGNED_BYTE, - &tempBytes[0]); - - //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) - GLfloat largest_supported_anisotropy; - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy); - } else { - if( mpTransition && !mbBrokenTexturesATI && !useMipmap) { - glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] ); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - } else { - buildMipmaps( pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] ); - - //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) - GLfloat largest_supported_anisotropy; - glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy ); - } - } - CHECK_GL_ERROR(); -} - -const OGLFormat* OGLTransitionerImpl::chooseFormats() -{ - const OGLFormat* pDetectedFormat=nullptr; - uno::Reference xIntColorSpace( - maSlideBitmapLayout.ColorSpace); - - if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB || - xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) ) - { - /* table for canvas->OGL format mapping. outer index is number - of color components (0:3, 1:4), then comes bits per pixel - (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra, - 2:argb, 3:abgr) - */ - static const OGLFormat lcl_RGB24[] = - { - // 24 bit RGB - {3, GL_BGR, GL_UNSIGNED_BYTE}, - {3, GL_RGB, GL_UNSIGNED_BYTE}, - {3, GL_BGR, GL_UNSIGNED_BYTE}, - {3, GL_RGB, GL_UNSIGNED_BYTE} - }; - -#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3) - // more format constants available - static const OGLFormat lcl_RGB16[] = - { - // 16 bit RGB - {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, - {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, - {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, - {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5} - }; - - static const OGLFormat lcl_ARGB16_4[] = - { - // 16 bit ARGB - {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, - {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, - {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4}, - {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4} - }; - - static const OGLFormat lcl_ARGB16_5[] = - { - // 16 bit ARGB - {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, - {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, - {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1}, - {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1} - }; - - static const OGLFormat lcl_ARGB32[] = - { - // 32 bit ARGB - {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, - {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, - {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8}, - {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8} - }; - - const uno::Sequence aComponentTags( - xIntColorSpace->getComponentTags()); - const uno::Sequence aComponentBitcounts( - xIntColorSpace->getComponentBitCounts()); - const sal_Int32 nNumComponents( aComponentBitcounts.getLength() ); - const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() ); - - // supported component ordering? - const int nComponentOrderIndex( - calcComponentOrderIndex(aComponentTags)); - if( nComponentOrderIndex != -1 ) - { - switch( nBitsPerPixel ) - { - case 16: - if( nNumComponents == 3 ) - { - pDetectedFormat = &lcl_RGB16[nComponentOrderIndex]; - } - else if( nNumComponents == 4 ) - { - if( aComponentBitcounts[1] == 4 ) - { - pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex]; - } - else if( aComponentBitcounts[1] == 5 ) - { - pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex]; - } - } - break; - case 24: - if( nNumComponents == 3 ) - { - pDetectedFormat = &lcl_RGB24[nComponentOrderIndex]; - } - break; - case 32: - if ( nNumComponents == 4 ) - { - pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex]; - } - break; - } - } -#else - const uno::Sequence aComponentTags( - xIntColorSpace->getComponentTags()); - const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags)); - if( aComponentTags.getLength() == 3 && - nComponentOrderIndex != -1 && - xIntColorSpace->getBitsPerPixel() == 24 ) - { - pDetectedFormat = &lcl_RGB24[nComponentOrderIndex]; - } -#endif - } - - return pDetectedFormat; -} - -void OGLTransitionerImpl::GLInitSlides() -{ - osl::MutexGuard const guard( m_aMutex ); - - if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion) - return; - -#if OSL_DEBUG_LEVEL > 0 - TimerContext aTimerContext("texture creation"); -#endif - - mpContext->makeCurrent(); - - const OGLFormat* pFormat = chooseFormats(); - - CHECK_GL_ERROR(); - createTexture( &maLeavingSlideGL, - mpTransition->getSettings().mbUseMipMapLeaving, - maLeavingBytes, - pFormat ); - - createTexture( &maEnteringSlideGL, - mpTransition->getSettings().mbUseMipMapEntering, - maEnteringBytes, - pFormat ); - - CHECK_GL_ERROR(); - mpContext->sync(); - CHECK_GL_ERROR(); -} - -void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException, std::exception) -{ -#if OSL_DEBUG_LEVEL > 0 - mnFrameCount ++; - m_UpdateStartTime = std::chrono::steady_clock::now(); - if( mnFrameCount == 1 ) { - m_StartTime = m_UpdateStartTime; - m_TotalUpdateDuration = std::chrono::seconds(0); - } -#endif - osl::MutexGuard const guard( m_aMutex ); - - if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion) - return; - - mpContext->makeCurrent(); - CHECK_GL_ERROR(); - - glEnable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - CHECK_GL_ERROR(); - - const GLWindow& rGLWindow(mpContext->getOpenGLWindow()); - mpTransition->display( nTime, maLeavingSlideGL, maEnteringSlideGL, - maSlideSize.Width, maSlideSize.Height, - static_cast(rGLWindow.Width), - static_cast(rGLWindow.Height) ); - - mpContext->swapBuffers(); - - mpContext->show(); - mpContext->sync(); - CHECK_GL_ERROR(); - -#if OSL_DEBUG_LEVEL > 0 - m_UpdateEndTime = std::chrono::steady_clock::now(); - - SAL_INFO("slideshow.opengl", "update time: " << nTime); - SAL_INFO("slideshow.opengl", "update took: " << std::chrono::duration_cast(m_UpdateEndTime - m_UpdateStartTime).count()); - m_TotalUpdateDuration += (m_UpdateEndTime - m_UpdateStartTime); -#endif -} - -void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView, - const Reference< rendering::XBitmap >& rLeavingBitmap, - const Reference< rendering::XBitmap >& rEnteringBitmap ) - throw (uno::RuntimeException, std::exception) -{ - SAL_INFO("slideshow.opengl", "transitioner: view changed"); - - impl_dispose(); - - initWindowFromSlideShowView( rView ); - setSlides( rLeavingBitmap, rEnteringBitmap ); - impl_prepareSlides(); - impl_prepareTransition(); -} - -void OGLTransitionerImpl::disposeTextures() -{ - mpContext->makeCurrent(); - CHECK_GL_ERROR(); - - glDeleteTextures(1,&maLeavingSlideGL); - maLeavingSlideGL = 0; - glDeleteTextures(1,&maEnteringSlideGL); - maEnteringSlideGL = 0; - - CHECK_GL_ERROR(); -} - -void OGLTransitionerImpl::impl_dispose() -{ - mpContext->makeCurrent(); - CHECK_GL_ERROR(); - - impl_finishTransition(); - disposeTextures(); - if( mpContext.is() ) - mpContext->dispose(); - mpContext.clear(); -} - -// we are about to be disposed (someone call dispose() on us) -void OGLTransitionerImpl::disposing() -{ - osl::MutexGuard const guard( m_aMutex ); - -#if OSL_DEBUG_LEVEL > 0 - SAL_INFO("slideshow.opengl", "dispose " << this); - if( mnFrameCount ) { - m_EndTime = std::chrono::steady_clock::now(); - auto const duration = m_EndTime - m_StartTime; - SAL_INFO("slideshow.opengl", - "whole transition (frames: " << mnFrameCount - << ") took: " << std::chrono::duration_cast(duration).count() - << " fps: " - << (((double)mnFrameCount*1000000000.0)/std::chrono::duration_cast(duration).count()) - << " time spent in updates: " << std::chrono::duration_cast(m_TotalUpdateDuration).count() - << " percentage of transition time: " - << (100*(((double)std::chrono::duration_cast(m_TotalUpdateDuration).count())/((double)std::chrono::duration_cast(duration).count()))) - << '%' - ); - } -#endif - - if (mbRestoreSync && bool(mpContext.is())) { - // try to reestablish synchronize state - const char* sal_synchronize = getenv("SAL_SYNCHRONIZE"); - mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' ); - } - - impl_dispose(); - - mpTransition.reset(); - - mxLeavingBitmap.clear(); - mxEnteringBitmap.clear(); - mxView.clear(); -} - -OGLTransitionerImpl::OGLTransitionerImpl() - : OGLTransitionerImplBase(m_aMutex) - , mpContext() - , maLeavingSlideGL(0) - , maEnteringSlideGL(0) - , mxView() - , maEnteringBytes() - , maLeavingBytes() - , mbRestoreSync(false) - , maSlideBitmapLayout() - , maSlideSize() - , mbBrokenTexturesATI(false) - , mnGLVersion(0) - , mbValidOpenGLContext(false) -#if OSL_DEBUG_LEVEL > 0 - , mnFrameCount(0) -#endif -{ -} - -typedef cppu::WeakComponentImplHelper OGLTransitionFactoryImplBase; - -class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase -{ -public: - explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) : - OGLTransitionFactoryImplBase(m_aMutex) - {} - - // XTransitionFactory - virtual sal_Bool SAL_CALL hasTransition( sal_Int16 transitionType, sal_Int16 transitionSubType ) throw (uno::RuntimeException, std::exception) override - { - // A set of css::animation::TransitionSubType that don't have any meaning (in the SMIL 2.0 - // standard) for MISCSHAPEWIPE have been chosen to refer to some of these "fancy" optional - // transitions. (The only subtypes of 'miscShapeWipe' defined in the standard are 'heart' - // and 'keyhole'.) The set of subtypes used seems to be a bit random; it starts from the - // beginning of the list (in the order (numeric) in our TransitionSubType set of constants) - // but then jumps a bit randomly. The numeric values as such have no meaning, but still. - - if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) { - switch( transitionSubType ) - { - case animations::TransitionSubType::LEFTTORIGHT: // 1 - case animations::TransitionSubType::TOPTOBOTTOM: // 2 - case animations::TransitionSubType::TOPLEFT: // 3 - case animations::TransitionSubType::TOPRIGHT: // 4 - case animations::TransitionSubType::BOTTOMRIGHT: // 5 - case animations::TransitionSubType::BOTTOMLEFT: // 6 - case animations::TransitionSubType::TOPCENTER: // 7 - case animations::TransitionSubType::RIGHTCENTER: // 8 - case animations::TransitionSubType::BOTTOMCENTER: // 9 - case animations::TransitionSubType::CORNERSIN: // 11 - case animations::TransitionSubType::CORNERSOUT: // 12 - case animations::TransitionSubType::VERTICAL: // 13 - case animations::TransitionSubType::HORIZONTAL: // 14 - case animations::TransitionSubType::DIAMOND: // 26 - case animations::TransitionSubType::CIRCLE: // 27 - case animations::TransitionSubType::HEART: // 31 - case animations::TransitionSubType::FANOUTHORIZONTAL: // 55 - case animations::TransitionSubType::ACROSS: // 108 - return true; - - default: - return false; - } - } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) { - return true; - } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) { - return true; - } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) { - return true; - } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) { - return true; - } else - return false; - } - - virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition( - sal_Int16 transitionType, - sal_Int16 transitionSubType, - const uno::Reference< presentation::XSlideShowView >& view, - const uno::Reference< rendering::XBitmap >& leavingBitmap, - const uno::Reference< rendering::XBitmap >& enteringBitmap ) - throw (uno::RuntimeException, std::exception) override - { - if( !hasTransition( transitionType, transitionSubType ) ) - return uno::Reference< presentation::XTransition >(); - - rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() ); - if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) ) - return uno::Reference< presentation::XTransition >(); - - std::shared_ptr pTransition; - - if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) { - switch( transitionSubType ) - { - case animations::TransitionSubType::LEFTTORIGHT: - pTransition = makeFallLeaving(); - break; - case animations::TransitionSubType::TOPTOBOTTOM: - pTransition = makeTurnAround(); - break; - case animations::TransitionSubType::TOPLEFT: - pTransition = makeIris(); - break; - case animations::TransitionSubType::TOPRIGHT: - pTransition = makeTurnDown(); - break; - case animations::TransitionSubType::BOTTOMRIGHT: - pTransition = makeRochade(); - break; - case animations::TransitionSubType::BOTTOMLEFT: - pTransition = makeVenetianBlinds( true, 8 ); - break; - case animations::TransitionSubType::TOPCENTER: - pTransition = makeVenetianBlinds( false, 6 ); - break; - case animations::TransitionSubType::RIGHTCENTER: - pTransition = makeStatic(); - break; - case animations::TransitionSubType::BOTTOMCENTER: - pTransition = makeDissolve(); - break; - case animations::TransitionSubType::CORNERSIN: - pTransition = makeInsideCubeFaceToLeft(); - break; - case animations::TransitionSubType::CORNERSOUT: - pTransition = makeOutsideCubeFaceToLeft(); - break; - case animations::TransitionSubType::VERTICAL: - pTransition = makeVortex(); - break; - case animations::TransitionSubType::HORIZONTAL: - pTransition = makeRipple(); - break; - case animations::TransitionSubType::CIRCLE: - pTransition = makeRevolvingCircles(8,128); - break; - case animations::TransitionSubType::FANOUTHORIZONTAL: - pTransition = makeHelix(20); - break; - case animations::TransitionSubType::ACROSS: - pTransition = makeNByMTileFlip(8,6); - break; - case animations::TransitionSubType::DIAMOND: - pTransition = makeGlitter(); - break; - case animations::TransitionSubType::HEART: - pTransition = makeHoneycomb(); - break; - } - } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) { - pTransition = makeFadeSmoothly(); - } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) { - pTransition = makeFadeThroughBlack(); - } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) { - pTransition = makeDiamond(); - } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) { - pTransition = makeNewsflash(); - } - - if ( !pTransition || !xRes->setTransition(pTransition) ) - return uno::Reference< presentation::XTransition >(); - - return uno::Reference(xRes.get()); - } -}; - -} - -namespace sdecl = comphelper::service_decl; - const sdecl::ServiceDecl OGLTransitionFactoryDecl( - sdecl::class_(), - "com.sun.star.comp.presentation.OGLTransitionFactory", - "com.sun.star.presentation.TransitionFactory" ); - -// The C shared lib entry points -extern "C" -SAL_DLLPUBLIC_EXPORT void* SAL_CALL ogltrans_component_getFactory( sal_Char const* pImplName, - void*, void* ) -{ - return sdecl::component_getFactoryHelper( pImplName, {&OGLTransitionFactoryDecl} ); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit