Skip to content

Commit

Permalink
Add initial support for OpenHarmony (#293)
Browse files Browse the repository at this point in the history
* Rename platform/android to platform/egl

* Add initial support for OpenHarmony

* Add `-ohos` build to CI

* Fix surfman/mod.rs comment

* Add Safety documentation to OH_NativeWindow_NativeWindowHandleOpt

* Make couple minor rustdoc adjustments

---------

Co-authored-by: Martin Robinson <[email protected]>
  • Loading branch information
jschwe and mrobinson authored May 29, 2024
1 parent b3b42f4 commit 1a522fa
Show file tree
Hide file tree
Showing 17 changed files with 536 additions and 114 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ jobs:
- os: windows-latest
target: "aarch64-pc-windows-msvc"
rust: stable
- os: ubuntu-22.04
target: "aarch64-unknown-linux-ohos"
rust: stable
steps:
- uses: actions/checkout@v4
- name: Install deps on linux
Expand Down
6 changes: 3 additions & 3 deletions surfman/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ log = "0.4"
sparkle = { version = "0.1", optional = true }
osmesa-sys = { version = "0.1", optional = true }
rwh_05 = { package = "raw-window-handle", version = "0.5.2", features = ["std"], optional = true }
rwh_06 = { package = "raw-window-handle", version = "0.6", features = ["std"], optional = true }
rwh_06 = { package = "raw-window-handle", version = "0.6.2", features = ["std"], optional = true }

[dev-dependencies]
clap = "2"
Expand All @@ -61,11 +61,11 @@ mach2 = "0.4"
metal = "0.24"
objc = "0.2"

[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies.wayland-sys]
[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android", target_env = "ohos"))))'.dependencies.wayland-sys]
version = "0.30"
features = ["client", "dlopen", "egl"]

[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies.x11]
[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android", target_env = "ohos"))))'.dependencies.x11]
version = "2.3.0"
features = ["xlib"]
optional = true
Expand Down
7 changes: 5 additions & 2 deletions surfman/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ fn main() {
cfg_aliases! {
// Platforms
android_platform: { target_os = "android" },
ohos_platform: { target_env = "ohos" },
web_platform: { all(target_family = "wasm", target_os = "unknown") },
macos_platform: { target_os = "macos" },
ios_platform: { target_os = "ios" },
windows_platform: { target_os = "windows" },
apple: { any(target_os = "ios", target_os = "macos") },
free_unix: { all(unix, not(apple), not(android_platform), not(target_os = "emscripten")) },
free_unix: { all(unix, not(apple), not(android_platform), not(target_os = "emscripten"), not(ohos_platform)) },

// Native displays.
x11_platform: { all(free_unix, feature = "sm-x11") },
Expand All @@ -36,11 +37,13 @@ fn main() {

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_family = env::var("CARGO_CFG_TARGET_FAMILY").ok();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());

// Generate EGL bindings.
if target_os == "android"
|| (target_os == "windows" && cfg!(feature = "sm-angle"))
|| target_env == "ohos"
|| target_family.as_ref().map_or(false, |f| f == "unix")
{
let mut file = File::create(dest.join("egl_bindings.rs")).unwrap();
Expand All @@ -49,7 +52,7 @@ fn main() {
}

// Generate GL bindings.
if target_os == "android" {
if target_os == "android" || target_env == "ohos" {
let mut file = File::create(dest.join("gl_bindings.rs")).unwrap();
let registry = Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, []);
registry.write_bindings(StructGenerator, &mut file).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions surfman/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ impl ContextAttributes {
}
}

#[cfg(target_os = "android")]
#[cfg(any(target_os = "android", target_env = "ohos"))]
pub(crate) fn current_context_uses_compatibility_profile(_gl: &Gl) -> bool {
false
}

#[cfg(not(target_os = "android"))]
#[cfg(not(any(target_os = "android", target_env = "ohos")))]
#[allow(dead_code)]
pub(crate) fn current_context_uses_compatibility_profile(gl: &Gl) -> bool {
unsafe {
Expand Down
5 changes: 3 additions & 2 deletions surfman/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ pub use crate::surface::{SurfaceAccess, SurfaceID, SurfaceInfo, SurfaceType, Sys

pub mod macros;

#[cfg(not(target_os = "android"))]
#[cfg(not(any(target_os = "android", target_env = "ohos")))]
pub(crate) use crate::gl::Gl;
#[cfg(target_os = "android")]
#[cfg(any(target_os = "android", target_env = "ohos"))]
pub(crate) use crate::gl::Gles2 as Gl;

mod gl_utils;
Expand All @@ -70,6 +70,7 @@ mod gl {

#[cfg(any(
target_os = "android",
target_env = "ohos",
all(target_os = "windows", feature = "sm-angle"),
unix
))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// surfman/surfman/src/platform/android/ffi.rs
// surfman/surfman/src/platform/egl/android_ffi.rs

use std::os::raw::c_int;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// surfman/surfman/src/platform/android/connection.rs
// surfman/surfman/src/platform/egl/connection.rs
//
//! A no-op connection for Android.
//!
//! FIXME(pcwalton): Should this instead wrap `EGLDisplay`? Is that thread-safe on Android?

use super::device::{Adapter, Device, NativeDevice};
use super::ffi::ANativeWindow;
use super::surface::NativeWidget;
use crate::Error;
use crate::GLApi;

#[cfg(android_platform)]
use super::android_ffi::ANativeWindow;
#[cfg(ohos_platform)]
use super::ohos_ffi::OHNativeWindow;

use euclid::default::Size2D;

use std::os::raw::c_void;
Expand Down Expand Up @@ -109,24 +113,34 @@ impl Connection {
Ok(Connection)
}

#[cfg(android_platform)]
fn create_native_widget_from_ptr_impl(raw: *mut c_void) -> NativeWidget {
NativeWidget {
native_window: raw as *mut ANativeWindow,
}
}

#[cfg(ohos_platform)]
fn create_native_widget_from_ptr_impl(raw: *mut c_void) -> NativeWidget {
NativeWidget {
native_window: raw as *mut OHNativeWindow,
}
}

/// Create a native widget from a raw pointer
pub unsafe fn create_native_widget_from_ptr(
&self,
raw: *mut c_void,
_size: Size2D<i32>,
) -> NativeWidget {
NativeWidget {
native_window: raw as *mut ANativeWindow,
}
debug_assert!(!raw.is_null());
Self::create_native_widget_from_ptr_impl(raw)
}

/// Create a native widget type from the given `RawWindowHandle`.
#[cfg(feature = "sm-raw-window-handle-05")]
#[cfg(all(feature = "sm-raw-window-handle-05", android_platform))]
#[inline]
pub fn create_native_widget_from_raw_window_handle(
&self,
fn create_native_widget_from_rwh_05_handle(
raw_handle: rwh_05::RawWindowHandle,
_size: Size2D<i32>,
) -> Result<NativeWidget, Error> {
use rwh_05::RawWindowHandle::AndroidNdk;

Expand All @@ -138,13 +152,29 @@ impl Connection {
}
}

/// Create a native widget type from the given `WindowHandle`.
#[cfg(feature = "sm-raw-window-handle-06")]
#[cfg(all(feature = "sm-raw-window-handle-05", ohos_platform))]
#[inline]
pub fn create_native_widget_from_window_handle(
fn create_native_widget_from_rwh_05_handle(
_raw_handle: rwh_05::RawWindowHandle,
) -> Result<NativeWidget, Error> {
Err(Error::IncompatibleNativeWidget)
}

/// Create a native widget type from the given `RawWindowHandle`.
#[cfg(feature = "sm-raw-window-handle-05")]
#[inline]
pub fn create_native_widget_from_raw_window_handle(
&self,
handle: rwh_06::WindowHandle,
raw_handle: rwh_05::RawWindowHandle,
_size: Size2D<i32>,
) -> Result<NativeWidget, Error> {
create_native_widget_from_rwh_05_handle(raw_handle)
}

#[cfg(all(feature = "sm-raw-window-handle-06", android_platform))]
#[inline]
fn create_native_widget_from_rwh_06_handle(
handle: rwh_06::WindowHandle,
) -> Result<NativeWidget, Error> {
use rwh_06::RawWindowHandle::AndroidNdk;

Expand All @@ -155,6 +185,32 @@ impl Connection {
_ => Err(Error::IncompatibleNativeWidget),
}
}

#[cfg(all(feature = "sm-raw-window-handle-06", ohos_platform))]
#[inline]
fn create_native_widget_from_rwh_06_handle(
handle: rwh_06::WindowHandle,
) -> Result<NativeWidget, Error> {
use rwh_06::RawWindowHandle::OhosNdk;

match handle.as_raw() {
OhosNdk(handle) => Ok(NativeWidget {
native_window: handle.native_window.as_ptr().cast(),
}),
_ => Err(Error::IncompatibleNativeWidget),
}
}

/// Create a native widget type from the given `WindowHandle`.
#[cfg(feature = "sm-raw-window-handle-06")]
#[inline]
pub fn create_native_widget_from_window_handle(
&self,
handle: rwh_06::WindowHandle,
_size: Size2D<i32>,
) -> Result<NativeWidget, Error> {
Self::create_native_widget_from_rwh_06_handle(handle)
}
}

impl NativeConnection {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// surfman/surfman/src/platform/android/context.rs
// surfman/surfman/src/platform/egl/context.rs
//
//! OpenGL rendering contexts.

Expand Down Expand Up @@ -212,11 +212,12 @@ impl Device {
..
}) => (egl_surface, egl_surface),
Framebuffer::External(ExternalEGLSurfaces { draw, read }) => (draw, read),
#[cfg(android_platform)]
Framebuffer::Surface(Surface {
objects: SurfaceObjects::HardwareBuffer { .. },
..
})
| Framebuffer::None => (context.pbuffer, context.pbuffer),
}) => (context.pbuffer, context.pbuffer),
Framebuffer::None => (context.pbuffer, context.pbuffer),
};

EGL_FUNCTIONS.with(|egl| {
Expand Down Expand Up @@ -366,11 +367,12 @@ impl Device {
..
}) => (egl_surface, egl_surface),
Framebuffer::External(ExternalEGLSurfaces { draw, read }) => (draw, read),
#[cfg(android_platform)]
Framebuffer::Surface(Surface {
objects: SurfaceObjects::HardwareBuffer { .. },
..
})
| Framebuffer::None => (context.pbuffer, context.pbuffer),
}) => (context.pbuffer, context.pbuffer),
Framebuffer::None => (context.pbuffer, context.pbuffer),
};

NativeContext {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// surfman/surfman/src/platform/android/device.rs
// surfman/surfman/src/platform/egl/device.rs
//
//! A thread-local handle to the device.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// surfman/surfman/src/platform/android/mod.rs
// surfman/surfman/src/platform/egl/mod.rs
//
//! Bindings to EGL on Android.

Expand All @@ -7,7 +7,11 @@ pub mod context;
pub mod device;
pub mod surface;

mod ffi;
#[cfg(android_platform)]
mod android_ffi;

#[cfg(ohos_platform)]
mod ohos_ffi;

#[path = "../../implementation/mod.rs"]
mod implementation;
Expand Down
47 changes: 47 additions & 0 deletions surfman/src/platform/egl/ohos_ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![allow(unused)]

#[repr(C)]
pub struct NativeWindow {
_unused: [u8; 0],
}

pub type OHNativeWindow = NativeWindow;

#[repr(transparent)]
pub(crate) struct NativeWindowOperation(core::ffi::c_int);

impl NativeWindowOperation {
pub const GET_BUFFER_GEOMETRY: Self = Self(1);
}

/// According to the [native window guidelines], users need to link against
/// both the NDK and `native_window`.
/// [native window guidelines]: <https://gitee.com/openharmony/docs/blob/master/en/application-dev/graphics/native-window-guidelines.md>
#[link(name = "native_window")]
#[link(name = "ace_ndk.z")]
extern "C" {
/// Sets or obtains the attributes of a native window
///
/// Can be used to query information like height and width.
/// See the official [Documentation] for detailed usage information.
///
/// # Safety
///
/// - The `window` handle must be valid.
/// - The variable arguments which must be passed to this function vary depending on the
/// value of `code`.
/// - For `NativeWindowOperation::GET_BUFFER_GEOMETRY` the function takes two output
/// i32 pointers, `height: *mut i32` and `width: *mut i32` which are passed as variadic
/// arguments.
///
///
/// [Documentation]: <https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis-arkgraphics2d/_native_window.md>
pub(crate) fn OH_NativeWindow_NativeWindowHandleOpt(
window: *mut OHNativeWindow,
code: NativeWindowOperation,
...
) -> i32;
}
Loading

0 comments on commit 1a522fa

Please sign in to comment.