summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-22 22:39:53 +0000
committerstuartmorgan@chromium.org <stuartmorgan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-22 22:39:53 +0000
commitcf6fc7ca949c0e05ac36cf72ecd223e59ae1ce90 (patch)
treed37d1567b27de4084a40396bf1daf8c8576ab367 /chrome
parent7e9f4a8e17e918412cfba8337e55873abed112cb (diff)
downloadchromium_src-cf6fc7ca949c0e05ac36cf72ecd223e59ae1ce90.zip
chromium_src-cf6fc7ca949c0e05ac36cf72ecd223e59ae1ce90.tar.gz
chromium_src-cf6fc7ca949c0e05ac36cf72ecd223e59ae1ce90.tar.bz2
Fix handling of Mac accelerated plugin layers across tab switch.
A few related changes to make tab switching work with accelerated plugins: - Re-attach our layer to the view layer whenever it changes; using setWantsLayer: creates a layer that AppKit manages at will, so we can't rely on it. - Override setFrame: on our layer to ignore bogus values sent by the view's layer. - Notify the accelerated surface when our parent (and thus drawing context) changes, so it can associate its texture with the new context. BUG=37701 TEST=Load the pepper test plugin (or a CA plugin in a build with CA enabled) and switch tabs away and back. The plugin should still be visible. Review URL: http://codereview.chromium.org/1166002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42273 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/renderer_host/accelerated_surface_container_mac.cc38
-rw-r--r--chrome/browser/renderer_host/accelerated_surface_container_mac.h7
-rw-r--r--chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc9
-rw-r--r--chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h15
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm120
6 files changed, 132 insertions, 61 deletions
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_mac.cc b/chrome/browser/renderer_host/accelerated_surface_container_mac.cc
index 8d3827c..f77ad3d 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_mac.cc
+++ b/chrome/browser/renderer_host/accelerated_surface_container_mac.cc
@@ -15,7 +15,8 @@ AcceleratedSurfaceContainerMac::AcceleratedSurfaceContainerMac()
surface_(NULL),
width_(0),
height_(0),
- texture_(0) {
+ texture_(0),
+ texture_needs_upload_(true) {
}
AcceleratedSurfaceContainerMac::~AcceleratedSurfaceContainerMac() {
@@ -77,22 +78,7 @@ void AcceleratedSurfaceContainerMac::Draw(CGLContextObj context) {
glBindTexture(target, texture_);
glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // When using an IOSurface, the texture does not need to be repeatedly
- // uploaded, so bind the IOSurface once during texture gen in this case.
- if (io_surface_support) {
- DCHECK(surface_);
- // Don't think we need to identify a plane.
- GLuint plane = 0;
- io_surface_support->CGLTexImageIOSurface2D(context,
- target,
- GL_RGBA,
- width_,
- height_,
- GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV,
- surface_,
- plane);
- } else {
+ if (!io_surface_support) {
// Reserve space on the card for the actual texture upload, done with the
// glTexSubImage2D() call, below.
glTexImage2D(target,
@@ -107,6 +93,24 @@ void AcceleratedSurfaceContainerMac::Draw(CGLContextObj context) {
}
}
+ // When using an IOSurface, the texture does not need to be repeatedly
+ // uploaded, just when we've been told we have to.
+ if (io_surface_support && texture_needs_upload_) {
+ DCHECK(surface_);
+ glBindTexture(target, texture_);
+ // Don't think we need to identify a plane.
+ GLuint plane = 0;
+ io_surface_support->CGLTexImageIOSurface2D(context,
+ target,
+ GL_RGBA,
+ width_,
+ height_,
+ GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ surface_,
+ plane);
+ texture_needs_upload_ = false;
+ }
// If using TransportDIBs, the texture needs to be uploaded every frame.
if (transport_dib_.get() != NULL) {
void* pixel_memory = transport_dib_->memory();
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_mac.h
index 5f2d12e..1778ea9 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_mac.h
+++ b/chrome/browser/renderer_host/accelerated_surface_container_mac.h
@@ -67,6 +67,10 @@ class AcceleratedSurfaceContainerMac {
// coordinate system will work out.
void Draw(CGLContextObj context);
+ // Causes the next Draw call to trigger a texture upload. Should be called any
+ // time the drawing context has changed.
+ void ForceTextureReload() { texture_needs_upload_ = true; }
+
// Enqueue our texture for later deletion. Call this before deleting
// this object.
void EnqueueTextureForDeletion(
@@ -104,6 +108,9 @@ class AcceleratedSurfaceContainerMac {
// with it.
GLuint texture_;
+ // True if we need to upload the texture again during the next draw.
+ bool texture_needs_upload_;
+
DISALLOW_COPY_AND_ASSIGN(AcceleratedSurfaceContainerMac);
};
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
index f7c39e5..2afbb0f 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
+++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc
@@ -81,6 +81,15 @@ void AcceleratedSurfaceContainerManagerMac::Draw(CGLContextObj context) {
glFlush();
}
+void AcceleratedSurfaceContainerManagerMac::ForceTextureReload() {
+ for (PluginWindowToContainerMap::const_iterator i =
+ plugin_window_to_container_map_.begin();
+ i != plugin_window_to_container_map_.end(); ++i) {
+ AcceleratedSurfaceContainerMac* container = i->second;
+ container->ForceTextureReload();
+ }
+}
+
void AcceleratedSurfaceContainerManagerMac::EnqueueTextureForDeletion(
GLuint texture) {
if (texture) {
diff --git a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
index 2456186..bcfd0aa 100644
--- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
+++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.h
@@ -53,6 +53,10 @@ class AcceleratedSurfaceContainerManagerMac {
// context, which must already be current.
void Draw(CGLContextObj context);
+ // Causes the next Draw call on each container to trigger a texture upload.
+ // Should be called any time the drawing context has changed.
+ void ForceTextureReload();
+
// Called by the container to enqueue its OpenGL texture objects for
// deletion.
void EnqueueTextureForDeletion(GLuint texture);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index bc9fbe9..fdbb497 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -52,11 +52,20 @@ class RWHVMEditCommandHelper;
// insertText: and insertNewline: to synthesize the corresponding Char event.
scoped_nsobject<NSEvent> currentKeyEvent_;
NSWindow* lastWindow_; // weak
+
+ // The Core Animation layer, if any, hosting the accelerated plugins' output.
+ scoped_nsobject<CALayer> accelerated_plugin_layer_;
}
- (void)setCanBeKeyView:(BOOL)can;
- (void)setCloseOnDeactivate:(BOOL)b;
- (void)setToolTipAtMousePoint:(NSString *)string;
+// Makes sure that the initial layer setup for accelerated plugin drawing has
+// been done. Can be called multiple times.
+- (void)ensureAcceleratedPluginLayer;
+// Triggers a refresh of the accelerated plugin layer; should be called whenever
+// the shared surface for one of the plugins is updated.
+- (void)drawAcceleratedPluginLayer;
@end
///////////////////////////////////////////////////////////////////////////////
@@ -139,6 +148,9 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void AcceleratedSurfaceBuffersSwapped(gfx::PluginWindowHandle window);
// Draws the current GPU-accelerated plug-in instances into the given context.
virtual void DrawAcceleratedSurfaceInstances(CGLContextObj context);
+ // Informs the plug-in instances that their drawing context has changed.
+ virtual void AcceleratedSurfaceContextChanged();
+
virtual void SetVisuallyDeemphasized(bool deemphasized);
void KillSelf();
@@ -207,9 +219,6 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
// methods needs it.
NSRect im_caret_rect_;
- // The Core Animation layer, if any, hosting the GPU plugins' output.
- scoped_nsobject<CALayer> gpu_plugin_layer_;
-
private:
// Updates the display cursor to the current cursor if the cursor is over this
// render view.
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index c671881..300dc3a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -49,6 +49,7 @@ static inline int ToWebKitModifiers(NSUInteger flags) {
- (void)keyEvent:(NSEvent *)theEvent wasKeyEquivalent:(BOOL)equiv;
- (void)cancelChildPopups;
- (void)callSetNeedsDisplayInRect:(NSValue*)rect;
+- (void)attachPluginLayer;
@end
namespace {
@@ -58,19 +59,19 @@ const size_t kMaxTooltipLength = 1024;
}
-// GPUPluginLayer --------------------------------------------------------------
+// AcceleratedPluginLayer ------------------------------------------------------
-// This subclass of CAOpenGLLayer hosts the output of the GPU-accelerated
-// plugins on the page.
+// This subclass of CAOpenGLLayer hosts the output of accelerated plugins on
+// the page.
-@interface GPUPluginLayer : CAOpenGLLayer {
+@interface AcceleratedPluginLayer : CAOpenGLLayer {
RenderWidgetHostViewMac* renderWidgetHostView_; // weak
}
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
@end
-@implementation GPUPluginLayer
+@implementation AcceleratedPluginLayer
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
self = [super init];
if (self != nil) {
@@ -79,16 +80,27 @@ const size_t kMaxTooltipLength = 1024;
return self;
}
--(void)drawInCGLContext:(CGLContextObj)glContext
- pixelFormat:(CGLPixelFormatObj)pixelFormat
- forLayerTime:(CFTimeInterval)timeInterval
- displayTime:(const CVTimeStamp *)timeStamp {
+- (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp *)timeStamp {
renderWidgetHostView_->DrawAcceleratedSurfaceInstances(glContext);
[super drawInCGLContext:glContext
pixelFormat:pixelFormat
forLayerTime:timeInterval
displayTime:timeStamp];
}
+
+- (void)setFrame:(CGRect)rect {
+ // The frame we get when the superlayer resizes doesn't make sense, so ignore
+ // it and just match the superlayer's size. See the email thread referenced in
+ // ensureAcceleratedPluginLayer for an explanation of why the superlayer
+ // isn't trustworthy.
+ if ([self superlayer])
+ [super setFrame:[[self superlayer] bounds]];
+ else
+ [super setFrame:rect];
+}
@end
// RenderWidgetHostView --------------------------------------------------------
@@ -217,9 +229,8 @@ gfx::NativeView RenderWidgetHostViewMac::GetNativeView() {
void RenderWidgetHostViewMac::MovePluginWindows(
const std::vector<webkit_glue::WebPluginGeometry>& moves) {
- // The only case we need to notice plugin window moves is the case
- // of the GPU plugin. As soon as the GPU plugin becomes the GPU
- // process all of this code will go away.
+ // Handle movement of accelerated plugins, which are the only "windowed"
+ // plugins that exist on the Mac.
if (moves.size() > 0) {
for (std::vector<webkit_glue::WebPluginGeometry>::const_iterator iter =
moves.begin();
@@ -236,9 +247,6 @@ void RenderWidgetHostViewMac::MovePluginWindows(
}
}
}
-
- // All plugin stuff is TBD. TODO(avi,awalker): fill in
- // http://crbug.com/8192
}
void RenderWidgetHostViewMac::Focus() {
@@ -516,29 +524,8 @@ void RenderWidgetHostViewMac::KillSelf() {
gfx::PluginWindowHandle
RenderWidgetHostViewMac::AllocateFakePluginWindowHandle() {
- // If we don't already have a GPUPluginLayer allocated for our view,
- // set one up now.
- if (gpu_plugin_layer_.get() == nil) {
- RenderWidgetHostViewCocoa* our_view = native_view();
- // Try to get AppKit to allocate the layer
- [our_view setWantsLayer:YES];
- CALayer* root_layer = [our_view layer];
- if (root_layer == nil) {
- root_layer = [CALayer layer];
- [our_view setLayer:root_layer];
- }
-
- GPUPluginLayer* gpu_layer =
- [[GPUPluginLayer alloc] initWithRenderWidgetHostViewMac:this];
-
- // Make our layer resize to fit the superlayer
- gpu_layer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
- // Set up its initial size
- [gpu_layer setFrame:NSRectToCGRect([our_view bounds])];
-
- [root_layer addSublayer:gpu_layer];
- gpu_plugin_layer_.reset(gpu_layer);
- }
+ // Make sure we have a layer for the plugin to draw into.
+ [cocoa_view_ ensureAcceleratedPluginLayer];
return plugin_container_manager_.AllocateFakePluginWindowHandle();
}
@@ -572,7 +559,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetTransportDIB(
void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
gfx::PluginWindowHandle window) {
- [gpu_plugin_layer_.get() setNeedsDisplay];
+ [cocoa_view_ drawAcceleratedPluginLayer];
}
void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstances(
@@ -590,6 +577,10 @@ void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstances(
plugin_container_manager_.Draw(context);
}
+void RenderWidgetHostViewMac::AcceleratedSurfaceContextChanged() {
+ plugin_container_manager_.ForceTextureReload();
+}
+
void RenderWidgetHostViewMac::SetVisuallyDeemphasized(bool deemphasized) {
// Mac uses tab-modal sheets, so this is a no-op.
}
@@ -1061,9 +1052,9 @@ bool RenderWidgetHostViewMac::ContainsNativeView(
renderWidgetHostView_->whiteout_start_time_ = base::TimeTicks::Now();
}
- // This helps keep the GPU plugins' output in better sync with the
+ // This helps keep accelerated plugins' output in better sync with the
// window as it resizes.
- [renderWidgetHostView_->gpu_plugin_layer_.get() setNeedsDisplay];
+ [accelerated_plugin_layer_.get() setNeedsDisplay];
}
- (BOOL)canBecomeKeyView {
@@ -1678,4 +1669,51 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
}
}
+- (void)ensureAcceleratedPluginLayer {
+ if (accelerated_plugin_layer_.get())
+ return;
+
+ AcceleratedPluginLayer* plugin_layer = [[AcceleratedPluginLayer alloc]
+ initWithRenderWidgetHostViewMac:renderWidgetHostView_.get()];
+ accelerated_plugin_layer_.reset(plugin_layer);
+ // Make our layer resize to fit the superlayer
+ plugin_layer.autoresizingMask = kCALayerWidthSizable |
+ kCALayerHeightSizable;
+ // Make the view layer-backed so that there will be a layer to hang the
+ // |layer| off of. This is not the "right" way to host a sublayer in a view,
+ // but the right way would require making the whole view's drawing system
+ // layer-based (using setLayer:). We don't want to do that (at least not
+ // yet) so instead we override setLayer: and re-bind our plugin layer each
+ // time the view's layer changes. For discussion see:
+ // http://lists.apple.com/archives/Cocoa-dev/2009/Feb/msg01132.html
+ [self setWantsLayer:YES];
+ [self attachPluginLayer];
+}
+
+- (void)attachPluginLayer {
+ CALayer* plugin_layer = accelerated_plugin_layer_.get();
+ if (!plugin_layer)
+ return;
+
+ CALayer* root_layer = [self layer];
+ DCHECK(root_layer != nil);
+ [plugin_layer setFrame:NSRectToCGRect([self bounds])];
+ [root_layer addSublayer:plugin_layer];
+ renderWidgetHostView_->AcceleratedSurfaceContextChanged();
+}
+
+- (void)setLayer:(CALayer *)newLayer {
+ CALayer* plugin_layer = accelerated_plugin_layer_.get();
+ if (!newLayer && [plugin_layer superlayer])
+ [plugin_layer removeFromSuperlayer];
+
+ [super setLayer:newLayer];
+ if ([self layer])
+ [self attachPluginLayer];
+}
+
+- (void)drawAcceleratedPluginLayer {
+ [accelerated_plugin_layer_.get() setNeedsDisplay];
+}
+
@end