зеркало из https://github.com/mozilla/gecko-dev.git
Bug 829284 - Unity plugin doesn't display in HiDPI mode. r=bgirard
This commit is contained in:
Родитель
e0f25c9274
Коммит
c20100d89c
|
@ -3050,7 +3050,8 @@ PluginInstanceChild::EnsureCurrentBuffer(void)
|
|||
bool avoidCGCrashes = !nsCocoaFeatures::OnMountainLionOrLater() &&
|
||||
(GetQuirks() & PluginModuleChild::QUIRK_FLASH_AVOID_CGMODE_CRASHES);
|
||||
caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw, this,
|
||||
avoidCGCrashes);
|
||||
avoidCGCrashes,
|
||||
mContentsScaleFactor);
|
||||
|
||||
if (!caLayer) {
|
||||
PLUGIN_LOG_DEBUG(("GetCGLayer failed."));
|
||||
|
|
|
@ -25,7 +25,8 @@ void InvokeNativeEventLoop();
|
|||
// Need to call back and send a cocoa draw event to the plugin.
|
||||
typedef void (*DrawPluginFunc) (CGContextRef, void*, nsIntRect aUpdateRect);
|
||||
|
||||
void* GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance, bool aAvoidCGCrashes);
|
||||
void* GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance,
|
||||
bool aAvoidCGCrashes, double aContentsScaleFactor);
|
||||
void ReleaseCGLayer(void* cgLayer);
|
||||
void Repaint(void* cgLayer, nsIntRect aRect);
|
||||
|
||||
|
|
|
@ -134,9 +134,36 @@ CGBitmapContextSetDataFunc CGBitmapContextSetDataPtr = NULL;
|
|||
@end
|
||||
|
||||
void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance,
|
||||
bool aAvoidCGCrashes)
|
||||
bool aAvoidCGCrashes, double aContentsScaleFactor)
|
||||
{
|
||||
CGBridgeLayer *bridgeLayer = [[CGBridgeLayer alloc] init ];
|
||||
CGBridgeLayer *bridgeLayer = [[CGBridgeLayer alloc] init];
|
||||
|
||||
// We need to make bridgeLayer behave properly when its superlayer changes
|
||||
// size (in nsCARenderer::SetBounds()).
|
||||
bridgeLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
|
||||
bridgeLayer.needsDisplayOnBoundsChange = YES;
|
||||
NSNull *nullValue = [NSNull null];
|
||||
NSDictionary *actions = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
nullValue, @"bounds",
|
||||
nullValue, @"contents",
|
||||
nullValue, @"contentsRect",
|
||||
nullValue, @"position",
|
||||
nil];
|
||||
[bridgeLayer setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]];
|
||||
|
||||
// For reasons that aren't clear (perhaps one or more OS bugs), we can only
|
||||
// use full HiDPI resolution here if the tree is built with the 10.7 SDK or
|
||||
// up. If we build with the 10.6 SDK, changing the contentsScale property
|
||||
// of bridgeLayer (even to the same value) causes it to stop working (go
|
||||
// blank). This doesn't happen with objects that are members of the CALayer
|
||||
// class (as opposed to one of its subclasses).
|
||||
#if defined(MAC_OS_X_VERSION_10_7) && \
|
||||
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if ([bridgeLayer respondsToSelector:@selector(setContentsScale:)]) {
|
||||
bridgeLayer.contentsScale = aContentsScaleFactor;
|
||||
}
|
||||
#endif
|
||||
|
||||
[bridgeLayer setDrawFunc:aFunc
|
||||
pluginInstance:aPluginInstance
|
||||
avoidCGCrashes:aAvoidCGCrashes];
|
||||
|
|
|
@ -25,9 +25,9 @@ enum AllowOfflineRendererEnum { ALLOW_OFFLINE_RENDERER, DISALLOW_OFFLINE_RENDERE
|
|||
|
||||
class nsCARenderer : public mozilla::RefCounted<nsCARenderer> {
|
||||
public:
|
||||
nsCARenderer() : mCARenderer(nullptr), mFBOTexture(0), mOpenGLContext(nullptr),
|
||||
mCGImage(nullptr), mCGData(nullptr), mIOSurface(nullptr), mFBO(0),
|
||||
mIOTexture(0),
|
||||
nsCARenderer() : mCARenderer(nullptr), mWrapperCALayer(nullptr), mFBOTexture(0),
|
||||
mOpenGLContext(nullptr), mCGImage(nullptr), mCGData(nullptr),
|
||||
mIOSurface(nullptr), mFBO(0), mIOTexture(0),
|
||||
mUnsupportedWidth(UINT32_MAX), mUnsupportedHeight(UINT32_MAX),
|
||||
mAllowOfflineRenderer(DISALLOW_OFFLINE_RENDERER),
|
||||
mContentsScaleFactor(1.0) {}
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
// Remove & Add the layer without destroying
|
||||
// the renderer for fast back buffer swapping.
|
||||
void DettachCALayer();
|
||||
void DetachCALayer();
|
||||
void AttachCALayer(void *aCALayer);
|
||||
#ifdef DEBUG
|
||||
static void SaveToDisk(MacIOSurface *surf);
|
||||
|
@ -77,6 +77,7 @@ private:
|
|||
void Destroy();
|
||||
|
||||
void *mCARenderer;
|
||||
void *mWrapperCALayer;
|
||||
GLuint mFBOTexture;
|
||||
_CGLContextObject *mOpenGLContext;
|
||||
CGImageRef mCGImage;
|
||||
|
|
|
@ -489,6 +489,10 @@ void nsCARenderer::Destroy() {
|
|||
caRenderer.layer = nullptr;
|
||||
[caRenderer release];
|
||||
}
|
||||
if (mWrapperCALayer) {
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
[wrapperLayer release];
|
||||
}
|
||||
if (mOpenGLContext) {
|
||||
if (mFBO || mIOTexture || mFBOTexture) {
|
||||
// Release these resources with the context that allocated them
|
||||
|
@ -517,6 +521,7 @@ void nsCARenderer::Destroy() {
|
|||
// mCGData is deallocated by cgdata_release_callback
|
||||
|
||||
mCARenderer = nil;
|
||||
mWrapperCALayer = nil;
|
||||
mFBOTexture = 0;
|
||||
mOpenGLContext = nullptr;
|
||||
mCGImage = nullptr;
|
||||
|
@ -538,9 +543,6 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CALayer* layer = (CALayer*)aCALayer;
|
||||
CARenderer* caRenderer = nullptr;
|
||||
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFAAccelerated,
|
||||
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
|
||||
|
@ -569,17 +571,27 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
|||
}
|
||||
::CGLDestroyPixelFormat(format);
|
||||
|
||||
caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext
|
||||
options:nil] retain];
|
||||
mCARenderer = caRenderer;
|
||||
CARenderer* caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext
|
||||
options:nil] retain];
|
||||
if (caRenderer == nil) {
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
CALayer* wrapperCALayer = [[CALayer layer] retain];
|
||||
if (wrapperCALayer == nil) {
|
||||
[caRenderer release];
|
||||
mUnsupportedWidth = aWidth;
|
||||
mUnsupportedHeight = aHeight;
|
||||
Destroy();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
caRenderer.layer = layer;
|
||||
mCARenderer = caRenderer;
|
||||
mWrapperCALayer = wrapperCALayer;
|
||||
caRenderer.layer = wrapperCALayer;
|
||||
[wrapperCALayer addSublayer:(CALayer*)aCALayer];
|
||||
mContentsScaleFactor = aContentsScaleFactor;
|
||||
size_t intScaleFactor = ceil(mContentsScaleFactor);
|
||||
SetBounds(aWidth, aHeight);
|
||||
|
@ -696,82 +708,54 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
|
|||
|
||||
void nsCARenderer::SetBounds(int aWidth, int aHeight) {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
CALayer* layer = [mCARenderer layer];
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* pluginLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
|
||||
// Create a transaction and disable animations
|
||||
// to make the position update instant.
|
||||
[CATransaction begin];
|
||||
NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"onOrderIn",
|
||||
[NSNull null], @"onOrderOut",
|
||||
[NSNull null], @"sublayers",
|
||||
[NSNull null], @"contents",
|
||||
[NSNull null], @"position",
|
||||
[NSNull null], @"bounds",
|
||||
nil];
|
||||
layer.actions = newActions;
|
||||
NSMutableDictionary *newActions =
|
||||
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNull null], @"onOrderIn",
|
||||
[NSNull null], @"onOrderOut",
|
||||
[NSNull null], @"sublayers",
|
||||
[NSNull null], @"contents",
|
||||
[NSNull null], @"position",
|
||||
[NSNull null], @"bounds",
|
||||
nil];
|
||||
wrapperLayer.actions = newActions;
|
||||
[newActions release];
|
||||
|
||||
// If we're in HiDPI mode, mContentsScaleFactor will (presumably) be 2.0.
|
||||
// For some reason, to make things work properly in HiDPI mode we need to
|
||||
// make caRenderer's 'bounds' and 'layer' different sizes -- to set 'bounds'
|
||||
// to the size of 'layer's backing store. To make plugins display at HiDPI
|
||||
// resolution we also need to set 'layer's contentScale to
|
||||
// mContentsScaleFactor.
|
||||
// to the size of 'layer's backing store. And to avoid this possibly
|
||||
// confusing the plugin, we need to hide it's effects from the plugin by
|
||||
// making pluginLayer (usually the CALayer* provided by the plugin) a
|
||||
// sublayer of our own wrapperLayer (see bug 829284).
|
||||
size_t intScaleFactor = ceil(mContentsScaleFactor);
|
||||
[CATransaction setValue: [NSNumber numberWithFloat:0.0f] forKey: kCATransactionAnimationDuration];
|
||||
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
|
||||
[layer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
|
||||
[wrapperLayer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[wrapperLayer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
|
||||
[pluginLayer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
[pluginLayer setFrame:CGRectMake(0, 0, aWidth, aHeight)];
|
||||
caRenderer.bounds = CGRectMake(0, 0, aWidth * intScaleFactor, aHeight * intScaleFactor);
|
||||
if (mContentsScaleFactor != 1.0) {
|
||||
CGAffineTransform affineTransform = [layer affineTransform];
|
||||
CGAffineTransform affineTransform = [wrapperLayer affineTransform];
|
||||
affineTransform.a = mContentsScaleFactor;
|
||||
affineTransform.d = mContentsScaleFactor;
|
||||
affineTransform.tx = ((double)aWidth)/mContentsScaleFactor;
|
||||
affineTransform.ty = ((double)aHeight)/mContentsScaleFactor;
|
||||
[layer setAffineTransform:affineTransform];
|
||||
if ([layer respondsToSelector:@selector(setContentsScale:)]) {
|
||||
// For reasons that aren't clear (perhaps one or more OS bugs), if layer
|
||||
// belongs to a subclass of CALayer we can only use full HiDPI resolution
|
||||
// here if the tree is built with the 10.7 SDK or up: If we change
|
||||
// layer.contentsScale (even to the same value), layer simply stops
|
||||
// working (goes blank). And even if we're building with the 10.7 SDK,
|
||||
// we can't use full HiDPI resolution if layer belongs to CAOpenGLLayer
|
||||
// or a subclass: Changing layer.contentsScale to values higher than
|
||||
// 1.0 makes it display only in the lower left part of its "box".
|
||||
// We use CGBridgeLayer (a subclass of CALayer) to implement CoreGraphics
|
||||
// mode for OOP plugins. Shockwave uses a subclass of CAOpenGLLayer
|
||||
// (SWRenderer) to implement CoreAnimation mode. The SlingPlayer plugin
|
||||
// uses another subclass of CAOpenGLLayer (CoreAnimationLayer).
|
||||
#if !defined(MAC_OS_X_VERSION_10_7) || \
|
||||
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
|
||||
if ([layer isMemberOfClass:[CALayer class]])
|
||||
#else
|
||||
if (![layer isKindOfClass:[CAOpenGLLayer class]])
|
||||
#endif
|
||||
{
|
||||
layer.contentsScale = mContentsScaleFactor;
|
||||
}
|
||||
}
|
||||
[wrapperLayer setAffineTransform:affineTransform];
|
||||
} else {
|
||||
// These settings are the default values. But they might have been
|
||||
// changed as above if we were previously running in a HiDPI mode
|
||||
// (i.e. if we just switched from that to a non-HiDPI mode).
|
||||
[layer setAffineTransform:CGAffineTransformIdentity];
|
||||
if ([layer respondsToSelector:@selector(setContentsScale:)]) {
|
||||
#if !defined(MAC_OS_X_VERSION_10_7) || \
|
||||
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
|
||||
if ([layer isMemberOfClass:[CALayer class]])
|
||||
#else
|
||||
if (![layer isKindOfClass:[CAOpenGLLayer class]])
|
||||
#endif
|
||||
{
|
||||
layer.contentsScale = 1.0;
|
||||
}
|
||||
}
|
||||
[wrapperLayer setAffineTransform:CGAffineTransformIdentity];
|
||||
}
|
||||
[CATransaction commit];
|
||||
|
||||
}
|
||||
|
||||
void nsCARenderer::SetViewport(int aWidth, int aHeight) {
|
||||
|
@ -855,11 +839,12 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
|||
if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0)
|
||||
return NS_OK;
|
||||
|
||||
if (!mCARenderer) {
|
||||
if (!mCARenderer || !mWrapperCALayer) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
size_t intScaleFactor = ceil(aContentsScaleFactor);
|
||||
int renderer_width = caRenderer.bounds.size.width / intScaleFactor;
|
||||
int renderer_height = caRenderer.bounds.size.height / intScaleFactor;
|
||||
|
@ -868,9 +853,10 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight,
|
|||
mContentsScaleFactor != aContentsScaleFactor) {
|
||||
// XXX: This should be optimized to not rescale the buffer
|
||||
// if we are resizing down.
|
||||
// caLayer is the CALayer* provided by the plugin, so we need to preserve
|
||||
// it across the call to Destroy().
|
||||
CALayer* caLayer = [caRenderer layer];
|
||||
// caLayer may be the CALayer* provided by the plugin, so we need to
|
||||
// preserve it across the call to Destroy().
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* caLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
// mIOSurface is set by AttachIOSurface(), not by SetupRenderer(). So
|
||||
// since it may have been set by a prior call to AttachIOSurface(), we
|
||||
// need to preserve it across the call to Destroy().
|
||||
|
@ -1005,17 +991,19 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsCARenderer::DettachCALayer() {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
|
||||
caRenderer.layer = nil;
|
||||
void nsCARenderer::DetachCALayer() {
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* oldLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
[oldLayer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
void nsCARenderer::AttachCALayer(void *aCALayer) {
|
||||
CARenderer* caRenderer = (CARenderer*)mCARenderer;
|
||||
|
||||
CALayer* caLayer = (CALayer*)aCALayer;
|
||||
caRenderer.layer = caLayer;
|
||||
CALayer* wrapperLayer = (CALayer*)mWrapperCALayer;
|
||||
NSArray* sublayers = [wrapperLayer sublayers];
|
||||
CALayer* oldLayer = (CALayer*) [sublayers objectAtIndex:0];
|
||||
[oldLayer removeFromSuperlayer];
|
||||
[wrapperLayer addSublayer:(CALayer*)aCALayer];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
Загрузка…
Ссылка в новой задаче