Skip to content

Commit

Permalink
Add DirectX function support
Browse files Browse the repository at this point in the history
  • Loading branch information
twistedfall committed Apr 22, 2024
1 parent 59769aa commit 880ec0f
Show file tree
Hide file tree
Showing 19 changed files with 435 additions and 74 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ once_cell = "1"
# version 0.8.20 doesn't contain the deficiency mentioned in https://deps.rs/crate/opencv/0.59.0#vulnerabilities
rgb = { version = "0.8.20", features = ["argb"], optional = true }

[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.56", features = ["Win32_Graphics_Direct3D9", "Win32_Graphics_Direct3D10", "Win32_Graphics_Direct3D11"] }

[build-dependencies]
opencv-binding-generator = { version = "0.88.0", path = "binding-generator" }
cc = { version = "1.0.83", features = ["parallel"] }
Expand Down
55 changes: 37 additions & 18 deletions binding-generator/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ pub use desc::ClassDesc;
use crate::comment::strip_doxygen_comment_markers;
use crate::debug::{DefinitionLocation, LocationName};
use crate::element::ExcludeKind;
use crate::entity::{WalkAction, WalkResult};
use crate::entity::{ToEntity, WalkAction, WalkResult};
use crate::field::FieldDesc;
use crate::func::{FuncCppBody, FuncDesc, FuncKind, FuncRustBody, FuncRustExtern, ReturnKind};
use crate::type_ref::{Constness, CppNameStyle, StrEnc, StrType, TypeRef, TypeRefDesc, TypeRefTypeHint};
use crate::writer::rust_native::element::RustElement;
use crate::{
settings, ClassSimplicity, Const, DefaultElement, Element, EntityExt, Enum, Field, Func, FuncTypeHint, GeneratedType,
settings, ClassKindOverride, Const, DefaultElement, Element, EntityExt, Enum, Field, Func, FuncTypeHint, GeneratedType,
GeneratorEnv, NameDebug, StrExt,
};

Expand Down Expand Up @@ -80,16 +80,17 @@ impl<'tu, 'ge> Class<'tu, 'ge> {
{
return ClassKind::Other;
}
match gen_env.get_export_config(entity).map(|c| c.simplicity) {
Some(ClassSimplicity::Simple) => {
match gen_env.get_export_config(entity).map(|c| c.class_kind_override) {
Some(ClassKindOverride::Simple) => {
if self.can_be_simple() {
ClassKind::Simple
} else {
ClassKind::BoxedForced
}
}
Some(ClassSimplicity::Boxed) => ClassKind::Boxed,
Some(ClassSimplicity::BoxedForced) => ClassKind::BoxedForced,
Some(ClassKindOverride::Boxed) => ClassKind::Boxed,
Some(ClassKindOverride::BoxedForced) => ClassKind::BoxedForced,
Some(ClassKindOverride::System) => ClassKind::System,
None => {
if self.is_system() {
ClassKind::System
Expand Down Expand Up @@ -589,20 +590,37 @@ impl<'tu, 'ge> Class<'tu, 'ge> {
}
}

impl<'tu> ToEntity<'tu> for &Class<'tu, '_> {
fn to_entity(self) -> Option<Entity<'tu>> {
match self {
Class::Clang { entity, .. } => Some(*entity),
Class::Desc(_) => None,
}
}
}

impl Element for Class<'_, '_> {
fn exclude_kind(&self) -> ExcludeKind {
match self {
Self::Clang { .. } => {
DefaultElement::exclude_kind(self)
.with_is_excluded(|| self.has_private_destructor())
.with_is_ignored(|| match self.template_kind() {
TemplateKind::No => !self.is_definition(),
Self::Clang { .. } => DefaultElement::exclude_kind(self)
.with_is_ignored(|| match self.kind() {
ClassKind::Other => true,
ClassKind::System => {
!settings::IMPLEMENTED_SYSTEM_CLASSES.contains(self.cpp_name(CppNameStyle::Reference).as_ref())
}
ClassKind::Simple | ClassKind::Boxed | ClassKind::BoxedForced => match self.template_kind() {
TemplateKind::Template => true,
TemplateKind::Specialization(_) => !settings::IMPLEMENTED_GENERICS.contains(self.cpp_name(CppNameStyle::Reference).as_ref()),
} || self.is_system() && !settings::IMPLEMENTED_SYSTEM_CLASSES.contains(self.cpp_name(CppNameStyle::Reference).as_ref())
|| matches!(self.kind(), ClassKind::Other)
|| self.cpp_namespace() == "")
}
TemplateKind::No => !self.is_definition() || self.cpp_namespace() == "",
TemplateKind::Specialization(_) => {
!settings::IMPLEMENTED_GENERICS.contains(self.cpp_name(CppNameStyle::Reference).as_ref())
}
},
})
.with_is_excluded(|| match self.kind() {
ClassKind::System | ClassKind::Other => true,
ClassKind::Simple => false,
ClassKind::Boxed | ClassKind::BoxedForced => self.has_private_destructor(),
}),
Self::Desc(desc) => desc.exclude_kind,
}
}
Expand Down Expand Up @@ -782,8 +800,9 @@ impl ClassKind {

pub fn is_boxed(self) -> bool {
match self {
Self::Boxed | Self::BoxedForced => true,
Self::Simple | Self::System | Self::Other => false,
// fixme: Self::System to return true is kind of hack to make sure that system classes are passed by void*, probably better to handle in explicitly in CppPassByVoidPtrRenderLane
Self::Boxed | Self::BoxedForced | Self::System => true,
Self::Simple | Self::Other => false,
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions binding-generator/src/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ impl Element for Entity<'_> {
}
}

pub trait ToEntity<'tu> {
fn to_entity(self) -> Option<Entity<'tu>>;
}

impl<'tu> ToEntity<'tu> for &Entity<'tu> {
fn to_entity(self) -> Option<Entity<'tu>> {
Some(*self)
}
}

#[derive(Copy, Clone)]
pub enum WalkAction {
Continue,
Expand Down Expand Up @@ -156,7 +166,7 @@ impl<'tu> EntityExt<'tu> for Entity<'tu> {
}

#[allow(unused)]
pub fn dbg_clang_entity(entity: Entity) {
pub fn dbg_clang_entity<'tu>(entity: impl ToEntity<'tu>) {
struct EntityWrapper<'tu>(Entity<'tu>);

impl fmt::Debug for EntityWrapper<'_> {
Expand Down Expand Up @@ -244,5 +254,7 @@ pub fn dbg_clang_entity(entity: Entity) {
.finish()
}
}
eprintln!("{:#?}", EntityWrapper(entity));
if let Some(entity) = entity.to_entity() {
eprintln!("{:#?}", EntityWrapper(entity));
}
}
11 changes: 10 additions & 1 deletion binding-generator/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use slice_arg_finder::SliceArgFinder;
use crate::comment::strip_doxygen_comment_markers;
use crate::debug::{DefinitionLocation, LocationName};
use crate::element::ExcludeKind;
use crate::entity::WalkAction;
use crate::entity::{ToEntity, WalkAction};
use crate::field::FieldDesc;
use crate::settings::{TypeRefFactory, ARG_OVERRIDE_SELF};
use crate::type_ref::{Constness, CppNameStyle, TypeRefDesc, TypeRefTypeHint};
Expand Down Expand Up @@ -612,6 +612,15 @@ impl<'tu, 'ge> Func<'tu, 'ge> {
}
}

impl<'tu> ToEntity<'tu> for &Func<'tu, '_> {
fn to_entity(self) -> Option<Entity<'tu>> {
match self {
Func::Clang { entity, .. } => Some(*entity),
Func::Desc(_) => None,
}
}
}

