diff options
Diffstat (limited to 'chrome')
19 files changed, 335 insertions, 44 deletions
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc index bf9c1c9..afa904c 100644 --- a/chrome/browser/gpu_process_host.cc +++ b/chrome/browser/gpu_process_host.cc @@ -308,11 +308,15 @@ class BuffersSwappedDispatcher : public Task { int32 renderer_id, int32 render_view_id, gfx::PluginWindowHandle window, - uint64 surface_id) + uint64 surface_id, + int32 route_id, + uint64 swap_buffers_count) : renderer_id_(renderer_id), render_view_id_(render_view_id), window_(window), - surface_id_(surface_id) { + surface_id_(surface_id), + route_id_(route_id), + swap_buffers_count_(swap_buffers_count) { } void Run() { @@ -323,7 +327,14 @@ class BuffersSwappedDispatcher : public Task { RenderWidgetHostView* view = host->view(); if (!view) return; - view->AcceleratedSurfaceBuffersSwapped(window_, surface_id_); + view->AcceleratedSurfaceBuffersSwapped( + // Parameters needed to swap the IOSurface. + window_, + surface_id_, + // Parameters needed to formulate an acknowledgment. + renderer_id_, + route_id_, + swap_buffers_count_); } private: @@ -331,6 +342,8 @@ class BuffersSwappedDispatcher : public Task { int32 render_view_id_; gfx::PluginWindowHandle window_; uint64 surface_id_; + int32 route_id_; + uint64 swap_buffers_count_; DISALLOW_COPY_AND_ASSIGN(BuffersSwappedDispatcher); }; @@ -338,14 +351,20 @@ class BuffersSwappedDispatcher : public Task { } // namespace void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( - int32 renderer_id, - int32 render_view_id, - gfx::PluginWindowHandle window, - uint64 surface_id) { + const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, new BuffersSwappedDispatcher( - renderer_id, render_view_id, window, surface_id)); + // These are the parameters needed to look up the IOSurface + // on this side. + params.renderer_id, + params.render_view_id, + params.window, + params.surface_id, + // These are additional parameters needed to formulate an + // acknowledgment. + params.route_id, + params.swap_buffers_count)); } #endif diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h index 69969c6..4b40a25 100644 --- a/chrome/browser/gpu_process_host.h +++ b/chrome/browser/gpu_process_host.h @@ -15,6 +15,7 @@ #include "gfx/native_widget_types.h" struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params; +struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params; class GPUInfo; class ResourceMessageFilter; @@ -90,10 +91,8 @@ class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe { #elif defined(OS_MACOSX) void OnAcceleratedSurfaceSetIOSurface( const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params); - void OnAcceleratedSurfaceBuffersSwapped(int32 renderer_id, - int32 render_view_id, - gfx::PluginWindowHandle window, - uint64 surface_id); + void OnAcceleratedSurfaceBuffersSwapped( + const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params); #endif // Sends the response for establish channel request to the renderer. 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 6b76b03..1ad09ba 100644 --- a/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc +++ b/chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc @@ -100,7 +100,7 @@ void AcceleratedSurfaceContainerManagerMac::Draw(CGLContextObj context, glColorMask(true, true, true, true); // Should match the clear color of RenderWidgetHostViewMac. - glClearColor(255, 255, 255, 255); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // TODO(thakis): Clearing the whole color buffer is wasteful, since most of // it is overwritten by the surface. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 2617cbd..4482bbd 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -1062,7 +1062,11 @@ void RenderWidgetHost::OnAcceleratedSurfaceSetTransportDIB( void RenderWidgetHost::OnAcceleratedSurfaceBuffersSwapped( gfx::PluginWindowHandle window, uint64 surface_id) { if (view_) { - view_->AcceleratedSurfaceBuffersSwapped(window, surface_id); + // This code path could be updated to implement flow control for + // updating of accelerated plugins as well. However, if we add support + // for composited plugins then this is not necessary. + view_->AcceleratedSurfaceBuffersSwapped(window, surface_id, + 0, 0, 0); } } #elif defined(OS_POSIX) diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 2c99926..4ad2c41 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -225,8 +225,18 @@ class RenderWidgetHostView { int32 width, int32 height, TransportDIB::Handle transport_dib) = 0; + // |window| and |surface_id| indicate which accelerated surface's + // buffers swapped. |renderer_id|, |route_id| and + // |swap_buffers_count| are used to formulate a reply to the GPU + // process to prevent it from getting too far ahead. They may all be + // zero, in which case no flow control is enforced; this case is + // currently used for accelerated plugins. virtual void AcceleratedSurfaceBuffersSwapped( - gfx::PluginWindowHandle window, uint64 surface_id) = 0; + gfx::PluginWindowHandle window, + uint64 surface_id, + int renderer_id, + int32 route_id, + uint64 swap_buffers_count) = 0; virtual void GpuRenderingStateDidChange() = 0; #endif 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 154c0c5..e539f14 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -243,8 +243,12 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { int32 width, int32 height, TransportDIB::Handle transport_dib); - virtual void AcceleratedSurfaceBuffersSwapped(gfx::PluginWindowHandle window, - uint64 surface_id); + virtual void AcceleratedSurfaceBuffersSwapped( + gfx::PluginWindowHandle window, + uint64 surface_id, + int32 renderer_id, + int32 route_id, + uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); void DrawAcceleratedSurfaceInstance( CGLContextObj context, @@ -273,6 +277,12 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { // should be called after the software backing store has been painted to. void HandleDelayedGpuViewHiding(); + // This is called from the display link thread, and provides the GPU + // process a notion of how quickly the browser is able to keep up with it. + void AcknowledgeSwapBuffers(int renderer_id, + int32 route_id, + uint64 swap_buffers_count); + // These member variables should be private, but the associated ObjC class // needs access to them and can't be made a friend. 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 bb4b57b..307eb2e 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -24,6 +24,7 @@ #include "chrome/browser/browser_trial.h" #import "chrome/browser/cocoa/rwhvm_editcommand_helper.h" #import "chrome/browser/cocoa/view_id_util.h" +#include "chrome/browser/gpu_process_host.h" #include "chrome/browser/plugin_process_host.h" #include "chrome/browser/renderer_host/backing_store_mac.h" #include "chrome/browser/renderer_host/render_process_host.h" @@ -33,6 +34,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/edit_command.h" +#include "chrome/common/gpu_messages.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" #include "skia/ext/platform_canvas.h" @@ -170,8 +172,21 @@ void DisablePasswordInput() { RenderWidgetHostViewMac* renderWidgetHostView_; // weak gfx::PluginWindowHandle pluginHandle_; // weak - // True if the backing IO surface was updated since we last painted. - BOOL surfaceWasSwapped_; + // The number of swap buffers calls that have been requested by the + // GPU process, or a monotonically increasing number of calls to + // updateSwapBuffersCount:fromRenderer:routeId: if the update came + // from an accelerated plugin. + uint64 swapBuffersCount_; + // The number of swap buffers calls that have been processed by the + // display link thread. This is only used with the GPU process + // update path. + volatile uint64 acknowledgedSwapBuffersCount_; + + // Auxiliary information needed to formulate an acknowledgment to + // the GPU process. These are constant after the first message. + // These are both zero for updates coming from a plugin process. + volatile int rendererId_; + volatile int32 routeId_; // Cocoa methods can only be called on the main thread, so have a copy of the // view's size, since it's required on the displaylink thread. @@ -186,6 +201,15 @@ void DisablePasswordInput() { pluginHandle:(gfx::PluginWindowHandle)pluginHandle; - (void)drawView; +// Updates the number of swap buffers calls that have been requested. +// This is currently called with non-zero values only in response to +// updates from the GPU process. For accelerated plugins, all zeros +// are passed, and the view takes this as a hint that no flow control +// or acknowledgment of the swap buffers are desired. +- (void)updateSwapBuffersCount:(uint64)count + fromRenderer:(int)rendererId + routeId:(int32)routeId; + // NSViews autorelease subviews when they die. The RWHVMac gets destroyed when // RHWVCocoa gets dealloc'd, which means the AcceleratedPluginView child views // can be around a little longer than the RWHVMac. This is called when the @@ -193,14 +217,10 @@ void DisablePasswordInput() { - (void)onRenderWidgetHostViewGone; // This _must_ be atomic, since it's accessed from several threads. -@property BOOL surfaceWasSwapped; - -// This _must_ be atomic, since it's accessed from several threads. @property NSSize cachedSize; @end @implementation AcceleratedPluginView -@synthesize surfaceWasSwapped = surfaceWasSwapped_; @synthesize cachedSize = cachedSize_; - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime { @@ -208,11 +228,22 @@ void DisablePasswordInput() { // called from a background thread. base::mac::ScopedNSAutoreleasePool pool; - if (![self surfaceWasSwapped]) + bool sendAck = (rendererId_ != 0 || routeId_ != 0); + uint64 currentSwapBuffersCount = swapBuffersCount_; + if (currentSwapBuffersCount == acknowledgedSwapBuffersCount_) { return kCVReturnSuccess; + } [self drawView]; - [self setSurfaceWasSwapped:NO]; + + acknowledgedSwapBuffersCount_ = currentSwapBuffersCount; + if (sendAck && renderWidgetHostView_) { + renderWidgetHostView_->AcknowledgeSwapBuffers( + rendererId_, + routeId_, + acknowledgedSwapBuffersCount_); + } + return kCVReturnSuccess; } @@ -235,6 +266,10 @@ static CVReturn DrawOneAcceleratedPluginCallback( renderWidgetHostView_ = r; pluginHandle_ = pluginHandle; cachedSize_ = NSZeroSize; + swapBuffersCount_ = 0; + acknowledgedSwapBuffersCount_ = 0; + rendererId_ = 0; + routeId_ = 0; [self setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin]; @@ -290,9 +325,25 @@ static CVReturn DrawOneAcceleratedPluginCallback( } CGLFlushDrawable(cglContext_); + CGLSetCurrentContext(0); CGLUnlockContext(cglContext_); } +- (void)updateSwapBuffersCount:(uint64)count + fromRenderer:(int)rendererId + routeId:(int32)routeId { + if (rendererId == 0 && routeId == 0) { + // This notification is coming from a plugin process, for which we + // don't have flow control implemented right now. Fake up a swap + // buffers count so that we can at least skip useless renders. + ++swapBuffersCount_; + } else { + rendererId_ = rendererId; + routeId_ = routeId; + swapBuffersCount_ = count; + } +} + - (void)onRenderWidgetHostViewGone { if (!renderWidgetHostView_) return; @@ -340,6 +391,7 @@ static CVReturn DrawOneAcceleratedPluginCallback( NSSize size = [self frame].size; glViewport(0, 0, size.width, size.height); + CGLSetCurrentContext(0); CGLUnlockContext(cglContext_); globalFrameDidChangeCGLLockCount_--; @@ -938,7 +990,11 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetTransportDIB( } void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( - gfx::PluginWindowHandle window, uint64 surface_id) { + gfx::PluginWindowHandle window, + uint64 surface_id, + int renderer_id, + int32 route_id, + uint64 swap_buffers_count) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); PluginViewMap::iterator it = plugin_views_.find(window); DCHECK(plugin_views_.end() != it); @@ -953,7 +1009,9 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( // The surface is hidden until its first paint, to not show gargabe. if (plugin_container_manager_.SurfaceShouldBeVisible(window)) [view setHidden:NO]; - [view setSurfaceWasSwapped:YES]; + [view updateSwapBuffersCount:swap_buffers_count + fromRenderer:renderer_id + routeId:route_id]; } void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility( @@ -988,6 +1046,43 @@ void RenderWidgetHostViewMac::HandleDelayedGpuViewHiding() { } } +namespace { +class BuffersSwappedAcknowledger : public Task { + public: + BuffersSwappedAcknowledger( + int renderer_id, + int32 route_id, + uint64 swap_buffers_count) + : renderer_id_(renderer_id), + route_id_(route_id), + swap_buffers_count_(swap_buffers_count) { + } + + void Run() { + GpuProcessHost::Get()->Send( + new GpuMsg_AcceleratedSurfaceBuffersSwappedACK( + renderer_id_, route_id_, swap_buffers_count_)); + } + + private: + int renderer_id_; + int32 route_id_; + uint64 swap_buffers_count_; + + DISALLOW_COPY_AND_ASSIGN(BuffersSwappedAcknowledger); +}; +} // anonymous namespace + +void RenderWidgetHostViewMac::AcknowledgeSwapBuffers( + int renderer_id, + int32 route_id, + uint64 swap_buffers_count) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + new BuffersSwappedAcknowledger( + renderer_id, route_id, swap_buffers_count)); +} + void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (GetRenderWidgetHost()->is_gpu_rendering_active()) { diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc index f3988e1..65d82e9 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.cc +++ b/chrome/browser/renderer_host/test/test_render_view_host.cc @@ -172,7 +172,11 @@ void TestRenderWidgetHostView::AcceleratedSurfaceSetTransportDIB( } void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped( - gfx::PluginWindowHandle window, uint64 surface_id) { + gfx::PluginWindowHandle window, + uint64 surface_id, + int renderer_id, + int32 route_id, + uint64 swap_buffers_count) { } void TestRenderWidgetHostView::GpuRenderingStateDidChange() { diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h index 4f262f4..fe6daa7 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -117,8 +117,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { int32 width, int32 height, TransportDIB::Handle transport_dib); - virtual void AcceleratedSurfaceBuffersSwapped(gfx::PluginWindowHandle window, - uint64 surface_id); + virtual void AcceleratedSurfaceBuffersSwapped( + gfx::PluginWindowHandle window, + uint64 surface_id, + int renderer_id, + int32 route_id, + uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); #endif virtual void SetVisuallyDeemphasized(bool deemphasized) { } diff --git a/chrome/common/gpu_messages.cc b/chrome/common/gpu_messages.cc index 1ba2efa..bd850a1 100644 --- a/chrome/common/gpu_messages.cc +++ b/chrome/common/gpu_messages.cc @@ -31,6 +31,15 @@ GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params:: identifier(0) { } +GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params:: + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params() + : renderer_id(0), + render_view_id(0), + window(NULL), + surface_id(0), + route_id(0), + swap_buffers_count(0) { +} #endif namespace IPC { @@ -78,6 +87,46 @@ void ParamTraits<GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params> ::Log( l->append(")"); } +void ParamTraits<GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params> ::Write( + Message* m, + const param_type& p) { + WriteParam(m, p.renderer_id); + WriteParam(m, p.render_view_id); + WriteParam(m, p.window); + WriteParam(m, p.surface_id); + WriteParam(m, p.route_id); + WriteParam(m, p.swap_buffers_count); +} + +bool ParamTraits<GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params> ::Read( + const Message* m, + void** iter, + param_type* p) { + return ReadParam(m, iter, &p->renderer_id) && + ReadParam(m, iter, &p->render_view_id) && + ReadParam(m, iter, &p->window) && + ReadParam(m, iter, &p->surface_id) && + ReadParam(m, iter, &p->route_id) && + ReadParam(m, iter, &p->swap_buffers_count); +} + +void ParamTraits<GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params> ::Log( + const param_type& p, + std::string* l) { + l->append("("); + LogParam(p.renderer_id, l); + l->append(", "); + LogParam(p.render_view_id, l); + l->append(", "); + LogParam(p.window, l); + l->append(", "); + LogParam(p.surface_id, l); + l->append(", "); + LogParam(p.route_id, l); + l->append(", "); + LogParam(p.swap_buffers_count, l); + l->append(")"); +} #endif // if defined(OS_MACOSX) void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) { diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h index 300cbef..c124530 100644 --- a/chrome/common/gpu_messages_internal.h +++ b/chrome/common/gpu_messages_internal.h @@ -51,6 +51,18 @@ IPC_BEGIN_MESSAGES(Gpu) // information. IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo) +#if defined(OS_MACOSX) + // Tells the GPU process that the browser process handled the swap + // buffers request with the given number. Note that it is possible + // for the browser process to coalesce frames; it is not guaranteed + // that every GpuHostMsg_AcceleratedSurfaceBuffersSwapped message + // will result in a buffer swap on the browser side. + IPC_MESSAGE_CONTROL3(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, + int /* renderer_id */, + int32 /* route_id */, + uint64 /* swap_buffers_count */) +#endif + // Tells the GPU process to crash. IPC_MESSAGE_CONTROL0(GpuMsg_Crash) @@ -99,11 +111,8 @@ IPC_BEGIN_MESSAGES(GpuHost) // This message notifies the browser process that the renderer // swapped the buffers associated with the given "window", which // should cause the browser to redraw the compositor's contents. - IPC_MESSAGE_CONTROL4(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, - int32, /* renderer_id */ - int32, /* render_view_id */ - gfx::PluginWindowHandle /* window */, - uint64 /* surface_id */) + IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) #endif IPC_END_MESSAGES(GpuHost) @@ -231,13 +240,6 @@ IPC_BEGIN_MESSAGES(GpuCommandBuffer) // browser. This message is currently used only on 10.6 and later. IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetWindowSize, gfx::Size /* size */) - - // This message is sent from the GPU process to the renderer process (and - // from there the browser process) that the buffers associated with the - // given "window" were swapped, which should cause the browser to redraw - // the various accelerated surfaces. - IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_AcceleratedSurfaceBuffersSwapped, - gfx::PluginWindowHandle /* window */) #endif IPC_END_MESSAGES(GpuCommandBuffer) diff --git a/chrome/common/gpu_param_traits.h b/chrome/common/gpu_param_traits.h index 2aac31a..3ebaca0 100644 --- a/chrome/common/gpu_param_traits.h +++ b/chrome/common/gpu_param_traits.h @@ -31,6 +31,17 @@ struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params { GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params(); }; + +struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params { + int32 renderer_id; + int32 render_view_id; + gfx::PluginWindowHandle window; + uint64 surface_id; + int32 route_id; + uint64 swap_buffers_count; + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params(); +}; #endif namespace IPC { @@ -42,6 +53,14 @@ struct ParamTraits<GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params> { static bool Read(const Message* m, void** iter, param_type* p); static void Log(const param_type& p, std::string* l); }; + +template <> +struct ParamTraits<GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params> { + typedef GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params param_type; + static void Write(Message* m, const param_type& p); + static bool Read(const Message* m, void** iter, param_type* p); + static void Log(const param_type& p, std::string* l); +}; #endif template <> diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc index 35b530e..7cd06d2 100644 --- a/chrome/gpu/gpu_channel.cc +++ b/chrome/gpu/gpu_channel.cc @@ -83,6 +83,16 @@ bool GpuChannel::Send(IPC::Message* message) { return channel_->Send(message); } +#if defined(OS_MACOSX) +void GpuChannel::AcceleratedSurfaceBuffersSwapped( + int32 route_id, uint64 swap_buffers_count) { + GpuCommandBufferStub* stub = stubs_.Lookup(route_id); + if (stub == NULL) + return; + stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); +} +#endif + void GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateViewCommandBuffer, diff --git a/chrome/gpu/gpu_channel.h b/chrome/gpu/gpu_channel.h index f359777..3d64355 100644 --- a/chrome/gpu/gpu_channel.h +++ b/chrome/gpu/gpu_channel.h @@ -60,6 +60,11 @@ class GpuChannel : public IPC::Channel::Listener, // IPC::Message::Sender implementation: virtual bool Send(IPC::Message* msg); +#if defined(OS_MACOSX) + virtual void AcceleratedSurfaceBuffersSwapped( + int32 route_id, uint64 swap_buffers_count); +#endif + private: void OnControlMessageReceived(const IPC::Message& msg); diff --git a/chrome/gpu/gpu_command_buffer_stub.cc b/chrome/gpu/gpu_command_buffer_stub.cc index 1adb22c..1872246 100644 --- a/chrome/gpu/gpu_command_buffer_stub.cc +++ b/chrome/gpu/gpu_command_buffer_stub.cc @@ -205,9 +205,25 @@ void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) { } void GpuCommandBufferStub::SwapBuffersCallback() { + OnSwapBuffers(); ChildThread* gpu_thread = ChildThread::current(); - gpu_thread->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped( - renderer_id_, render_view_id_, handle_, processor_->GetSurfaceId())); + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.window = handle_; + params.surface_id = processor_->GetSurfaceId(); + params.route_id = route_id(); +#if defined(OS_MACOSX) + params.swap_buffers_count = processor_->swap_buffers_count(); +#endif + gpu_thread->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); +} + +void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( + uint64 swap_buffers_count) { + processor_->set_acknowledged_swap_buffers_count(swap_buffers_count); + // Wake up the GpuProcessor to start doing work again. + processor_->ScheduleProcessCommands(); } #endif // defined(OS_MACOSX) diff --git a/chrome/gpu/gpu_command_buffer_stub.h b/chrome/gpu/gpu_command_buffer_stub.h index 1a1e9be..ef57715 100644 --- a/chrome/gpu/gpu_command_buffer_stub.h +++ b/chrome/gpu/gpu_command_buffer_stub.h @@ -51,6 +51,11 @@ class GpuCommandBufferStub int32 route_id() const { return route_id_; } +#if defined(OS_MACOSX) + // Called only by the GpuChannel. + void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count); +#endif + private: // Message handlers: void OnInitialize(int32 size, base::SharedMemoryHandle* ring_buffer); diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc index dc12737..d81a09a 100644 --- a/chrome/gpu/gpu_thread.cc +++ b/chrome/gpu/gpu_thread.cc @@ -61,6 +61,10 @@ void GpuThread::OnControlMessageReceived(const IPC::Message& msg) { OnSynchronize) IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo) +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, + OnAcceleratedSurfaceBuffersSwappedACK) +#endif IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash) IPC_MESSAGE_HANDLER(GpuMsg_Hang, @@ -107,6 +111,17 @@ void GpuThread::OnCollectGraphicsInfo() { Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_)); } +#if defined(OS_MACOSX) +void GpuThread::OnAcceleratedSurfaceBuffersSwappedACK( + int renderer_id, int32 route_id, uint64 swap_buffers_count) { + GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); + if (iter == gpu_channels_.end()) + return; + scoped_refptr<GpuChannel> channel = iter->second; + channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count); +} +#endif + void GpuThread::OnCrash() { // Good bye, cruel world. volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL; diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h index 275fa12..26b7966 100644 --- a/chrome/gpu/gpu_thread.h +++ b/chrome/gpu/gpu_thread.h @@ -35,6 +35,10 @@ class GpuThread : public ChildThread { void OnEstablishChannel(int renderer_id); void OnSynchronize(); void OnCollectGraphicsInfo(); +#if defined(OS_MACOSX) + void OnAcceleratedSurfaceBuffersSwappedACK( + int renderer_id, int32 route_id, uint64 swap_buffers_count); +#endif void OnCrash(); void OnHang(); diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc index b983514..6cd9a33 100644 --- a/chrome/renderer/ggl/ggl.cc +++ b/chrome/renderer/ggl/ggl.cc @@ -34,6 +34,12 @@ const int32 kCommandBufferSize = 1024 * 1024; // creation attributes. const int32 kTransferBufferSize = 1024 * 1024; +// TODO(kbr) / TODO(apatrick): determine the best number of pending frames +// in the general case. On Mac OS X it seems we really want this to be 1, +// because otherwise the renderer process produces frames that do not +// actually reach the screen. +const int kMaxFramesPending = 1; + // Singleton used to initialize and terminate the gles2 library. class GLES2Initializer { public: @@ -132,6 +138,8 @@ class Context : public base::SupportsWeakPtr<Context> { gpu::gles2::GLES2Implementation* gles2_implementation_; gfx::Size size_; + int32 swap_buffer_tokens_[kMaxFramesPending]; + Error last_error_; DISALLOW_COPY_AND_ASSIGN(Context); @@ -147,6 +155,8 @@ Context::Context(GpuChannelHost* channel, Context* parent) gles2_implementation_(NULL), last_error_(SUCCESS) { DCHECK(channel); + for (int i = 0; i < kMaxFramesPending; ++i) + swap_buffer_tokens_[i] = -1; } Context::~Context() { @@ -376,7 +386,18 @@ bool Context::SwapBuffers() { if (command_buffer_->GetLastState().error != gpu::error::kNoError) return false; + // Throttle until there are not too many frames pending. + if (swap_buffer_tokens_[0] != -1) { + gles2_helper_->WaitForToken(swap_buffer_tokens_[0]); + } + gles2_implementation_->SwapBuffers(); + + // Insert a new token to throttle against for this frame. + for (int i = 0; i < kMaxFramesPending - 1; ++i) + swap_buffer_tokens_[i] = swap_buffer_tokens_[i + 1]; + swap_buffer_tokens_[kMaxFramesPending - 1] = gles2_helper_->InsertToken(); + return true; } |