Skip to content

Commit

Permalink
Add web_rwh feature
Browse files Browse the repository at this point in the history
  • Loading branch information
jinleili committed Nov 16, 2024
1 parent 450e87a commit daab811
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 118 deletions.
Binary file not shown.
2 changes: 1 addition & 1 deletion Cargo.lock

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

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ noise = { version = "0.8", default-features = false }
pollster = "0.3"
rand = "0.7.2"
wgpu = "23"
# wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "445fa6019b47079c9d336881dbee1c3be3ed4c38" }
# wgpu = { git = "https://github.com/jinleili/wgpu", branch="visionOS" }
winit = { version = "=0.30.5" }
web-time = "1"
Expand Down
4 changes: 3 additions & 1 deletion app-surface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "app-surface"
authors = ["jinleili"]
description = "Integrate wgpu into your existing iOS, Android and Web apps without relying on winit."
edition = "2021"
version = "1.3.0"
version = "1.3.1"
rust-version = "1.76"
repository = "https://github.com/jinleili/wgpu-in-app"
keywords = ["android", "SurfaceView", "CAMetalLayer", "Canvas", "wgpu"]
Expand All @@ -16,6 +16,8 @@ crate-type = ["rlib"]
default = []
webgl = ["wgpu/webgl"]
mac_catalyst = []
# Use Canvas / OffscreenCanvas + raw-window-handle directly on the web, no need for winit
web_rwh = []

[dependencies]
cfg-if.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use winit::window::Window;

pub struct AppSurface {
pub view: Option<Arc<Window>>,
pub is_offscreen_canvas: bool,
pub scale_factor: f32,
pub maximum_frames: i32,
pub ctx: crate::IASDQContext,
Expand All @@ -17,8 +16,6 @@ struct ViewSetting {
view: Option<Arc<Window>>,
scale_factor: f32,
physical_size: (u32, u32),
#[cfg(target_arch = "wasm32")]
offscreen_canvas: Option<web_sys::OffscreenCanvas>,
}

impl AppSurface {
Expand All @@ -42,32 +39,10 @@ impl AppSurface {
return self.view.as_ref().unwrap();
}

#[cfg(target_arch = "wasm32")]
pub async fn from_offscreen_canvas(
offscreen_canvas: web_sys::OffscreenCanvas,
scale_factor: f32,
physical_size: (u32, u32),
) -> Self {
let view_setting = ViewSetting {
scale_factor,
physical_size,
offscreen_canvas: Some(offscreen_canvas),
..Default::default()
};
Self::create(view_setting).await
}

#[allow(unused_variables)]
async fn create(view_setting: ViewSetting) -> Self {
let view = view_setting.view.unwrap();
#[cfg(not(target_arch = "wasm32"))]
let is_offscreen_canvas = false;
#[cfg(target_arch = "wasm32")]
let is_offscreen_canvas = if view_setting.offscreen_canvas.is_some() {
true
} else {
false
};

let scale_factor = view_setting.scale_factor;
let default_backends = if cfg!(feature = "webgl") {
wgpu::Backends::GL
Expand All @@ -83,18 +58,7 @@ impl AppSurface {

cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
let surface = if is_offscreen_canvas {
// let offscreen = canvas.transfer_control_to_offscreen().unwrap();
instance.create_surface(
wgpu::SurfaceTarget::OffscreenCanvas(view_setting.offscreen_canvas.unwrap())
)
} else {
// use winit::platform::web::WindowExtWebSys;
// let canvas: web_sys::HtmlCanvasElement =
// view.as_ref().canvas().unwrap();
// instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas))
instance.create_surface(view.clone())
};
let surface = instance.create_surface(view.clone());
} else {
let surface = instance.create_surface(view.clone());
}
Expand All @@ -110,7 +74,6 @@ impl AppSurface {

AppSurface {
view: Some(view),
is_offscreen_canvas,
scale_factor,
maximum_frames: 60,
ctx,
Expand All @@ -121,12 +84,8 @@ impl AppSurface {
}

pub fn get_view_size(&self) -> (u32, u32) {
if self.is_offscreen_canvas {
panic!("Offscreen canvas cannot provide any DOM interfaces.");
} else {
let physical = self.get_view().inner_size();
(physical.width.max(1), physical.height.max(1))
}
let physical = self.get_view().inner_size();
(physical.width.max(1), physical.height.max(1))
}

pub fn request_redraw(&self) {
Expand Down
57 changes: 42 additions & 15 deletions app-surface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
use std::{ops::Deref, sync::Arc};
use std::ops::Deref;
use wgpu::{Instance, Surface};

mod touch;
pub use touch::*;

#[cfg_attr(target_os = "ios", path = "ios.rs")]
#[cfg_attr(
any(target_os = "ios", all(feature = "mac_catalyst", target_os = "macos")),
path = "ios.rs"
)]
#[cfg_attr(target_os = "android", path = "android.rs")]
#[cfg_attr(all(feature = "mac_catalyst", target_os = "macos"), path = "ios.rs")]
#[cfg_attr(
all(target_arch = "wasm32", feature = "web_rwh"),
path = "web_rwh/mod.rs"
)]
#[cfg_attr(
any(
all(not(feature = "mac_catalyst"), target_os = "macos"),
target_os = "windows",
target_os = "linux",
),
path = "app_surface_use_winit.rs"
)]
#[cfg_attr(
all(target_arch = "wasm32", not(feature = "web_rwh")),
path = "app_surface_use_winit.rs"
)]
mod app_surface;
pub use app_surface::*;

