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

@@ -6,6 +6,7 @@
#define CC_OUTPUT_SOFTWARE_OUTPUT_DEVICE_H_ #define CC_OUTPUT_SOFTWARE_OUTPUT_DEVICE_H_
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h" #include "cc/base/cc_export.h"
#include "skia/ext/refptr.h" #include "skia/ext/refptr.h"
// TODO(robertphillips): change this to "class SkBaseDevice;" // TODO(robertphillips): change this to "class SkBaseDevice;"
@@ -17,6 +18,10 @@
class SkBitmap; class SkBitmap;
class SkCanvas; class SkCanvas;
namespace gfx {
class VSyncProvider;
}
namespace cc { namespace cc {
class SoftwareFrameData; class SoftwareFrameData;
@@ -65,11 +70,16 @@ class CC_EXPORT SoftwareOutputDevice {
// displayed. // displayed.
virtual void ReclaimSoftwareFrame(unsigned id); 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: protected:
gfx::Size viewport_size_; gfx::Size viewport_size_;
gfx::Rect damage_rect_; gfx::Rect damage_rect_;
skia::RefPtr<SkBaseDevice> device_; skia::RefPtr<SkBaseDevice> device_;
skia::RefPtr<SkCanvas> canvas_; skia::RefPtr<SkCanvas> canvas_;
scoped_ptr<gfx::VSyncProvider> vsync_provider_;
private: private:
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDevice); DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDevice);

@@ -9,10 +9,8 @@
#include "base/location.h" #include "base/location.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "cc/output/compositor_frame.h"
#include "content/browser/aura/reflector_impl.h" #include "content/browser/aura/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.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.h"
#include "ui/compositor/compositor_switches.h" #include "ui/compositor/compositor_switches.h"
@@ -29,6 +27,31 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
output_surface_map_(output_surface_map), output_surface_map_(output_surface_map),
compositor_message_loop_(compositor_message_loop), compositor_message_loop_(compositor_message_loop),
compositor_(compositor) { 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(); CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kUIMaxFramesPending)) { if (command_line->HasSwitch(switches::kUIMaxFramesPending)) {
std::string string_value = command_line->GetSwitchValueASCII( std::string string_value = command_line->GetSwitchValueASCII(
@@ -40,14 +63,8 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
LOG(ERROR) << "Trouble parsing --" << switches::kUIMaxFramesPending; LOG(ERROR) << "Trouble parsing --" << switches::kUIMaxFramesPending;
} }
capabilities_.adjust_deadline_for_parent = false; capabilities_.adjust_deadline_for_parent = false;
DetachFromThread();
}
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() { DetachFromThread();
DCHECK(CalledOnValidThread());
if (!HasClient())
return;
output_surface_map_->Remove(surface_id_);
} }
bool BrowserCompositorOutputSurface::BindToClient( bool BrowserCompositorOutputSurface::BindToClient(
@@ -70,29 +87,6 @@ void BrowserCompositorOutputSurface::Reshape(gfx::Size size,
reflector_->OnReshape(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( void BrowserCompositorOutputSurface::OnUpdateVSyncParameters(
base::TimeTicks timebase, base::TimeTicks timebase,
base::TimeDelta interval) { base::TimeDelta interval) {

@@ -9,9 +9,14 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "cc/output/output_surface.h" #include "cc/output/output_surface.h"
#include "content/common/content_export.h"
namespace base { class MessageLoopProxy; } namespace base { class MessageLoopProxy; }
namespace cc {
class SoftwareOutputDevice;
}
namespace ui { class Compositor; } namespace ui { class Compositor; }
namespace content { namespace content {
@@ -19,13 +24,23 @@ class ContextProviderCommandBuffer;
class ReflectorImpl; class ReflectorImpl;
class WebGraphicsContext3DCommandBufferImpl; class WebGraphicsContext3DCommandBufferImpl;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a class CONTENT_EXPORT BrowserCompositorOutputSurface
// cc::OutputSurface that also handles vsync parameter updates
// arriving from the GPU process.
class BrowserCompositorOutputSurface
: public cc::OutputSurface, : public cc::OutputSurface,
public base::NonThreadSafe { public base::NonThreadSafe {
public: 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( BrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context, const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id, int surface_id,
@@ -33,25 +48,25 @@ class BrowserCompositorOutputSurface
base::MessageLoopProxy* compositor_message_loop, base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor); 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_; int surface_id_;
IDMap<BrowserCompositorOutputSurface>* output_surface_map_; IDMap<BrowserCompositorOutputSurface>* output_surface_map_;
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_; scoped_refptr<base::MessageLoopProxy> compositor_message_loop_;
base::WeakPtr<ui::Compositor> compositor_; base::WeakPtr<ui::Compositor> compositor_;
scoped_refptr<ReflectorImpl> reflector_; scoped_refptr<ReflectorImpl> reflector_;
private:
void Initialize();
DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOutputSurface);
}; };
} // namespace content } // namespace content

@@ -8,6 +8,7 @@
#include "base/id_map.h" #include "base/id_map.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "content/common/content_export.h"
namespace base { class SingleThreadTaskRunner; } namespace base { class SingleThreadTaskRunner; }
@@ -17,7 +18,7 @@ namespace content {
class BrowserCompositorOutputSurface; class BrowserCompositorOutputSurface;
// Directs vsync updates to the appropriate BrowserCompositorOutputSurface. // Directs vsync updates to the appropriate BrowserCompositorOutputSurface.
class BrowserCompositorOutputSurfaceProxy class CONTENT_EXPORT BrowserCompositorOutputSurfaceProxy
: public base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy> { : public base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy> {
public: public:
BrowserCompositorOutputSurfaceProxy( BrowserCompositorOutputSurfaceProxy(
@@ -30,6 +31,7 @@ class BrowserCompositorOutputSurfaceProxy
private: private:
friend class base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy>; friend class base::RefCountedThreadSafe<BrowserCompositorOutputSurfaceProxy>;
friend class SoftwareBrowserCompositorOutputSurface;
~BrowserCompositorOutputSurfaceProxy(); ~BrowserCompositorOutputSurfaceProxy();
void OnMessageReceivedOnCompositorThread(const IPC::Message& message); 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 "cc/output/output_surface.h"
#include "content/browser/aura/browser_compositor_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/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/reflector_impl.h"
#include "content/browser/aura/software_browser_compositor_output_surface.h" #include "content/browser/aura/software_browser_compositor_output_surface.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.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."; " compositing with browser threaded compositing. Aborting.";
} }
scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface = scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface(
SoftwareBrowserCompositorOutputSurface::Create( new SoftwareBrowserCompositorOutputSurface(
CreateSoftwareOutputDevice(compositor)); 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>(); return surface.PassAs<cc::OutputSurface>();
} }
@@ -219,7 +225,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
compositor_thread_task_runner.get()); compositor_thread_task_runner.get());
scoped_ptr<BrowserCompositorOutputSurface> surface( scoped_ptr<BrowserCompositorOutputSurface> surface(
new BrowserCompositorOutputSurface( new GpuBrowserCompositorOutputSurface(
context_provider, context_provider,
per_compositor_data_[compositor]->surface_id, per_compositor_data_[compositor]->surface_id,
&output_surface_map_, &output_surface_map_,

@@ -4,18 +4,34 @@
#include "content/browser/aura/software_browser_compositor_output_surface.h" #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/message_loop/message_loop.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame.h"
#include "cc/output/software_output_device.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 "content/browser/renderer_host/render_widget_host_impl.h"
#include "ui/events/latency_info.h" #include "ui/events/latency_info.h"
#include "ui/gl/vsync_provider.h"
namespace content { namespace content {
SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface( SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device) scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
: cc::OutputSurface(software_device.Pass()) {} 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( void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) { cc::CompositorFrame* frame) {
@@ -28,6 +44,15 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
base::Bind( base::Bind(
&RenderWidgetHostImpl::CompositorFrameDrawn, &RenderWidgetHostImpl::CompositorFrameDrawn,
latency_info)); 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 } // namespace content

@@ -2,32 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CONTENT_BROWSER_AURA_SOFTWARE_OUTPUT_SURFACE_H_ #ifndef CONTENT_BROWSER_AURA_SOFTWARE_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_AURA_SOFTWARE_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 { namespace content {
// TODO(danakj): Inherit from BrowserCompositorOutputSurface to share stuff like class BrowserCompositorOutputSurfaceProxy;
// reflectors, when we split the GL-specific stuff out of the class.
class SoftwareBrowserCompositorOutputSurface : public cc::OutputSurface { class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
: public BrowserCompositorOutputSurface {
public: public:
static scoped_ptr<SoftwareBrowserCompositorOutputSurface> Create( SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device) { scoped_refptr<BrowserCompositorOutputSurfaceProxy> surface_proxy,
return make_scoped_ptr( scoped_ptr<cc::SoftwareOutputDevice> software_device,
new SoftwareBrowserCompositorOutputSurface(software_device.Pass())); int surface_id,
} IDMap<BrowserCompositorOutputSurface>* output_surface_map,
base::MessageLoopProxy* compositor_message_loop,
base::WeakPtr<ui::Compositor> compositor);
virtual ~SoftwareBrowserCompositorOutputSurface();
private: private:
explicit SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device);
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE; 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 } // 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/reflector_impl.h',
'browser/aura/resize_lock.cc', 'browser/aura/resize_lock.cc',
'browser/aura/resize_lock.h', '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.cc',
'browser/aura/software_browser_compositor_output_surface.h', 'browser/aura/software_browser_compositor_output_surface.h',
'browser/aura/software_output_device_ozone.cc', 'browser/aura/software_output_device_ozone.cc',

@@ -325,6 +325,7 @@
'browser/accessibility/browser_accessibility_manager_unittest.cc', 'browser/accessibility/browser_accessibility_manager_unittest.cc',
'browser/accessibility/browser_accessibility_win_unittest.cc', 'browser/accessibility/browser_accessibility_win_unittest.cc',
'browser/appcache/chrome_appcache_service_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/aura/software_output_device_ozone_unittest.cc',
'browser/browser_thread_unittest.cc', 'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc', 'browser/browser_url_handler_impl_unittest.cc',