0

Adding support for VSyncProvider to the software drawing path

BUG=

Review URL: https://codereview.chromium.org/57883007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233985 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
dnicoara@chromium.org
2013-11-08 20:57:29 +00:00
parent eeaef77cee
commit bb47c8c5f6
13 changed files with 382 additions and 71 deletions

@@ -9,6 +9,7 @@
#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/skia_util.h"
#include "ui/gl/vsync_provider.h"
namespace cc {
@@ -56,4 +57,8 @@ void SoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
NOTIMPLEMENTED();
}
gfx::VSyncProvider* SoftwareOutputDevice::GetVSyncProvider() {
return vsync_provider_.get();
}
} // namespace cc

@@ -6,6 +6,7 @@
#define CC_OUTPUT_SOFTWARE_OUTPUT_DEVICE_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "skia/ext/refptr.h"
// TODO(robertphillips): change this to "class SkBaseDevice;"
@@ -17,6 +18,10 @@
class SkBitmap;
class SkCanvas;
namespace gfx {
class VSyncProvider;
}
namespace cc {
class SoftwareFrameData;
@@ -65,11 +70,16 @@ class CC_EXPORT SoftwareOutputDevice {
// displayed.
virtual void ReclaimSoftwareFrame(unsigned id);
// VSyncProvider used to update the timer used to schedule draws with the
// hardware vsync. Return NULL if a provider doesn't exist.
virtual gfx::VSyncProvider* GetVSyncProvider();
protected:
gfx::Size viewport_size_;
gfx::Rect damage_rect_;
skia::RefPtr<SkBaseDevice> device_;
skia::RefPtr<SkCanvas> canvas_;
scoped_ptr<gfx::VSyncProvider> vsync_provider_;
private:
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDevice);

@@ -9,10 +9,8 @@
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h"
#include "cc/output/compositor_frame.h"
#include "content/browser/aura/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
@@ -29,6 +27,31 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
output_surface_map_(output_surface_map),
compositor_message_loop_(compositor_message_loop),
compositor_(compositor) {
Initialize();
}
BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor)
: OutputSurface(software_device.Pass()),
surface_id_(surface_id),
output_surface_map_(output_surface_map),
compositor_message_loop_(compositor_message_loop),
compositor_(compositor) {
Initialize();
}
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
DCHECK(CalledOnValidThread());
if (!HasClient())
return;
output_surface_map_->Remove(surface_id_);
}
void BrowserCompositorOutputSurface::Initialize() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUIMaxFramesPending)) {
std::string string_value = command_line->GetSwitchValueASCII(
@@ -40,14 +63,8 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
LOG(ERROR) << "Trouble parsing --" << switches::kUIMaxFramesPending;
}
capabilities_.adjust_deadline_for_parent = false;
DetachFromThread();
}
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
DCHECK(CalledOnValidThread());
if (!HasClient())
return;
output_surface_map_->Remove(surface_id_);
DetachFromThread();
}
bool BrowserCompositorOutputSurface::BindToClient(
@@ -70,29 +87,6 @@ void BrowserCompositorOutputSurface::Reshape(gfx::Size size,
reflector_->OnReshape(size);
}
void BrowserCompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
DCHECK(frame->gl_frame_data);
WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
static_cast<WebGraphicsContext3DCommandBufferImpl*>(
context_provider_->Context3d());
CommandBufferProxyImpl* command_buffer_proxy =
command_buffer_context->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
context_provider_->Context3d()->shallowFlushCHROMIUM();
command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
if (reflector_.get()) {
if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size))
reflector_->OnSwapBuffers();
else
reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
}
OutputSurface::SwapBuffers(frame);
}
void BrowserCompositorOutputSurface::OnUpdateVSyncParameters(
base::TimeTicks timebase,
base::TimeDelta interval) {

@@ -9,9 +9,14 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "cc/output/output_surface.h"
#include "content/common/content_export.h"
namespace base { class MessageLoopProxy; }
namespace cc {
class SoftwareOutputDevice;
}
namespace ui { class Compositor; }
namespace content {
@@ -19,13 +24,23 @@ class ContextProviderCommandBuffer;
class ReflectorImpl;
class WebGraphicsContext3DCommandBufferImpl;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates
// arriving from the GPU process.
class BrowserCompositorOutputSurface
class CONTENT_EXPORT BrowserCompositorOutputSurface
: public cc::OutputSurface,
public base::NonThreadSafe {
public:
virtual ~BrowserCompositorOutputSurface();
// cc::OutputSurface implementation.
virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE;
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
void SetReflector(ReflectorImpl* reflector);
protected:
// Constructor used by the accelerated implementation.
BrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
@@ -33,25 +48,25 @@ class BrowserCompositorOutputSurface
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor);
virtual ~BrowserCompositorOutputSurface();
// Constructor used by the software implementation.
BrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor);
// cc::OutputSurface implementation.
virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
virtual void Reshape(gfx::Size size, float scale_factor) OVERRIDE;
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
void SetReflector(ReflectorImpl* reflector);
private:
int surface_id_;
IDMap<BrowserCompositorOutputSurface>* output_surface_map_;
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_;
base::WeakPtr<ui::Compositor> compositor_;
scoped_refptr<ReflectorImpl> reflector_;
private:
void Initialize();
DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOutputSurface);
};
} // namespace content