#[cfg(target_arch = "wasm32")]
pub mod web;
// #[cfg(all(target_arch = "wasm32", feature = "web_rwh"))]
// compile_error!("web_rwh feature is enabled for wasm32");

// #[cfg(all(target_arch = "wasm32", not(feature = "web_rwh")))]
// compile_error!("web_rwh feature is not enabled -");

#[repr(C)]
#[derive(Debug)]
Expand All @@ -20,13 +41,19 @@ pub struct ViewSize {
pub height: u32,
}

#[cfg(target_arch = "wasm32")]
use std::rc::Rc as SharedPtr;
#[cfg(not(target_arch = "wasm32"))]
use std::sync::Arc as SharedPtr;
/// 在 wasm32 环境中,Instance、Surface、Adapter、Device 和 Queue 这些类型都不是 Send 和 Sync 的
#[derive(Clone)]
pub struct IASDQContext {
pub instance: Arc<wgpu::Instance>,
pub surface: Arc<wgpu::Surface<'static>>,
pub instance: SharedPtr<wgpu::Instance>,
pub surface: SharedPtr<wgpu::Surface<'static>>,
pub config: wgpu::SurfaceConfiguration,
pub adapter: Arc<wgpu::Adapter>,
pub device: Arc<wgpu::Device>,
pub queue: Arc<wgpu::Queue>,
pub adapter: SharedPtr<wgpu::Adapter>,
pub device: SharedPtr<wgpu::Device>,
pub queue: SharedPtr<wgpu::Queue>,
}

