Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(507)

Unified Diff: content/browser/renderer_host/render_widget_host_view_mac.mm

Issue 267073003: Make --enable-delegated-renderer show stuff on Mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix null checks" Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/render_widget_host_view_mac.mm
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 1ffe041c9d6fa4a33f2d6b43dd7675dafa31b465..03cfd9acb21a8e704d359575b5bb3943569bd50b 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -27,12 +27,16 @@
#include "base/sys_info.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
+#include "content/browser/compositor/resize_lock.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
#include "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
#include "content/browser/renderer_host/compositing_iosurface_mac.h"
+#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
@@ -61,6 +65,8 @@
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/base/layout.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/display.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect_conversions.h"
@@ -108,6 +114,18 @@ static NSString* const NSWindowDidChangeBackingPropertiesNotification =
#endif // 10.7
+// Declare methods used to present swaps to this view.
+@interface NSView (ContentCompositingView)
+- (void)onNativeSurfaceBuffersSwappedWithParams:
+ (GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)params;
+@end
+
+@implementation NSView (ContentCompositingView)
+- (void)onNativeSurfaceBuffersSwappedWithParams:
+ (GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)params {
+}
+@end
+
// This method will return YES for OS X versions 10.7.3 and later, and NO
// otherwise.
// Used to prevent a crash when building with the 10.7 SDK and accessing the
@@ -250,6 +268,17 @@ static float ScaleFactorForView(NSView* view) {
namespace {
+// Class used to manage the lifetime of the UI compositor.
+class CompositorInitializer {
+ public:
+ CompositorInitializer() {
+ ui::Compositor::Initialize();
+ }
+ ~CompositorInitializer() {
+ ui::Compositor::Terminate();
+ }
+};
+
// Maximum number of characters we allow in a tooltip.
const size_t kMaxTooltipLength = 1024;
@@ -393,6 +422,93 @@ void RemoveLayerFromSuperlayer(
namespace content {
///////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHelper, public:
+
+void RenderWidgetHelper::OnNativeSurfaceBuffersSwapped(
piman 2014/05/06 00:59:01 nit: move to render_widget_helper.cc
ccameron 2014/05/06 17:15:56 This need to (at some point), bottom out in Object
piman 2014/05/06 19:58:09 I guess render_widget_helper_mac.mm is probably th
ccameron 2014/05/06 20:39:00 Done.
+ const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
+ if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ // Immediately acknowledge this frame on the IO thread instead of the UI
+ // thread. The UI thread will wait on the GPU process. If the UI thread
+ // were to be responsible for acking swaps, then there would be a cycle
+ // and a potential deadlock.
+ // TODO(ccameron): This immediate ack circumvents GPU back-pressure that
+ // is necessary to throttle renderers. Fix that.
+ // TODO(ccameron): It is possible that the IOSurface will be deleted or
+ // reused soon as it is acked. Take out a reference to the IOSurface here,
+ // to ensure the IOSurface does not disappear before routing to the UI
+ // thread.
+ GpuProcessHost* gpu_process_host = GpuProcessHost::Get(
+ GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH);
piman 2014/05/06 00:59:01 This is coming from GpuProcessHost::OnAccelerated
ccameron 2014/05/06 17:15:56 Good idea. Done.
+ if (gpu_process_host) {
+ AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
+ ack_params.sync_point = 0;
+ ack_params.renderer_id = 0;
+ gpu_process_host->Send(new AcceleratedSurfaceMsg_BufferPresented(
+ params.route_id, ack_params));
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&OnNativeSurfaceBuffersSwapped, params));
+ return;
+ }
+
+ gfx::AcceleratedWidget native_widget =
+ GpuSurfaceTracker::Get()->AcquireNativeWidget(params.surface_id);
piman 2014/05/06 00:59:01 Because of races, this could be kNullAcceleratedWi
ccameron 2014/05/06 17:15:56 Calling a method on a NULL object in Objective C i
piman 2014/05/06 19:58:09 Ok, thanks.
+ [native_widget onNativeSurfaceBuffersSwappedWithParams:params];
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DelegatedFrameHost, public:
+
+ui::Compositor* RenderWidgetHostViewMac::GetCompositor() const {
+ return compositor_.get();
+}
+
+ui::Layer* RenderWidgetHostViewMac::GetLayer() {
+ return root_layer_.get();
+}
+
+RenderWidgetHostImpl* RenderWidgetHostViewMac::GetHost() {
+ return render_widget_host_;
+}
+
+void RenderWidgetHostViewMac::SchedulePaintInRect(
+ const gfx::Rect& damage_rect_in_dip) {
+ compositor_->ScheduleFullRedraw();
+}
+
+bool RenderWidgetHostViewMac::IsVisible() {
+ return !render_widget_host_->is_hidden();
+}
+
+gfx::Size RenderWidgetHostViewMac::DesiredFrameSize() {
+ return GetViewBounds().size();
+}
+
+float RenderWidgetHostViewMac::CurrentDeviceScaleFactor() {
+ return ViewScaleFactor();
+}
+
+gfx::Size RenderWidgetHostViewMac::ConvertViewSizeToPixel(
+ const gfx::Size& size) {
+ return gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(size),
+ ViewScaleFactor())).size();
+}
+
+scoped_ptr<ResizeLock> RenderWidgetHostViewMac::CreateResizeLock(
+ bool defer_compositor_lock) {
+ NOTREACHED();
+ ResizeLock* lock = NULL;
+ return scoped_ptr<ResizeLock>(lock);
+}
+
+DelegatedFrameHost* RenderWidgetHostViewMac::GetDelegatedFrameHost() const {
+ return delegated_frame_host_.get();
+}
+
+///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewBase, public:
// static
@@ -448,6 +564,11 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
// pointer.
cocoa_view_ = nil;
+ // Delete the delegated frame state.
+ delegated_frame_host_.reset();
+ compositor_.reset();
+ root_layer_.reset();
+
UnlockMouse();
// Make sure that the layer doesn't reach into the now-invalid object.
@@ -795,6 +916,8 @@ void RenderWidgetHostViewMac::WasShown() {
web_contents_switch_paint_time_ = base::TimeTicks::Now();
render_widget_host_->WasShown();
software_frame_manager_->SetVisibility(true);
+ if (delegated_frame_host_)
+ delegated_frame_host_->WasShown();
// Call setNeedsDisplay before pausing for new frames to come in -- if any
// do, and are drawn, then the needsDisplay bit will be cleared.
@@ -819,6 +942,8 @@ void RenderWidgetHostViewMac::WasHidden() {
// reduce its resource utilization.
render_widget_host_->WasHidden();
software_frame_manager_->SetVisibility(false);
+ if (delegated_frame_host_)
+ delegated_frame_host_->WasHidden();
// There can be a transparent flash as this view is removed and the next is
// added, because of OSX windowing races between displaying the contents of
@@ -920,6 +1045,9 @@ bool RenderWidgetHostViewMac::HasFocus() const {
}
bool RenderWidgetHostViewMac::IsSurfaceAvailableForCopy() const {
+ if (delegated_frame_host_)
+ return delegated_frame_host_->CanCopyToBitmap();
+
return software_frame_manager_->HasCurrentFrame() ||
(compositing_iosurface_ && compositing_iosurface_->HasIOSurface());
}
@@ -1160,6 +1288,12 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
const SkBitmap::Config config) {
+ if (delegated_frame_host_) {
+ delegated_frame_host_->CopyFromCompositingSurface(
+ src_subrect, dst_size, callback, config);
+ return;
+ }
+
if (config != SkBitmap::kARGB_8888_Config) {
NOTIMPLEMENTED();
callback.Run(false, SkBitmap());
@@ -1217,6 +1351,12 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
const base::Callback<void(bool)>& callback) {
+ if (delegated_frame_host_) {
+ delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
+ src_subrect, target, callback);
+ return;
+ }
+
base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
if (!render_widget_host_->is_accelerated_compositing_active() ||
!compositing_iosurface_ ||
@@ -1245,6 +1385,9 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
}
bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const {
+ if (delegated_frame_host_)
+ return delegated_frame_host_->CanCopyToVideoFrame();
+
return (!software_frame_manager_->HasCurrentFrame() &&
render_widget_host_->is_accelerated_compositing_active() &&
compositing_iosurface_ &&
@@ -1252,15 +1395,27 @@ bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const {
}
bool RenderWidgetHostViewMac::CanSubscribeFrame() const {
+ if (delegated_frame_host_)
+ return delegated_frame_host_->CanSubscribeFrame();
+
return !software_frame_manager_->HasCurrentFrame();
}
void RenderWidgetHostViewMac::BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
+ if (delegated_frame_host_) {
+ delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
+ return;
+ }
frame_subscriber_ = subscriber.Pass();
}
void RenderWidgetHostViewMac::EndFrameSubscription() {
+ if (delegated_frame_host_) {
+ delegated_frame_host_->EndFrameSubscription();
+ return;
+ }
+
frame_subscriber_.reset();
}
@@ -1778,43 +1933,68 @@ bool RenderWidgetHostViewMac::HasAcceleratedSurface(
void RenderWidgetHostViewMac::OnSwapCompositorFrame(
uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
- // Only software compositor frames are accepted.
- if (!frame->software_frame_data) {
+ if (frame->delegated_frame_data) {
+ // Initialize the global UI compositor once.
+ static base::LazyInstance<CompositorInitializer>
+ compositor_initializer_;
piman 2014/05/06 00:59:01 Can we move this to BrowserMainLoop? That is where
ccameron 2014/05/06 17:15:56 Done.
+ ignore_result(compositor_initializer_.Get());
+
+ if (!compositor_) {
+ compositor_.reset(new ui::Compositor(cocoa_view_));
+ root_layer_.reset(new ui::Layer(ui::LAYER_TEXTURED));
+ delegated_frame_host_.reset(new DelegatedFrameHost(this));
+ }
+
+ delegated_frame_host_->SwapDelegatedFrame(
+ output_surface_id,
+ frame->delegated_frame_data.Pass(),
+ frame->metadata.device_scale_factor,
+ frame->metadata.latency_info);
+
+ gfx::Size size = ToCeiledSize(frame->metadata.viewport_size);
+ float scale_factor = frame->metadata.page_scale_factor;
+ if (compositor_->size() != size ||
+ compositor_->device_scale_factor() != scale_factor) {
+ compositor_->SetScaleAndSize(scale_factor, size);
+ root_layer_->SetBounds(gfx::Rect(0, 0, size.width(), size.height()));
piman 2014/05/06 00:59:01 I think both of these should be done when the RWHV
ccameron 2014/05/06 17:15:56 I've found it best to resize everything to match t
piman 2014/05/06 19:58:09 What about the non-CA path? I guess what you sugg
ccameron 2014/05/06 20:39:00 non-CA path will be deleted soon (grin).
+ }
+ if (compositor_->root_layer() != root_layer_)
+ compositor_->SetRootLayer(root_layer_.get());
+ } else if (frame->software_frame_data) {
+ if (!software_frame_manager_->SwapToNewFrame(
+ output_surface_id,
+ frame->software_frame_data.get(),
+ frame->metadata.device_scale_factor,
+ render_widget_host_->GetProcess()->GetHandle())) {
+ render_widget_host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+
+ // Add latency info to report when the frame finishes drawing.
+ AddPendingLatencyInfo(frame->metadata.latency_info);
piman 2014/05/06 00:59:01 you'll want to do this in either case.
ccameron 2014/05/06 17:15:56 The DelegatedFrameHost tracks the latency_info for
piman 2014/05/06 19:58:09 Ok.
+ GotSoftwareFrame();
+
+ cc::CompositorFrameAck ack;
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ render_widget_host_->GetRoutingID(),
+ software_frame_manager_->GetCurrentFrameOutputSurfaceId(),
+ render_widget_host_->GetProcess()->GetID(),
+ ack);
+ software_frame_manager_->SwapToNewFrameComplete(
+ !render_widget_host_->is_hidden());
+
+ // Notify observers, tab capture observers in particular, that a new
+ // software frame has come in.
+ NotificationService::current()->Notify(
+ NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
+ Source<RenderWidgetHost>(render_widget_host_),
+ NotificationService::NoDetails());
+ } else {
DLOG(ERROR) << "Received unexpected frame type.";
RecordAction(
base::UserMetricsAction("BadMessageTerminate_UnexpectedFrameType"));
render_widget_host_->GetProcess()->ReceivedBadMessage();
- return;
- }
-
- if (!software_frame_manager_->SwapToNewFrame(
- output_surface_id,
- frame->software_frame_data.get(),
- frame->metadata.device_scale_factor,
- render_widget_host_->GetProcess()->GetHandle())) {
- render_widget_host_->GetProcess()->ReceivedBadMessage();
- return;
}
-
- // Add latency info to report when the frame finishes drawing.
- AddPendingLatencyInfo(frame->metadata.latency_info);
- GotSoftwareFrame();
-
- cc::CompositorFrameAck ack;
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- render_widget_host_->GetRoutingID(),
- software_frame_manager_->GetCurrentFrameOutputSurfaceId(),
- render_widget_host_->GetProcess()->GetID(),
- ack);
- software_frame_manager_->SwapToNewFrameComplete(
- !render_widget_host_->is_hidden());
-
- // Notify observers, tab capture observers in particular, that a new software
- // frame has come in.
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
- Source<RenderWidgetHost>(render_widget_host_),
- NotificationService::NoDetails());
}
void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() {
@@ -3114,6 +3294,8 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
renderWidgetHostView_->render_widget_host_->SendScreenRects();
renderWidgetHostView_->render_widget_host_->WasResized();
+ if (renderWidgetHostView_->delegated_frame_host_)
+ renderWidgetHostView_->delegated_frame_host_->WasResized();
// Wait for the frame that WasResize might have requested. If the view is
// being made visible at a new size, then this call will have no effect
@@ -3173,6 +3355,16 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
}
}
+- (void)onNativeSurfaceBuffersSwappedWithParams:
+ (GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)params {
+
+ renderWidgetHostView_->CompositorSwapBuffers(
+ params.surface_handle,
+ params.size,
+ params.scale_factor,
+ params.latency_info);
+}
+
- (void)drawRect:(NSRect)dirtyRect {
TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect");
DCHECK(!renderWidgetHostView_->use_core_animation_);

Powered by Google App Engine
This is Rietveld 408576698