Skip to content

Commit

Permalink
Add feature to disable web renderer (#335)
Browse files Browse the repository at this point in the history
  • Loading branch information
noituri authored Jan 5, 2024
1 parent 084dee8 commit baf90e5
Show file tree
Hide file tree
Showing 22 changed files with 508 additions and 299 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/package_for_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ jobs:
name: video_compositor_linux_x86_64.tar.gz
path: video_compositor_linux_x86_64.tar.gz

- uses: actions/upload-artifact@v3
with:
name: video_compositor_with_web_renderer_linux_x86_64.tar.gz
path: video_compositor_with_web_renderer_linux_x86_64.tar.gz

macos_x86_64:
runs-on: macos-latest
steps:
Expand All @@ -44,6 +49,11 @@ jobs:
with:
name: video_compositor_darwin_x86_64.tar.gz
path: video_compositor_darwin_x86_64.tar.gz

- uses: actions/upload-artifact@v3
with:
name: video_compositor_with_web_renderer_darwin_x86_64.tar.gz
path: video_compositor_with_web_renderer_darwin_x86_64.tar.gz

macos-aarch64:
runs-on: macos-latest-xlarge
Expand All @@ -64,3 +74,8 @@ jobs:
with:
name: video_compositor_darwin_aarch64.tar.gz
path: video_compositor_darwin_aarch64.tar.gz

- uses: actions/upload-artifact@v3
with:
name: video_compositor_with_web_renderer_darwin_aarch64.tar.gz
path: video_compositor_with_web_renderer_darwin_aarch64.tar.gz
2 changes: 1 addition & 1 deletion .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ jobs:

- name: shellcheck
run: |
shellcheck ./scripts/release.sh ./scripts/compositor_runtime_wrapper.sh
shellcheck ./scripts/release.sh ./src/bin/package_for_release/linux_runtime_wrapper.sh
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace]
members = [
"compositor_render",
"compositor_pipeline",
"compositor_chromium",
]
members = ["compositor_render", "compositor_pipeline", "compositor_chromium"]
resolver = "2"

[features]
default = ["web_renderer"]
web_renderer = ["dep:compositor_chromium", "compositor_render/web_renderer"]

