diff --git a/linphone-desktop/CMakeLists.txt b/linphone-desktop/CMakeLists.txt index d587207cc..8aaccf6be 100644 --- a/linphone-desktop/CMakeLists.txt +++ b/linphone-desktop/CMakeLists.txt @@ -72,6 +72,7 @@ set(SOURCES src/app/Paths.cpp src/app/ThumbnailProvider.cpp src/components/camera/Camera.cpp + src/components/camera/MSFunctions.cpp src/components/call/CallModel.cpp src/components/calls/CallsListModel.cpp src/components/chat/ChatModel.cpp @@ -100,6 +101,7 @@ set(HEADERS src/app/Paths.hpp src/app/ThumbnailProvider.hpp src/components/camera/Camera.hpp + src/components/camera/MSFunctions.hpp src/components/call/CallModel.hpp src/components/calls/CallsListModel.hpp src/components/chat/ChatModel.hpp @@ -186,10 +188,10 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E copy find_package(Qt5 COMPONENTS ${QT5_PACKAGES} REQUIRED) if(CMAKE_INSTALL_RPATH) - get_target_property(LUPDATE_PATH Qt5::lupdate LOCATION) - get_filename_component(LUPDATE_PATH "${LUPDATE_PATH}" DIRECTORY) - get_filename_component(QT_PATH "${LUPDATE_PATH}/../lib" ABSOLUTE) - list(APPEND CMAKE_INSTALL_RPATH "${QT_PATH}") + get_target_property(LUPDATE_PATH Qt5::lupdate LOCATION) + get_filename_component(LUPDATE_PATH "${LUPDATE_PATH}" DIRECTORY) + get_filename_component(QT_PATH "${LUPDATE_PATH}/../lib" ABSOLUTE) + list(APPEND CMAKE_INSTALL_RPATH "${QT_PATH}") endif() # Add languages support. @@ -230,4 +232,3 @@ install(TARGETS ${TARGET_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) - diff --git a/linphone-desktop/src/components/camera/Camera.cpp b/linphone-desktop/src/components/camera/Camera.cpp index 0f44ed7fc..6a78546ad 100644 --- a/linphone-desktop/src/components/camera/Camera.cpp +++ b/linphone-desktop/src/components/camera/Camera.cpp @@ -21,11 +21,11 @@ */ #include -#include -#include +#include #include "../../utils.hpp" #include "../core/CoreManager.hpp" +#include "MSFunctions.hpp" #include "Camera.hpp" @@ -58,6 +58,8 @@ struct CameraStateBinder { struct ContextInfo { GLuint width; GLuint height; + + OpenGlFunctions *functions; }; // ----------------------------------------------------------------------------- @@ -101,11 +103,25 @@ void CameraRenderer::render () { f->glClearColor(0.f, 0.f, 0.f, 0.f); f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_camera->getCall()->getLinphoneCall()->oglRender(m_camera->m_is_preview); + // Draw with ms filter. + MSFunctions *ms_functions = MSFunctions::getInstance(); + ms_functions->bind(f); + m_camera->getCall()->getLinphoneCall()->oglRender(m_camera->m_is_preview); + ms_functions->bind(nullptr); + + // Synchronize opengl calls with QML. + if (m_window) + m_window->resetOpenGLState(); + + // Process at next tick. update(); } +void CameraRenderer::synchronize (QQuickFramebufferObject *item) { + m_window = item->window(); +} + // ----------------------------------------------------------------------------- Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) { @@ -116,9 +132,16 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) { setMirrorVertically(true); m_context_info = new ContextInfo(); + m_context_info->functions = MSFunctions::getInstance()->getFunctions(); } Camera::~Camera () { + // Reset context in ms filter. + if (m_is_preview) + CoreManager::getInstance()->getCore()->setNativePreviewWindowId(nullptr); + else + m_call->getLinphoneCall()->setNativeVideoWindowId(nullptr); + delete m_context_info; } diff --git a/linphone-desktop/src/components/camera/Camera.hpp b/linphone-desktop/src/components/camera/Camera.hpp index ff43ddd7f..e0db60615 100644 --- a/linphone-desktop/src/components/camera/Camera.hpp +++ b/linphone-desktop/src/components/camera/Camera.hpp @@ -41,12 +41,14 @@ public: CameraRenderer (const Camera *camera); ~CameraRenderer () = default; +protected: QOpenGLFramebufferObject *createFramebufferObject (const QSize &size) override; - void render () override; + void synchronize (QQuickFramebufferObject *item) override; private: const Camera *m_camera; + QQuickWindow *m_window; }; // ----------------------------------------------------------------------------- @@ -83,9 +85,9 @@ private: bool m_is_preview = false; CallModel *m_call = nullptr; ContextInfo *m_context_info; + QImage m_screenshot; mutable CameraRenderer *m_renderer; - QImage m_screenshot; }; #endif // CAMERA_H_ diff --git a/linphone-desktop/src/components/camera/MSFunctions.cpp b/linphone-desktop/src/components/camera/MSFunctions.cpp new file mode 100644 index 000000000..1fd826ed5 --- /dev/null +++ b/linphone-desktop/src/components/camera/MSFunctions.cpp @@ -0,0 +1,57 @@ +#include + +// Do not include this header before `QOpenGLFunctions`!!! +#include + +#include "MSFunctions.hpp" + +// ============================================================================= + +MSFunctions *MSFunctions::m_instance = nullptr; + +// ----------------------------------------------------------------------------- + +MSFunctions::MSFunctions () { + OpenGlFunctions *f = m_functions = new OpenGlFunctions(); + + f->glActiveTexture = qtResolveGlActiveTexture; + f->glAttachShader = qtResolveGlAttachShader; + f->glBindAttribLocation = qtResolveGlBindAttribLocation; + f->glBindTexture = qtResolveGlBindTexture; + f->glClear = qtResolveGlClear; + f->glClearColor = qtResolveGlClearColor; + f->glCompileShader = qtResolveGlCompileShader; + f->glCreateProgram = qtResolveGlCreateProgram; + f->glCreateShader = qtResolveGlCreateShader; + f->glDeleteProgram = qtResolveGlDeleteProgram; + f->glDeleteShader = qtResolveGlDeleteShader; + f->glDeleteTextures = qtResolveGlDeleteTextures; + f->glDisable = qtResolveGlDisable; + f->glDrawArrays = qtResolveGlDrawArrays; + f->glEnableVertexAttribArray = qtResolveGlEnableVertexAttribArray; + f->glGenTextures = qtResolveGlGenTextures; + f->glGetError = qtResolveGlGetError; + f->glGetProgramInfoLog = qtResolveGlGetProgramInfoLog; + f->glGetProgramiv = qtResolveGlGetProgramiv; + f->glGetShaderInfoLog = qtResolveGlGetShaderInfoLog; + f->glGetShaderiv = qtResolveGlGetShaderiv; + f->glGetString = qtResolveGlGetString; + f->glGetUniformLocation = qtResolveGlGetUniformLocation; + f->glLinkProgram = qtResolveGlLinkProgram; + f->glPixelStorei = qtResolveGlPixelStorei; + f->glShaderSource = qtResolveGlShaderSource; + f->glTexImage2D = qtResolveGlTexImage2D; + f->glTexParameteri = qtResolveGlTexParameteri; + f->glTexSubImage2D = qtResolveGlTexSubImage2D; + f->glUniform1f = qtResolveGlUniform1f; + f->glUniform1i = qtResolveGlUniform1i; + f->glUniformMatrix4fv = qtResolveGlUniformMatrix4fv; + f->glUseProgram = qtResolveGlUseProgram; + f->glValidateProgram = qtResolveGlValidateProgram; + f->glVertexAttribPointer = qtResolveGlVertexAttribPointer; + f->glViewport = qtResolveGlViewport; +} + +MSFunctions::~MSFunctions () { + delete m_functions; +} diff --git a/linphone-desktop/src/components/camera/MSFunctions.hpp b/linphone-desktop/src/components/camera/MSFunctions.hpp new file mode 100644 index 000000000..7320092a7 --- /dev/null +++ b/linphone-desktop/src/components/camera/MSFunctions.hpp @@ -0,0 +1,196 @@ +#ifndef MS_FUNCTIONS_H_ +#define MS_FUNCTIONS_H_ + +#include + +#define GL_CALL(CALL) \ + Q_ASSERT(QOpenGLContext::currentContext()->functions() == m_instance->m_q_functions); \ + m_instance->m_q_functions->CALL; + +#define GL_CALL_RET(CALL) \ + Q_ASSERT(QOpenGLContext::currentContext()->functions() == m_instance->m_q_functions); \ + return m_instance->m_q_functions->CALL; + +// ============================================================================= + +struct OpenGlFunctions; + +class MSFunctions { +public: + ~MSFunctions (); + + void bind (QOpenGLFunctions *f) { + m_q_functions = f; + } + + OpenGlFunctions *getFunctions () { + return m_functions; + } + + // --------------------------------------------------------------------------- + + static MSFunctions *getInstance () { + if (!m_instance) + m_instance = new MSFunctions(); + + return m_instance; + } + + // --------------------------------------------------------------------------- + + static void qtResolveGlActiveTexture (GLenum texture) { + GL_CALL(glActiveTexture(texture)); + } + + static void qtResolveGlAttachShader (GLuint program, GLuint shader) { + GL_CALL(glAttachShader(program, shader)); + } + + static void qtResolveGlBindAttribLocation (GLuint program, GLuint index, const char *name) { + GL_CALL(glBindAttribLocation(program, index, name)); + } + + static void qtResolveGlBindTexture (GLenum target, GLuint texture) { + GL_CALL(glBindTexture(target, texture)); + } + + static void qtResolveGlClear (GLbitfield mask) { + GL_CALL(glClear(mask)); + } + + static void qtResolveGlClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + GL_CALL(glClearColor(red, green, blue, alpha)); + } + + static void qtResolveGlCompileShader (GLuint shader) { + GL_CALL(glCompileShader(shader)); + } + + static GLuint qtResolveGlCreateProgram () { + GL_CALL_RET(glCreateProgram()); + } + + static GLuint qtResolveGlCreateShader (GLenum type) { + GL_CALL_RET(glCreateShader(type)); + } + + static void qtResolveGlDeleteProgram (GLuint program) { + GL_CALL(glDeleteProgram(program)); + } + + static void qtResolveGlDeleteShader (GLuint shader) { + GL_CALL(glDeleteShader(shader)); + } + + static void qtResolveGlDeleteTextures (GLsizei n, const GLuint *textures) { + GL_CALL(glDeleteTextures(n, textures)); + } + + static void qtResolveGlDisable (GLenum cap) { + GL_CALL(glDisable(cap)); + } + + static void qtResolveGlDrawArrays (GLenum mode, GLint first, GLsizei count) { + GL_CALL(glDrawArrays(mode, first, count)); + } + + static void qtResolveGlEnableVertexAttribArray (GLuint index) { + GL_CALL(glEnableVertexAttribArray(index)); + } + + static void qtResolveGlGenTextures (GLsizei n, GLuint *textures) { + GL_CALL(glGenTextures(n, textures)); + } + + static GLenum qtResolveGlGetError () { + GL_CALL_RET(glGetError()); + } + + static void qtResolveGlGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei *length, char *infolog) { + GL_CALL(glGetProgramInfoLog(program, bufsize, length, infolog)); + } + + static void qtResolveGlGetProgramiv (GLuint program, GLenum pname, GLint *params) { + GL_CALL(glGetProgramiv(program, pname, params)); + } + + static void qtResolveGlGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei *length, char *infolog) { + GL_CALL(glGetShaderInfoLog(shader, bufsize, length, infolog)); + } + + static void qtResolveGlGetShaderiv (GLuint shader, GLenum pname, GLint *params) { + GL_CALL(glGetShaderiv(shader, pname, params)); + } + + static const GLubyte *qtResolveGlGetString (GLenum name) { + GL_CALL_RET(glGetString(name)); + } + + static GLint qtResolveGlGetUniformLocation (GLuint program, const char *name) { + GL_CALL_RET(glGetUniformLocation(program, name)); + } + + static void qtResolveGlLinkProgram (GLuint program) { + GL_CALL(glLinkProgram(program)); + } + + static void qtResolveGlPixelStorei (GLenum pname, GLint param) { + GL_CALL(glPixelStorei(pname, param)); + } + + static void qtResolveGlShaderSource (GLuint shader, GLsizei count, const char **string, const GLint *length) { + GL_CALL(glShaderSource(shader, count, string, length)); + } + + static void qtResolveGlTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { + GL_CALL(glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels)); + } + + static void qtResolveGlTexParameteri (GLenum target, GLenum pname, GLint param) { + GL_CALL(glTexParameteri(target, pname, param)); + } + + static void qtResolveGlTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { + GL_CALL(glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels)); + } + + static void qtResolveGlUniform1f (GLint location, GLfloat x) { + GL_CALL(glUniform1f(location, x)); + } + + static void qtResolveGlUniform1i (GLint location, GLint x) { + GL_CALL(glUniform1i(location, x)); + } + + static void qtResolveGlUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + GL_CALL(glUniformMatrix4fv(location, count, transpose, value)); + } + + static void qtResolveGlUseProgram (GLuint program) { + GL_CALL(glUseProgram(program)); + } + + static void qtResolveGlValidateProgram (GLuint program) { + GL_CALL(glValidateProgram(program)); + } + + static void qtResolveGlVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr) { + GL_CALL(glVertexAttribPointer(indx, size, type, normalized, stride, ptr)); + } + + static void qtResolveGlViewport (GLint x, GLint y, GLsizei width, GLsizei height) { + GL_CALL(glViewport(x, y, width, height)); + } + + // --------------------------------------------------------------------------- + +private: + MSFunctions (); + + OpenGlFunctions *m_functions = nullptr; + QOpenGLFunctions *m_q_functions = nullptr; + + static MSFunctions *m_instance; +}; + +#endif // MS_FUNCTIONS_H_ diff --git a/linphone-desktop/src/utils.hpp b/linphone-desktop/src/utils.hpp index 9711f412b..77bb76c9c 100644 --- a/linphone-desktop/src/utils.hpp +++ b/linphone-desktop/src/utils.hpp @@ -23,6 +23,7 @@ #ifndef UTILS_H_ #define UTILS_H_ +#include #include // ============================================================================= @@ -35,6 +36,19 @@ namespace Utils { inline std::string qStringToLinphoneString (const QString &string) { return string.toLocal8Bit().constData(); } + + template + T *findParentType (const QObject *object) { + QObject *parent = object->parent(); + if (!parent) + return nullptr; + + T *found = qobject_cast(parent); + if (found) + return found; + + return findParentType(parent); + } } #endif // UTILS_H_ diff --git a/submodules/linphone b/submodules/linphone index 4849ca2e3..f4d1fd0fe 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 4849ca2e35747752edb02c5378ba650a2caffb5e +Subproject commit f4d1fd0fe77b2fedc2eaeccd566619bdbdb37544