diff options
author | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-13 08:59:30 +0000 |
---|---|---|
committer | ccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-13 08:59:30 +0000 |
commit | d0c709d668f0a935f933c3a11fc55041261e443b (patch) | |
tree | 6d16f7c51d42da4bae6999f2a2c2722263e75a30 /content | |
parent | 77d83548dd628eb33a86ba4057399d75e8aa2266 (diff) | |
download | chromium_src-d0c709d668f0a935f933c3a11fc55041261e443b.zip chromium_src-d0c709d668f0a935f933c3a11fc55041261e443b.tar.gz chromium_src-d0c709d668f0a935f933c3a11fc55041261e443b.tar.bz2 |
Work before enabling software compositing on Mac
Implement RenderWidgetHostViewMac::CopyFromCompositingSurface for the
software compositing path and disable copying to video frames and frame
subscription (this path needs to be functional, but not particularly
performant).
Fix a bug where RenderWidgetHostViewMac::SoftwareFrameWasFreed would
reach in to a destroyed RenderWidgetHostImpl.
Fix a bug where RenderWidgetHostViewMac::software_latency_info_ was
not updated in RenderWidgetHostViewMac::OnSwapCompositorFrame.
Fix a bug where the ack for a software frame is sent immediately, instead
of when the frame is actually drawn.
BUG=286038
R=hclam@chromium.org
Review URL: https://codereview.chromium.org/113603002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240558 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
5 files changed, 106 insertions, 26 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc index c6cb8d6..60172d3 100644 --- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc @@ -648,6 +648,20 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture return; RenderWidgetHostViewPort* rwhvp = GetRenderWidgetHostViewPort(); + if (video_frame && !rwhvp->CanCopyToVideoFrame()) { + // This should only happen on Mac when using the software compositor. + // Otherwise, raise an error. This can be removed when Mac is moved to a + // browser compositor. + // http://crbug.com/314190 +#if defined(OS_MACOSX) + if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) { + LOG(WARNING) << ("Blindly passing this test because copying to " + "video frames is not supported on this platform."); + return; + } +#endif + NOTREACHED(); + } // The page is loaded in the renderer, wait for a new frame to arrive. uint32 frame = rwhvp->RendererFrameNumber(); diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 00c4282..b6825b0 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -435,6 +435,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, // This holds the current software compositing framebuffer, if any. scoped_ptr<SoftwareFrameManager> software_frame_manager_; + // This is set when a new software frame is received and un-set when the + // frame's ack is sent back to the renderer. + bool software_frame_needs_to_send_ack_; + // Whether to allow overlapping views. bool allow_overlapping_views_; 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 9b5de7f..9e1c6fd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -412,6 +412,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) last_frame_was_accelerated_(false), text_input_type_(ui::TEXT_INPUT_TYPE_NONE), can_compose_inline_(true), + software_frame_needs_to_send_ack_(false), allow_overlapping_views_(false), use_core_animation_(false), is_loading_(false), @@ -845,6 +846,7 @@ bool RenderWidgetHostViewMac::HasFocus() const { bool RenderWidgetHostViewMac::IsSurfaceAvailableForCopy() const { return !!render_widget_host_->GetBackingStore(false) || + software_frame_manager_->HasCurrentFrame() || (compositing_iosurface_ && compositing_iosurface_->HasIOSurface()); } @@ -1144,19 +1146,51 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface( const base::Callback<void(bool, const SkBitmap&)>& callback) { base::ScopedClosureRunner scoped_callback_runner( base::Bind(callback, false, SkBitmap())); - if (!compositing_iosurface_ || - !compositing_iosurface_->HasIOSurface()) - return; - float scale = ScaleFactor(cocoa_view_); gfx::Size dst_pixel_size = gfx::ToFlooredSize( gfx::ScaleSize(dst_size, scale)); + if (compositing_iosurface_ && compositing_iosurface_->HasIOSurface()) { + ignore_result(scoped_callback_runner.Release()); + compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect), + dst_pixel_size, + callback); + } else if (software_frame_manager_->HasCurrentFrame()) { + gfx::Rect src_pixel_rect = gfx::ToEnclosingRect(gfx::ScaleRect( + src_subrect, + software_frame_manager_->GetCurrentFrameDeviceScaleFactor())); + SkBitmap source_bitmap; + source_bitmap.setConfig( + SkBitmap::kARGB_8888_Config, + software_frame_manager_->GetCurrentFrameSizeInPixels().width(), + software_frame_manager_->GetCurrentFrameSizeInPixels().height(), + 0, + kOpaque_SkAlphaType); + source_bitmap.setPixels(software_frame_manager_->GetCurrentFramePixels()); + + SkBitmap target_bitmap; + target_bitmap.setConfig( + SkBitmap::kARGB_8888_Config, + dst_pixel_size.width(), + dst_pixel_size.height(), + 0, + kOpaque_SkAlphaType); + if (!target_bitmap.allocPixels()) + return; - ignore_result(scoped_callback_runner.Release()); + SkCanvas target_canvas(target_bitmap); + SkRect src_pixel_skrect = SkRect::MakeXYWH( + src_pixel_rect.x(), src_pixel_rect.y(), + src_pixel_rect.width(), src_pixel_rect.height()); + target_canvas.drawBitmapRectToRect( + source_bitmap, + &src_pixel_skrect, + SkRect::MakeXYWH(0, 0, dst_pixel_size.width(), dst_pixel_size.height()), + NULL, + SkCanvas::kNone_DrawBitmapRectFlag); - compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect), - dst_pixel_size, - callback); + ignore_result(scoped_callback_runner.Release()); + callback.Run(true, target_bitmap); + } } void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame( @@ -1192,13 +1226,14 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame( bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const { return (!render_widget_host_->GetBackingStore(false) && + !software_frame_manager_->HasCurrentFrame() && render_widget_host_->is_accelerated_compositing_active() && compositing_iosurface_ && compositing_iosurface_->HasIOSurface()); } bool RenderWidgetHostViewMac::CanSubscribeFrame() const { - return true; + return !software_frame_manager_->HasCurrentFrame(); } void RenderWidgetHostViewMac::BeginFrameSubscription( @@ -1729,7 +1764,10 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame( return; } - GotSoftwareFrame(); + // Ack any swaps that didn't make it to the display. + if (software_frame_needs_to_send_ack_) + FrameSwapped(); + if (!software_frame_manager_->SwapToNewFrame( output_surface_id, frame->software_frame_data.get(), @@ -1738,15 +1776,10 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame( render_widget_host_->GetProcess()->ReceivedBadMessage(); return; } - software_frame_manager_->SwapToNewFrameComplete( - !render_widget_host_->is_hidden()); - cc::CompositorFrameAck ack; - RenderWidgetHostImpl::SendSwapCompositorFrameAck( - render_widget_host_->GetRoutingID(), - output_surface_id, - render_widget_host_->GetProcess()->GetID(), - ack); + GotSoftwareFrame(); + software_latency_info_.MergeWith(frame->metadata.latency_info); + software_frame_needs_to_send_ack_ = true; [cocoa_view_ setNeedsDisplay:YES]; } @@ -1837,6 +1870,8 @@ bool RenderWidgetHostViewMac::Send(IPC::Message* message) { void RenderWidgetHostViewMac::SoftwareFrameWasFreed( uint32 output_surface_id, unsigned frame_id) { + if (!render_widget_host_) + return; cc::CompositorFrameAck ack; ack.last_software_frame_id = frame_id; RenderWidgetHostImpl::SendReclaimCompositorResources( @@ -2002,6 +2037,20 @@ gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect( } void RenderWidgetHostViewMac::FrameSwapped() { + if (software_frame_needs_to_send_ack_ && + software_frame_manager_->HasCurrentFrame()) { + software_frame_manager_->SwapToNewFrameComplete( + !render_widget_host_->is_hidden()); + + cc::CompositorFrameAck ack; + RenderWidgetHostImpl::SendSwapCompositorFrameAck( + render_widget_host_->GetRoutingID(), + software_frame_manager_->GetCurrentFrameOutputSurfaceId(), + render_widget_host_->GetProcess()->GetID(), + ack); + software_frame_needs_to_send_ack_ = false; + } + software_latency_info_.AddLatencyNumber( ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0); render_widget_host_->FrameSwapped(software_latency_info_); diff --git a/content/browser/renderer_host/software_frame_manager.cc b/content/browser/renderer_host/software_frame_manager.cc index f9cc1d8..147c21e 100644 --- a/content/browser/renderer_host/software_frame_manager.cc +++ b/content/browser/renderer_host/software_frame_manager.cc @@ -32,7 +32,7 @@ class CONTENT_EXPORT SoftwareFrame : public base::RefCounted<SoftwareFrame> { base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client, uint32 output_surface_id, unsigned frame_id, - gfx::Size frame_size_dip, + float frame_device_scale_factor, gfx::Size frame_size_pixels, scoped_ptr<base::SharedMemory> shared_memory); ~SoftwareFrame(); @@ -40,7 +40,7 @@ class CONTENT_EXPORT SoftwareFrame : public base::RefCounted<SoftwareFrame> { base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client_; const uint32 output_surface_id_; const unsigned frame_id_; - const gfx::Size frame_size_dip_; + float frame_device_scale_factor_; const gfx::Size frame_size_pixels_; scoped_ptr<base::SharedMemory> shared_memory_; @@ -51,13 +51,13 @@ SoftwareFrame::SoftwareFrame( base::WeakPtr<SoftwareFrameManagerClient> frame_manager_client, uint32 output_surface_id, unsigned frame_id, - gfx::Size frame_size_dip, + float frame_device_scale_factor, gfx::Size frame_size_pixels, scoped_ptr<base::SharedMemory> shared_memory) : frame_manager_client_(frame_manager_client), output_surface_id_(output_surface_id), frame_id_(frame_id), - frame_size_dip_(frame_size_dip), + frame_device_scale_factor_(frame_device_scale_factor), frame_size_pixels_(frame_size_pixels), shared_memory_(shared_memory.Pass()) {} @@ -125,7 +125,7 @@ bool SoftwareFrameManager::SwapToNewFrame( client_, output_surface_id, frame_data->id, - ConvertSizeToDIP(frame_device_scale_factor, frame_data->size), + frame_device_scale_factor, frame_data->size, shared_memory.Pass())); current_frame_.swap(next_frame); @@ -154,6 +154,11 @@ void SoftwareFrameManager::SetVisibility(bool visible) { } } +uint32 SoftwareFrameManager::GetCurrentFrameOutputSurfaceId() const { + DCHECK(HasCurrentFrame()); + return current_frame_->output_surface_id_; +} + void SoftwareFrameManager::GetCurrentFrameMailbox( cc::TextureMailbox* mailbox, scoped_ptr<cc::SingleReleaseCallback>* callback) { @@ -164,13 +169,18 @@ void SoftwareFrameManager::GetCurrentFrameMailbox( base::Bind(ReleaseMailbox, current_frame_)); } -const void* SoftwareFrameManager::GetCurrentFramePixels() const { +void* SoftwareFrameManager::GetCurrentFramePixels() const { DCHECK(HasCurrentFrame()); DCHECK(base::SharedMemory::IsHandleValid( current_frame_->shared_memory_->handle())); return current_frame_->shared_memory_->memory(); } +float SoftwareFrameManager::GetCurrentFrameDeviceScaleFactor() const { + DCHECK(HasCurrentFrame()); + return current_frame_->frame_device_scale_factor_; +} + gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const { DCHECK(HasCurrentFrame()); return current_frame_->frame_size_pixels_; @@ -178,7 +188,8 @@ gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInPixels() const { gfx::Size SoftwareFrameManager::GetCurrentFrameSizeInDIP() const { DCHECK(HasCurrentFrame()); - return current_frame_->frame_size_dip_; + return ConvertSizeToDIP(current_frame_->frame_device_scale_factor_, + current_frame_->frame_size_pixels_); } void SoftwareFrameManager::EvictCurrentFrame() { diff --git a/content/browser/renderer_host/software_frame_manager.h b/content/browser/renderer_host/software_frame_manager.h index 503a40d..6d19afd 100644 --- a/content/browser/renderer_host/software_frame_manager.h +++ b/content/browser/renderer_host/software_frame_manager.h @@ -52,10 +52,12 @@ class CONTENT_EXPORT SoftwareFrameManager : public RendererFrameManagerClient { void SetVisibility(bool visible); bool HasCurrentFrame() const; void DiscardCurrentFrame(); + uint32 GetCurrentFrameOutputSurfaceId() const; void GetCurrentFrameMailbox( cc::TextureMailbox* mailbox, scoped_ptr<cc::SingleReleaseCallback>* callback); - const void* GetCurrentFramePixels() const; + void* GetCurrentFramePixels() const; + float GetCurrentFrameDeviceScaleFactor() const; gfx::Size GetCurrentFrameSizeInPixels() const; gfx::Size GetCurrentFrameSizeInDIP() const; |