dom/plugins/ipc/PluginUtilsOSX.mm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 // vim:set ts=2 sts=2 sw=2 et cin:
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include <dlfcn.h>
michael@0 8 #import <AppKit/AppKit.h>
michael@0 9 #import <QuartzCore/QuartzCore.h>
michael@0 10 #include "PluginUtilsOSX.h"
michael@0 11
michael@0 12 // Remove definitions for try/catch interfering with ObjCException macros.
michael@0 13 #include "nsObjCExceptions.h"
michael@0 14 #include "nsCocoaUtils.h"
michael@0 15
michael@0 16 #include "nsDebug.h"
michael@0 17
michael@0 18 @interface CALayer (ContentsScale)
michael@0 19 - (double)contentsScale;
michael@0 20 - (void)setContentsScale:(double)scale;
michael@0 21 @end
michael@0 22
michael@0 23 using namespace mozilla::plugins::PluginUtilsOSX;
michael@0 24
michael@0 25 @interface CGBridgeLayer : CALayer {
michael@0 26 DrawPluginFunc mDrawFunc;
michael@0 27 void* mPluginInstance;
michael@0 28 nsIntRect mUpdateRect;
michael@0 29 BOOL mAvoidCGCrashes;
michael@0 30 CGContextRef mLastCGContext;
michael@0 31 }
michael@0 32 - (void)setDrawFunc:(DrawPluginFunc)aFunc
michael@0 33 pluginInstance:(void*)aPluginInstance
michael@0 34 avoidCGCrashes:(BOOL)aAvoidCGCrashes;
michael@0 35 - (void)updateRect:(nsIntRect)aRect;
michael@0 36 - (void)protectLastCGContext;
michael@0 37
michael@0 38 @end
michael@0 39
michael@0 40 // CGBitmapContextSetData() is an undocumented function present (with
michael@0 41 // the same signature) since at least OS X 10.5. As the name suggests,
michael@0 42 // it's used to replace the "data" in a bitmap context that was
michael@0 43 // originally specified in a call to CGBitmapContextCreate() or
michael@0 44 // CGBitmapContextCreateWithData().
michael@0 45 typedef void (*CGBitmapContextSetDataFunc) (CGContextRef c,
michael@0 46 size_t x,
michael@0 47 size_t y,
michael@0 48 size_t width,
michael@0 49 size_t height,
michael@0 50 void* data,
michael@0 51 size_t bitsPerComponent,
michael@0 52 size_t bitsPerPixel,
michael@0 53 size_t bytesPerRow);
michael@0 54 CGBitmapContextSetDataFunc CGBitmapContextSetDataPtr = NULL;
michael@0 55
michael@0 56 @implementation CGBridgeLayer
michael@0 57 - (void) updateRect:(nsIntRect)aRect
michael@0 58 {
michael@0 59 mUpdateRect.UnionRect(mUpdateRect, aRect);
michael@0 60 }
michael@0 61
michael@0 62 - (void) setDrawFunc:(DrawPluginFunc)aFunc
michael@0 63 pluginInstance:(void*)aPluginInstance
michael@0 64 avoidCGCrashes:(BOOL)aAvoidCGCrashes
michael@0 65 {
michael@0 66 mDrawFunc = aFunc;
michael@0 67 mPluginInstance = aPluginInstance;
michael@0 68 mAvoidCGCrashes = aAvoidCGCrashes;
michael@0 69 mLastCGContext = nil;
michael@0 70 }
michael@0 71
michael@0 72 // The Flash plugin, in very unusual circumstances, can (in CoreGraphics
michael@0 73 // mode) try to access the CGContextRef from -[CGBridgeLayer drawInContext:]
michael@0 74 // outside of any call to NPP_HandleEvent(NPCocoaEventDrawRect). This usually
michael@0 75 // crashes the plugin process (probably because it tries to access deleted
michael@0 76 // memory). We stop these crashes from happening by holding a reference to
michael@0 77 // the CGContextRef, and also by ensuring that it's data won't get deleted.
michael@0 78 // The CGContextRef won't "work" in this form. But this won't cause trouble
michael@0 79 // for plugins that do things correctly (that don't access this CGContextRef
michael@0 80 // outside of the call to NPP_HandleEvent() that passes it to the plugin).
michael@0 81 // The OS may reuse this CGContextRef (it may get passed to other calls to
michael@0 82 // -[CGBridgeLayer drawInContext:]). But before each call the OS calls
michael@0 83 // CGBitmapContextSetData() to replace its data, which undoes the changes
michael@0 84 // we make here. See bug 804606.
michael@0 85 - (void)protectLastCGContext
michael@0 86 {
michael@0 87 if (!mAvoidCGCrashes || !mLastCGContext) {
michael@0 88 return;
michael@0 89 }
michael@0 90
michael@0 91 static char ensuredData[128] = {0};
michael@0 92
michael@0 93 if (!CGBitmapContextSetDataPtr) {
michael@0 94 CGBitmapContextSetDataPtr = (CGBitmapContextSetDataFunc)
michael@0 95 dlsym(RTLD_DEFAULT, "CGBitmapContextSetData");
michael@0 96 }
michael@0 97
michael@0 98 if (CGBitmapContextSetDataPtr && (GetContextType(mLastCGContext) == CG_CONTEXT_TYPE_BITMAP)) {
michael@0 99 CGBitmapContextSetDataPtr(mLastCGContext, 0, 0, 1, 1, ensuredData, 8, 32, 64);
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 - (void)drawInContext:(CGContextRef)aCGContext
michael@0 104 {
michael@0 105 ::CGContextSaveGState(aCGContext);
michael@0 106 ::CGContextTranslateCTM(aCGContext, 0, self.bounds.size.height);
michael@0 107 ::CGContextScaleCTM(aCGContext, (CGFloat) 1, (CGFloat) -1);
michael@0 108
michael@0 109 mUpdateRect = nsIntRect(0, 0, self.bounds.size.width, self.bounds.size.height);
michael@0 110
michael@0 111 mDrawFunc(aCGContext, mPluginInstance, mUpdateRect);
michael@0 112
michael@0 113 ::CGContextRestoreGState(aCGContext);
michael@0 114
michael@0 115 if (mAvoidCGCrashes) {
michael@0 116 if (mLastCGContext) {
michael@0 117 ::CGContextRelease(mLastCGContext);
michael@0 118 }
michael@0 119 mLastCGContext = aCGContext;
michael@0 120 ::CGContextRetain(mLastCGContext);
michael@0 121 }
michael@0 122
michael@0 123 mUpdateRect.SetEmpty();
michael@0 124 }
michael@0 125
michael@0 126 - (void)dealloc
michael@0 127 {
michael@0 128 if (mLastCGContext) {
michael@0 129 ::CGContextRelease(mLastCGContext);
michael@0 130 }
michael@0 131 [super dealloc];
michael@0 132 }
michael@0 133
michael@0 134 @end
michael@0 135
michael@0 136 void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance,
michael@0 137 bool aAvoidCGCrashes, double aContentsScaleFactor)
michael@0 138 {
michael@0 139 CGBridgeLayer *bridgeLayer = [[CGBridgeLayer alloc] init];
michael@0 140
michael@0 141 // We need to make bridgeLayer behave properly when its superlayer changes
michael@0 142 // size (in nsCARenderer::SetBounds()).
michael@0 143 bridgeLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
michael@0 144 bridgeLayer.needsDisplayOnBoundsChange = YES;
michael@0 145 NSNull *nullValue = [NSNull null];
michael@0 146 NSDictionary *actions = [NSDictionary dictionaryWithObjectsAndKeys:
michael@0 147 nullValue, @"bounds",
michael@0 148 nullValue, @"contents",
michael@0 149 nullValue, @"contentsRect",
michael@0 150 nullValue, @"position",
michael@0 151 nil];
michael@0 152 [bridgeLayer setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]];
michael@0 153
michael@0 154 // For reasons that aren't clear (perhaps one or more OS bugs), we can only
michael@0 155 // use full HiDPI resolution here if the tree is built with the 10.7 SDK or
michael@0 156 // up. If we build with the 10.6 SDK, changing the contentsScale property
michael@0 157 // of bridgeLayer (even to the same value) causes it to stop working (go
michael@0 158 // blank). This doesn't happen with objects that are members of the CALayer
michael@0 159 // class (as opposed to one of its subclasses).
michael@0 160 #if defined(MAC_OS_X_VERSION_10_7) && \
michael@0 161 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
michael@0 162 if ([bridgeLayer respondsToSelector:@selector(setContentsScale:)]) {
michael@0 163 bridgeLayer.contentsScale = aContentsScaleFactor;
michael@0 164 }
michael@0 165 #endif
michael@0 166
michael@0 167 [bridgeLayer setDrawFunc:aFunc
michael@0 168 pluginInstance:aPluginInstance
michael@0 169 avoidCGCrashes:aAvoidCGCrashes];
michael@0 170 return bridgeLayer;
michael@0 171 }
michael@0 172
michael@0 173 void mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(void *cgLayer) {
michael@0 174 CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)cgLayer;
michael@0 175 [bridgeLayer release];
michael@0 176 }
michael@0 177
michael@0 178 void mozilla::plugins::PluginUtilsOSX::Repaint(void *caLayer, nsIntRect aRect) {
michael@0 179 CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)caLayer;
michael@0 180 [CATransaction begin];
michael@0 181 [bridgeLayer updateRect:aRect];
michael@0 182 [bridgeLayer setNeedsDisplay];
michael@0 183 [bridgeLayer displayIfNeeded];
michael@0 184 [CATransaction commit];
michael@0 185 [bridgeLayer protectLastCGContext];
michael@0 186 }
michael@0 187
michael@0 188 @interface EventProcessor : NSObject {
michael@0 189 RemoteProcessEvents aRemoteEvents;
michael@0 190 void *aPluginModule;
michael@0 191 }
michael@0 192 - (void)setRemoteEvents:(RemoteProcessEvents) remoteEvents pluginModule:(void*) pluginModule;
michael@0 193 - (void)onTick;
michael@0 194 @end
michael@0 195
michael@0 196 @implementation EventProcessor
michael@0 197 - (void) onTick
michael@0 198 {
michael@0 199 aRemoteEvents(aPluginModule);
michael@0 200 }
michael@0 201
michael@0 202 - (void)setRemoteEvents:(RemoteProcessEvents) remoteEvents pluginModule:(void*) pluginModule
michael@0 203 {
michael@0 204 aRemoteEvents = remoteEvents;
michael@0 205 aPluginModule = pluginModule;
michael@0 206 }
michael@0 207 @end
michael@0 208
michael@0 209 #define EVENT_PROCESS_DELAY 0.05 // 50 ms
michael@0 210
michael@0 211 NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int aX, int aY, void* pluginModule, RemoteProcessEvents remoteEvent)
michael@0 212 {
michael@0 213 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 214
michael@0 215 // Set the native cursor to the OS default (an arrow) before displaying the
michael@0 216 // context menu. Otherwise (if the plugin has changed the cursor) it may
michael@0 217 // stay as the plugin has set it -- which means it may be invisible. We
michael@0 218 // need to do this because we display the context menu without making the
michael@0 219 // plugin process the foreground process. If we did, the cursor would
michael@0 220 // change to an arrow cursor automatically -- as it does in Chrome.
michael@0 221 [[NSCursor arrowCursor] set];
michael@0 222
michael@0 223 // Create a timer to process browser events while waiting
michael@0 224 // on the menu. This prevents the browser from hanging
michael@0 225 // during the lifetime of the menu.
michael@0 226 EventProcessor* eventProcessor = [[EventProcessor alloc] init];
michael@0 227 [eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
michael@0 228 NSTimer *eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
michael@0 229 target:eventProcessor selector:@selector(onTick)
michael@0 230 userInfo:nil repeats:TRUE];
michael@0 231 // Use NSEventTrackingRunLoopMode otherwise the timer will
michael@0 232 // not fire during the right click menu.
michael@0 233 [[NSRunLoop currentRunLoop] addTimer:eventTimer
michael@0 234 forMode:NSEventTrackingRunLoopMode];
michael@0 235
michael@0 236 NSMenu* nsmenu = reinterpret_cast<NSMenu*>(aMenu);
michael@0 237 NSPoint screen_point = ::NSMakePoint(aX, aY);
michael@0 238
michael@0 239 [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
michael@0 240
michael@0 241 [eventTimer invalidate];
michael@0 242 [eventProcessor release];
michael@0 243
michael@0 244 return NPERR_NO_ERROR;
michael@0 245
michael@0 246 NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
michael@0 247 }
michael@0 248
michael@0 249 void mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop()
michael@0 250 {
michael@0 251 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 252 ::CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, true);
michael@0 253 NS_OBJC_END_TRY_ABORT_BLOCK;
michael@0 254 }
michael@0 255
michael@0 256
michael@0 257 #define UNDOCUMENTED_SESSION_CONSTANT ((int)-2)
michael@0 258 namespace mozilla {
michael@0 259 namespace plugins {
michael@0 260 namespace PluginUtilsOSX {
michael@0 261 static void *sApplicationASN = NULL;
michael@0 262 static void *sApplicationInfoItem = NULL;
michael@0 263 }
michael@0 264 }
michael@0 265 }
michael@0 266
michael@0 267 bool mozilla::plugins::PluginUtilsOSX::SetProcessName(const char* aProcessName) {
michael@0 268 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 269 nsAutoreleasePool localPool;
michael@0 270
michael@0 271 if (!aProcessName || strcmp(aProcessName, "") == 0) {
michael@0 272 return false;
michael@0 273 }
michael@0 274
michael@0 275 NSString *currentName = [[[NSBundle mainBundle] localizedInfoDictionary]
michael@0 276 objectForKey:(NSString *)kCFBundleNameKey];
michael@0 277
michael@0 278 char formattedName[1024];
michael@0 279 snprintf(formattedName, sizeof(formattedName),
michael@0 280 "%s (%s)", [currentName UTF8String], aProcessName);
michael@0 281
michael@0 282 aProcessName = formattedName;
michael@0 283
michael@0 284 // This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
michael@0 285 typedef CFTypeRef (*LSGetASNType)();
michael@0 286 typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef,
michael@0 287 CFStringRef,
michael@0 288 CFStringRef,
michael@0 289 CFDictionaryRef*);
michael@0 290
michael@0 291 CFBundleRef launchServices = ::CFBundleGetBundleWithIdentifier(
michael@0 292 CFSTR("com.apple.LaunchServices"));
michael@0 293 if (!launchServices) {
michael@0 294 NS_WARNING("Failed to set process name: Could not open LaunchServices bundle");
michael@0 295 return false;
michael@0 296 }
michael@0 297
michael@0 298 if (!sApplicationASN) {
michael@0 299 sApplicationASN = ::CFBundleGetFunctionPointerForName(launchServices,
michael@0 300 CFSTR("_LSGetCurrentApplicationASN"));
michael@0 301 }
michael@0 302
michael@0 303 LSGetASNType getASNFunc = reinterpret_cast<LSGetASNType>
michael@0 304 (sApplicationASN);
michael@0 305
michael@0 306 if (!sApplicationInfoItem) {
michael@0 307 sApplicationInfoItem = ::CFBundleGetFunctionPointerForName(launchServices,
michael@0 308 CFSTR("_LSSetApplicationInformationItem"));
michael@0 309 }
michael@0 310
michael@0 311 LSSetInformationItemType setInformationItemFunc
michael@0 312 = reinterpret_cast<LSSetInformationItemType>
michael@0 313 (sApplicationInfoItem);
michael@0 314
michael@0 315 void * displayNameKeyAddr = ::CFBundleGetDataPointerForName(launchServices,
michael@0 316 CFSTR("_kLSDisplayNameKey"));
michael@0 317
michael@0 318 CFStringRef displayNameKey = nil;
michael@0 319 if (displayNameKeyAddr) {
michael@0 320 displayNameKey = reinterpret_cast<CFStringRef>(*(CFStringRef*)displayNameKeyAddr);
michael@0 321 }
michael@0 322
michael@0 323 // Rename will fail without this
michael@0 324 ProcessSerialNumber psn;
michael@0 325 if (::GetCurrentProcess(&psn) != noErr) {
michael@0 326 return false;
michael@0 327 }
michael@0 328
michael@0 329 CFTypeRef currentAsn = getASNFunc();
michael@0 330
michael@0 331 if (!getASNFunc || !setInformationItemFunc ||
michael@0 332 !displayNameKey || !currentAsn) {
michael@0 333 NS_WARNING("Failed to set process name: Accessing launchServices failed");
michael@0 334 return false;
michael@0 335 }
michael@0 336
michael@0 337 CFStringRef processName = ::CFStringCreateWithCString(nil,
michael@0 338 aProcessName,
michael@0 339 kCFStringEncodingASCII);
michael@0 340 if (!processName) {
michael@0 341 NS_WARNING("Failed to set process name: Could not create CFStringRef");
michael@0 342 return false;
michael@0 343 }
michael@0 344
michael@0 345 OSErr err = setInformationItemFunc(UNDOCUMENTED_SESSION_CONSTANT, currentAsn,
michael@0 346 displayNameKey, processName,
michael@0 347 nil); // Optional out param
michael@0 348 ::CFRelease(processName);
michael@0 349 if (err != noErr) {
michael@0 350 NS_WARNING("Failed to set process name: LSSetInformationItemType err");
michael@0 351 return false;
michael@0 352 }
michael@0 353
michael@0 354 return true;
michael@0 355 NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
michael@0 356 }
michael@0 357
michael@0 358 namespace mozilla {
michael@0 359 namespace plugins {
michael@0 360 namespace PluginUtilsOSX {
michael@0 361
michael@0 362 size_t nsDoubleBufferCARenderer::GetFrontSurfaceWidth() {
michael@0 363 if (!HasFrontSurface()) {
michael@0 364 return 0;
michael@0 365 }
michael@0 366
michael@0 367 return mFrontSurface->GetWidth();
michael@0 368 }
michael@0 369
michael@0 370 size_t nsDoubleBufferCARenderer::GetFrontSurfaceHeight() {
michael@0 371 if (!HasFrontSurface()) {
michael@0 372 return 0;
michael@0 373 }
michael@0 374
michael@0 375 return mFrontSurface->GetHeight();
michael@0 376 }
michael@0 377
michael@0 378 double nsDoubleBufferCARenderer::GetFrontSurfaceContentsScaleFactor() {
michael@0 379 if (!HasFrontSurface()) {
michael@0 380 return 1.0;
michael@0 381 }
michael@0 382
michael@0 383 return mFrontSurface->GetContentsScaleFactor();
michael@0 384 }
michael@0 385
michael@0 386 size_t nsDoubleBufferCARenderer::GetBackSurfaceWidth() {
michael@0 387 if (!HasBackSurface()) {
michael@0 388 return 0;
michael@0 389 }
michael@0 390
michael@0 391 return mBackSurface->GetWidth();
michael@0 392 }
michael@0 393
michael@0 394 size_t nsDoubleBufferCARenderer::GetBackSurfaceHeight() {
michael@0 395 if (!HasBackSurface()) {
michael@0 396 return 0;
michael@0 397 }
michael@0 398
michael@0 399 return mBackSurface->GetHeight();
michael@0 400 }
michael@0 401
michael@0 402 double nsDoubleBufferCARenderer::GetBackSurfaceContentsScaleFactor() {
michael@0 403 if (!HasBackSurface()) {
michael@0 404 return 1.0;
michael@0 405 }
michael@0 406
michael@0 407 return mBackSurface->GetContentsScaleFactor();
michael@0 408 }
michael@0 409
michael@0 410 IOSurfaceID nsDoubleBufferCARenderer::GetFrontSurfaceID() {
michael@0 411 if (!HasFrontSurface()) {
michael@0 412 return 0;
michael@0 413 }
michael@0 414
michael@0 415 return mFrontSurface->GetIOSurfaceID();
michael@0 416 }
michael@0 417
michael@0 418 bool nsDoubleBufferCARenderer::HasBackSurface() {
michael@0 419 return !!mBackSurface;
michael@0 420 }
michael@0 421
michael@0 422 bool nsDoubleBufferCARenderer::HasFrontSurface() {
michael@0 423 return !!mFrontSurface;
michael@0 424 }
michael@0 425
michael@0 426 bool nsDoubleBufferCARenderer::HasCALayer() {
michael@0 427 return !!mCALayer;
michael@0 428 }
michael@0 429
michael@0 430 void nsDoubleBufferCARenderer::SetCALayer(void *aCALayer) {
michael@0 431 mCALayer = aCALayer;
michael@0 432 }
michael@0 433
michael@0 434 bool nsDoubleBufferCARenderer::InitFrontSurface(size_t aWidth, size_t aHeight,
michael@0 435 double aContentsScaleFactor,
michael@0 436 AllowOfflineRendererEnum aAllowOfflineRenderer) {
michael@0 437 if (!mCALayer) {
michael@0 438 return false;
michael@0 439 }
michael@0 440
michael@0 441 mContentsScaleFactor = aContentsScaleFactor;
michael@0 442 mFrontSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, mContentsScaleFactor);
michael@0 443 if (!mFrontSurface) {
michael@0 444 mCARenderer = nullptr;
michael@0 445 return false;
michael@0 446 }
michael@0 447
michael@0 448 if (!mCARenderer) {
michael@0 449 mCARenderer = new nsCARenderer();
michael@0 450 if (!mCARenderer) {
michael@0 451 mFrontSurface = nullptr;
michael@0 452 return false;
michael@0 453 }
michael@0 454
michael@0 455 mCARenderer->AttachIOSurface(mFrontSurface);
michael@0 456
michael@0 457 nsresult result = mCARenderer->SetupRenderer(mCALayer,
michael@0 458 mFrontSurface->GetWidth(),
michael@0 459 mFrontSurface->GetHeight(),
michael@0 460 mContentsScaleFactor,
michael@0 461 aAllowOfflineRenderer);
michael@0 462
michael@0 463 if (result != NS_OK) {
michael@0 464 mCARenderer = nullptr;
michael@0 465 mFrontSurface = nullptr;
michael@0 466 return false;
michael@0 467 }
michael@0 468 } else {
michael@0 469 mCARenderer->AttachIOSurface(mFrontSurface);
michael@0 470 }
michael@0 471
michael@0 472 return true;
michael@0 473 }
michael@0 474
michael@0 475 void nsDoubleBufferCARenderer::Render() {
michael@0 476 if (!HasFrontSurface() || !mCARenderer) {
michael@0 477 return;
michael@0 478 }
michael@0 479
michael@0 480 mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(),
michael@0 481 mContentsScaleFactor, nullptr);
michael@0 482 }
michael@0 483
michael@0 484 void nsDoubleBufferCARenderer::SwapSurfaces() {
michael@0 485 RefPtr<MacIOSurface> prevFrontSurface = mFrontSurface;
michael@0 486 mFrontSurface = mBackSurface;
michael@0 487 mBackSurface = prevFrontSurface;
michael@0 488
michael@0 489 if (mFrontSurface) {
michael@0 490 mCARenderer->AttachIOSurface(mFrontSurface);
michael@0 491 }
michael@0 492 }
michael@0 493
michael@0 494 void nsDoubleBufferCARenderer::ClearFrontSurface() {
michael@0 495 mFrontSurface = nullptr;
michael@0 496 if (!mFrontSurface && !mBackSurface) {
michael@0 497 mCARenderer = nullptr;
michael@0 498 }
michael@0 499 }
michael@0 500
michael@0 501 void nsDoubleBufferCARenderer::ClearBackSurface() {
michael@0 502 mBackSurface = nullptr;
michael@0 503 if (!mFrontSurface && !mBackSurface) {
michael@0 504 mCARenderer = nullptr;
michael@0 505 }
michael@0 506 }
michael@0 507
michael@0 508 } //PluginUtilsOSX
michael@0 509 } //plugins
michael@0 510 } //mozilla
michael@0 511

mercurial