1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/MacIOSurface.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,426 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:set ts=2 sts=2 sw=2 et cin: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "MacIOSurface.h" 1.11 +#include <OpenGL/gl.h> 1.12 +#include <QuartzCore/QuartzCore.h> 1.13 +#include <dlfcn.h> 1.14 +#include "mozilla/RefPtr.h" 1.15 +#include "mozilla/Assertions.h" 1.16 + 1.17 +using namespace mozilla; 1.18 +// IOSurface signatures 1.19 +#define IOSURFACE_FRAMEWORK_PATH \ 1.20 + "/System/Library/Frameworks/IOSurface.framework/IOSurface" 1.21 +#define OPENGL_FRAMEWORK_PATH \ 1.22 + "/System/Library/Frameworks/OpenGL.framework/OpenGL" 1.23 +#define COREGRAPHICS_FRAMEWORK_PATH \ 1.24 + "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics" 1.25 + 1.26 + 1.27 + 1.28 +#define GET_CONST(const_name) \ 1.29 + ((CFStringRef*) dlsym(sIOSurfaceFramework, const_name)) 1.30 +#define GET_IOSYM(dest,sym_name) \ 1.31 + (typeof(dest)) dlsym(sIOSurfaceFramework, sym_name) 1.32 +#define GET_CGLSYM(dest,sym_name) \ 1.33 + (typeof(dest)) dlsym(sOpenGLFramework, sym_name) 1.34 +#define GET_CGSYM(dest,sym_name) \ 1.35 + (typeof(dest)) dlsym(sCoreGraphicsFramework, sym_name) 1.36 + 1.37 +MacIOSurfaceLib::LibraryUnloader MacIOSurfaceLib::sLibraryUnloader; 1.38 +bool MacIOSurfaceLib::isLoaded = false; 1.39 +void* MacIOSurfaceLib::sIOSurfaceFramework; 1.40 +void* MacIOSurfaceLib::sOpenGLFramework; 1.41 +void* MacIOSurfaceLib::sCoreGraphicsFramework; 1.42 +IOSurfaceCreateFunc MacIOSurfaceLib::sCreate; 1.43 +IOSurfaceGetIDFunc MacIOSurfaceLib::sGetID; 1.44 +IOSurfaceLookupFunc MacIOSurfaceLib::sLookup; 1.45 +IOSurfaceGetBaseAddressFunc MacIOSurfaceLib::sGetBaseAddress; 1.46 +IOSurfaceGetWidthFunc MacIOSurfaceLib::sWidth; 1.47 +IOSurfaceGetHeightFunc MacIOSurfaceLib::sHeight; 1.48 +IOSurfaceGetBytesPerRowFunc MacIOSurfaceLib::sBytesPerRow; 1.49 +IOSurfaceLockFunc MacIOSurfaceLib::sLock; 1.50 +IOSurfaceUnlockFunc MacIOSurfaceLib::sUnlock; 1.51 +CGLTexImageIOSurface2DFunc MacIOSurfaceLib::sTexImage; 1.52 +IOSurfaceContextCreateFunc MacIOSurfaceLib::sIOSurfaceContextCreate; 1.53 +IOSurfaceContextCreateImageFunc MacIOSurfaceLib::sIOSurfaceContextCreateImage; 1.54 +IOSurfaceContextGetSurfaceFunc MacIOSurfaceLib::sIOSurfaceContextGetSurface; 1.55 +unsigned int (*MacIOSurfaceLib::sCGContextGetTypePtr) (CGContextRef) = nullptr; 1.56 + 1.57 +CFStringRef MacIOSurfaceLib::kPropWidth; 1.58 +CFStringRef MacIOSurfaceLib::kPropHeight; 1.59 +CFStringRef MacIOSurfaceLib::kPropBytesPerElem; 1.60 +CFStringRef MacIOSurfaceLib::kPropBytesPerRow; 1.61 +CFStringRef MacIOSurfaceLib::kPropIsGlobal; 1.62 + 1.63 +bool MacIOSurfaceLib::isInit() { 1.64 + // Guard against trying to reload the library 1.65 + // if it is not available. 1.66 + if (!isLoaded) 1.67 + LoadLibrary(); 1.68 + MOZ_ASSERT(sIOSurfaceFramework); 1.69 + return sIOSurfaceFramework; 1.70 +} 1.71 + 1.72 +IOSurfacePtr MacIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) { 1.73 + return sCreate(properties); 1.74 +} 1.75 + 1.76 +IOSurfacePtr MacIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) { 1.77 + return sLookup(aIOSurfaceID); 1.78 +} 1.79 + 1.80 +IOSurfaceID MacIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) { 1.81 + return sGetID(aIOSurfacePtr); 1.82 +} 1.83 + 1.84 +void* MacIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) { 1.85 + return sGetBaseAddress(aIOSurfacePtr); 1.86 +} 1.87 + 1.88 +size_t MacIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) { 1.89 + return sWidth(aIOSurfacePtr); 1.90 +} 1.91 + 1.92 +size_t MacIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) { 1.93 + return sHeight(aIOSurfacePtr); 1.94 +} 1.95 + 1.96 +size_t MacIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) { 1.97 + return sBytesPerRow(aIOSurfacePtr); 1.98 +} 1.99 + 1.100 +IOReturn MacIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr, 1.101 + uint32_t options, uint32_t *seed) { 1.102 + return sLock(aIOSurfacePtr, options, seed); 1.103 +} 1.104 + 1.105 +IOReturn MacIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr, 1.106 + uint32_t options, uint32_t *seed) { 1.107 + return sUnlock(aIOSurfacePtr, options, seed); 1.108 +} 1.109 + 1.110 +CGLError MacIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt, 1.111 + GLenum target, GLenum internalFormat, 1.112 + GLsizei width, GLsizei height, 1.113 + GLenum format, GLenum type, 1.114 + IOSurfacePtr ioSurface, GLuint plane) { 1.115 + return sTexImage(ctxt, target, internalFormat, width, height, 1.116 + format, type, ioSurface, plane); 1.117 +} 1.118 + 1.119 +CGContextRef MacIOSurfaceLib::IOSurfaceContextCreate(IOSurfacePtr aIOSurfacePtr, 1.120 + unsigned aWidth, unsigned aHeight, 1.121 + unsigned aBitsPerComponent, unsigned aBytes, 1.122 + CGColorSpaceRef aColorSpace, CGBitmapInfo bitmapInfo) { 1.123 + if (!sIOSurfaceContextCreate) 1.124 + return nullptr; 1.125 + return sIOSurfaceContextCreate(aIOSurfacePtr, aWidth, aHeight, aBitsPerComponent, aBytes, aColorSpace, bitmapInfo); 1.126 +} 1.127 + 1.128 +CGImageRef MacIOSurfaceLib::IOSurfaceContextCreateImage(CGContextRef aContext) { 1.129 + if (!sIOSurfaceContextCreateImage) 1.130 + return nullptr; 1.131 + return sIOSurfaceContextCreateImage(aContext); 1.132 +} 1.133 + 1.134 +IOSurfacePtr MacIOSurfaceLib::IOSurfaceContextGetSurface(CGContextRef aContext) { 1.135 + if (!sIOSurfaceContextGetSurface) 1.136 + return nullptr; 1.137 + return sIOSurfaceContextGetSurface(aContext); 1.138 +} 1.139 + 1.140 +CFStringRef MacIOSurfaceLib::GetIOConst(const char* symbole) { 1.141 + CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole); 1.142 + if (!address) 1.143 + return nullptr; 1.144 + 1.145 + return *address; 1.146 +} 1.147 + 1.148 +void MacIOSurfaceLib::LoadLibrary() { 1.149 + if (isLoaded) { 1.150 + return; 1.151 + } 1.152 + isLoaded = true; 1.153 + sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH, 1.154 + RTLD_LAZY | RTLD_LOCAL); 1.155 + sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH, 1.156 + RTLD_LAZY | RTLD_LOCAL); 1.157 + 1.158 + sCoreGraphicsFramework = dlopen(COREGRAPHICS_FRAMEWORK_PATH, 1.159 + RTLD_LAZY | RTLD_LOCAL); 1.160 + if (!sIOSurfaceFramework || !sOpenGLFramework || !sCoreGraphicsFramework) { 1.161 + if (sIOSurfaceFramework) 1.162 + dlclose(sIOSurfaceFramework); 1.163 + if (sOpenGLFramework) 1.164 + dlclose(sOpenGLFramework); 1.165 + if (sCoreGraphicsFramework) 1.166 + dlclose(sCoreGraphicsFramework); 1.167 + sIOSurfaceFramework = nullptr; 1.168 + sOpenGLFramework = nullptr; 1.169 + sCoreGraphicsFramework = nullptr; 1.170 + return; 1.171 + } 1.172 + 1.173 + kPropWidth = GetIOConst("kIOSurfaceWidth"); 1.174 + kPropHeight = GetIOConst("kIOSurfaceHeight"); 1.175 + kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement"); 1.176 + kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow"); 1.177 + kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal"); 1.178 + sCreate = GET_IOSYM(sCreate, "IOSurfaceCreate"); 1.179 + sGetID = GET_IOSYM(sGetID, "IOSurfaceGetID"); 1.180 + sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth"); 1.181 + sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight"); 1.182 + sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow"); 1.183 + sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup"); 1.184 + sLock = GET_IOSYM(sLock, "IOSurfaceLock"); 1.185 + sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock"); 1.186 + sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress"); 1.187 + sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D"); 1.188 + sCGContextGetTypePtr = (unsigned int (*)(CGContext*))dlsym(RTLD_DEFAULT, "CGContextGetType"); 1.189 + 1.190 + // Optional symbols 1.191 + sIOSurfaceContextCreate = GET_CGSYM(sIOSurfaceContextCreate, "CGIOSurfaceContextCreate"); 1.192 + sIOSurfaceContextCreateImage = GET_CGSYM(sIOSurfaceContextCreateImage, "CGIOSurfaceContextCreateImage"); 1.193 + sIOSurfaceContextGetSurface = GET_CGSYM(sIOSurfaceContextGetSurface, "CGIOSurfaceContextGetSurface"); 1.194 + 1.195 + if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress || 1.196 + !kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal || 1.197 + !sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow || 1.198 + !sBytesPerRow) { 1.199 + CloseLibrary(); 1.200 + } 1.201 +} 1.202 + 1.203 +void MacIOSurfaceLib::CloseLibrary() { 1.204 + if (sIOSurfaceFramework) { 1.205 + dlclose(sIOSurfaceFramework); 1.206 + } 1.207 + if (sOpenGLFramework) { 1.208 + dlclose(sOpenGLFramework); 1.209 + } 1.210 + sIOSurfaceFramework = nullptr; 1.211 + sOpenGLFramework = nullptr; 1.212 +} 1.213 + 1.214 +MacIOSurface::~MacIOSurface() { 1.215 + CFRelease(mIOSurfacePtr); 1.216 +} 1.217 + 1.218 +TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight, 1.219 + double aContentsScaleFactor, 1.220 + bool aHasAlpha) { 1.221 + if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) 1.222 + return nullptr; 1.223 + 1.224 + CFMutableDictionaryRef props = ::CFDictionaryCreateMutable( 1.225 + kCFAllocatorDefault, 4, 1.226 + &kCFTypeDictionaryKeyCallBacks, 1.227 + &kCFTypeDictionaryValueCallBacks); 1.228 + if (!props) 1.229 + return nullptr; 1.230 + 1.231 + int32_t bytesPerElem = 4; 1.232 + size_t intScaleFactor = ceil(aContentsScaleFactor); 1.233 + aWidth *= intScaleFactor; 1.234 + aHeight *= intScaleFactor; 1.235 + CFNumberRef cfWidth = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aWidth); 1.236 + CFNumberRef cfHeight = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aHeight); 1.237 + CFNumberRef cfBytesPerElem = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytesPerElem); 1.238 + ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropWidth, 1.239 + cfWidth); 1.240 + ::CFRelease(cfWidth); 1.241 + ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropHeight, 1.242 + cfHeight); 1.243 + ::CFRelease(cfHeight); 1.244 + ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropBytesPerElem, 1.245 + cfBytesPerElem); 1.246 + ::CFRelease(cfBytesPerElem); 1.247 + ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropIsGlobal, 1.248 + kCFBooleanTrue); 1.249 + 1.250 + IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceCreate(props); 1.251 + ::CFRelease(props); 1.252 + 1.253 + if (!surfaceRef) 1.254 + return nullptr; 1.255 + 1.256 + RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha); 1.257 + if (!ioSurface) { 1.258 + ::CFRelease(surfaceRef); 1.259 + return nullptr; 1.260 + } 1.261 + 1.262 + return ioSurface.forget(); 1.263 +} 1.264 + 1.265 +TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID, 1.266 + double aContentsScaleFactor, 1.267 + bool aHasAlpha) { 1.268 + if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) 1.269 + return nullptr; 1.270 + 1.271 + IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID); 1.272 + if (!surfaceRef) 1.273 + return nullptr; 1.274 + 1.275 + RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha); 1.276 + if (!ioSurface) { 1.277 + ::CFRelease(surfaceRef); 1.278 + return nullptr; 1.279 + } 1.280 + return ioSurface.forget(); 1.281 +} 1.282 + 1.283 +IOSurfaceID MacIOSurface::GetIOSurfaceID() { 1.284 + return MacIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr); 1.285 +} 1.286 + 1.287 +void* MacIOSurface::GetBaseAddress() { 1.288 + return MacIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr); 1.289 +} 1.290 + 1.291 +size_t MacIOSurface::GetWidth() { 1.292 + size_t intScaleFactor = ceil(mContentsScaleFactor); 1.293 + return GetDevicePixelWidth() / intScaleFactor; 1.294 +} 1.295 + 1.296 +size_t MacIOSurface::GetHeight() { 1.297 + size_t intScaleFactor = ceil(mContentsScaleFactor); 1.298 + return GetDevicePixelHeight() / intScaleFactor; 1.299 +} 1.300 + 1.301 +size_t MacIOSurface::GetDevicePixelWidth() { 1.302 + return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr); 1.303 +} 1.304 + 1.305 +size_t MacIOSurface::GetDevicePixelHeight() { 1.306 + return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr); 1.307 +} 1.308 + 1.309 +size_t MacIOSurface::GetBytesPerRow() { 1.310 + return MacIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr); 1.311 +} 1.312 + 1.313 +#define READ_ONLY 0x1 1.314 +void MacIOSurface::Lock() { 1.315 + MacIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, nullptr); 1.316 +} 1.317 + 1.318 +void MacIOSurface::Unlock() { 1.319 + MacIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, nullptr); 1.320 +} 1.321 + 1.322 +#include "SourceSurfaceRawData.h" 1.323 +using mozilla::gfx::SourceSurface; 1.324 +using mozilla::gfx::SourceSurfaceRawData; 1.325 +using mozilla::gfx::IntSize; 1.326 +using mozilla::gfx::SurfaceFormat; 1.327 + 1.328 +TemporaryRef<SourceSurface> 1.329 +MacIOSurface::GetAsSurface() { 1.330 + Lock(); 1.331 + size_t bytesPerRow = GetBytesPerRow(); 1.332 + size_t ioWidth = GetDevicePixelWidth(); 1.333 + size_t ioHeight = GetDevicePixelHeight(); 1.334 + 1.335 + unsigned char* ioData = (unsigned char*)GetBaseAddress(); 1.336 + unsigned char* dataCpy = (unsigned char*)malloc(bytesPerRow*ioHeight); 1.337 + for (size_t i = 0; i < ioHeight; i++) { 1.338 + memcpy(dataCpy + i * bytesPerRow, 1.339 + ioData + i * bytesPerRow, ioWidth * 4); 1.340 + } 1.341 + 1.342 + Unlock(); 1.343 + 1.344 + SurfaceFormat format = HasAlpha() ? mozilla::gfx::SurfaceFormat::B8G8R8A8 : 1.345 + mozilla::gfx::SurfaceFormat::B8G8R8X8; 1.346 + 1.347 + RefPtr<SourceSurfaceRawData> surf = new SourceSurfaceRawData(); 1.348 + surf->InitWrappingData(dataCpy, IntSize(ioWidth, ioHeight), bytesPerRow, format, true); 1.349 + 1.350 + return surf.forget(); 1.351 +} 1.352 + 1.353 +CGLError 1.354 +MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx) 1.355 +{ 1.356 + return MacIOSurfaceLib::CGLTexImageIOSurface2D(ctx, 1.357 + GL_TEXTURE_RECTANGLE_ARB, 1.358 + HasAlpha() ? GL_RGBA : GL_RGB, 1.359 + GetDevicePixelWidth(), 1.360 + GetDevicePixelHeight(), 1.361 + GL_BGRA, 1.362 + GL_UNSIGNED_INT_8_8_8_8_REV, 1.363 + mIOSurfacePtr, 0); 1.364 +} 1.365 + 1.366 +static 1.367 +CGColorSpaceRef CreateSystemColorSpace() { 1.368 + CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); 1.369 + if (!cspace) { 1.370 + cspace = ::CGColorSpaceCreateDeviceRGB(); 1.371 + } 1.372 + return cspace; 1.373 +} 1.374 + 1.375 +CGContextRef MacIOSurface::CreateIOSurfaceContext() { 1.376 + CGColorSpaceRef cspace = CreateSystemColorSpace(); 1.377 + CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr, 1.378 + GetDevicePixelWidth(), 1.379 + GetDevicePixelHeight(), 1.380 + 8, 32, cspace, 0x2002); 1.381 + ::CGColorSpaceRelease(cspace); 1.382 + return ref; 1.383 +} 1.384 + 1.385 +CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) { 1.386 + if (!MacIOSurfaceLib::isInit()) 1.387 + return nullptr; 1.388 + 1.389 + return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext); 1.390 +} 1.391 + 1.392 +TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext, 1.393 + double aContentsScaleFactor, 1.394 + bool aHasAlpha) { 1.395 + if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0) 1.396 + return nullptr; 1.397 + 1.398 + IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceContextGetSurface(aContext); 1.399 + if (!surfaceRef) 1.400 + return nullptr; 1.401 + 1.402 + // Retain the IOSurface because MacIOSurface will release it 1.403 + CFRetain(surfaceRef); 1.404 + 1.405 + RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha); 1.406 + if (!ioSurface) { 1.407 + ::CFRelease(surfaceRef); 1.408 + return nullptr; 1.409 + } 1.410 + return ioSurface.forget(); 1.411 +} 1.412 + 1.413 + 1.414 +CGContextType GetContextType(CGContextRef ref) 1.415 +{ 1.416 + if (!MacIOSurfaceLib::isInit() || !MacIOSurfaceLib::sCGContextGetTypePtr) 1.417 + return CG_CONTEXT_TYPE_UNKNOWN; 1.418 + 1.419 + unsigned int type = MacIOSurfaceLib::sCGContextGetTypePtr(ref); 1.420 + if (type == CG_CONTEXT_TYPE_BITMAP) { 1.421 + return CG_CONTEXT_TYPE_BITMAP; 1.422 + } else if (type == CG_CONTEXT_TYPE_IOSURFACE) { 1.423 + return CG_CONTEXT_TYPE_IOSURFACE; 1.424 + } else { 1.425 + return CG_CONTEXT_TYPE_UNKNOWN; 1.426 + } 1.427 +} 1.428 + 1.429 +