@@ -8,6 +8,7 @@
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
namespace base { class SingleThreadTaskRunner; }
@@ -17,7 +18,7 @@ namespace content {
class BrowserCompositorOutputSurface;
// Directs vsync updates to the appropriate BrowserCompositorOutputSurface.
class BrowserCompositorOutputSurfaceProxy
class CONTENT_EXPORT BrowserCompositorOutputSurfaceProxy
: public base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy> {
public:
BrowserCompositorOutputSurfaceProxy(
@@ -30,6 +31,7 @@ class BrowserCompositorOutputSurfaceProxy
private:
friend class base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy>;
friend class SoftwareBrowserCompositorOutputSurface;
~BrowserCompositorOutputSurfaceProxy();
void OnMessageReceivedOnCompositorThread(const IPC::Message& message);

@@ -0,0 +1,51 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/aura/gpu_browser_compositor_output_surface.h"
#include "cc/output/compositor_frame.h"
#include "content/browser/aura/reflector_impl.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
namespace content {
GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor)
: BrowserCompositorOutputSurface(context,
surface_id,
output_surface_map,
compositor_message_loop,
compositor) {}
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
void GpuBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
DCHECK(frame->gl_frame_data);
WebGraphicsContext3DCommandBufferImpl* command_buffer_context =
static_cast<WebGraphicsContext3DCommandBufferImpl*>(
context_provider_->Context3d());
CommandBufferProxyImpl* command_buffer_proxy =
command_buffer_context->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
context_provider_->Context3d()->shallowFlushCHROMIUM();
command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
if (reflector_.get()) {
if (frame->gl_frame_data->sub_buffer_rect ==
gfx::Rect(frame->gl_frame_data->size))
reflector_->OnSwapBuffers();
else
reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
}
OutputSurface::SwapBuffers(frame);
}
} // namespace content

@@ -0,0 +1,36 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include "content/browser/aura/browser_compositor_output_surface.h"
namespace content {
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates
// arriving from the GPU process.
class GpuBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
GpuBrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor);
virtual ~GpuBrowserCompositorOutputSurface();
private:
// cc::OutputSurface implementation.
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
};
} // namespace content
#endif // CONTENT_BROWSER_AURA_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_

