3
3
#[ cfg( target_os = "macos" ) ]
4
4
use std:: os:: raw:: c_void;
5
5
6
- #[ cfg( all( feature = "accelerated_paint" , target_os = "macos" ) ) ]
7
- use ash:: vk;
8
6
#[ cfg( all( feature = "accelerated_paint" , target_os = "macos" ) ) ]
9
7
use core_foundation:: base:: { CFType , TCFType } ;
10
8
#[ cfg( all( feature = "accelerated_paint" , target_os = "macos" ) ) ]
11
9
use objc2_io_surface:: { IOSurface , IOSurfaceRef } ;
12
10
#[ cfg( all( feature = "accelerated_paint" , target_os = "macos" ) ) ]
11
+ use objc2_metal:: { MTLDevice , MTLPixelFormat , MTLTexture , MTLTextureDescriptor , MTLTextureType , MTLTextureUsage } ;
12
+ #[ cfg( all( feature = "accelerated_paint" , target_os = "macos" ) ) ]
13
13
use wgpu:: hal:: api;
14
14
15
- use super :: common:: { TextureImportError , TextureImportResult , TextureImporter , format, texture, vulkan } ;
15
+ use super :: common:: { TextureImportError , TextureImportResult , TextureImporter , format, texture} ;
16
16
use cef:: sys:: cef_color_type_t;
17
17
18
18
#[ cfg( target_os = "macos" ) ]
@@ -30,13 +30,13 @@ impl TextureImporter for IOSurfaceImporter {
30
30
#[ cfg( feature = "accelerated_paint" ) ]
31
31
{
32
32
if self . supports_hardware_acceleration ( device) {
33
- match self . import_via_vulkan ( device) {
33
+ match self . import_via_metal ( device) {
34
34
Ok ( texture) => {
35
- tracing:: trace!( "Successfully imported IOSurface texture via Vulkan " ) ;
35
+ tracing:: trace!( "Successfully imported IOSurface texture via Metal " ) ;
36
36
return Ok ( texture) ;
37
37
}
38
38
Err ( e) => {
39
- tracing:: warn!( "Failed to import IOSurface via Vulkan : {}, falling back to CPU texture" , e) ;
39
+ tracing:: warn!( "Failed to import IOSurface via Metal : {}, falling back to CPU texture" , e) ;
40
40
}
41
41
}
42
42
}
@@ -54,8 +54,8 @@ impl TextureImporter for IOSurfaceImporter {
54
54
return false ;
55
55
}
56
56
57
- // Check if wgpu is using Vulkan backend
58
- vulkan :: is_vulkan_backend ( device)
57
+ // Check if wgpu is using Metal backend
58
+ self . is_metal_backend ( device)
59
59
}
60
60
#[ cfg( not( feature = "accelerated_paint" ) ) ]
61
61
{
@@ -68,23 +68,23 @@ impl TextureImporter for IOSurfaceImporter {
68
68
#[ cfg( target_os = "macos" ) ]
69
69
impl IOSurfaceImporter {
70
70
#[ cfg( feature = "accelerated_paint" ) ]
71
- fn import_via_vulkan ( & self , device : & wgpu:: Device ) -> TextureImportResult {
72
- // Get wgpu's Vulkan instance and device
73
- use wgpu:: { TextureUses , wgc:: api:: Vulkan } ;
71
+ fn import_via_metal ( & self , device : & wgpu:: Device ) -> TextureImportResult {
72
+ // Get wgpu's Metal device
73
+ use wgpu:: { hal :: Api , wgc:: api:: Metal } ;
74
74
let hal_texture = unsafe {
75
- device. as_hal :: < api:: Vulkan , _ , _ > ( |device| {
75
+ device. as_hal :: < api:: Metal , _ , _ > ( |device| {
76
76
let Some ( device) = device else {
77
77
return Err ( TextureImportError :: HardwareUnavailable {
78
- reason : "Device is not using Vulkan backend" . to_string ( ) ,
78
+ reason : "Device is not using Metal backend" . to_string ( ) ,
79
79
} ) ;
80
80
} ;
81
81
82
- // Import IOSurface handle into Vulkan via Metal
83
- let vk_image = self . import_iosurface_to_vulkan ( device) ?;
82
+ // Import IOSurface handle into Metal texture
83
+ let metal_texture = self . import_iosurface_to_metal ( device) ?;
84
84
85
- // Wrap VkImage in wgpu-hal texture
86
- let hal_texture = <api:: Vulkan as wgpu:: hal:: Api >:: Device :: texture_from_raw (
87
- vk_image ,
85
+ // Wrap Metal texture in wgpu-hal texture
86
+ let hal_texture = <api:: Metal as wgpu:: hal:: Api >:: Device :: texture_from_raw (
87
+ metal_texture ,
88
88
& wgpu:: hal:: TextureDescriptor {
89
89
label : Some ( "CEF IOSurface Texture" ) ,
90
90
size : wgpu:: Extent3d {
@@ -96,7 +96,7 @@ impl IOSurfaceImporter {
96
96
sample_count : 1 ,
97
97
dimension : wgpu:: TextureDimension :: D2 ,
98
98
format : format:: cef_to_wgpu ( self . format ) ?,
99
- usage : TextureUses :: COPY_DST | TextureUses :: RESOURCE ,
99
+ usage : wgpu :: hal :: TextureUses :: RESOURCE ,
100
100
memory_flags : wgpu:: hal:: MemoryFlags :: empty ( ) ,
101
101
view_formats : vec ! [ ] ,
102
102
} ,
@@ -109,7 +109,7 @@ impl IOSurfaceImporter {
109
109
110
110
// Import hal texture into wgpu
111
111
let texture = unsafe {
112
- device. create_texture_from_hal :: < Vulkan > (
112
+ device. create_texture_from_hal :: < Metal > (
113
113
hal_texture,
114
114
& wgpu:: TextureDescriptor {
115
115
label : Some ( "CEF IOSurface Texture" ) ,
@@ -132,64 +132,66 @@ impl IOSurfaceImporter {
132
132
}
133
133
134
134
#[ cfg( feature = "accelerated_paint" ) ]
135
- fn import_iosurface_to_vulkan ( & self , hal_device : & <api:: Vulkan as wgpu:: hal:: Api >:: Device ) -> Result < vk:: Image , TextureImportError > {
136
- // Get raw Vulkan handles
137
- let device = hal_device. raw_device ( ) ;
138
- let _instance = hal_device. shared_instance ( ) . raw_instance ( ) ;
139
-
135
+ fn import_iosurface_to_metal ( & self , hal_device : & <api:: Metal as wgpu:: hal:: Api >:: Device ) -> Result < <api:: Metal as wgpu:: hal:: Api >:: Texture , TextureImportError > {
140
136
// Validate dimensions
141
137
if self . width == 0 || self . height == 0 {
142
138
return Err ( TextureImportError :: InvalidHandle ( "Invalid IOSurface texture dimensions" . to_string ( ) ) ) ;
143
139
}
144
140
145
141
// Convert handle to IOSurface
146
- let _iosurface = unsafe {
142
+ let iosurface = unsafe {
147
143
let cf_type = CFType :: wrap_under_get_rule ( self . handle as IOSurfaceRef ) ;
148
144
IOSurface :: from ( cf_type)
149
145
} ;
150
146
151
- // Note: Full Metal-to-Vulkan import would require:
152
- // 1. Creating Metal texture from IOSurface
153
- // 2. Using VK_EXT_metal_objects to import Metal texture into Vulkan
154
- // 3. Proper synchronization between Metal and Vulkan
155
- //
156
- // This is complex and not fully supported by current objc2 bindings.
157
- // For now, we create a minimal Vulkan image and rely on fallback.
158
-
159
- // Create external memory image info for Metal objects
160
- let mut external_memory_info = vk:: ExternalMemoryImageCreateInfo :: default ( ) . handle_types ( vk:: ExternalMemoryHandleTypeFlags :: MTLTEXTURE_EXT ) ;
161
-
162
- // Create image create info
163
- let image_create_info = vk:: ImageCreateInfo :: default ( )
164
- . image_type ( vk:: ImageType :: TYPE_2D )
165
- . format ( format:: cef_to_vulkan ( self . format ) ?)
166
- . extent ( vk:: Extent3D {
167
- width : self . width ,
168
- height : self . height ,
169
- depth : 1 ,
170
- } )
171
- . mip_levels ( 1 )
172
- . array_layers ( 1 )
173
- . samples ( vk:: SampleCountFlags :: TYPE_1 )
174
- . tiling ( vk:: ImageTiling :: OPTIMAL )
175
- . usage ( vk:: ImageUsageFlags :: SAMPLED | vk:: ImageUsageFlags :: COLOR_ATTACHMENT )
176
- . sharing_mode ( vk:: SharingMode :: EXCLUSIVE )
177
- . push_next ( & mut external_memory_info) ;
178
-
179
- // Create the image
180
- let image = unsafe {
181
- device. create_image ( & image_create_info, None ) . map_err ( |e| TextureImportError :: VulkanError {
182
- operation : format ! ( "Failed to create Vulkan image: {:?}" , e) ,
183
- } ) ?
147
+ // Get the Metal device from wgpu-hal
148
+ let metal_device = hal_device. raw_device ( ) ;
149
+
150
+ // Convert CEF format to Metal pixel format
151
+ let metal_format = self . cef_to_metal_format ( self . format ) ?;
152
+
153
+ // Create Metal texture descriptor
154
+ let texture_descriptor = MTLTextureDescriptor :: new ( ) ;
155
+ texture_descriptor. setTextureType ( MTLTextureType :: Type2D ) ;
156
+ texture_descriptor. setPixelFormat ( metal_format) ;
157
+ texture_descriptor. setWidth ( self . width as usize ) ;
158
+ texture_descriptor. setHeight ( self . height as usize ) ;
159
+ texture_descriptor. setDepth ( 1 ) ;
160
+ texture_descriptor. setMipmapLevelCount ( 1 ) ;
161
+ texture_descriptor. setSampleCount ( 1 ) ;
162
+ texture_descriptor. setUsage ( MTLTextureUsage :: ShaderRead ) ;
163
+
164
+ // Create Metal texture from IOSurface
165
+ let metal_texture = unsafe { metal_device. newTextureWithDescriptor_iosurface_plane ( & texture_descriptor, & iosurface, 0 ) } ;
166
+
167
+ let Some ( metal_texture) = metal_texture else {
168
+ return Err ( TextureImportError :: PlatformError {
169
+ message : "Failed to create Metal texture from IOSurface" . to_string ( ) ,
170
+ } ) ;
184
171
} ;
185
172
186
- // Note: The actual Metal-to-Vulkan import would require VK_EXT_metal_objects
187
- // and proper Metal texture handle extraction, which is complex and not
188
- // fully supported in the current objc2 bindings. For now, we return the
189
- // image and rely on fallback behavior.
173
+ tracing:: trace!( "Successfully created Metal texture from IOSurface" ) ;
174
+ Ok ( metal_texture)
175
+ }
190
176
191
- tracing:: warn!( "Metal-to-Vulkan texture import not fully implemented" ) ;
177
+ #[ cfg( feature = "accelerated_paint" ) ]
178
+ fn cef_to_metal_format ( & self , format : cef_color_type_t ) -> Result < MTLPixelFormat , TextureImportError > {
179
+ match format {
180
+ cef_color_type_t:: CEF_COLOR_TYPE_BGRA_8888 => Ok ( MTLPixelFormat :: BGRA8Unorm_sRGB ) ,
181
+ cef_color_type_t:: CEF_COLOR_TYPE_RGBA_8888 => Ok ( MTLPixelFormat :: RGBA8Unorm_sRGB ) ,
182
+ _ => Err ( TextureImportError :: UnsupportedFormat { format } ) ,
183
+ }
184
+ }
192
185
193
- Ok ( image)
186
+ #[ cfg( feature = "accelerated_paint" ) ]
187
+ fn is_metal_backend ( & self , device : & wgpu:: Device ) -> bool {
188
+ use wgpu:: hal:: api;
189
+ let mut is_metal = false ;
190
+ unsafe {
191
+ device. as_hal :: < api:: Metal , _ , _ > ( |device| {
192
+ is_metal = device. is_some ( ) ;
193
+ } ) ;
194
+ }
195
+ is_metal
194
196
}
195
197
}
0 commit comments