diff --git a/BUILDING.md b/BUILDING.md index 4bacf0189e..7f47286c2e 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -62,7 +62,7 @@ _Note: if you ran docker with sudo, CasparCG server will not be able to run with 2. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master` 3. `cd casparcg-server-master` 4. Install dependencies, this can be done with `sudo ./tools/linux/install-dependencies` -5. Extract Boost, FFmpeg and CEF from the docker images via `sudo ./tools/linux/extract-deps-from-docker`. Alternatively these can be prepared manually by following the steps laid out in each Dockerfile +5. Extract Boost and FFmpeg from the docker images via `sudo ./tools/linux/extract-deps-from-docker`. Alternatively these can be prepared manually by following the steps laid out in each Dockerfile 6. `mkdir build && cd build` 7. `cmake ../src` 8. `make -j8` diff --git a/src/CMakeModules/Bootstrap_Linux.cmake b/src/CMakeModules/Bootstrap_Linux.cmake index d239d2ad28..44ec516fa9 100644 --- a/src/CMakeModules/Bootstrap_Linux.cmake +++ b/src/CMakeModules/Bootstrap_Linux.cmake @@ -1,5 +1,7 @@ cmake_minimum_required (VERSION 3.16) +include(ExternalProject) + # Determine build (target) platform INCLUDE (PlatformIntrospection) _DETERMINE_PLATFORM (CONFIG_PLATFORM) @@ -39,8 +41,29 @@ FIND_PACKAGE (SFML 2 COMPONENTS graphics window system REQUIRED) FIND_PACKAGE (X11 REQUIRED) if (ENABLE_HTML) - SET(CEF_ROOT_DIR "/opt/cef" CACHE STRING "Path to CEF") - FIND_PACKAGE (CEF REQUIRED) + casparcg_add_external_project(cef) + ExternalProject_Add(cef + URL https://cef-builds.spotifycdn.com/cef_binary_103.0.12%2Bg8eb56c7%2Bchromium-103.0.5060.134_linux64_minimal.tar.bz2 + URL_HASH SHA1=2f6500b81ea780feaabae41570192aef71d60963 + DOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE} + CMAKE_ARGS -DUSE_SANDBOX=Off + INSTALL_COMMAND "" + BUILD_BYPRODUCTS + "/Release/libcef.so" + "/libcef_dll_wrapper/libcef_dll_wrapper.a" + ) + ExternalProject_Get_Property(cef SOURCE_DIR) + ExternalProject_Get_Property(cef BINARY_DIR) + + # Note: All of these must be referenced in the BUILD_BYPRODUCTS above, to satisfy ninja + set(CEF_LIB + "${SOURCE_DIR}/Release/libcef.so" + "${BINARY_DIR}/libcef_dll_wrapper/libcef_dll_wrapper.a" + ) + + set(CEF_INCLUDE_PATH "${SOURCE_DIR}") + set(CEF_BIN_PATH "${SOURCE_DIR}/Release") + set(CEF_RESOURCE_PATH "${SOURCE_DIR}/Resources") endif () SET (BOOST_INCLUDE_PATH "${Boost_INCLUDE_DIRS}") @@ -50,10 +73,6 @@ SET (SFML_INCLUDE_PATH "${SFML_INCLUDE_DIR}") SET (FFMPEG_INCLUDE_PATH "${FFMPEG_INCLUDE_DIRS}") SET (FREEIMAGE_INCLUDE_PATH "${FreeImage_INCLUDE_DIRS}") -set(CEF_INCLUDE_PATH "${CEF_ROOT_DIR}") -set(CEF_BIN_PATH "${CEF_ROOT_DIR}/Release") -set(CEF_RESOURCE_PATH "${CEF_ROOT_DIR}/Resources") - SET_PROPERTY (GLOBAL PROPERTY USE_FOLDERS ON) ADD_DEFINITIONS (-DSFML_STATIC) diff --git a/src/CMakeModules/Bootstrap_Windows.cmake b/src/CMakeModules/Bootstrap_Windows.cmake index 9f8380a93b..dde2bb4a86 100644 --- a/src/CMakeModules/Bootstrap_Windows.cmake +++ b/src/CMakeModules/Bootstrap_Windows.cmake @@ -206,8 +206,8 @@ casparcg_add_runtime_dependency("${LIBERATION_FONTS_BIN_PATH}/LiberationMono-Reg if (ENABLE_HTML) casparcg_add_external_project(cef) ExternalProject_Add(cef - URL ${CASPARCG_DOWNLOAD_MIRROR}/cef/cef_binary_4638_windows_x64.zip - URL_HASH MD5=14ad547122903eba3f145322fb02bc6d + URL https://builds.julusian.dev/casparcg/dependencies/cef_binary_103.0.0-5060-shared-textures.2596%2Bgaa7dcf4%2Bchromium-103.0.5060.134_windows64_minimal.zip + URL_HASH MD5=240f5cebcc019410643c7e787a31ff75 DOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE} CMAKE_ARGS -DUSE_SANDBOX=Off -DCEF_RUNTIME_LIBRARY_FLAG=/MD INSTALL_COMMAND "" @@ -227,7 +227,6 @@ if (ENABLE_HTML) casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/resources.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/icudtl.dat") - casparcg_add_runtime_dependency_dir("${CEF_BIN_PATH}/swiftshader") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/snapshot_blob.bin") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/v8_context_snapshot.bin") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/libcef.dll") diff --git a/src/CMakeModules/FindCEF.cmake b/src/CMakeModules/FindCEF.cmake deleted file mode 100644 index 7528879cff..0000000000 --- a/src/CMakeModules/FindCEF.cmake +++ /dev/null @@ -1,69 +0,0 @@ -include(FindPackageHandleStandardArgs) - -SET(CEF_ROOT_DIR "" CACHE PATH "Path to a CEF distributed build") - -message(STATUS "Looking for Chromium Embedded Framework in ${CEF_ROOT_DIR}") - -find_path(CEF_INCLUDE_DIR "include/cef_version.h" - HINTS ${CEF_ROOT_DIR}) - -if(APPLE) - find_library(CEF_LIBRARY - NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" - NO_DEFAULT_PATH - PATHS ${CEF_ROOT_DIR} ${CEF_ROOT_DIR}/Release) - find_library(CEFWRAPPER_LIBRARY - NAMES cef_dll_wrapper libcef_dll_wrapper - NO_DEFAULT_PATH - PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Release - ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release - ${CEF_ROOT_DIR}/build/libcef_dll - ${CEF_ROOT_DIR}/build/libcef_dll_wrapper) -else() - find_library(CEF_LIBRARY - NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" - PATHS ${CEF_ROOT_DIR} ${CEF_ROOT_DIR}/Release) - find_library(CEFWRAPPER_LIBRARY - NAMES cef_dll_wrapper libcef_dll_wrapper - PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Release - ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release - ${CEF_ROOT_DIR}/build/libcef_dll - ${CEF_ROOT_DIR}/build/libcef_dll_wrapper - ${CEF_ROOT_DIR}/Release) - if(WIN32) - find_library(CEFWRAPPER_LIBRARY_DEBUG - NAMES cef_dll_wrapper libcef_dll_wrapper - PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Debug ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Debug) - endif() -endif() - -if(NOT CEF_LIBRARY) - set(CEF_FOUND FALSE) - message(FATAL_ERROR "Could not find the CEF shared library" ) - return() -endif() - -if(NOT CEFWRAPPER_LIBRARY) -set(CEF_FOUND FALSE) - message(FATAL_ERROR "Could not find the CEF wrapper library" ) - return() -endif() - -if(WIN32) - set(CEF_LIBRARIES - ${CEF_LIBRARY} - optimized ${CEFWRAPPER_LIBRARY}) - if (CEFWRAPPER_LIBRARY_DEBUG) - list(APPEND CEF_LIBRARIES - debug ${CEFWRAPPER_LIBRARY_DEBUG}) - endif() -else() - set(CEF_LIBRARIES - ${CEF_LIBRARY} - ${CEFWRAPPER_LIBRARY}) -endif() - -find_package_handle_standard_args(CEF DEFAULT_MSG CEF_LIBRARY - CEFWRAPPER_LIBRARY CEF_INCLUDE_DIR) -mark_as_advanced(CEF_LIBRARY CEF_WRAPPER_LIBRARY CEF_LIBRARIES - CEF_INCLUDE_DIR) diff --git a/src/accelerator/d3d/d3d_device.cpp b/src/accelerator/d3d/d3d_device.cpp index aed05529dc..510338691d 100644 --- a/src/accelerator/d3d/d3d_device.cpp +++ b/src/accelerator/d3d/d3d_device.cpp @@ -22,11 +22,6 @@ namespace caspar { namespace accelerator { namespace d3d { struct d3d_device::impl : public std::enable_shared_from_this { - using texture_queue_t = tbb::concurrent_bounded_queue>; - - mutable std::mutex device_pools_mutex_; - tbb::concurrent_unordered_map device_pools_; - std::wstring adaptor_name_ = L"N/A"; std::shared_ptr device_; std::shared_ptr ctx_; diff --git a/src/accelerator/d3d/d3d_texture2d.cpp b/src/accelerator/d3d/d3d_texture2d.cpp index 9f02f2839e..b7539ab365 100644 --- a/src/accelerator/d3d/d3d_texture2d.cpp +++ b/src/accelerator/d3d/d3d_texture2d.cpp @@ -45,7 +45,11 @@ d3d_texture2d::~d3d_texture2d() ogl->dispatch_sync([&] { const std::shared_ptr interop = ogl->d3d_interop(); if (texture_handle_ != nullptr && interop != nullptr) { - wglDXUnlockObjectsNV(interop.get(), 1, &texture_handle_); + if (is_locked_) { + wglDXUnlockObjectsNV(interop.get(), 1, &texture_handle_); + is_locked_ = false; + } + wglDXUnregisterObjectNV(interop.get(), texture_handle_); texture_handle_ = nullptr; } @@ -100,7 +104,63 @@ void d3d_texture2d::gen_gl_texture(std::shared_ptr ogl) gl_texture_id_ = 0; CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to lock shared d3d texture.")); } + + is_locked_ = true; }); } +void d3d_texture2d::lock_gl() +{ + if (is_locked_) + return; + + if (!texture_handle_ || gl_texture_id_ == 0) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("texture is not ready to be locked.")); + } + + const std::shared_ptr ogl = ogl_.lock(); + if (ogl == nullptr) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("failed to lock opengl device.")); + } + + const std::shared_ptr interop = ogl->d3d_interop(); + if (!interop) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("d3d interop not setup to lock shared d3d texture.")); + } + + bool res = ogl->dispatch_sync([&] { return wglDXLockObjectsNV(interop.get(), 1, &texture_handle_); }); + if (!res) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to lock shared d3d texture.")); + } + + is_locked_ = true; +} + +void d3d_texture2d::unlock_gl() +{ + if (!is_locked_) + return; + + if (!texture_handle_ || gl_texture_id_ == 0) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("texture is not ready to be locked.")); + } + + const std::shared_ptr ogl = ogl_.lock(); + if (ogl == nullptr) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("failed to lock opengl device.")); + } + + const std::shared_ptr interop = ogl->d3d_interop(); + if (!interop) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("d3d interop not setup to unlock shared d3d texture.")); + } + + bool res = ogl->dispatch_sync([&] { return wglDXUnlockObjectsNV(interop.get(), 1, &texture_handle_); }); + if (!res) { + CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to unlock shared d3d texture.")); + } + + is_locked_ = false; +} + }}} // namespace caspar::accelerator::d3d diff --git a/src/accelerator/d3d/d3d_texture2d.h b/src/accelerator/d3d/d3d_texture2d.h index 61fe4dc09a..cb2dc2ecef 100644 --- a/src/accelerator/d3d/d3d_texture2d.h +++ b/src/accelerator/d3d/d3d_texture2d.h @@ -33,6 +33,10 @@ class d3d_texture2d void gen_gl_texture(std::shared_ptr); + void lock_gl(); + + void unlock_gl(); + private: HANDLE share_handle_; @@ -44,5 +48,6 @@ class d3d_texture2d std::weak_ptr ogl_; HANDLE texture_handle_ = nullptr; uint32_t gl_texture_id_ = 0; + bool is_locked_ = false; }; }}} // namespace caspar::accelerator::d3d diff --git a/src/accelerator/ogl/image/image_mixer.cpp b/src/accelerator/ogl/image/image_mixer.cpp index 77f314a37c..00c774cd85 100644 --- a/src/accelerator/ogl/image/image_mixer.cpp +++ b/src/accelerator/ogl/image/image_mixer.cpp @@ -341,8 +341,11 @@ struct image_mixer::impl // map directx texture with wgl texture if (d3d_texture->gl_texture_id() == 0) d3d_texture->gen_gl_texture(ogl_); + else + // signal d3d to flush/sync the texture + d3d_texture->lock_gl(); - // copy directx texture to gl texture + // copy d3d texture to gl texture auto gl_texture = ogl_->dispatch_sync([=] { return ogl_->copy_async(d3d_texture->gl_texture_id(), d3d_texture->width(), d3d_texture->height(), 4); }); @@ -350,6 +353,9 @@ struct image_mixer::impl // make gl texture to draw std::vector textures{make_ready_future(gl_texture.get())}; + // signal d3d is free to take ownership + d3d_texture->unlock_gl(); + std::weak_ptr weak_self = shared_from_this(); core::pixel_format_desc desc(core::pixel_format::bgra); desc.planes.push_back(core::pixel_format_desc::plane(d3d_texture->width(), d3d_texture->height(), 4)); diff --git a/src/modules/html/CMakeLists.txt b/src/modules/html/CMakeLists.txt index 01f7084486..60afd653a6 100644 --- a/src/modules/html/CMakeLists.txt +++ b/src/modules/html/CMakeLists.txt @@ -41,8 +41,7 @@ if(MSVC) ) else() target_link_libraries(html - ${CEF_BIN_PATH}/libcef.so - ${CEF_BIN_PATH}/libcef_dll_wrapper.a + ${CEF_LIB} ) endif() diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index ff1cce406d..ecc5b98b25 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -168,7 +168,6 @@ else () ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CEF_RESOURCE_PATH}/icudtl.dat ${CMAKE_BINARY_DIR}/staging/lib/icudtl.dat) ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CEF_RESOURCE_PATH}/resources.pak ${CMAKE_BINARY_DIR}/staging/lib/resources.pak) - ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CEF_BIN_PATH}/swiftshader ${CMAKE_BINARY_DIR}/staging/lib/swiftshader) ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CEF_BIN_PATH}/chrome-sandbox ${CMAKE_BINARY_DIR}/staging/lib/chrome-sandbox) ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CEF_BIN_PATH}/libcef.so ${CMAKE_BINARY_DIR}/staging/lib/libcef.so) ADD_CUSTOM_COMMAND (TARGET casparcg POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CEF_BIN_PATH}/libEGL.so ${CMAKE_BINARY_DIR}/staging/lib/libEGL.so) diff --git a/tools/linux/Dockerfile b/tools/linux/Dockerfile index 292af505d8..48f872e8c6 100644 --- a/tools/linux/Dockerfile +++ b/tools/linux/Dockerfile @@ -1,16 +1,13 @@ ARG IMAGE_BASE ARG IMAGE_BOOST ARG IMAGE_FFMPEG -ARG IMAGE_CEF FROM ${IMAGE_BOOST} as boost FROM ${IMAGE_FFMPEG} as ffmpeg -FROM ${IMAGE_CEF} as cef FROM ${IMAGE_BASE} as build-casparcg COPY --from=boost /opt/boost /opt/boost COPY --from=ffmpeg /opt/ffmpeg /opt/ffmpeg - COPY --from=cef /opt/cef /opt/cef RUN mkdir /source && mkdir /build && mkdir /install diff --git a/tools/linux/build-base-images b/tools/linux/build-base-images index a6deab5b49..769aa8a19f 100755 --- a/tools/linux/build-base-images +++ b/tools/linux/build-base-images @@ -2,6 +2,6 @@ source $(dirname "$0")/image-versions -docker rmi $IMAGE_BASE $IMAGE_CEF $IMAGE_BOOST $IMAGE_FFMPEG +docker rmi $IMAGE_BASE $IMAGE_BOOST $IMAGE_FFMPEG $(dirname "$0")/ensure-base-images diff --git a/tools/linux/build-in-docker b/tools/linux/build-in-docker index 745764f4c4..c53f0e7fb4 100755 --- a/tools/linux/build-in-docker +++ b/tools/linux/build-in-docker @@ -10,7 +10,6 @@ docker build -t casparcg/server \ --build-arg PROC_COUNT \ --build-arg GIT_HASH \ --build-arg IMAGE_BASE \ - --build-arg IMAGE_CEF \ --build-arg IMAGE_BOOST \ --build-arg IMAGE_FFMPEG \ -f $PWD/tools/linux/Dockerfile $PWD diff --git a/tools/linux/cef/Dockerfile b/tools/linux/cef/Dockerfile deleted file mode 100644 index 91e9798a8a..0000000000 --- a/tools/linux/cef/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -ARG IMAGE_BASE - -FROM ${IMAGE_BASE} as BUILD - ARG PROC_COUNT=8 - - WORKDIR /opt - - ADD https://cdn-fastly.obsproject.com/downloads/cef_binary_4638_linux64.tar.bz2 /opt/cef.tar.bz2 - RUN tar -jxf cef.tar.bz2 && mv /opt/cef_binary_* /opt/cef - RUN mkdir /opt/build - WORKDIR /opt/build - RUN cmake /opt/cef && make -j $PROC_COUNT - RUN cp /opt/build/libcef_dll_wrapper/libcef_dll_wrapper.a /opt/cef/Release/ - RUN strip /opt/cef/Release/libcef.so - -FROM scratch - COPY --from=BUILD /opt/cef /opt/cef diff --git a/tools/linux/ensure-base-images b/tools/linux/ensure-base-images index 8b4b7f425a..e087b343ea 100755 --- a/tools/linux/ensure-base-images +++ b/tools/linux/ensure-base-images @@ -3,13 +3,11 @@ source $(dirname "$0")/image-versions docker pull $IMAGE_BASE || docker build --pull -f tools/linux/base/Dockerfile -t $IMAGE_BASE tools/linux -docker pull $IMAGE_CEF || docker build -t $IMAGE_CEF --build-arg PROC_COUNT --build-arg IMAGE_BASE tools/linux/cef docker pull $IMAGE_BOOST || docker build -t $IMAGE_BOOST --build-arg PROC_COUNT --build-arg IMAGE_BASE tools/linux/boost docker pull $IMAGE_FFMPEG || docker build -t $IMAGE_FFMPEG --build-arg PROC_COUNT --build-arg IMAGE_BASE tools/linux/ffmpeg if [ "$CASPARCG_PUSH_IMAGES" = true ]; then docker push $IMAGE_BASE - docker push $IMAGE_CEF docker push $IMAGE_BOOST docker push $IMAGE_FFMPEG fi diff --git a/tools/linux/extract-deps-from-docker b/tools/linux/extract-deps-from-docker index d0155d2c65..0be143bf90 100755 --- a/tools/linux/extract-deps-from-docker +++ b/tools/linux/extract-deps-from-docker @@ -2,13 +2,6 @@ source $(dirname "$0")/image-versions -# CEF -echo "Extracting CEF" -rm -Rf /opt/cef -tempContainer=$(docker create $IMAGE_CEF sh) -docker cp $tempContainer:/opt/cef /opt/cef -docker rm -v $tempContainer - # FFmpeg echo "Extracting FFmpeg" rm -Rf /opt/ffmpeg diff --git a/tools/linux/image-versions b/tools/linux/image-versions index d87e1fa96a..994afb6efa 100644 --- a/tools/linux/image-versions +++ b/tools/linux/image-versions @@ -3,6 +3,5 @@ export IMAGE_PREFIX=ghcr.io/casparcg/server/ export IMAGE_BASE=${IMAGE_PREFIX}base:jammy-0 -export IMAGE_CEF=${IMAGE_PREFIX}cef:95.0.4638.69-obs-2 export IMAGE_BOOST=${IMAGE_PREFIX}boost:1.67-2 export IMAGE_FFMPEG=${IMAGE_PREFIX}ffmpeg:5.1.3-1