gfx/2d/MacIOSurface.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 // vim:set ts=2 sts=2 sw=2 et cin:
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "MacIOSurface.h"
     8 #include <OpenGL/gl.h>
     9 #include <QuartzCore/QuartzCore.h>
    10 #include <dlfcn.h>
    11 #include "mozilla/RefPtr.h"
    12 #include "mozilla/Assertions.h"
    14 using namespace mozilla;
    15 // IOSurface signatures
    16 #define IOSURFACE_FRAMEWORK_PATH \
    17   "/System/Library/Frameworks/IOSurface.framework/IOSurface"
    18 #define OPENGL_FRAMEWORK_PATH \
    19   "/System/Library/Frameworks/OpenGL.framework/OpenGL"
    20 #define COREGRAPHICS_FRAMEWORK_PATH \
    21   "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics"
    25 #define GET_CONST(const_name) \
    26   ((CFStringRef*) dlsym(sIOSurfaceFramework, const_name))
    27 #define GET_IOSYM(dest,sym_name) \
    28   (typeof(dest)) dlsym(sIOSurfaceFramework, sym_name)
    29 #define GET_CGLSYM(dest,sym_name) \
    30   (typeof(dest)) dlsym(sOpenGLFramework, sym_name)
    31 #define GET_CGSYM(dest,sym_name) \
    32   (typeof(dest)) dlsym(sCoreGraphicsFramework, sym_name)
    34 MacIOSurfaceLib::LibraryUnloader MacIOSurfaceLib::sLibraryUnloader;
    35 bool                          MacIOSurfaceLib::isLoaded = false;
    36 void*                         MacIOSurfaceLib::sIOSurfaceFramework;
    37 void*                         MacIOSurfaceLib::sOpenGLFramework;
    38 void*                         MacIOSurfaceLib::sCoreGraphicsFramework;
    39 IOSurfaceCreateFunc           MacIOSurfaceLib::sCreate;
    40 IOSurfaceGetIDFunc            MacIOSurfaceLib::sGetID;
    41 IOSurfaceLookupFunc           MacIOSurfaceLib::sLookup;
    42 IOSurfaceGetBaseAddressFunc   MacIOSurfaceLib::sGetBaseAddress;
    43 IOSurfaceGetWidthFunc         MacIOSurfaceLib::sWidth;
    44 IOSurfaceGetHeightFunc        MacIOSurfaceLib::sHeight;
    45 IOSurfaceGetBytesPerRowFunc   MacIOSurfaceLib::sBytesPerRow;
    46 IOSurfaceLockFunc             MacIOSurfaceLib::sLock;
    47 IOSurfaceUnlockFunc           MacIOSurfaceLib::sUnlock;
    48 CGLTexImageIOSurface2DFunc    MacIOSurfaceLib::sTexImage;
    49 IOSurfaceContextCreateFunc    MacIOSurfaceLib::sIOSurfaceContextCreate;
    50 IOSurfaceContextCreateImageFunc   MacIOSurfaceLib::sIOSurfaceContextCreateImage;
    51 IOSurfaceContextGetSurfaceFunc    MacIOSurfaceLib::sIOSurfaceContextGetSurface;
    52 unsigned int                  (*MacIOSurfaceLib::sCGContextGetTypePtr) (CGContextRef) = nullptr;
    54 CFStringRef                   MacIOSurfaceLib::kPropWidth;
    55 CFStringRef                   MacIOSurfaceLib::kPropHeight;
    56 CFStringRef                   MacIOSurfaceLib::kPropBytesPerElem;
    57 CFStringRef                   MacIOSurfaceLib::kPropBytesPerRow;
    58 CFStringRef                   MacIOSurfaceLib::kPropIsGlobal;
    60 bool MacIOSurfaceLib::isInit() {
    61   // Guard against trying to reload the library
    62   // if it is not available.
    63   if (!isLoaded)
    64     LoadLibrary();
    65   MOZ_ASSERT(sIOSurfaceFramework);
    66   return sIOSurfaceFramework;
    67 }
    69 IOSurfacePtr MacIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
    70   return sCreate(properties);
    71 }
    73 IOSurfacePtr MacIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
    74   return sLookup(aIOSurfaceID);
    75 }
    77 IOSurfaceID MacIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
    78   return sGetID(aIOSurfacePtr);
    79 }
    81 void* MacIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
    82   return sGetBaseAddress(aIOSurfacePtr);
    83 }
    85 size_t MacIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
    86   return sWidth(aIOSurfacePtr);
    87 }
    89 size_t MacIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
    90   return sHeight(aIOSurfacePtr);
    91 }
    93 size_t MacIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
    94   return sBytesPerRow(aIOSurfacePtr);
    95 }
    97 IOReturn MacIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr, 
    98                                        uint32_t options, uint32_t *seed) {
    99   return sLock(aIOSurfacePtr, options, seed);
   100 }
   102 IOReturn MacIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr, 
   103                                          uint32_t options, uint32_t *seed) {
   104   return sUnlock(aIOSurfacePtr, options, seed);
   105 }
   107 CGLError MacIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
   108                              GLenum target, GLenum internalFormat,
   109                              GLsizei width, GLsizei height,
   110                              GLenum format, GLenum type,
   111                              IOSurfacePtr ioSurface, GLuint plane) {
   112   return sTexImage(ctxt, target, internalFormat, width, height,
   113                    format, type, ioSurface, plane);
   114 }
   116 CGContextRef MacIOSurfaceLib::IOSurfaceContextCreate(IOSurfacePtr aIOSurfacePtr,
   117                              unsigned aWidth, unsigned aHeight,
   118                              unsigned aBitsPerComponent, unsigned aBytes,
   119                              CGColorSpaceRef aColorSpace, CGBitmapInfo bitmapInfo) {
   120   if (!sIOSurfaceContextCreate)
   121     return nullptr;
   122   return sIOSurfaceContextCreate(aIOSurfacePtr, aWidth, aHeight, aBitsPerComponent, aBytes, aColorSpace, bitmapInfo);
   123 }
   125 CGImageRef MacIOSurfaceLib::IOSurfaceContextCreateImage(CGContextRef aContext) {
   126   if (!sIOSurfaceContextCreateImage)
   127     return nullptr;
   128   return sIOSurfaceContextCreateImage(aContext);
   129 }
   131 IOSurfacePtr MacIOSurfaceLib::IOSurfaceContextGetSurface(CGContextRef aContext) {
   132   if (!sIOSurfaceContextGetSurface)
   133     return nullptr;
   134   return sIOSurfaceContextGetSurface(aContext);
   135 }
   137 CFStringRef MacIOSurfaceLib::GetIOConst(const char* symbole) {
   138   CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole);
   139   if (!address)
   140     return nullptr;
   142   return *address;
   143 }
   145 void MacIOSurfaceLib::LoadLibrary() {
   146   if (isLoaded) {
   147     return;
   148   } 
   149   isLoaded = true;
   150   sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH,
   151                             RTLD_LAZY | RTLD_LOCAL);
   152   sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH,
   153                             RTLD_LAZY | RTLD_LOCAL);
   155   sCoreGraphicsFramework = dlopen(COREGRAPHICS_FRAMEWORK_PATH,
   156                             RTLD_LAZY | RTLD_LOCAL);
   157   if (!sIOSurfaceFramework || !sOpenGLFramework || !sCoreGraphicsFramework) {
   158     if (sIOSurfaceFramework)
   159       dlclose(sIOSurfaceFramework);
   160     if (sOpenGLFramework)
   161       dlclose(sOpenGLFramework);
   162     if (sCoreGraphicsFramework)
   163       dlclose(sCoreGraphicsFramework);
   164     sIOSurfaceFramework = nullptr;
   165     sOpenGLFramework = nullptr;
   166     sCoreGraphicsFramework = nullptr;
   167     return;
   168   }
   170   kPropWidth = GetIOConst("kIOSurfaceWidth");
   171   kPropHeight = GetIOConst("kIOSurfaceHeight");
   172   kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement");
   173   kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow");
   174   kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal");
   175   sCreate = GET_IOSYM(sCreate, "IOSurfaceCreate");
   176   sGetID  = GET_IOSYM(sGetID,  "IOSurfaceGetID");
   177   sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth");
   178   sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight");
   179   sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow");
   180   sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup");
   181   sLock = GET_IOSYM(sLock, "IOSurfaceLock");
   182   sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock");
   183   sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress");
   184   sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D");
   185   sCGContextGetTypePtr = (unsigned int (*)(CGContext*))dlsym(RTLD_DEFAULT, "CGContextGetType");
   187   // Optional symbols
   188   sIOSurfaceContextCreate = GET_CGSYM(sIOSurfaceContextCreate, "CGIOSurfaceContextCreate");
   189   sIOSurfaceContextCreateImage = GET_CGSYM(sIOSurfaceContextCreateImage, "CGIOSurfaceContextCreateImage");
   190   sIOSurfaceContextGetSurface = GET_CGSYM(sIOSurfaceContextGetSurface, "CGIOSurfaceContextGetSurface");
   192   if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress ||
   193       !kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal ||
   194       !sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow ||
   195       !sBytesPerRow) {
   196     CloseLibrary();
   197   }
   198 }
   200 void MacIOSurfaceLib::CloseLibrary() {
   201   if (sIOSurfaceFramework) {
   202     dlclose(sIOSurfaceFramework);
   203   }
   204   if (sOpenGLFramework) {
   205     dlclose(sOpenGLFramework);
   206   }
   207   sIOSurfaceFramework = nullptr;
   208   sOpenGLFramework = nullptr;
   209 }
   211 MacIOSurface::~MacIOSurface() {
   212   CFRelease(mIOSurfacePtr);
   213 }
   215 TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight,
   216                                                          double aContentsScaleFactor,
   217                                                          bool aHasAlpha) {
   218   if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
   219     return nullptr;
   221   CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
   222                       kCFAllocatorDefault, 4,
   223                       &kCFTypeDictionaryKeyCallBacks,
   224                       &kCFTypeDictionaryValueCallBacks);
   225   if (!props)
   226     return nullptr;
   228   int32_t bytesPerElem = 4;
   229   size_t intScaleFactor = ceil(aContentsScaleFactor);
   230   aWidth *= intScaleFactor;
   231   aHeight *= intScaleFactor;
   232   CFNumberRef cfWidth = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aWidth);
   233   CFNumberRef cfHeight = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aHeight);
   234   CFNumberRef cfBytesPerElem = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytesPerElem);
   235   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropWidth,
   236                                 cfWidth);
   237   ::CFRelease(cfWidth);
   238   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropHeight,
   239                                 cfHeight);
   240   ::CFRelease(cfHeight);
   241   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropBytesPerElem, 
   242                                 cfBytesPerElem);
   243   ::CFRelease(cfBytesPerElem);
   244   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropIsGlobal, 
   245                                 kCFBooleanTrue);
   247   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceCreate(props);
   248   ::CFRelease(props);
   250   if (!surfaceRef)
   251     return nullptr;
   253   RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
   254   if (!ioSurface) {
   255     ::CFRelease(surfaceRef);
   256     return nullptr;
   257   }
   259   return ioSurface.forget();
   260 }
   262 TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID,
   263                                                        double aContentsScaleFactor,
   264                                                        bool aHasAlpha) { 
   265   if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
   266     return nullptr;
   268   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
   269   if (!surfaceRef)
   270     return nullptr;
   272   RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
   273   if (!ioSurface) {
   274     ::CFRelease(surfaceRef);
   275     return nullptr;
   276   }
   277   return ioSurface.forget();
   278 }
   280 IOSurfaceID MacIOSurface::GetIOSurfaceID() { 
   281   return MacIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
   282 }
   284 void* MacIOSurface::GetBaseAddress() { 
   285   return MacIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
   286 }
   288 size_t MacIOSurface::GetWidth() {
   289   size_t intScaleFactor = ceil(mContentsScaleFactor);
   290   return GetDevicePixelWidth() / intScaleFactor;
   291 }
   293 size_t MacIOSurface::GetHeight() {
   294   size_t intScaleFactor = ceil(mContentsScaleFactor);
   295   return GetDevicePixelHeight() / intScaleFactor;
   296 }
   298 size_t MacIOSurface::GetDevicePixelWidth() {
   299   return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
   300 }
   302 size_t MacIOSurface::GetDevicePixelHeight() {
   303   return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
   304 }
   306 size_t MacIOSurface::GetBytesPerRow() { 
   307   return MacIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
   308 }
   310 #define READ_ONLY 0x1
   311 void MacIOSurface::Lock() {
   312   MacIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, nullptr);
   313 }
   315 void MacIOSurface::Unlock() {
   316   MacIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, nullptr);
   317 }
   319 #include "SourceSurfaceRawData.h"
   320 using mozilla::gfx::SourceSurface;
   321 using mozilla::gfx::SourceSurfaceRawData;
   322 using mozilla::gfx::IntSize;
   323 using mozilla::gfx::SurfaceFormat;
   325 TemporaryRef<SourceSurface>
   326 MacIOSurface::GetAsSurface() {
   327   Lock();
   328   size_t bytesPerRow = GetBytesPerRow();
   329   size_t ioWidth = GetDevicePixelWidth();
   330   size_t ioHeight = GetDevicePixelHeight();
   332   unsigned char* ioData = (unsigned char*)GetBaseAddress();
   333   unsigned char* dataCpy = (unsigned char*)malloc(bytesPerRow*ioHeight);
   334   for (size_t i = 0; i < ioHeight; i++) {
   335     memcpy(dataCpy + i * bytesPerRow,
   336            ioData + i * bytesPerRow, ioWidth * 4);
   337   }
   339   Unlock();
   341   SurfaceFormat format = HasAlpha() ? mozilla::gfx::SurfaceFormat::B8G8R8A8 :
   342                                       mozilla::gfx::SurfaceFormat::B8G8R8X8;
   344   RefPtr<SourceSurfaceRawData> surf = new SourceSurfaceRawData();
   345   surf->InitWrappingData(dataCpy, IntSize(ioWidth, ioHeight), bytesPerRow, format, true);
   347   return surf.forget();
   348 }
   350 CGLError
   351 MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx)
   352 {
   353   return MacIOSurfaceLib::CGLTexImageIOSurface2D(ctx,
   354                                                 GL_TEXTURE_RECTANGLE_ARB,
   355                                                 HasAlpha() ? GL_RGBA : GL_RGB,
   356                                                 GetDevicePixelWidth(),
   357                                                 GetDevicePixelHeight(),
   358                                                 GL_BGRA,
   359                                                 GL_UNSIGNED_INT_8_8_8_8_REV,
   360                                                 mIOSurfacePtr, 0);
   361 }
   363 static
   364 CGColorSpaceRef CreateSystemColorSpace() {
   365   CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
   366   if (!cspace) {
   367     cspace = ::CGColorSpaceCreateDeviceRGB();
   368   }
   369   return cspace;
   370 }
   372 CGContextRef MacIOSurface::CreateIOSurfaceContext() {
   373   CGColorSpaceRef cspace = CreateSystemColorSpace();
   374   CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr,
   375                                                 GetDevicePixelWidth(),
   376                                                 GetDevicePixelHeight(),
   377                                                 8, 32, cspace, 0x2002);
   378   ::CGColorSpaceRelease(cspace);
   379   return ref;
   380 }
   382 CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) {
   383   if (!MacIOSurfaceLib::isInit())
   384     return nullptr;
   386   return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext);
   387 }
   389 TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext,
   390                                                                     double aContentsScaleFactor,
   391                                                                     bool aHasAlpha) {
   392   if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
   393     return nullptr;
   395   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceContextGetSurface(aContext);
   396   if (!surfaceRef)
   397     return nullptr;
   399   // Retain the IOSurface because MacIOSurface will release it
   400   CFRetain(surfaceRef);
   402   RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
   403   if (!ioSurface) {
   404     ::CFRelease(surfaceRef);
   405     return nullptr;
   406   }
   407   return ioSurface.forget();
   408 }
   411 CGContextType GetContextType(CGContextRef ref)
   412 {
   413   if (!MacIOSurfaceLib::isInit() || !MacIOSurfaceLib::sCGContextGetTypePtr)
   414     return CG_CONTEXT_TYPE_UNKNOWN;
   416   unsigned int type = MacIOSurfaceLib::sCGContextGetTypePtr(ref);
   417   if (type == CG_CONTEXT_TYPE_BITMAP) {
   418     return CG_CONTEXT_TYPE_BITMAP;
   419   } else if (type == CG_CONTEXT_TYPE_IOSURFACE) {
   420     return CG_CONTEXT_TYPE_IOSURFACE;
   421   } else {
   422     return CG_CONTEXT_TYPE_UNKNOWN;
   423   }
   424 }

mercurial