1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <dlfcn.h> 6 7 #include "base/memory/singleton.h" 8 #include "ui/gl/io_surface_support_mac.h" 9 10 typedef CFTypeRef (*IOSurfaceCreateProcPtr)(CFDictionaryRef properties); 11 typedef uint32 (*IOSurfaceGetIDProcPtr)(CFTypeRef io_surface); 12 typedef CFTypeRef (*IOSurfaceLookupProcPtr)(uint32 io_surface_id); 13 typedef mach_port_t (*IOSurfaceCreateMachPortProcPtr)(CFTypeRef io_surface); 14 typedef CFTypeRef (*IOSurfaceLookupFromMachPortProcPtr)(mach_port_t port); 15 typedef size_t (*IOSurfaceGetWidthPtr)(CFTypeRef io_surface); 16 typedef size_t (*IOSurfaceGetHeightPtr)(CFTypeRef io_surface); 17 typedef size_t (*IOSurfaceGetBytesPerRowPtr)(CFTypeRef io_surface); 18 typedef void* (*IOSurfaceGetBaseAddressPtr)(CFTypeRef io_surface); 19 typedef IOReturn (*IOSurfaceLockPtr)(CFTypeRef io_surface, 20 uint32 options, 21 uint32* seed); 22 typedef IOReturn (*IOSurfaceUnlockPtr)(CFTypeRef io_surface, 23 uint32 options, 24 uint32* seed); 25 26 typedef CGLError (*CGLTexImageIOSurface2DProcPtr)(CGLContextObj ctx, 27 GLenum target, 28 GLenum internal_format, 29 GLsizei width, 30 GLsizei height, 31 GLenum format, 32 GLenum type, 33 CFTypeRef io_surface, 34 GLuint plane); 35 typedef CFTypeRef (*CVPixelBufferGetIOSurfaceProcPtr)( 36 CVPixelBufferRef pixel_buffer); 37 38 class IOSurfaceSupportImpl : public IOSurfaceSupport { 39 public: 40 static IOSurfaceSupportImpl* GetInstance(); 41 42 bool InitializedSuccessfully() { 43 return initialized_successfully_; 44 } 45 46 virtual CFStringRef GetKIOSurfaceWidth() OVERRIDE; 47 virtual CFStringRef GetKIOSurfaceHeight() OVERRIDE; 48 virtual CFStringRef GetKIOSurfaceBytesPerElement() OVERRIDE; 49 virtual CFStringRef GetKIOSurfacePixelFormat() OVERRIDE; 50 virtual CFStringRef GetKIOSurfaceIsGlobal() OVERRIDE; 51 52 virtual CFTypeRef IOSurfaceCreate(CFDictionaryRef properties) OVERRIDE; 53 virtual uint32 IOSurfaceGetID(CFTypeRef io_surface) OVERRIDE; 54 virtual CFTypeRef IOSurfaceLookup(uint32 io_surface_id) OVERRIDE; 55 virtual mach_port_t IOSurfaceCreateMachPort(CFTypeRef io_surface) OVERRIDE; 56 virtual CFTypeRef IOSurfaceLookupFromMachPort(mach_port_t port) OVERRIDE; 57 58 virtual size_t IOSurfaceGetWidth(CFTypeRef io_surface) OVERRIDE; 59 virtual size_t IOSurfaceGetHeight(CFTypeRef io_surface) OVERRIDE; 60 virtual size_t IOSurfaceGetBytesPerRow(CFTypeRef io_surface) OVERRIDE; 61 virtual void* IOSurfaceGetBaseAddress(CFTypeRef io_surface) OVERRIDE; 62 63 virtual IOReturn IOSurfaceLock(CFTypeRef io_surface, 64 uint32 options, 65 uint32* seed) OVERRIDE; 66 virtual IOReturn IOSurfaceUnlock(CFTypeRef io_surface, 67 uint32 options, 68 uint32* seed) OVERRIDE; 69 70 virtual CGLError CGLTexImageIOSurface2D(CGLContextObj ctx, 71 GLenum target, 72 GLenum internal_format, 73 GLsizei width, 74 GLsizei height, 75 GLenum format, 76 GLenum type, 77 CFTypeRef io_surface, 78 GLuint plane) OVERRIDE; 79 80 virtual CFTypeRef CVPixelBufferGetIOSurface( 81 CVPixelBufferRef pixel_buffer) OVERRIDE; 82 83 private: 84 IOSurfaceSupportImpl(); 85 virtual ~IOSurfaceSupportImpl(); 86 87 void CloseLibraryHandles(); 88 89 void* iosurface_handle_; 90 void* opengl_handle_; 91 void* core_video_handle_; 92 CFStringRef k_io_surface_width_; 93 CFStringRef k_io_surface_height_; 94 CFStringRef k_io_surface_bytes_per_element_; 95 CFStringRef k_io_surface_pixel_format_; 96 CFStringRef k_io_surface_is_global_; 97 IOSurfaceCreateProcPtr io_surface_create_; 98 IOSurfaceGetIDProcPtr io_surface_get_id_; 99 IOSurfaceLookupProcPtr io_surface_lookup_; 100 IOSurfaceCreateMachPortProcPtr io_surface_create_mach_port_; 101 IOSurfaceLookupFromMachPortProcPtr io_surface_lookup_from_mach_port_; 102 IOSurfaceGetWidthPtr io_surface_get_width_; 103 IOSurfaceGetHeightPtr io_surface_get_height_; 104 IOSurfaceGetBytesPerRowPtr io_surface_get_bytes_per_row_; 105 IOSurfaceGetBaseAddressPtr io_surface_get_base_address_; 106 IOSurfaceLockPtr io_surface_lock_; 107 IOSurfaceUnlockPtr io_surface_unlock_; 108 CGLTexImageIOSurface2DProcPtr cgl_tex_image_io_surface_2d_; 109 CVPixelBufferGetIOSurfaceProcPtr cv_pixel_buffer_get_io_surface_; 110 bool initialized_successfully_; 111 112 friend struct DefaultSingletonTraits<IOSurfaceSupportImpl>; 113 DISALLOW_COPY_AND_ASSIGN(IOSurfaceSupportImpl); 114 }; 115 116 IOSurfaceSupportImpl* IOSurfaceSupportImpl::GetInstance() { 117 IOSurfaceSupportImpl* impl = Singleton<IOSurfaceSupportImpl>::get(); 118 if (impl->InitializedSuccessfully()) 119 return impl; 120 return NULL; 121 } 122 123 CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceWidth() { 124 return k_io_surface_width_; 125 } 126 127 CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceHeight() { 128 return k_io_surface_height_; 129 } 130 131 CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceBytesPerElement() { 132 return k_io_surface_bytes_per_element_; 133 } 134 135 CFStringRef IOSurfaceSupportImpl::GetKIOSurfacePixelFormat() { 136 return k_io_surface_pixel_format_; 137 } 138 139 CFStringRef IOSurfaceSupportImpl::GetKIOSurfaceIsGlobal() { 140 return k_io_surface_is_global_; 141 } 142 143 CFTypeRef IOSurfaceSupportImpl::IOSurfaceCreate(CFDictionaryRef properties) { 144 return io_surface_create_(properties); 145 } 146 147 uint32 IOSurfaceSupportImpl::IOSurfaceGetID( 148 CFTypeRef io_surface) { 149 return io_surface_get_id_(io_surface); 150 } 151 152 CFTypeRef IOSurfaceSupportImpl::IOSurfaceLookup(uint32 io_surface_id) { 153 return io_surface_lookup_(io_surface_id); 154 } 155 156 mach_port_t IOSurfaceSupportImpl::IOSurfaceCreateMachPort( 157 CFTypeRef io_surface) { 158 return io_surface_create_mach_port_(io_surface); 159 } 160 161 CFTypeRef IOSurfaceSupportImpl::IOSurfaceLookupFromMachPort(mach_port_t port) { 162 return io_surface_lookup_from_mach_port_(port); 163 } 164 165 size_t IOSurfaceSupportImpl::IOSurfaceGetWidth(CFTypeRef io_surface) { 166 return io_surface_get_width_(io_surface); 167 } 168 169 size_t IOSurfaceSupportImpl::IOSurfaceGetHeight(CFTypeRef io_surface) { 170 return io_surface_get_height_(io_surface); 171 } 172 173 size_t IOSurfaceSupportImpl::IOSurfaceGetBytesPerRow(CFTypeRef io_surface) { 174 return io_surface_get_bytes_per_row_(io_surface); 175 } 176 177 void* IOSurfaceSupportImpl::IOSurfaceGetBaseAddress(CFTypeRef io_surface) { 178 return io_surface_get_base_address_(io_surface); 179 } 180 181 IOReturn IOSurfaceSupportImpl::IOSurfaceLock(CFTypeRef io_surface, 182 uint32 options, 183 uint32* seed) { 184 return io_surface_lock_(io_surface, options, seed); 185 } 186 187 IOReturn IOSurfaceSupportImpl::IOSurfaceUnlock(CFTypeRef io_surface, 188 uint32 options, 189 uint32* seed) { 190 return io_surface_unlock_(io_surface, options, seed); 191 } 192 193 CGLError IOSurfaceSupportImpl::CGLTexImageIOSurface2D(CGLContextObj ctx, 194 GLenum target, 195 GLenum internal_format, 196 GLsizei width, 197 GLsizei height, 198 GLenum format, 199 GLenum type, 200 CFTypeRef io_surface, 201 GLuint plane) { 202 return cgl_tex_image_io_surface_2d_(ctx, 203 target, 204 internal_format, 205 width, 206 height, 207 format, 208 type, 209 io_surface, 210 plane); 211 } 212 213 CFTypeRef IOSurfaceSupportImpl::CVPixelBufferGetIOSurface( 214 CVPixelBufferRef pixel_buffer) { 215 return cv_pixel_buffer_get_io_surface_(pixel_buffer); 216 } 217 218 IOSurfaceSupportImpl::IOSurfaceSupportImpl() 219 : iosurface_handle_(NULL), 220 opengl_handle_(NULL), 221 core_video_handle_(NULL), 222 k_io_surface_width_(NULL), 223 k_io_surface_height_(NULL), 224 k_io_surface_bytes_per_element_(NULL), 225 k_io_surface_pixel_format_(NULL), 226 k_io_surface_is_global_(NULL), 227 io_surface_create_(NULL), 228 io_surface_get_id_(NULL), 229 io_surface_lookup_(NULL), 230 io_surface_create_mach_port_(NULL), 231 io_surface_lookup_from_mach_port_(NULL), 232 io_surface_get_width_(NULL), 233 io_surface_get_height_(NULL), 234 io_surface_get_bytes_per_row_(NULL), 235 io_surface_get_base_address_(NULL), 236 io_surface_lock_(NULL), 237 io_surface_unlock_(NULL), 238 cgl_tex_image_io_surface_2d_(NULL), 239 cv_pixel_buffer_get_io_surface_(NULL), 240 initialized_successfully_(false) { 241 iosurface_handle_ = dlopen( 242 "/System/Library/Frameworks/IOSurface.framework/IOSurface", 243 RTLD_LAZY | RTLD_LOCAL); 244 opengl_handle_ = dlopen( 245 "/System/Library/Frameworks/OpenGL.framework/OpenGL", 246 RTLD_LAZY | RTLD_LOCAL); 247 core_video_handle_ = dlopen( 248 "/System/Library/Frameworks/CoreVideo.framework/CoreVideo", 249 RTLD_LAZY | RTLD_LOCAL); 250 if (!iosurface_handle_ || 251 !opengl_handle_ || 252 !core_video_handle_) { 253 CloseLibraryHandles(); 254 return; 255 } 256 257 void* surface_width_ptr = dlsym(iosurface_handle_, "kIOSurfaceWidth"); 258 void* surface_height_ptr = dlsym(iosurface_handle_, "kIOSurfaceHeight"); 259 void* surface_bytes_per_element_ptr = 260 dlsym(iosurface_handle_, "kIOSurfaceBytesPerElement"); 261 void* surface_pixel_format_ptr = 262 dlsym(iosurface_handle_, "kIOSurfacePixelFormat"); 263 void* surface_is_global_ptr = 264 dlsym(iosurface_handle_, "kIOSurfaceIsGlobal"); 265 void* surface_create_ptr = dlsym(iosurface_handle_, "IOSurfaceCreate"); 266 void* surface_get_id_ptr = dlsym(iosurface_handle_, "IOSurfaceGetID"); 267 void* surface_lookup_ptr = dlsym(iosurface_handle_, "IOSurfaceLookup"); 268 void* surface_create_mach_port_ptr = 269 dlsym(iosurface_handle_, "IOSurfaceCreateMachPort"); 270 void* surface_lookup_from_mach_port_ptr = 271 dlsym(iosurface_handle_, "IOSurfaceLookupFromMachPort"); 272 void* io_surface_get_width_ptr = 273 dlsym(iosurface_handle_, "IOSurfaceGetWidth"); 274 void* io_surface_get_height_ptr = 275 dlsym(iosurface_handle_, "IOSurfaceGetHeight"); 276 void* io_surface_get_bytes_per_row_ptr = 277 dlsym(iosurface_handle_, "IOSurfaceGetBytesPerRow"); 278 void* io_surface_get_base_address_ptr = 279 dlsym(iosurface_handle_, "IOSurfaceGetBaseAddress"); 280 void* io_surface_lock_ptr = dlsym(iosurface_handle_, "IOSurfaceLock"); 281 void* io_surface_unlock_ptr = dlsym(iosurface_handle_, "IOSurfaceUnlock"); 282 void* tex_image_io_surface_2d_ptr = 283 dlsym(opengl_handle_, "CGLTexImageIOSurface2D"); 284 void* cv_pixel_buffer_get_io_surface = 285 dlsym(core_video_handle_, "CVPixelBufferGetIOSurface"); 286 if (!surface_width_ptr || 287 !surface_height_ptr || 288 !surface_bytes_per_element_ptr || 289 !surface_pixel_format_ptr || 290 !surface_is_global_ptr || 291 !surface_create_ptr || 292 !surface_get_id_ptr || 293 !surface_lookup_ptr || 294 !surface_create_mach_port_ptr || 295 !surface_lookup_from_mach_port_ptr || 296 !io_surface_get_width_ptr || 297 !io_surface_get_height_ptr || 298 !io_surface_get_bytes_per_row_ptr || 299 !io_surface_get_base_address_ptr || 300 !io_surface_lock_ptr || 301 !io_surface_unlock_ptr || 302 !tex_image_io_surface_2d_ptr || 303 !cv_pixel_buffer_get_io_surface) { 304 CloseLibraryHandles(); 305 return; 306 } 307 308 k_io_surface_width_ = *static_cast<CFStringRef*>(surface_width_ptr); 309 k_io_surface_height_ = *static_cast<CFStringRef*>(surface_height_ptr); 310 k_io_surface_bytes_per_element_ = 311 *static_cast<CFStringRef*>(surface_bytes_per_element_ptr); 312 k_io_surface_pixel_format_ = 313 *static_cast<CFStringRef*>(surface_pixel_format_ptr); 314 k_io_surface_is_global_ = *static_cast<CFStringRef*>(surface_is_global_ptr); 315 io_surface_create_ = reinterpret_cast<IOSurfaceCreateProcPtr>( 316 surface_create_ptr); 317 io_surface_get_id_ = 318 reinterpret_cast<IOSurfaceGetIDProcPtr>(surface_get_id_ptr); 319 io_surface_lookup_ = 320 reinterpret_cast<IOSurfaceLookupProcPtr>(surface_lookup_ptr); 321 io_surface_create_mach_port_ = 322 reinterpret_cast<IOSurfaceCreateMachPortProcPtr>( 323 surface_create_mach_port_ptr); 324 io_surface_lookup_from_mach_port_ = 325 reinterpret_cast<IOSurfaceLookupFromMachPortProcPtr>( 326 surface_lookup_from_mach_port_ptr); 327 io_surface_get_width_ = 328 reinterpret_cast<IOSurfaceGetWidthPtr>( 329 io_surface_get_width_ptr); 330 io_surface_get_height_ = 331 reinterpret_cast<IOSurfaceGetHeightPtr>( 332 io_surface_get_height_ptr); 333 io_surface_get_bytes_per_row_ = 334 reinterpret_cast<IOSurfaceGetBytesPerRowPtr>( 335 io_surface_get_bytes_per_row_ptr); 336 io_surface_get_base_address_ = 337 reinterpret_cast<IOSurfaceGetBaseAddressPtr>( 338 io_surface_get_base_address_ptr); 339 io_surface_lock_ = reinterpret_cast<IOSurfaceLockPtr>(io_surface_lock_ptr); 340 io_surface_unlock_ = reinterpret_cast<IOSurfaceUnlockPtr>( 341 io_surface_unlock_ptr); 342 cgl_tex_image_io_surface_2d_ = 343 reinterpret_cast<CGLTexImageIOSurface2DProcPtr>( 344 tex_image_io_surface_2d_ptr); 345 cv_pixel_buffer_get_io_surface_ = 346 reinterpret_cast<CVPixelBufferGetIOSurfaceProcPtr>( 347 cv_pixel_buffer_get_io_surface); 348 initialized_successfully_ = true; 349 } 350 351 IOSurfaceSupportImpl::~IOSurfaceSupportImpl() { 352 CloseLibraryHandles(); 353 } 354 355 void IOSurfaceSupportImpl::CloseLibraryHandles() { 356 if (iosurface_handle_) { 357 dlclose(iosurface_handle_); 358 iosurface_handle_ = NULL; 359 } 360 if (opengl_handle_) { 361 dlclose(opengl_handle_); 362 opengl_handle_ = NULL; 363 } 364 if (core_video_handle_) { 365 dlclose(core_video_handle_); 366 core_video_handle_ = NULL; 367 } 368 } 369 370 IOSurfaceSupport* IOSurfaceSupport::Initialize() { 371 return IOSurfaceSupportImpl::GetInstance(); 372 } 373 374 IOSurfaceSupport::IOSurfaceSupport() { 375 } 376 377 IOSurfaceSupport::~IOSurfaceSupport() { 378 } 379 380