summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gpu_process_host.cc35
-rw-r--r--chrome/browser/gpu_process_host.h7
-rw-r--r--chrome/browser/renderer_host/accelerated_surface_container_manager_mac.cc2
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h12
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h14
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm115
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc6
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h8
-rw-r--r--chrome/common/gpu_messages.cc49
-rw-r--r--chrome/common/gpu_messages_internal.h26
-rw-r--r--chrome/common/gpu_param_traits.h19
-rw-r--r--chrome/gpu/gpu_channel.cc10
-rw-r--r--chrome/gpu/gpu_channel.h5
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.cc20
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.h5
-rw-r--r--chrome/gpu/gpu_thread.cc15
-rw-r--r--chrome/gpu/gpu_thread.h4
-rw-r--r--chrome/renderer/ggl/ggl.cc21
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;
}