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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 6993043: Fix the mac hangup when force-compositing-mode is enabled (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: split raf-stall fix Created 9 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <QuartzCore/QuartzCore.h> 5 #include <QuartzCore/QuartzCore.h>
6 6
7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h"
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 HandleDelayedGpuViewHiding(); 567 HandleDelayedGpuViewHiding();
568 } 568 }
569 569
570 void RenderWidgetHostViewMac::RenderViewGone(base::TerminationStatus status, 570 void RenderWidgetHostViewMac::RenderViewGone(base::TerminationStatus status,
571 int error_code) { 571 int error_code) {
572 // TODO(darin): keep this around, and draw sad-tab into it. 572 // TODO(darin): keep this around, and draw sad-tab into it.
573 Destroy(); 573 Destroy();
574 } 574 }
575 575
576 void RenderWidgetHostViewMac::Destroy() { 576 void RenderWidgetHostViewMac::Destroy() {
577 TRACE_EVENT0("browser", "RenderWidgetHostViewMac::Destroy");
577 // On Windows, popups are implemented with a popup window style, so that when 578 // On Windows, popups are implemented with a popup window style, so that when
578 // an event comes in that would "cancel" it, it receives the OnCancelMode 579 // an event comes in that would "cancel" it, it receives the OnCancelMode
579 // message and can kill itself. Alas, on the Mac, views cannot capture events 580 // message and can kill itself. Alas, on the Mac, views cannot capture events
580 // outside of themselves. On Windows, if Destroy is being called on a view, 581 // outside of themselves. On Windows, if Destroy is being called on a view,
581 // then the event causing the destroy had also cancelled any popups by the 582 // then the event causing the destroy had also cancelled any popups by the
582 // time Destroy() was called. On the Mac we have to destroy all the popups 583 // time Destroy() was called. On the Mac we have to destroy all the popups
583 // ourselves. 584 // ourselves.
584 585
585 // Depth-first destroy all popups. Use ShutdownHost() to enforce 586 // Depth-first destroy all popups. Use ShutdownHost() to enforce
586 // deepest-first ordering. 587 // deepest-first ordering.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 697
697 // |render_widget_host_| is set to NULL when |RWHVMac::Destroy()| has 698 // |render_widget_host_| is set to NULL when |RWHVMac::Destroy()| has
698 // completed. If |AllocateFakePluginWindowHandle()| is called after that, 699 // completed. If |AllocateFakePluginWindowHandle()| is called after that,
699 // we will crash when the AcceleratedPluginView we allocate below is 700 // we will crash when the AcceleratedPluginView we allocate below is
700 // destroyed. 701 // destroyed.
701 DCHECK(render_widget_host_); 702 DCHECK(render_widget_host_);
702 703
703 // Create an NSView to host the plugin's/compositor's pixels. 704 // Create an NSView to host the plugin's/compositor's pixels.
704 gfx::PluginWindowHandle handle = 705 gfx::PluginWindowHandle handle =
705 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root); 706 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root);
707 TRACE_EVENT1("browser",
708 "RenderWidgetHostViewMac::AllocateFakePluginWindowHandle",
709 "window", handle);
706 710
707 scoped_nsobject<AcceleratedPluginView> plugin_view( 711 scoped_nsobject<AcceleratedPluginView> plugin_view(
708 [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this 712 [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this
709 pluginHandle:handle]); 713 pluginHandle:handle]);
710 [plugin_view setHidden:YES]; 714 [plugin_view setHidden:YES];
711 715
712 [cocoa_view_ addSubview:plugin_view]; 716 [cocoa_view_ addSubview:plugin_view];
713 plugin_views_[handle] = plugin_view; 717 plugin_views_[handle] = plugin_view;
714 718
715 return handle; 719 return handle;
716 } 720 }
717 721
718 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle( 722 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle(
719 gfx::PluginWindowHandle window) { 723 gfx::PluginWindowHandle window) {
720 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 724 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
725 TRACE_EVENT1("browser",
726 "RenderWidgetHostViewMac::DestroyFakePluginWindowHandle",
727 "window", window);
721 PluginViewMap::iterator it = plugin_views_.find(window); 728 PluginViewMap::iterator it = plugin_views_.find(window);
722 DCHECK(plugin_views_.end() != it); 729 DCHECK(plugin_views_.end() != it);
723 if (plugin_views_.end() == it) { 730 if (plugin_views_.end() == it) {
724 return; 731 return;
725 } 732 }
726 [it->second removeFromSuperview]; 733 [it->second removeFromSuperview];
727 plugin_views_.erase(it); 734 plugin_views_.erase(it);
728 735
729 // The view's dealloc will call DeallocFakePluginWindowHandle(), which will 736 // The view's dealloc will call DeallocFakePluginWindowHandle(), which will
730 // remove the handle from |plugin_container_manager_|. This code path is 737 // remove the handle from |plugin_container_manager_|. This code path is
731 // taken if a plugin is removed, but the RWHVMac itself stays alive. 738 // taken if a plugin is removed, but the RWHVMac itself stays alive.
732 } 739 }
733 740
734 // This is called by AcceleratedPluginView's -dealloc. 741 // This is called by AcceleratedPluginView's -dealloc.
735 void RenderWidgetHostViewMac::DeallocFakePluginWindowHandle( 742 void RenderWidgetHostViewMac::DeallocFakePluginWindowHandle(
736 gfx::PluginWindowHandle window) { 743 gfx::PluginWindowHandle window) {
744 TRACE_EVENT1("browser",
745 "RenderWidgetHostViewMac::DeallocFakePluginWindowHandle",
746 "window", window);
737 // When a browser window with a GpuScheduler is closed, the render process 747 // When a browser window with a GpuScheduler is closed, the render process
738 // will attempt to finish all GL commands. It will busy-wait on the GPU 748 // will attempt to finish all GL commands. It will busy-wait on the GPU
739 // process until the command queue is empty. If a paint is pending, the GPU 749 // process until the command queue is empty. If a paint is pending, the GPU
740 // process won't process any GL commands until the browser sends a paint ack, 750 // process won't process any GL commands until the browser sends a paint ack,
741 // but since the browser window is already closed, it will never arrive. 751 // but since the browser window is already closed, it will never arrive.
742 // To resolve this we ask the GPU process to destroy the command buffer 752 // To resolve this we ask the GPU process to destroy the command buffer
743 // associated with the given render widget. Once the command buffer is 753 // associated with the given render widget. Once the command buffer is
744 // destroyed, all GL commands from the renderer will immediately receive 754 // destroyed, all GL commands from the renderer will immediately receive
745 // channel error. 755 // channel error.
746 if (render_widget_host_ && 756 if (render_widget_host_ &&
747 plugin_container_manager_.IsRootContainer(window)) { 757 plugin_container_manager_.IsRootContainer(window)) {
748 GpuProcessHost::SendOnIO( 758 GpuProcessHost::SendOnIO(
749 render_widget_host_->process()->id(), 759 render_widget_host_->process()->id(),
750 content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, 760 content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
751 new GpuMsg_DestroyCommandBuffer( 761 new GpuMsg_DestroyCommandBuffer(
752 render_widget_host_->process()->id(), 762 render_widget_host_->process()->id(),
753 render_widget_host_->routing_id())); 763 render_widget_host_->routing_id()));
754 } 764 }
755 765
756 plugin_container_manager_.DestroyFakePluginWindowHandle(window); 766 plugin_container_manager_.DestroyFakePluginWindowHandle(window);
757 } 767 }
758 768
759 AcceleratedPluginView* RenderWidgetHostViewMac::ViewForPluginWindowHandle( 769 AcceleratedPluginView* RenderWidgetHostViewMac::ViewForPluginWindowHandle(
760 gfx::PluginWindowHandle window) { 770 gfx::PluginWindowHandle window) {
761 PluginViewMap::iterator it = plugin_views_.find(window); 771 PluginViewMap::iterator it = plugin_views_.find(window);
762 DCHECK(plugin_views_.end() != it);
763 if (plugin_views_.end() == it) 772 if (plugin_views_.end() == it)
764 return nil; 773 return nil;
765 return it->second; 774 return it->second;
766 } 775 }
767 776
768 void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( 777 void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface(
769 gfx::PluginWindowHandle window, 778 gfx::PluginWindowHandle window,
770 int32 width, 779 int32 width,
771 int32 height, 780 int32 height,
772 uint64 io_surface_identifier) { 781 uint64 io_surface_identifier) {
(...skipping 30 matching lines...) Expand all
803 transport_dib); 812 transport_dib);
804 } 813 }
805 814
806 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( 815 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
807 gfx::PluginWindowHandle window, 816 gfx::PluginWindowHandle window,
808 uint64 surface_id, 817 uint64 surface_id,
809 int renderer_id, 818 int renderer_id,
810 int32 route_id, 819 int32 route_id,
811 int gpu_host_id, 820 int gpu_host_id,
812 uint64 swap_buffers_count) { 821 uint64 swap_buffers_count) {
813 TRACE_EVENT0("browser",
814 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
815 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 822 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
823 TRACE_EVENT2("browser",
824 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped",
825 "window", window,
826 "frame", swap_buffers_count);
827
816 AcceleratedPluginView* view = ViewForPluginWindowHandle(window); 828 AcceleratedPluginView* view = ViewForPluginWindowHandle(window);
817 DCHECK(view); 829 if (!view) {
818 if (!view) 830 // TODO: Fix the root cause of invalid PluginWindowHandles.
819 return; 831 LOG(ERROR) << "ViewForPluginWindowHandle returned NULL. "
832 << "Did the renderer specify an invalid PluginWindowHandle?";
833 } else {
834 plugin_container_manager_.SetSurfaceWasPaintedTo(window, surface_id);
820 835
821 plugin_container_manager_.SetSurfaceWasPaintedTo(window, surface_id); 836 // The surface is hidden until its first paint, to not show gargabe.
837 if (plugin_container_manager_.SurfaceShouldBeVisible(window))
838 [view setHidden:NO];
822 839
823 // The surface is hidden until its first paint, to not show gargabe. 840 // Present the frame.
824 if (plugin_container_manager_.SurfaceShouldBeVisible(window)) 841 [view drawView];
825 [view setHidden:NO]; 842 }
826 [view updateSwapBuffersCount:swap_buffers_count 843
827 fromRenderer:renderer_id 844 // Always acknowledge swap buffers to avoid renderer->GPU deadlocks.
828 routeId:route_id 845 if (renderer_id != 0 || route_id != 0)
829 gpuHostId:gpu_host_id]; 846 AcknowledgeSwapBuffers(renderer_id,
847 route_id,
848 gpu_host_id,
849 swap_buffers_count);
830 } 850 }
831 851
832 void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility( 852 void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility(
833 bool show_gpu_widget) { 853 bool show_gpu_widget) {
834 // Plugins are destroyed on page navigate. The compositor layer on the other 854 // Plugins are destroyed on page navigate. The compositor layer on the other
835 // hand is created on demand and then stays alive until its renderer process 855 // hand is created on demand and then stays alive until its renderer process
836 // dies (usually on cross-domain navigation). Instead, only a flag 856 // dies (usually on cross-domain navigation). Instead, only a flag
837 // |is_accelerated_compositing_active()| is flipped when the compositor output 857 // |is_accelerated_compositing_active()| is flipped when the compositor output
838 // should be shown/hidden. 858 // should be shown/hidden.
839 // Show/hide the view belonging to the compositor here. 859 // Show/hide the view belonging to the compositor here.
(...skipping 16 matching lines...) Expand all
856 UpdateRootGpuViewVisibility(false); 876 UpdateRootGpuViewVisibility(false);
857 needs_gpu_visibility_update_after_repaint_ = false; 877 needs_gpu_visibility_update_after_repaint_ = false;
858 } 878 }
859 } 879 }
860 880
861 void RenderWidgetHostViewMac::AcknowledgeSwapBuffers( 881 void RenderWidgetHostViewMac::AcknowledgeSwapBuffers(
862 int renderer_id, 882 int renderer_id,
863 int32 route_id, 883 int32 route_id,
864 int gpu_host_id, 884 int gpu_host_id,
865 uint64 swap_buffers_count) { 885 uint64 swap_buffers_count) {
866 TRACE_EVENT1("gpu", "RenderWidgetHostViewMac::AcknowledgeSwapBuffers", 886 TRACE_EVENT1("browser", "RenderWidgetHostViewMac::AcknowledgeSwapBuffers",
867 "swap_buffers_count", swap_buffers_count); 887 "frame", swap_buffers_count);
868 // Called on the display link thread. Hand actual work off to the IO thread, 888 // Called on the display link thread. Hand actual work off to the IO thread,
869 // because |GpuProcessHost::Get()| can only be called there. 889 // because |GpuProcessHost::Get()| can only be called there.
870 // Currently, this is never called for plugins. 890 // Currently, this is never called for plugins.
871 if (render_widget_host_) { 891 if (render_widget_host_) {
872 DCHECK_EQ(render_widget_host_->process()->id(), renderer_id); 892 DCHECK_EQ(render_widget_host_->process()->id(), renderer_id);
873 // |render_widget_host_->routing_id()| and |route_id| are usually not 893 // |render_widget_host_->routing_id()| and |route_id| are usually not
874 // equal: The former identifies the channel from the RWH in the browser 894 // equal: The former identifies the channel from the RWH in the browser
875 // process to the corresponding render widget in the renderer process, while 895 // process to the corresponding render widget in the renderer process, while
876 // the latter identifies the channel from the GpuCommandBufferStub in the 896 // the latter identifies the channel from the GpuCommandBufferStub in the
877 // GPU process to the corresponding command buffer client in the renderer. 897 // GPU process to the corresponding command buffer client in the renderer.
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 gfx::Rect gpuRect; 1558 gfx::Rect gpuRect;
1539 1559
1540 gfx::PluginWindowHandle root_handle = 1560 gfx::PluginWindowHandle root_handle =
1541 renderWidgetHostView_->plugin_container_manager_.root_container_handle(); 1561 renderWidgetHostView_->plugin_container_manager_.root_container_handle();
1542 if (root_handle != gfx::kNullPluginWindow) { 1562 if (root_handle != gfx::kNullPluginWindow) {
1543 AcceleratedPluginView* view = 1563 AcceleratedPluginView* view =
1544 renderWidgetHostView_->ViewForPluginWindowHandle(root_handle); 1564 renderWidgetHostView_->ViewForPluginWindowHandle(root_handle);
1545 DCHECK(view); 1565 DCHECK(view);
1546 if (view && ![view isHidden]) { 1566 if (view && ![view isHidden]) {
1547 NSRect frame = [view frame]; 1567 NSRect frame = [view frame];
1548 frame.size = [view cachedSize];
1549 gpuRect = [self flipNSRectToRect:frame]; 1568 gpuRect = [self flipNSRectToRect:frame];
1550 } 1569 }
1551 } 1570 }
1552 1571
1553 [self fillBottomRightRemainderOfRect:gpuRect dirtyRect:damagedRect]; 1572 [self fillBottomRightRemainderOfRect:gpuRect dirtyRect:damagedRect];
1554 return; 1573 return;
1555 } 1574 }
1556 1575
1557 DCHECK(!renderWidgetHostView_->about_to_validate_and_paint_); 1576 DCHECK(!renderWidgetHostView_->about_to_validate_and_paint_);
1558 1577
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after
2569 if (!string) return NO; 2588 if (!string) return NO;
2570 2589
2571 // If the user is currently using an IME, confirm the IME input, 2590 // If the user is currently using an IME, confirm the IME input,
2572 // and then insert the text from the service, the same as TextEdit and Safari. 2591 // and then insert the text from the service, the same as TextEdit and Safari.
2573 [self confirmComposition]; 2592 [self confirmComposition];
2574 [self insertText:string]; 2593 [self insertText:string];
2575 return YES; 2594 return YES;
2576 } 2595 }
2577 2596
2578 @end 2597 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698