| Index: cc/output/output_surface.cc
|
| diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
|
| index fe2b074ee46d033f7900054ccb164dc3b3992cae..4ffdc42cff590e9ea3166c28a34621d9bfa48b4b 100644
|
| --- a/cc/output/output_surface.cc
|
| +++ b/cc/output/output_surface.cc
|
| @@ -8,10 +8,12 @@
|
| #include <string>
|
| #include <vector>
|
|
|
| +#include "base/debug/trace_event.h"
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| #include "base/strings/string_split.h"
|
| #include "cc/output/output_surface_client.h"
|
| +#include "cc/scheduler/delay_based_time_source.h"
|
| #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
|
| #include "third_party/khronos/GLES2/gl2.h"
|
| #include "third_party/khronos/GLES2/gl2ext.h"
|
| @@ -29,7 +31,7 @@ class OutputSurfaceCallbacks
|
| WebGraphicsSwapBuffersCompleteCallbackCHROMIUM,
|
| public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
|
| public:
|
| - explicit OutputSurfaceCallbacks(OutputSurfaceClient* client)
|
| + explicit OutputSurfaceCallbacks(OutputSurface* client)
|
| : client_(client) {}
|
|
|
| // WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation.
|
| @@ -39,21 +41,27 @@ class OutputSurfaceCallbacks
|
| virtual void onContextLost() { client_->DidLoseOutputSurface(); }
|
|
|
| private:
|
| - OutputSurfaceClient* client_;
|
| + OutputSurface* client_;
|
| };
|
|
|
| OutputSurface::OutputSurface(
|
| scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
|
| : client_(NULL),
|
| context3d_(context3d.Pass()),
|
| - has_gl_discard_backbuffer_(false) {
|
| + has_gl_discard_backbuffer_(false),
|
| + max_frames_pending_(0),
|
| + pending_swap_buffers_(0),
|
| + begin_frame_pending_(false) {
|
| }
|
|
|
| OutputSurface::OutputSurface(
|
| scoped_ptr<cc::SoftwareOutputDevice> software_device)
|
| : client_(NULL),
|
| software_device_(software_device.Pass()),
|
| - has_gl_discard_backbuffer_(false) {
|
| + has_gl_discard_backbuffer_(false),
|
| + max_frames_pending_(0),
|
| + pending_swap_buffers_(0),
|
| + begin_frame_pending_(false) {
|
| }
|
|
|
| OutputSurface::OutputSurface(
|
| @@ -62,18 +70,115 @@ OutputSurface::OutputSurface(
|
| : client_(NULL),
|
| context3d_(context3d.Pass()),
|
| software_device_(software_device.Pass()),
|
| - has_gl_discard_backbuffer_(false) {
|
| + has_gl_discard_backbuffer_(false),
|
| + max_frames_pending_(0),
|
| + pending_swap_buffers_(0),
|
| + begin_frame_pending_(false) {
|
| +}
|
| +
|
| +void OutputSurface::InitializeBeginFrameEmulation(
|
| + Thread* thread,
|
| + bool throttle_frame_production,
|
| + base::TimeDelta interval,
|
| + bool swap_buffers_complete_supported) {
|
| + DCHECK(!frame_rate_controller_);
|
| + if (throttle_frame_production){
|
| + frame_rate_controller_.reset(
|
| + new FrameRateController(
|
| + DelayBasedTimeSource::Create(interval, thread)));
|
| + } else {
|
| + frame_rate_controller_.reset(new FrameRateController(thread));
|
| + }
|
| +
|
| + frame_rate_controller_->SetClient(this);
|
| + frame_rate_controller_->SetSwapBuffersCompleteSupported(
|
| + swap_buffers_complete_supported);
|
| + frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
|
| +}
|
| +
|
| +void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->SetMaxSwapsPending(max_frames_pending);
|
| + max_frames_pending_ = max_frames_pending;
|
| +}
|
| +
|
| +void OutputSurface::OnVSyncParametersChanged(base::TimeTicks timebase,
|
| + base::TimeDelta interval) {
|
| + TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged",
|
| + "timebase", (timebase - base::TimeTicks()).InSecondsF(),
|
| + "interval", interval.InSecondsF());
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
|
| +}
|
| +
|
| +void OutputSurface::FrameRateControllerTick(bool throttled) {
|
| + DCHECK(frame_rate_controller_);
|
| + if (!throttled)
|
| + BeginFrame(frame_rate_controller_->LastTickTime());
|
| +}
|
| +
|
| +// Forwarded to OutputSurfaceClient
|
| +void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) {
|
| + TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
|
| + client_->SetNeedsRedrawRect(damage_rect);
|
| +}
|
| +
|
| +void OutputSurface::SetNeedsBeginFrame(bool enable) {
|
| + begin_frame_pending_ = false;
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->SetActive(enable);
|
| +}
|
| +
|
| +void OutputSurface::BeginFrame(base::TimeTicks frame_time) {
|
| + // TODO(brianderson): Remove this early return once Android has
|
| + // Browser-side throttling.
|
| + if (begin_frame_pending_ || pending_swap_buffers_ >= max_frames_pending_)
|
| + return;
|
| + TRACE_EVENT0("cc", "OutputSurface::BeginFrame");
|
| + begin_frame_pending_ = true;
|
| + client_->BeginFrame(frame_time);
|
| +}
|
| +
|
| +void OutputSurface::OnSendFrameToParentCompositorAck(
|
| + const CompositorFrameAck& ack) {
|
| + TRACE_EVENT0("cc", "OutputSurface::OnSendFrameToParentCompositorAck");
|
| + client_->OnSendFrameToParentCompositorAck(ack);
|
| +}
|
| +
|
| +void OutputSurface::DidSwapBuffers() {
|
| + begin_frame_pending_ = false;
|
| + pending_swap_buffers_++;
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->DidSwapBuffers();
|
| +}
|
| +
|
| +void OutputSurface::OnSwapBuffersComplete() {
|
| + TRACE_EVENT0("cc", "OutputSurface::OnSwapBuffersComplete");
|
| + pending_swap_buffers_--;
|
| + client_->OnSwapBuffersComplete();
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->DidSwapBuffersComplete();
|
| +}
|
| +
|
| +void OutputSurface::DidLoseOutputSurface() {
|
| + TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
|
| + begin_frame_pending_ = false;
|
| + pending_swap_buffers_ = 0;
|
| + client_->DidLoseOutputSurface();
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->DidAbortAllPendingFrames();
|
| }
|
|
|
| OutputSurface::~OutputSurface() {
|
| + if (frame_rate_controller_)
|
| + frame_rate_controller_->SetActive(false);
|
| }
|
|
|
| bool OutputSurface::ForcedDrawToSoftwareDevice() const {
|
| return false;
|
| }
|
|
|
| -bool OutputSurface::BindToClient(
|
| - cc::OutputSurfaceClient* client) {
|
| +bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
|
| DCHECK(client);
|
| if (context3d_ && !context3d_->makeContextCurrent())
|
| return false;
|
| @@ -88,7 +193,7 @@ bool OutputSurface::BindToClient(
|
| has_gl_discard_backbuffer_ =
|
| extensions.count("GL_CHROMIUM_discard_backbuffer") > 0;
|
|
|
| - callbacks_.reset(new OutputSurfaceCallbacks(client_));
|
| + callbacks_.reset(new OutputSurfaceCallbacks(this));
|
| context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get());
|
| context3d_->setContextLostCallback(callbacks_.get());
|
|
|
| @@ -126,6 +231,7 @@ void OutputSurface::SwapBuffers(const ui::LatencyInfo& latency_info) {
|
| // Note that currently this has the same effect as SwapBuffers; we should
|
| // consider exposing a different entry point on WebGraphicsContext3D.
|
| context3d_->prepareTexture();
|
| + DidSwapBuffers();
|
| }
|
|
|
| void OutputSurface::PostSubBuffer(gfx::Rect rect,
|
| @@ -133,6 +239,7 @@ void OutputSurface::PostSubBuffer(gfx::Rect rect,
|
| DCHECK(context3d_);
|
| context3d_->postSubBufferCHROMIUM(
|
| rect.x(), rect.y(), rect.width(), rect.height());
|
| + DidSwapBuffers();
|
| }
|
|
|
| } // namespace cc
|
|
|