impl Element for Func<'_, '_> {
fn exclude_kind(&self) -> ExcludeKind {
let func_id = self.func_id();
Expand Down
10 changes: 5 additions & 5 deletions binding-generator/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::type_ref::{CppNameStyle, FishStyle, TypeRef, TypeRefKind};
use crate::typedef::NewTypedefResult;
use crate::writer::rust_native::element::RustElement;
use crate::{
get_definition_text, line_reader, settings, AbstractRefWrapper, Class, ClassSimplicity, Const, Element, EntityExt,
get_definition_text, line_reader, settings, AbstractRefWrapper, Class, ClassKindOverride, Const, Element, EntityExt,
EntityWalkerExt, EntityWalkerVisitor, Enum, Func, GeneratorEnv, LineReaderAction, SmartPtr, Tuple, Typedef, Vector,
};

Expand Down Expand Up @@ -101,7 +101,7 @@ impl<'tu, V: GeneratorVisitor> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_
if BOXED.contains(&name.as_str()) {
self.gen_env.make_export_config(entity);
} else if SIMPLE.contains(&name.as_str()) {
self.gen_env.make_export_config(entity).simplicity = ClassSimplicity::Simple;
self.gen_env.make_export_config(entity).class_kind_override = ClassKindOverride::Simple;
} else if let Some(rename_macro) = RENAME.iter().find(|&r| r == &name) {
if let Some(new_name) = get_definition_text(entity)
.strip_prefix(rename_macro)
Expand Down Expand Up @@ -177,10 +177,10 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
});
class_decl.walk_classes_while(|sub_cls| {
if !gen_env.get_export_config(sub_cls).is_some() {
gen_env.make_export_config(sub_cls).simplicity = if Class::new(sub_cls, gen_env).can_be_simple() {
ClassSimplicity::Simple
gen_env.make_export_config(sub_cls).class_kind_override = if Class::new(sub_cls, gen_env).can_be_simple() {
ClassKindOverride::Simple
} else {
ClassSimplicity::Boxed
ClassKindOverride::Boxed
};
}
Self::process_class(visitor, gen_env, sub_cls);
Expand Down
24 changes: 15 additions & 9 deletions binding-generator/src/generator_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,25 @@ use crate::{
};

#[derive(Copy, Clone, Debug)]
pub enum ClassSimplicity {
pub enum ClassKindOverride {
Boxed,
Simple,
BoxedForced,
System,
}

impl ClassSimplicity {
impl ClassKindOverride {
pub fn is_boxed(self) -> bool {
match self {
ClassSimplicity::Boxed | ClassSimplicity::BoxedForced => true,
ClassSimplicity::Simple => false,
ClassKindOverride::Boxed | ClassKindOverride::BoxedForced => true,
ClassKindOverride::Simple | ClassKindOverride::System => false,
}
}
}

#[derive(Clone, Debug)]
pub struct ExportConfig {
pub simplicity: ClassSimplicity,
pub class_kind_override: ClassKindOverride,
pub deprecated: bool,
pub no_return: bool,
pub no_except: bool,
Expand All @@ -45,7 +46,7 @@ pub struct ExportConfig {
impl Default for ExportConfig {
fn default() -> Self {
Self {
simplicity: ClassSimplicity::Boxed,
class_kind_override: ClassKindOverride::Boxed,
deprecated: false,
no_return: false,
no_except: false,
Expand All @@ -66,17 +67,22 @@ impl ExportConfig {
}

pub fn override_boxed(mut src: ExportConfig) -> Option<ExportConfig> {
src.simplicity = ClassSimplicity::Boxed;
src.class_kind_override = ClassKindOverride::Boxed;
Some(src)
}

pub fn force_boxed(mut src: ExportConfig) -> Option<ExportConfig> {
src.simplicity = ClassSimplicity::BoxedForced;
src.class_kind_override = ClassKindOverride::BoxedForced;
Some(src)
}

pub fn simple(mut src: ExportConfig) -> Option<ExportConfig> {
src.simplicity = ClassSimplicity::Simple;
src.class_kind_override = ClassKindOverride::Simple;
Some(src)
}

pub fn system(mut src: ExportConfig) -> Option<ExportConfig> {
src.class_kind_override = ClassKindOverride::System;
Some(src)
}
}
Expand Down
2 changes: 1 addition & 1 deletion binding-generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use enumeration::Enum;
use field::Field;
pub use func::{Func, FuncId, FuncTypeHint};
pub use generator::{GeneratedType, Generator, GeneratorVisitor};
pub use generator_env::{ClassSimplicity, ExportConfig, GeneratorEnv};
pub use generator_env::{ClassKindOverride, ExportConfig, GeneratorEnv};
pub use iterator_ext::IteratorExt;
use memoize::{MemoizeMap, MemoizeMapExt};
use name_pool::NamePool;
Expand Down
33 changes: 5 additions & 28 deletions binding-generator/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ pub use func_replace::{FuncInheritFactory, FUNC_REPLACE};
pub use func_specialize::{TypeRefFactory, FUNC_SPECIALIZE};
pub use func_unsafe::FUNC_UNSAFE;
pub use generator_module_tweaks::{ModuleTweak, GENERATOR_MODULE_TWEAKS};
pub use implemented::{
IMPLEMENTED_CONST_GENERICS, IMPLEMENTED_FUNCTION_LIKE_MACROS, IMPLEMENTED_GENERICS, IMPLEMENTED_MANUAL_DEBUG,
IMPLEMENTED_SYSTEM_CLASSES,
};

mod argument_names;
mod argument_override;
Expand All @@ -31,15 +35,7 @@ mod func_replace;
mod func_specialize;
mod func_unsafe;
mod generator_module_tweaks;

pub static IMPLEMENTED_FUNCTION_LIKE_MACROS: Lazy<HashSet<&str>> = Lazy::new(|| HashSet::from(["CV_MAKETYPE"]));

pub static IMPLEMENTED_SYSTEM_CLASSES: Lazy<HashSet<&str>> =
Lazy::new(|| HashSet::from(["std::pair", "std::string", "std::tuple", "std::vector"]));

/// classes that have a manual `Debug` implementation, element is cpp_name(Reference)
pub static IMPLEMENTED_MANUAL_DEBUG: Lazy<HashSet<&str>> =
Lazy::new(|| HashSet::from(["cv::Mat", "cv::MatSize", "cv::dnn::DictValue"]));
mod implemented;

// fixme, generalize, make it use constant::ValueKind
pub static CONST_TYPE_USIZE: Lazy<HashSet<&str>> = Lazy::new(|| HashSet::from(["Mat_AUTO_STEP"]));
Expand Down Expand Up @@ -140,25 +136,6 @@ pub static DATA_TYPES: Lazy<HashSet<&str>> = Lazy::new(|| {
])
});

/// cpp_name(Reference)
pub static IMPLEMENTED_CONST_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| HashSet::from(["cv::Vec"]));

/// cpp_name(Reference)
pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| {
let mut out = HashSet::from([
"cv::Affine3",
"cv::Mat_",
"cv::Matx",
"cv::Point3_",
"cv::Point_",
"cv::Rect_",
"cv::Scalar_",
"cv::Size_",
]);
out.extend(&*IMPLEMENTED_CONST_GENERICS);
out
});

pub static NO_SKIP_NAMESPACE_IN_LOCALNAME: Lazy<HashMap<&str, HashMap<&str, &str>>> = Lazy::new(|| {
HashMap::from([
("*", HashMap::from([("detail", "Detail")])),
Expand Down
7 changes: 7 additions & 0 deletions binding-generator/src/settings/element_export_tweak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ pub static ELEMENT_EXPORT_TWEAK: Lazy<HashMap<&str, fn(ExportConfig) -> Option<E
HashMap::from([
("VADisplay", ExportConfig::export as _),
("VASurfaceID", ExportConfig::export as _),
("ID3D11Device", ExportConfig::system as _),
("ID3D11Texture2D", ExportConfig::system as _),
("ID3D10Device", ExportConfig::system as _),
("ID3D10Texture2D", ExportConfig::system as _),
("IDirect3DDevice9", ExportConfig::system as _),
("IDirect3DDevice9Ex", ExportConfig::system as _),
("IDirect3DSurface9", ExportConfig::system as _),
("cv::AffineWarper", ExportConfig::export as _), // 3.2 3.4 stitching warpers
("cv::CompressedRectilinearPortraitWarper", ExportConfig::export as _), // 3.2 3.4 stitching warpers
("cv::CompressedRectilinearWarper", ExportConfig::export as _), // 3.2 3.4 stitching warpers
Expand Down
44 changes: 44 additions & 0 deletions binding-generator/src/settings/implemented.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::collections::HashSet;

use once_cell::sync::Lazy;

pub static IMPLEMENTED_FUNCTION_LIKE_MACROS: Lazy<HashSet<&str>> = Lazy::new(|| HashSet::from(["CV_MAKETYPE"]));

pub static IMPLEMENTED_SYSTEM_CLASSES: Lazy<HashSet<&str>> = Lazy::new(|| {
HashSet::from([
"std::pair",
"std::string",
"std::tuple",
"std::vector",
"ID3D11Device",
"ID3D11Texture2D",
"ID3D10Device",
"ID3D10Texture2D",
"IDirect3DDevice9",
"IDirect3DDevice9Ex",
"IDirect3DSurface9",
])
});

/// classes that have a manual `Debug` implementation, element is cpp_name(Reference)
pub static IMPLEMENTED_MANUAL_DEBUG: Lazy<HashSet<&str>> =
Lazy::new(|| HashSet::from(["cv::Mat", "cv::MatSize", "cv::dnn::DictValue"]));

/// cpp_name(Reference)
pub static IMPLEMENTED_CONST_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| HashSet::from(["cv::Vec"]));

/// cpp_name(Reference)
pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| {
let mut out = HashSet::from([
"cv::Affine3",
"cv::Mat_",
"cv::Matx",
"cv::Point3_",
"cv::Point_",
"cv::Rect_",
"cv::Scalar_",
"cv::Size_",
]);
out.extend(&*IMPLEMENTED_CONST_GENERICS);
out
});
1 change: 1 addition & 0 deletions binding-generator/src/string_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ impl StrExt for str {
out.replacen_in_place("p3_p", 1, "p3p");
out.replacen_in_place("_u_mat", 1, "_umat");
out.replacen_in_place("i_d3_d", 1, "id_3d_");
out.replacen_in_place("d3_d", 1, "d3d");
out.replacen_in_place("2_d", 1, "_2d");
out.replacen_in_place("3_d", 1, "_3d");
out.replacen_in_place("open_gl", 1, "opengl");
Expand Down

0 comments on commit 880ec0f

Please sign in to comment.