[workspace.dependencies]
bytes = "1.4.0"
serde_json = { version = "1.0.99", features = ["preserve_order"] }
Expand All @@ -31,7 +31,7 @@ rtp = "0.9.0"
[dependencies]
compositor_render = { path = "compositor_render" }
compositor_pipeline = { path = "compositor_pipeline" }
compositor_chromium = { path = "compositor_chromium" }
compositor_chromium = { path = "compositor_chromium", optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
Expand All @@ -57,3 +57,8 @@ libc = "0.2.151"

[dev-dependencies]
reqwest = { workspace = true }

[[bin]]
name = "process_helper"
path = "src/bin/process_helper/main.rs"
required-features = ["web_renderer"]
2 changes: 0 additions & 2 deletions compositor_pipeline/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
compositor_render = { path = "../compositor_render" }
compositor_chromium = { path = "../compositor_chromium" }
bytes = { workspace = true }
crossbeam-channel = { workspace = true }
anyhow = "1.0.71"
Expand Down
2 changes: 1 addition & 1 deletion compositor_pipeline/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pub struct Options {
}

impl<Input: PipelineInput, Output: PipelineOutput> Pipeline<Input, Output> {
pub fn new(opts: Options) -> Result<(Self, EventLoop), InitRendererEngineError> {
pub fn new(opts: Options) -> Result<(Self, Arc<dyn EventLoop>), InitRendererEngineError> {
let (renderer, event_loop) = Renderer::new(RendererOptions {
web_renderer: opts.web_renderer,
framerate: opts.framerate,
Expand Down
4 changes: 3 additions & 1 deletion compositor_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
web_renderer = ["dep:compositor_chromium"]

[dependencies]
pollster = "0.3.0"
thiserror = { workspace = true }
wgpu = { version = "0.16.1", features = ["naga"] }
compositor_chromium = { path = "../compositor_chromium" }
compositor_chromium = { path = "../compositor_chromium", optional = true }
image = { workspace = true }
reqwest = { workspace = true }
bytes = { workspace = true }
Expand Down
32 changes: 2 additions & 30 deletions compositor_render/src/event_loop.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,8 @@
use std::sync::Arc;

use compositor_chromium::cef;

pub struct EventLoop {
cef_ctx: Option<Arc<cef::Context>>,
}

impl EventLoop {
pub fn new(cef_ctx: Option<Arc<cef::Context>>) -> Self {
Self { cef_ctx }
}

pub trait EventLoop {
/// Runs the event loop. It must run on the main thread.
/// `fallback` is used when web rendering is disabled.
/// Blocks the thread indefinitely.
pub fn run_with_fallback(&self, fallback: impl FnOnce()) -> Result<(), EventLoopRunError> {
match &self.cef_ctx {
Some(ctx) => self.cef_event_loop(ctx)?,
None => fallback(),
}

Ok(())
}

fn cef_event_loop(&self, ctx: &cef::Context) -> Result<(), EventLoopRunError> {
if !ctx.currently_on_thread(cef::ThreadId::UI) {
return Err(EventLoopRunError::WrongThread);
}

ctx.run_message_loop();
Ok(())
}
fn run_with_fallback(&self, fallback: &dyn Fn()) -> Result<(), EventLoopRunError>;
}

#[derive(Debug, thiserror::Error)]
Expand Down
10 changes: 6 additions & 4 deletions compositor_render/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::image;
use crate::scene::OutputScene;
use crate::transformations::image_renderer::Image;
use crate::transformations::shader::Shader;
use crate::transformations::web_renderer::WebRenderer;
use crate::transformations::web_renderer::{self, WebRenderer};
use crate::{
error::{InitRendererEngineError, RenderSceneError, UpdateSceneError},
transformations::{
Expand All @@ -19,7 +19,7 @@ use crate::{
scene::{self, SceneState},
wgpu::{WgpuCtx, WgpuErrorScope},
};
use crate::{shader, web_renderer, RegistryType, RendererId};
use crate::{shader, RegistryType, RendererId};

use self::{
render_graph::RenderGraph,
Expand Down Expand Up @@ -79,9 +79,11 @@ pub enum RendererSpec {
}

impl Renderer {
pub fn new(opts: RendererOptions) -> Result<(Self, EventLoop), InitRendererEngineError> {
pub fn new(
opts: RendererOptions,
) -> Result<(Self, Arc<dyn EventLoop>), InitRendererEngineError> {
let renderer = InnerRenderer::new(opts)?;
let event_loop = EventLoop::new(renderer.chromium_context.cef_context());
let event_loop = renderer.chromium_context.event_loop();

Ok((Self(Arc::new(Mutex::new(renderer))), event_loop))
}
Expand Down
173 changes: 17 additions & 156 deletions compositor_render/src/transformations/web_renderer.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
use crate::{FallbackStrategy, RendererId, Resolution};
use bytes::Bytes;
use nalgebra_glm::Mat4;
use std::env;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};

use crate::state::render_graph::NodeId;
use crate::state::{RegisterCtx, RenderCtx};
use crate::transformations::web_renderer::shader::WebRendererShader;
use crate::wgpu::common_pipeline::CreateShaderError;
use crate::wgpu::texture::{BGRATexture, NodeTexture, Texture};
use crate::{FallbackStrategy, RendererId, Resolution};
#[cfg(feature = "web_renderer")]
mod renderer;

use crate::transformations::web_renderer::browser_client::BrowserClient;
use crate::transformations::web_renderer::chromium_sender::ChromiumSender;
use crate::transformations::web_renderer::embedder::{EmbedError, EmbeddingHelper};
use log::{error, info};
#[cfg(not(feature = "web_renderer"))]
#[path = "web_renderer/disabled_renderer.rs"]
mod renderer;

use self::embedder::RenderInfo;
pub use renderer::*;

pub mod browser_client;
pub mod chromium_context;
pub(crate) mod node;

#[cfg(feature = "web_renderer")]
pub mod browser_client;
#[cfg(feature = "web_renderer")]
mod chromium_sender;
#[cfg(feature = "web_renderer")]
mod chromium_sender_thread;
#[cfg(feature = "web_renderer")]
mod embedder;
pub(crate) mod node;
#[cfg(feature = "web_renderer")]
mod shader;
#[cfg(feature = "web_renderer")]
mod shared_memory;

pub const EMBED_SOURCE_FRAMES_MESSAGE: &str = "EMBED_SOURCE_FRAMES";
Expand All @@ -42,7 +43,7 @@ pub struct WebRendererInitOptions {
impl Default for WebRendererInitOptions {
fn default() -> Self {
Self {
init: true,
init: cfg!(feature = "web_renderer"),
disable_gpu: false,
}
}
Expand All @@ -69,143 +70,3 @@ pub enum WebEmbeddingMethod {
/// The website's background has to be transparent
NativeEmbeddingUnderContent,
}

#[derive(Debug)]
pub struct WebRenderer {
spec: WebRendererSpec,
frame_data: FrameData,
source_transforms: SourceTransforms,
embedding_helper: EmbeddingHelper,

website_texture: BGRATexture,
render_website_shader: WebRendererShader,
}

impl WebRenderer {
pub fn new(ctx: &RegisterCtx, spec: WebRendererSpec) -> Result<Self, CreateWebRendererError> {
if ctx.chromium.cef_context().is_none() {
return Err(CreateWebRendererError::WebRendererDisabled);
}

info!("Starting web renderer for {}", &spec.url);

let frame_data = Arc::new(Mutex::new(Bytes::new()));
let source_transforms = Arc::new(Mutex::new(Vec::new()));

let client = BrowserClient::new(
frame_data.clone(),
source_transforms.clone(),
spec.resolution,
);
let chromium_sender = ChromiumSender::new(ctx, spec.url.clone(), client);
let embedding_helper = EmbeddingHelper::new(ctx, chromium_sender, spec.embedding_method);
let render_website_shader = WebRendererShader::new(&ctx.wgpu_ctx)?;
let website_texture = BGRATexture::new(&ctx.wgpu_ctx, spec.resolution);

Ok(Self {
spec,
frame_data,
source_transforms,
embedding_helper,
website_texture,
render_website_shader,
})
}

pub fn render(
&self,
ctx: &RenderCtx,
node_id: &NodeId,
sources: &[(&NodeId, &NodeTexture)],
buffers: &[Arc<wgpu::Buffer>],
target: &mut NodeTexture,
) -> Result<(), RenderWebsiteError> {
self.embedding_helper
.prepare_embedding(node_id, sources, buffers)
.map_err(|err| RenderWebsiteError::EmbeddingFailed(self.spec.url.clone(), err))?;

if let Some(frame) = self.retrieve_frame() {
let target = target.ensure_size(ctx.wgpu_ctx, self.spec.resolution);
self.website_texture.upload(ctx.wgpu_ctx, &frame);

let render_textures = self.prepare_textures(sources);

self.render_website_shader
.render(ctx.wgpu_ctx, &render_textures, target);
}

Ok(())
}

fn prepare_textures<'a>(
&'a self,
sources: &'a [(&NodeId, &NodeTexture)],
) -> Vec<(Option<&Texture>, RenderInfo)> {
let mut source_info = sources
.iter()
.zip(self.source_transforms.lock().unwrap().iter())
.map(|((_node_id, node_texture), transform)| {
(
node_texture.texture(),
RenderInfo::source_transform(transform),
)
})
.collect();

let website_info = (Some(self.website_texture.texture()), RenderInfo::website());

let mut result = Vec::new();
match self.spec.embedding_method {
WebEmbeddingMethod::NativeEmbeddingOverContent => {
result.push(website_info);
result.append(&mut source_info);
}
WebEmbeddingMethod::NativeEmbeddingUnderContent => {
result.append(&mut source_info);
result.push(website_info);
}
WebEmbeddingMethod::ChromiumEmbedding => {
result.push(website_info);
}
};

result
}

fn retrieve_frame(&self) -> Option<Bytes> {
let frame_data = self.frame_data.lock().unwrap();
if frame_data.is_empty() {
return None;
}
Some(frame_data.clone())
}

pub fn resolution(&self) -> Resolution {
self.spec.resolution
}

pub fn shared_memory_root_path(renderer_id: &str) -> PathBuf {
env::temp_dir()
.join("video_compositor")
.join(format!("instance_{}", renderer_id))
}

pub fn fallback_strategy(&self) -> FallbackStrategy {
self.spec.fallback_strategy
}
}

#[derive(Debug, thiserror::Error)]
pub enum CreateWebRendererError {
#[error(transparent)]
CreateShaderFailed(#[from] CreateShaderError),

#[error("Web rendering is disabled")]
WebRendererDisabled,
}

#[derive(Debug, thiserror::Error)]
pub enum RenderWebsiteError {
#[error("Failed to embed source on the website \"{0}\": {1}")]
EmbeddingFailed(String, #[source] EmbedError),
}
Loading

0 comments on commit baf90e5

Please sign in to comment.