impl IASDQContext {
Expand Down Expand Up @@ -182,12 +209,12 @@ async fn create_iasdq_context(
surface.configure(&device, &config);

IASDQContext {
instance: Arc::new(instance),
surface: Arc::new(surface),
instance: SharedPtr::new(instance),
surface: SharedPtr::new(surface),
config,
adapter: Arc::new(adapter),
device: Arc::new(device),
queue: Arc::new(queue),
adapter: SharedPtr::new(adapter),
device: SharedPtr::new(device),
queue: SharedPtr::new(queue),
}
}

Expand Down
File renamed without changes.
77 changes: 22 additions & 55 deletions app-surface/src/web/mod.rs → app-surface/src/web_rwh/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::IASDQContext;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::ops::Deref;

mod canvas;
pub use canvas::*;
Expand All @@ -14,6 +13,7 @@ pub struct AppSurface {
pub ctx: IASDQContext,
}

#[allow(dead_code)]
impl AppSurface {
pub async fn new(view: ViewObj) -> Self {
let (scale_factor, logical_size) = match view {
Expand Down Expand Up @@ -56,6 +56,27 @@ impl AppSurface {
}
}

/// 用 Canvas id 创建 AppSurface
///
/// element_id: 存在于当前页面中的 canvas 元素的 id
/// handle: 用于 WebGPU 的 raw handle number, 0 是保留的值, 不能使用
pub async fn from_canvas(element_id: &str, handle: u32) -> Self {
let wrapper = CanvasWrapper::new(Canvas::new(element_id, handle));
Self::new(ViewObj::Canvas(wrapper)).await
}

/// 用 OffscreenCanvas 创建 AppSurface
///
/// handle: 用于 WebGPU 的 raw handle number, 0 是保留的值, 不能使用
pub async fn from_offscreen_canvas(
offscreen_canvas: web_sys::OffscreenCanvas,
scale_factor: f32,
handle: u32,
) -> Self {
let wrapper = OffscreenCanvasWrapper::new(OffscreenCanvas::new(offscreen_canvas, scale_factor, handle));
Self::new(ViewObj::Offscreen(wrapper)).await
}

pub fn get_view_size(&self) -> (u32, u32) {
let (scale_factor, logical_size) = match self.view {
ViewObj::Canvas(ref canvas) => (canvas.scale_factor, canvas.logical_resolution()),
Expand All @@ -70,15 +91,6 @@ impl AppSurface {
}
}

/// 用 Canvas id 创建 AppSurface
///
/// element_id: 存在于当前页面中的 canvas 元素的 id
/// handle: 用于 WebGPU 的 raw handle number, 0 是保留的值, 不能使用
pub async fn app_surface_from_canvas(element_id: &str, handle: u32) -> AppSurface {
let wrapper = CanvasWrapper::new(Canvas::new(element_id, handle));
AppSurface::new(ViewObj::Canvas(wrapper)).await
}

// 封装 ViewObj 来同时支持 Canvas 与 Offscreen
#[derive(Debug)]
pub enum ViewObj {
Expand All @@ -101,48 +113,3 @@ pub(crate) struct SendSyncWrapper<T>(pub(crate) T);

unsafe impl<T> Send for SendSyncWrapper<T> {}
unsafe impl<T> Sync for SendSyncWrapper<T> {}

impl Deref for AppSurface {
type Target = IASDQContext;
fn deref(&self) -> &Self::Target {
&self.ctx
}
}

impl crate::SurfaceFrame for AppSurface {
fn view_size(&self) -> crate::ViewSize {
let size = self.get_view_size();
crate::ViewSize {
width: size.0,
height: size.1,
}
}

fn resize_surface(&mut self) {
let size = self.get_view_size();
self.ctx.config.width = size.0;
self.ctx.config.height = size.1;
self.surface.configure(&self.device, &self.config);
}

fn resize_surface_by_size(&mut self, size: (u32, u32)) {
self.ctx.config.width = size.0;
self.ctx.config.height = size.1;
self.surface.configure(&self.device, &self.config);
}

fn normalize_touch_point(&self, touch_point_x: f32, touch_point_y: f32) -> (f32, f32) {
let size = self.get_view_size();
(
touch_point_x * self.scale_factor / size.0 as f32,
touch_point_y * self.scale_factor / size.1 as f32,
)
}

fn get_current_frame_view(
&self,
view_format: Option<wgpu::TextureFormat>,
) -> (wgpu::SurfaceTexture, wgpu::TextureView) {
self.create_current_frame_view(&self.device, &self.surface, &self.config, view_format)
}
}
File renamed without changes.
1 change: 1 addition & 0 deletions wgpu-in-app/src/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(16);

#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
enum Mode {
#[allow(dead_code)]
Wait,
WaitUntil,
#[default]
Expand Down

0 comments on commit daab811

Please sign in to comment.