@@ -15,6 +15,7 @@
#include "cc/output/output_surface.h"
#include "content/browser/aura/browser_compositor_output_surface.h"
#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
#include "content/browser/aura/gpu_browser_compositor_output_surface.h"
#include "content/browser/aura/reflector_impl.h"
#include "content/browser/aura/software_browser_compositor_output_surface.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
@@ -202,9 +203,14 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
" compositing with browser threaded compositing. Aborting.";
}
scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface =
SoftwareBrowserCompositorOutputSurface::Create(
CreateSoftwareOutputDevice(compositor));
scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface(
new SoftwareBrowserCompositorOutputSurface(
output_surface_proxy_,
CreateSoftwareOutputDevice(compositor),
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,
base::MessageLoopProxy::current().get(),
compositor->AsWeakPtr()));
return surface.PassAs<cc::OutputSurface>();
}
@@ -219,7 +225,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
compositor_thread_task_runner.get());
scoped_ptr<BrowserCompositorOutputSurface> surface(
new BrowserCompositorOutputSurface(
new GpuBrowserCompositorOutputSurface(
context_provider,
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,

@@ -4,18 +4,34 @@
#include "content/browser/aura/software_browser_compositor_output_surface.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/software_output_device.h"
#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "ui/events/latency_info.h"
#include "ui/gl/vsync_provider.h"
namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device)
: cc::OutputSurface(software_device.Pass()) {}
scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor)
: BrowserCompositorOutputSurface(software_device.Pass(),
surface_id,
output_surface_map,
compositor_message_loop,
compositor),
output_surface_proxy_(surface_proxy) {}
SoftwareBrowserCompositorOutputSurface::
~SoftwareBrowserCompositorOutputSurface() {}
void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
@@ -28,6 +44,15 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
base::Bind(
&RenderWidgetHostImpl::CompositorFrameDrawn,
latency_info));
gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
if (vsync_provider) {
vsync_provider->GetVSyncParameters(
base::Bind(&BrowserCompositorOutputSurfaceProxy::
OnUpdateVSyncParametersOnCompositorThread,
output_surface_proxy_,
surface_id_));
}
}
} // namespace content

@@ -2,32 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
#ifndef CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include "cc/output/output_surface.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/aura/browser_compositor_output_surface.h"
#include "content/common/content_export.h"
#include "ui/compositor/compositor.h"
namespace cc { class SoftwareOutputDevice; }
namespace base {
class MessageLoopProxy;
}
namespace cc {
class SoftwareOutputDevice;
}
namespace content {
// TODO(danakj): Inherit from BrowserCompositorOutputSurface to share stuff like
// reflectors, when we split the GL-specific stuff out of the class.
class SoftwareBrowserCompositorOutputSurface : public cc::OutputSurface {
class BrowserCompositorOutputSurfaceProxy;
class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public:
static scoped_ptr<SoftwareBrowserCompositorOutputSurface> Create(
scoped_ptr<cc::SoftwareOutputDevice> software_device) {
return make_scoped_ptr(
new SoftwareBrowserCompositorOutputSurface(software_device.Pass()));
}
SoftwareBrowserCompositorOutputSurface(
scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor);
virtual ~SoftwareBrowserCompositorOutputSurface();
private:
explicit SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device);
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
// On the software path we need to explicitly call the proxy to update the
// VSync parameters.
scoped_refptr<BrowserCompositorOutputSurfaceProxy> output_surface_proxy_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurface);
};
} // namespace content
#endif // CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_
#endif // CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_

