summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-12 21:10:24 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-12 21:10:24 +0000
commit652257791aa8aa96c53edd18edf2bd8c4dcaec1b (patch)
tree4f88b09862e79a8f6419d503641b943fe476f1ac /content
parenta1b621b3d14415485da5fc2f2df44f6dfcde84fd (diff)
downloadchromium_src-652257791aa8aa96c53edd18edf2bd8c4dcaec1b.zip
chromium_src-652257791aa8aa96c53edd18edf2bd8c4dcaec1b.tar.gz
chromium_src-652257791aa8aa96c53edd18edf2bd8c4dcaec1b.tar.bz2
Drive compositor scheduling with the swapbuffers callback.
This modifies the compositor to hold DoDeferredUpdate until the previous frames are ack'd by the GPU. This vastly improves rendering smoothness. There is some complexity in the way we intercept the SwapBuffers callback due to the different types of GraphicsContexts that get scheduled by render_widget. BUG=80480,53051 Review URL: http://codereview.chromium.org/6902106 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85186 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/gpu/gpu_process_host_ui_shim.cc3
-rw-r--r--content/browser/renderer_host/render_widget_host.cc8
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc3
-rw-r--r--content/renderer/render_view.cc17
-rw-r--r--content/renderer/render_view.h7
-rw-r--r--content/renderer/render_widget.cc126
-rw-r--r--content/renderer/render_widget.h30
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.cc13
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.h7
-rw-r--r--content/renderer/renderer_gl_context.cc8
-rw-r--r--content/renderer/renderer_gl_context.h1
-rw-r--r--content/renderer/webgraphicscontext3d_command_buffer_impl.cc11
-rw-r--r--content/renderer/webgraphicscontext3d_command_buffer_impl.h5
13 files changed, 208 insertions, 31 deletions
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc
index 0d50d68..276dca4 100644
--- a/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/id_map.h"
#include "base/process_util.h"
+#include "base/debug/trace_event.h"
#include "chrome/browser/browser_process.h"
#include "content/browser/browser_thread.h"
#include "content/browser/gpu/gpu_data_manager.h"
@@ -307,6 +308,8 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceSetIOSurface(
void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
+ TRACE_EVENT0("renderer",
+ "GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped");
RenderViewHost* host = RenderViewHost::FromID(params.renderer_id,
params.render_view_id);
if (!host)
diff --git a/content/browser/renderer_host/render_widget_host.cc b/content/browser/renderer_host/render_widget_host.cc
index 4fab721..34881ce 100644
--- a/content/browser/renderer_host/render_widget_host.cc
+++ b/content/browser/renderer_host/render_widget_host.cc
@@ -507,6 +507,7 @@ void RenderWidgetHost::SystemThemeChanged() {
}
void RenderWidgetHost::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardMouseEvent");
if (ignore_input_events_ || process_->ignore_input_events())
return;
@@ -532,6 +533,7 @@ void RenderWidgetHost::OnMouseActivate() {
void RenderWidgetHost::ForwardWheelEvent(
const WebMouseWheelEvent& wheel_event) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent");
if (ignore_input_events_ || process_->ignore_input_events())
return;
@@ -567,6 +569,7 @@ void RenderWidgetHost::ForwardWheelEvent(
void RenderWidgetHost::ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardKeyboardEvent");
if (ignore_input_events_ || process_->ignore_input_events())
return;
@@ -628,6 +631,8 @@ void RenderWidgetHost::ForwardKeyboardEvent(
void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
int event_size,
bool is_keyboard_shortcut) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardInputEvent");
+
if (!process_->HasConnection())
return;
@@ -670,6 +675,7 @@ void RenderWidgetHost::ForwardEditCommandsForNextKeyEvent(
#if defined(TOUCH_UI)
void RenderWidgetHost::ForwardTouchEvent(
const WebKit::WebTouchEvent& touch_event) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardTouchEvent");
ForwardInputEvent(touch_event, sizeof(WebKit::WebTouchEvent), false);
}
#endif
@@ -955,6 +961,8 @@ void RenderWidgetHost::OnMsgUpdateRect(
}
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
+ TRACE_EVENT0("renderer_host", "RenderWidgetHost::OnMsgInputEventAck");
+
// Log the time delta for processing an input event.
TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta);
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index f4e0ddc..d68bbfb 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -352,6 +352,7 @@ void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
}
void GpuCommandBufferStub::SwapBuffersCallback() {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::SwapBuffersCallback");
OnSwapBuffers();
GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
@@ -369,6 +370,8 @@ void GpuCommandBufferStub::SwapBuffersCallback() {
void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
uint64 swap_buffers_count) {
+ TRACE_EVENT0("gpu",
+ "GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped");
scheduler_->set_acknowledged_swap_buffers_count(swap_buffers_count);
// Wake up the GpuScheduler to start doing work again.
diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc
index 62b1e99..2469fcf 100644
--- a/content/renderer/render_view.cc
+++ b/content/renderer/render_view.cc
@@ -3695,6 +3695,14 @@ void RenderView::DidFlushPaint() {
}
}
+void RenderView::OnViewContextSwapBuffersComplete() {
+ RenderWidget::OnSwapBuffersComplete();
+}
+
+void RenderView::OnViewContextSwapBuffersAborted() {
+ RenderWidget::OnSwapBuffersAborted();
+}
+
webkit::ppapi::PluginInstance* RenderView::GetBitmapForOptimizedPluginPaint(
const gfx::Rect& paint_bounds,
TransportDIB** dib,
@@ -3885,6 +3893,15 @@ void RenderView::OnWasRestored(bool needs_repainting) {
#endif // OS_MACOSX
}
+bool RenderView::SupportsAsynchronousSwapBuffers() {
+ WebKit::WebGraphicsContext3D* context = webview()->graphicsContext3D();
+ if (!context)
+ return false;
+ std::string extensions(context->getRequestableExtensionsCHROMIUM().utf8());
+ return extensions.find("GL_CHROMIUM_swapbuffers_complete_callback") !=
+ std::string::npos;
+}
+
void RenderView::OnSetFocus(bool enable) {
RenderWidget::OnSetFocus(enable);
diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h
index a5c7f28..4715d84 100644
--- a/content/renderer/render_view.h
+++ b/content/renderer/render_view.h
@@ -198,6 +198,11 @@ class RenderView : public RenderWidget,
// May return NULL when the view is closing.
WebKit::WebView* webview() const;
+ // Called by a GraphicsContext associated with this view when swapbuffers
+ // completes or is aborted.
+ void OnViewContextSwapBuffersComplete();
+ void OnViewContextSwapBuffersAborted();
+
int page_id() const { return page_id_; }
PepperPluginDelegateImpl* pepper_delegate() { return &pepper_delegate_; }
@@ -576,7 +581,6 @@ class RenderView : public RenderWidget,
// Please do not add your stuff randomly to the end here. If there is an
// appropriate section, add it there. If not, there are some random functions
// nearer to the top you can add it to.
-
virtual void DidFlushPaint();
// Cannot use std::set unfortunately since linked_ptr<> does not support
@@ -601,6 +605,7 @@ class RenderView : public RenderWidget,
virtual void OnSetFocus(bool enable);
virtual void OnWasHidden();
virtual void OnWasRestored(bool needs_repainting);
+ virtual bool SupportsAsynchronousSwapBuffers() OVERRIDE;
private:
// For unit tests.
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 7572b7e..aad4b22 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -69,6 +69,8 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread,
current_paint_buf_(NULL),
next_paint_flags_(0),
update_reply_pending_(false),
+ using_asynchronous_swapbuffers_(false),
+ num_swapbuffers_complete_pending_(0),
did_show_(false),
is_hidden_(false),
needs_repainting_on_restore_(false),
@@ -83,7 +85,8 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread,
suppress_next_char_events_(false),
is_accelerated_compositing_active_(false),
animation_update_pending_(false),
- animation_task_posted_(false) {
+ animation_task_posted_(false),
+ invalidation_task_posted_(false) {
RenderProcess::current()->AddRefProcess();
DCHECK(render_thread_);
}
@@ -346,14 +349,68 @@ void RenderWidget::OnUpdateRectAck() {
current_paint_buf_ = NULL;
}
+ // If swapbuffers is still pending, then defer the update until the
+ // swapbuffers occurs.
+ if (num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
+ TRACE_EVENT0("renderer", "EarlyOut_SwapStillPending");
+ return;
+ }
+
// Notify subclasses.
DidFlushPaint();
// Continue painting if necessary...
- CallDoDeferredUpdate();
+ DoDeferredUpdateAndSendInputAck();
+}
+
+bool RenderWidget::SupportsAsynchronousSwapBuffers()
+{
+ return false;
+}
+
+void RenderWidget::OnSwapBuffersAborted()
+{
+ TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersAborted");
+ num_swapbuffers_complete_pending_ = 0;
+ using_asynchronous_swapbuffers_ = false;
+ // Schedule another frame so the compositor learns about it.
+ scheduleComposite();
+}
+
+void RenderWidget::OnSwapBuffersComplete()
+{
+ TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete");
+ // When compositing deactivates, we reset the swapbuffers pending count. The
+ // swapbuffers acks may still arrive, however.
+ if (num_swapbuffers_complete_pending_ == 0) {
+ TRACE_EVENT0("renderer", "EarlyOut_ZeroSwapbuffersPending");
+ return;
+ }
+ num_swapbuffers_complete_pending_--;
+
+ // If update reply is still pending, then defer the update until that reply
+ // occurs.
+ if (update_reply_pending_){
+ TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
+ return;
+ }
+
+ // If we are not accelerated rendering, then this is a stale swapbuffers from
+ // when we were previously rendering.
+ if (!is_accelerated_compositing_active_) {
+ TRACE_EVENT0("renderer", "EarlyOut_AcceleratedCompositingOff");
+ return;
+ }
+
+ // Notify subclasses.
+ DidFlushPaint();
+
+ // Continue painting if necessary...
+ DoDeferredUpdateAndSendInputAck();
}
void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
+ TRACE_EVENT0("renderer", "RenderWidget::OnHandleInputEvent");
void* iter = NULL;
const char* data;
@@ -536,7 +593,7 @@ void RenderWidget::AnimationCallback() {
base::TimeDelta::FromMilliseconds(30),
25);
}
- CallDoDeferredUpdate();
+ DoDeferredUpdateAndSendInputAck();
}
void RenderWidget::AnimateIfNeeded() {
@@ -575,7 +632,12 @@ void RenderWidget::AnimateIfNeeded() {
NewRunnableMethod(this, &RenderWidget::AnimationCallback), delay);
}
-void RenderWidget::CallDoDeferredUpdate() {
+void RenderWidget::InvalidationCallback() {
+ invalidation_task_posted_ = false;
+ DoDeferredUpdateAndSendInputAck();
+}
+
+void RenderWidget::DoDeferredUpdateAndSendInputAck() {
DoDeferredUpdate();
if (pending_input_event_ack_.get())
@@ -585,13 +647,22 @@ void RenderWidget::CallDoDeferredUpdate() {
void RenderWidget::DoDeferredUpdate() {
TRACE_EVENT0("renderer", "RenderWidget::DoDeferredUpdate");
- if (!webwidget_ || update_reply_pending())
+ if (!webwidget_)
+ return;
+ if (update_reply_pending()) {
+ TRACE_EVENT0("renderer", "EarlyOut_UpdateReplyPending");
return;
+ }
+ if (num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending) {
+ TRACE_EVENT0("renderer", "EarlyOut_MaxSwapBuffersPending");
+ return;
+ }
// Suppress updating when we are hidden.
if (is_hidden_ || size_.IsEmpty()) {
paint_aggregator_.ClearPendingUpdate();
needs_repainting_on_restore_ = true;
+ TRACE_EVENT0("renderer", "EarlyOut_NotVisible");
return;
}
@@ -604,8 +675,10 @@ void RenderWidget::DoDeferredUpdate() {
// Suppress painting if nothing is dirty. This has to be done after updating
// animations running layout as these may generate further invalidations.
- if (!paint_aggregator_.HasPendingUpdate())
+ if (!paint_aggregator_.HasPendingUpdate()) {
+ TRACE_EVENT0("renderer", "EarlyOut_NoPendingUpdate");
return;
+ }
// OK, save the pending update to a local since painting may cause more
// invalidation. Some WebCore rendering objects only layout when painted.
@@ -673,6 +746,8 @@ void RenderWidget::DoDeferredUpdate() {
} else { // Accelerated compositing path
// Begin painting.
webwidget_->composite(false);
+ if (using_asynchronous_swapbuffers_)
+ num_swapbuffers_complete_pending_++;
}
// sending an ack to browser process that the paint is complete...
@@ -710,9 +785,6 @@ void RenderWidget::DoDeferredUpdate() {
// WebWidgetClient
void RenderWidget::didInvalidateRect(const WebRect& rect) {
- // We only want one pending DoDeferredUpdate call at any time...
- bool update_pending = paint_aggregator_.HasPendingUpdate();
-
// The invalidated rect might be outside the bounds of the view.
gfx::Rect view_rect(size_);
gfx::Rect damaged_rect = view_rect.Intersect(rect);
@@ -722,11 +794,17 @@ void RenderWidget::didInvalidateRect(const WebRect& rect) {
paint_aggregator_.InvalidateRect(damaged_rect);
// We may not need to schedule another call to DoDeferredUpdate.
- if (update_pending)
+ if (invalidation_task_posted_)
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (update_reply_pending())
+ if (update_reply_pending() ||
+ num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending)
+ return;
+
+ // When GPU rendering, combine pending animations and invalidations into
+ // a single update.
+ if (is_accelerated_compositing_active_ && animation_task_posted_)
return;
// Perform updating asynchronously. This serves two purposes:
@@ -734,8 +812,9 @@ void RenderWidget::didInvalidateRect(const WebRect& rect) {
// on the call stack.
// 2) Allows us to collect more damage rects before painting to help coalesce
// the work that we will need to do.
+ invalidation_task_posted_ = true;
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &RenderWidget::CallDoDeferredUpdate));
+ this, &RenderWidget::InvalidationCallback));
}
void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
@@ -744,9 +823,6 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
if (is_accelerated_compositing_active_)
return;
- // We only want one pending DoDeferredUpdate call at any time...
- bool update_pending = paint_aggregator_.HasPendingUpdate();
-
// The scrolled rect might be outside the bounds of the view.
gfx::Rect view_rect(size_);
gfx::Rect damaged_rect = view_rect.Intersect(clip_rect);
@@ -756,11 +832,17 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
paint_aggregator_.ScrollRect(dx, dy, damaged_rect);
// We may not need to schedule another call to DoDeferredUpdate.
- if (update_pending)
+ if (invalidation_task_posted_)
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (update_reply_pending())
+ if (update_reply_pending() ||
+ num_swapbuffers_complete_pending_ >= kMaxSwapBuffersPending)
+ return;
+
+ // When GPU rendering, combine pending animations and invalidations into
+ // a single update.
+ if (is_accelerated_compositing_active_ && animation_task_posted_)
return;
// Perform updating asynchronously. This serves two purposes:
@@ -768,14 +850,20 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
// on the call stack.
// 2) Allows us to collect more damage rects before painting to help coalesce
// the work that we will need to do.
+ invalidation_task_posted_ = true;
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
- this, &RenderWidget::CallDoDeferredUpdate));
+ this, &RenderWidget::InvalidationCallback));
}
void RenderWidget::didActivateAcceleratedCompositing(bool active) {
is_accelerated_compositing_active_ = active;
Send(new ViewHostMsg_DidActivateAcceleratedCompositing(
- routing_id_, is_accelerated_compositing_active_));
+ routing_id_, is_accelerated_compositing_active_));
+
+ if (active)
+ using_asynchronous_swapbuffers_ = SupportsAsynchronousSwapBuffers();
+ else if (using_asynchronous_swapbuffers_)
+ using_asynchronous_swapbuffers_ = false;
}
void RenderWidget::scheduleComposite() {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 74944f6..b4b22af 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -171,7 +171,8 @@ class RenderWidget : public IPC::Channel::Listener,
void AnimationCallback();
void AnimateIfNeeded();
- void CallDoDeferredUpdate();
+ void InvalidationCallback();
+ void DoDeferredUpdateAndSendInputAck();
void DoDeferredUpdate();
void DoDeferredClose();
void DoDeferredSetWindowRect(const WebKit::WebRect& pos);
@@ -218,6 +219,17 @@ class RenderWidget : public IPC::Channel::Listener,
virtual void DidInitiatePaint() {}
virtual void DidFlushPaint() {}
+ // Override and return true when the widget is rendered with a graphics
+ // context that supports asynchronous swapbuffers. When returning true,
+ // the subclass must call RenderWidget::OnSwapBuffersComplete() when
+ // swaps complete, and OnSwapBuffersAborted if the context is lost.
+ virtual bool SupportsAsynchronousSwapBuffers();
+
+ // Notifies scheduler that the RenderWidget's subclass has finished or aborted
+ // a swap buffers.
+ void OnSwapBuffersAborted();
+ void OnSwapBuffersComplete();
+
// Detects if a suitable opaque plugin covers the given paint bounds with no
// compositing necessary.
//
@@ -327,6 +339,21 @@ class RenderWidget : public IPC::Channel::Listener,
// UpdateRect message has been sent).
bool update_reply_pending_;
+ // True if the underlying graphics context supports asynchronous swap.
+ // Cached on the RenderWidget because determining support is costly.
+ bool using_asynchronous_swapbuffers_;
+
+ // Number of OnSwapBuffersComplete we are expecting. Incremented each time
+ // WebWidget::composite has been been performed when the RenderWidget subclass
+ // SupportsAsynchronousSwapBuffers. Decremented in OnSwapBuffers. Will block
+ // rendering.
+ int num_swapbuffers_complete_pending_;
+
+ // When accelerated rendering is on, is the maximum number of swapbuffers that
+ // can be outstanding before we start throttling based on
+ // OnSwapBuffersComplete callback.
+ static const int kMaxSwapBuffersPending = 2;
+
// Set to true if we should ignore RenderWidget::Show calls.
bool did_show_;
@@ -395,6 +422,7 @@ class RenderWidget : public IPC::Channel::Listener,
base::Time animation_floor_time_;
bool animation_update_pending_;
bool animation_task_posted_;
+ bool invalidation_task_posted_;
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
};
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index ae8aeb7..30a5380 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -308,6 +308,10 @@ WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
return new PepperWidget(plugin_, this);
}
+bool RenderWidgetFullscreenPepper::SupportsAsynchronousSwapBuffers() {
+ return context_ != NULL;
+}
+
void RenderWidgetFullscreenPepper::CreateContext() {
DCHECK(!context_);
RenderThread* render_thread = RenderThread::current();
@@ -340,7 +344,9 @@ void RenderWidgetFullscreenPepper::CreateContext() {
return;
}
context_->SetSwapBuffersCallback(
- NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint));
+ NewCallback(this,
+ &RenderWidgetFullscreenPepper::
+ OnSwapBuffersCompleteByRendererGLContext));
context_->SetContextLostCallback(
NewCallback(this, &RenderWidgetFullscreenPepper::OnLostContext));
}
@@ -459,4 +465,9 @@ void RenderWidgetFullscreenPepper::OnLostContext() {
context_ = NULL;
program_ = 0;
buffer_ = 0;
+ OnSwapBuffersAborted();
+}
+
+void RenderWidgetFullscreenPepper::OnSwapBuffersCompleteByRendererGLContext() {
+ OnSwapBuffersComplete();
}
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h
index c7a235f..e83ca18 100644
--- a/content/renderer/render_widget_fullscreen_pepper.h
+++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -61,6 +61,9 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
// RenderWidgetFullscreen API.
virtual WebKit::WebWidget* CreateWebWidget();
+ // RenderWidget overrides.
+ virtual bool SupportsAsynchronousSwapBuffers() OVERRIDE;
+
private:
// Creates the GL context for compositing.
void CreateContext();
@@ -75,6 +78,10 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
// Called when the compositing context gets lost.
void OnLostContext();
+ // Binding of RendererGLContext swapbuffers callback to
+ // RenderWidget::OnSwapBuffersCompleted.
+ void OnSwapBuffersCompleteByRendererGLContext();
+
// URL that is responsible for this widget, passed to ggl::CreateViewContext.
GURL active_url_;
diff --git a/content/renderer/renderer_gl_context.cc b/content/renderer/renderer_gl_context.cc
index b0a28be..3c5ba17 100644
--- a/content/renderer/renderer_gl_context.cc
+++ b/content/renderer/renderer_gl_context.cc
@@ -293,7 +293,9 @@ bool RendererGLContext::MakeCurrent(RendererGLContext* context) {
}
bool RendererGLContext::SwapBuffers() {
- TRACE_EVENT0("gpu", "RendererGLContext::SwapBuffers");
+ TRACE_EVENT1("gpu", "RendererGLContext::SwapBuffers", "frame", frame_number_);
+ frame_number_++;
+
// Don't request latest error status from service. Just use the locally cached
// information from the last flush.
if (command_buffer_->GetLastState().error != gpu::error::kNoError)
@@ -364,7 +366,8 @@ RendererGLContext::RendererGLContext(GpuChannelHost* channel,
gles2_helper_(NULL),
transfer_buffer_id_(-1),
gles2_implementation_(NULL),
- last_error_(SUCCESS) {
+ last_error_(SUCCESS),
+ frame_number_(0) {
DCHECK(channel);
}
@@ -592,4 +595,3 @@ bool RendererGLContext::GetChildToParentLatch(uint32* child_to_parent_latch) {
}
return false;
}
-
diff --git a/content/renderer/renderer_gl_context.h b/content/renderer/renderer_gl_context.h
index f91618a..7617b56 100644
--- a/content/renderer/renderer_gl_context.h
+++ b/content/renderer/renderer_gl_context.h
@@ -231,6 +231,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
gpu::gles2::GLES2Implementation* gles2_implementation_;
gfx::Size size_;
Error last_error_;
+ int frame_number_;
DISALLOW_COPY_AND_ASSIGN(RendererGLContext);
};
diff --git a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
index 0ed31f6..dec846e 100644
--- a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
@@ -110,7 +110,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
if (context_) {
context_->SetSwapBuffersCallback(
NewCallback(this,
- &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffers));
+ &WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete));
}
} else {
bool compositing_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
@@ -1045,12 +1045,12 @@ void WebGraphicsContext3DCommandBufferImpl::copyTextureToCompositor(
glFlush();
}
-void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffers() {
+void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete() {
// This may be called after tear-down of the RenderView.
RenderView* renderview =
web_view_ ? RenderView::FromWebView(web_view_) : NULL;
if (renderview)
- renderview->DidFlushPaint();
+ renderview->OnViewContextSwapBuffersComplete();
}
void WebGraphicsContext3DCommandBufferImpl::setContextLostCallback(
@@ -1063,6 +1063,11 @@ void WebGraphicsContext3DCommandBufferImpl::OnContextLost() {
if (context_lost_callback_) {
context_lost_callback_->onContextLost();
}
+
+ RenderView* renderview =
+ web_view_ ? RenderView::FromWebView(web_view_) : NULL;
+ if (renderview)
+ renderview->OnViewContextSwapBuffersAborted();
}
#endif // defined(ENABLE_GPU)
diff --git a/content/renderer/webgraphicscontext3d_command_buffer_impl.h b/content/renderer/webgraphicscontext3d_command_buffer_impl.h
index 93c70ca..c968e9b 100644
--- a/content/renderer/webgraphicscontext3d_command_buffer_impl.h
+++ b/content/renderer/webgraphicscontext3d_command_buffer_impl.h
@@ -430,8 +430,8 @@ class WebGraphicsContext3DCommandBufferImpl
WebGraphicsContext3D::WebGraphicsContextLostCallback* callback);
private:
- // SwapBuffers callback;
- void OnSwapBuffers();
+ // SwapBuffers callback.
+ void OnSwapBuffersComplete();
virtual void OnContextLost();
// The context we use for OpenGL rendering.
@@ -463,4 +463,3 @@ class WebGraphicsContext3DCommandBufferImpl
#endif // defined(ENABLE_GPU)
#endif // CONTENT_RENDERER_WEBGRAPHICSCONTEXT3D_COMMAND_BUFFER_IMPL_H_
-