@@ -0,0 +1,147 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/message_loop/message_loop.h"
#include "cc/output/compositor_frame.h"
#include "content/browser/aura/browser_compositor_output_surface_proxy.h"
#include "content/browser/aura/software_browser_compositor_output_surface.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/test/context_factories_for_test.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/vsync_provider.h"
namespace {
class FakeVSyncProvider : public gfx::VSyncProvider {
public:
FakeVSyncProvider() : call_count_(0) {}
virtual ~FakeVSyncProvider() {}
virtual void GetVSyncParameters(const UpdateVSyncCallback& callback)
OVERRIDE {
callback.Run(timebase_, interval_);
call_count_++;
}
int call_count() const { return call_count_; }
void set_timebase(base::TimeTicks timebase) { timebase_ = timebase; }
void set_interval(base::TimeDelta interval) { interval_ = interval; }
private:
base::TimeTicks timebase_;
base::TimeDelta interval_;
int call_count_;
DISALLOW_COPY_AND_ASSIGN(FakeVSyncProvider);
};
class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
public:
FakeSoftwareOutputDevice() : vsync_provider_(new FakeVSyncProvider()) {}
virtual ~FakeSoftwareOutputDevice() {}
virtual gfx::VSyncProvider* GetVSyncProvider() OVERRIDE {
return vsync_provider_.get();
}
private:
scoped_ptr<gfx::VSyncProvider> vsync_provider_;
DISALLOW_COPY_AND_ASSIGN(FakeSoftwareOutputDevice);
};
} // namespace
class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
public:
SoftwareBrowserCompositorOutputSurfaceTest();
virtual ~SoftwareBrowserCompositorOutputSurfaceTest();
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
scoped_ptr<content::BrowserCompositorOutputSurface> CreateSurface(
scoped_ptr<cc::SoftwareOutputDevice> device);
protected:
scoped_ptr<content::BrowserCompositorOutputSurface> output_surface_;
scoped_ptr<base::MessageLoop> message_loop_;
scoped_ptr<ui::Compositor> compositor_;
IDMap<content::BrowserCompositorOutputSurface> surface_map_;
scoped_refptr<content::BrowserCompositorOutputSurfaceProxy> surface_proxy_;
DISALLOW_COPY_AND_ASSIGN(SoftwareBrowserCompositorOutputSurfaceTest);
};
SoftwareBrowserCompositorOutputSurfaceTest::
SoftwareBrowserCompositorOutputSurfaceTest() {
CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
}
SoftwareBrowserCompositorOutputSurfaceTest::
~SoftwareBrowserCompositorOutputSurfaceTest() {}
void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
ui::InitializeContextFactoryForTests(false);
ui::Compositor::Initialize();
compositor_.reset(new ui::Compositor(true, gfx::kNullAcceleratedWidget));
surface_proxy_ =
new content::BrowserCompositorOutputSurfaceProxy(&surface_map_);
}
void SoftwareBrowserCompositorOutputSurfaceTest::TearDown() {
output_surface_.reset();
compositor_.reset();
EXPECT_TRUE(surface_map_.IsEmpty());
surface_map_.Clear();
ui::TerminateContextFactoryForTests();
ui::Compositor::Terminate();
}
scoped_ptr<content::BrowserCompositorOutputSurface>
SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
scoped_ptr<cc::SoftwareOutputDevice> device) {
return scoped_ptr<content::BrowserCompositorOutputSurface>(
new content::SoftwareBrowserCompositorOutputSurface(
surface_proxy_,
device.Pass(),
1,
&surface_map_,
compositor_->GetCompositorMessageLoop(),
compositor_->AsWeakPtr()));
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
scoped_ptr<cc::SoftwareOutputDevice> software_device(
new cc::SoftwareOutputDevice());
output_surface_ = CreateSurface(software_device.Pass());
cc::CompositorFrame frame;
output_surface_->SwapBuffers(&frame);
EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider());
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
scoped_ptr<cc::SoftwareOutputDevice> software_device(
new FakeSoftwareOutputDevice());
output_surface_ = CreateSurface(software_device.Pass());
FakeVSyncProvider* vsync_provider = static_cast<FakeVSyncProvider*>(
output_surface_->software_device()->GetVSyncProvider());
EXPECT_EQ(0, vsync_provider->call_count());
cc::CompositorFrame frame;
output_surface_->SwapBuffers(&frame);
EXPECT_EQ(1, vsync_provider->call_count());
}

@@ -306,6 +306,8 @@
'browser/aura/reflector_impl.h',
'browser/aura/resize_lock.cc',
'browser/aura/resize_lock.h',
'browser/aura/gpu_browser_compositor_output_surface.cc',
'browser/aura/gpu_browser_compositor_output_surface.h',
'browser/aura/software_browser_compositor_output_surface.cc',
'browser/aura/software_browser_compositor_output_surface.h',
'browser/aura/software_output_device_ozone.cc',

@@ -325,6 +325,7 @@
'browser/accessibility/browser_accessibility_manager_unittest.cc',
'browser/accessibility/browser_accessibility_win_unittest.cc',
'browser/appcache/chrome_appcache_service_unittest.cc',
'browser/aura/software_browser_compositor_output_surface_unittest.cc',
'browser/aura/software_output_device_ozone_unittest.cc',
'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc',