Commit fdc3baa3 authored by jbauman's avatar jbauman Committed by Commit bot

Avoid destroying surface before the parent surface stops referencing it.

Add surface sequence numbers, which are used to schedule the
destruction of surfaces. The child surface's destruction can
wait on a set of sequence numbers, and the parent surface can
later queue a frame that satisfies those numbers, causing the
former child surface to be destroyed.

Also move ownership of the SurfaceIdAllocator to the
ui::Compositor, so that the surface id namespace for a
compositor will stay the same across all output surfaces it
ever uses.

BUG=411118

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

Cr-Commit-Position: refs/heads/master@{#299022}
parent f4180013
......@@ -46,6 +46,10 @@ class CC_EXPORT CompositorFrameMetadata {
ViewportSelectionBound selection_end;
std::vector<ui::LatencyInfo> latency_info;
// A set of SurfaceSequences that this frame satisfies (always in the same
// namespace as the current Surface).
std::vector<uint32_t> satisfies_sequences;
};
} // namespace cc
......
......@@ -7,6 +7,7 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_manager.h"
namespace cc {
......@@ -17,7 +18,7 @@ static const int kFrameIndexStart = 2;
Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory)
: surface_id_(id),
size_(size),
factory_(factory),
factory_(factory->AsWeakPtr()),
frame_index_(kFrameIndexStart) {
}
......@@ -28,7 +29,7 @@ Surface::~Surface() {
(*it)->SendEmptyResult();
}
copy_requests_.clear();
if (current_frame_) {
if (current_frame_ && factory_) {
ReturnedResourceArray current_resources;
TransferableResource::ReturnResources(
current_frame_->delegated_frame_data->resource_list,
......@@ -39,6 +40,7 @@ Surface::~Surface() {
void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
const base::Closure& callback) {
DCHECK(factory_);
for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin();
it != copy_requests_.end();
++it) {
......@@ -63,6 +65,8 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
if (!draw_callback_.is_null())
draw_callback_.Run();
draw_callback_ = callback;
factory_->manager()->DidSatisfySequences(
surface_id_, &current_frame_->metadata.satisfies_sequences);
}
void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) {
......
......@@ -11,6 +11,7 @@
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "cc/base/scoped_ptr_vector.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface_id.h"
......@@ -50,12 +51,12 @@ class CC_SURFACES_EXPORT Surface {
void TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info);
void RunDrawCallbacks();
SurfaceFactory* factory() { return factory_; }
base::WeakPtr<SurfaceFactory> factory() { return factory_; }
private:
SurfaceId surface_id_;
gfx::Size size_;
SurfaceFactory* factory_;
base::WeakPtr<SurfaceFactory> factory_;
// TODO(jamesr): Support multiple frames in flight.
scoped_ptr<CompositorFrame> current_frame_;
int frame_index_;
......
......@@ -29,17 +29,26 @@ void SurfaceFactory::Create(SurfaceId surface_id, const gfx::Size& size) {
void SurfaceFactory::Destroy(SurfaceId surface_id) {
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory() == this);
DCHECK(it->second->factory().get() == this);
manager_->DeregisterSurface(surface_id);
surface_map_.erase(it);
}
void SurfaceFactory::DestroyOnSequence(
SurfaceId surface_id,
const std::set<SurfaceSequence>& dependency_set) {
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory().get() == this);
manager_->DestroyOnSequence(surface_map_.take_and_erase(it), dependency_set);
}
void SurfaceFactory::SubmitFrame(SurfaceId surface_id,
scoped_ptr<CompositorFrame> frame,
const base::Closure& callback) {
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory() == this);
DCHECK(it->second->factory().get() == this);
it->second->QueueFrame(frame.Pass(), callback);
manager_->SurfaceModified(surface_id);
}
......@@ -52,7 +61,7 @@ void SurfaceFactory::RequestCopyOfSurface(
copy_request->SendEmptyResult();
return;
}
DCHECK(it->second->factory() == this);
DCHECK(it->second->factory().get() == this);
it->second->RequestCopyOfOutput(copy_request.Pass());
manager_->SurfaceModified(surface_id);
}
......
......@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surface_resource_holder.h"
#include "cc/surfaces/surface_sequence.h"
#include "cc/surfaces/surfaces_export.h"
namespace gfx {
......@@ -37,6 +38,8 @@ class CC_SURFACES_EXPORT SurfaceFactory
void Create(SurfaceId surface_id, const gfx::Size& size);
void Destroy(SurfaceId surface_id);
void DestroyOnSequence(SurfaceId surface_id,
const std::set<SurfaceSequence>& dependency_set);
// A frame can only be submitted to a surface created by this factory,
// although the frame may reference surfaces created by other factories.
// The callback is called the first time this frame is used to draw.
......@@ -52,6 +55,8 @@ class CC_SURFACES_EXPORT SurfaceFactory
void RefResources(const TransferableResourceArray& resources);
void UnrefResources(const ReturnedResourceArray& resources);
SurfaceManager* manager() { return manager_; }
private:
SurfaceManager* manager_;
SurfaceFactoryClient* client_;
......
......@@ -372,5 +372,32 @@ TEST_F(SurfaceFactoryTest, DestroyWithResourceRefs) {
factory_.SubmitFrame(id, frame.Pass(), base::Closure());
}
TEST_F(SurfaceFactoryTest, DestroySequence) {
SurfaceId id2(5);
factory_.Create(id2, gfx::Size(5, 5));
// Check that waiting before the sequence is satisfied works.
std::set<SurfaceSequence> sequence;
sequence.insert(SurfaceSequence(0, 4));
factory_.DestroyOnSequence(id2, sequence);
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->metadata.satisfies_sequences.push_back(6);
frame->metadata.satisfies_sequences.push_back(4);
frame->delegated_frame_data = frame_data.Pass();
DCHECK(manager_.GetSurfaceForId(id2));
factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure());
DCHECK(!manager_.GetSurfaceForId(id2));
// Check that waiting after the sequence is satisfied works.
factory_.Create(id2, gfx::Size(5, 5));
sequence.clear();
sequence.insert(SurfaceSequence(0, 6));
DCHECK(manager_.GetSurfaceForId(id2));
factory_.DestroyOnSequence(id2, sequence);
DCHECK(!manager_.GetSurfaceForId(id2));
}
} // namespace
} // namespace cc
......@@ -21,6 +21,8 @@ class CC_SURFACES_EXPORT SurfaceIdAllocator {
static uint32_t NamespaceForId(SurfaceId id);
uint32_t id_namespace() const { return id_namespace_; }
private:
const uint32_t id_namespace_;
uint32_t next_id_;
......
......@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_id_allocator.h"
namespace cc {
......@@ -15,6 +16,12 @@ SurfaceManager::SurfaceManager() {
SurfaceManager::~SurfaceManager() {
DCHECK(thread_checker_.CalledOnValidThread());
for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin();
it != surfaces_to_destroy_.end();
++it) {
DeregisterSurface(it->first->surface_id());
delete it->first;
}
}
void SurfaceManager::RegisterSurface(Surface* surface) {
......@@ -31,6 +38,51 @@ void SurfaceManager::DeregisterSurface(SurfaceId surface_id) {
surface_map_.erase(it);
}
void SurfaceManager::DestroyOnSequence(
scoped_ptr<Surface> surface,
const std::set<SurfaceSequence>& dependency_set) {
surfaces_to_destroy_.push_back(make_pair(surface.release(), dependency_set));
SearchForSatisfaction();
}
void SurfaceManager::DidSatisfySequences(SurfaceId id,
std::vector<uint32_t>* sequence) {
for (std::vector<uint32_t>::iterator it = sequence->begin();
it != sequence->end();
++it) {
satisfied_sequences_.insert(
SurfaceSequence(SurfaceIdAllocator::NamespaceForId(id), *it));
}
sequence->clear();
SearchForSatisfaction();
}
void SurfaceManager::SearchForSatisfaction() {
for (SurfaceDestroyList::iterator dest_it = surfaces_to_destroy_.begin();
dest_it != surfaces_to_destroy_.end();) {
std::set<SurfaceSequence>& dependency_set = dest_it->second;
for (std::set<SurfaceSequence>::iterator it = dependency_set.begin();
it != dependency_set.end();) {
if (satisfied_sequences_.count(*it) > 0) {
satisfied_sequences_.erase(*it);
std::set<SurfaceSequence>::iterator old_it = it;
++it;
dependency_set.erase(old_it);
} else {
++it;
}
}
if (dependency_set.empty()) {
scoped_ptr<Surface> surf(dest_it->first);
DeregisterSurface(surf->surface_id());
dest_it = surfaces_to_destroy_.erase(dest_it);
} else {
++dest_it;
}
}
}
Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) {
DCHECK(thread_checker_.CalledOnValidThread());
SurfaceMap::iterator it = surface_map_.find(surface_id);
......
......@@ -5,12 +5,17 @@
#ifndef CC_SURFACES_SURFACE_MANAGER_H_
#define CC_SURFACES_SURFACE_MANAGER_H_
#include <list>
#include <set>
#include <vector>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "cc/surfaces/surface_damage_observer.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surface_sequence.h"
#include "cc/surfaces/surfaces_export.h"
namespace cc {
......@@ -25,6 +30,10 @@ class CC_SURFACES_EXPORT SurfaceManager {
void RegisterSurface(Surface* surface);
void DeregisterSurface(SurfaceId surface_id);
// Destroy the Surface once a set of sequence numbers has been satisfied.
void DestroyOnSequence(scoped_ptr<Surface> surface,
const std::set<SurfaceSequence>& dependency_set);
Surface* GetSurfaceForId(SurfaceId surface_id);
void AddObserver(SurfaceDamageObserver* obs) {
......@@ -37,12 +46,27 @@ class CC_SURFACES_EXPORT SurfaceManager {
void SurfaceModified(SurfaceId surface_id);
// A frame for a surface satisfies a set of sequence numbers.
void DidSatisfySequences(SurfaceId id, std::vector<uint32_t>* sequence);
private:
void SearchForSatisfaction();
typedef base::hash_map<SurfaceId, Surface*> SurfaceMap;
SurfaceMap surface_map_;
ObserverList<SurfaceDamageObserver> observer_list_;
base::ThreadChecker thread_checker_;
// List of surfaces to be destroyed, along with what sequences they're still
// waiting on.
typedef std::list<std::pair<Surface*, std::set<SurfaceSequence>>>
SurfaceDestroyList;
SurfaceDestroyList surfaces_to_destroy_;
// Set of SurfaceSequences that have been satisfied by a frame but not yet
// waited on.
std::set<SurfaceSequence> satisfied_sequences_;
DISALLOW_COPY_AND_ASSIGN(SurfaceManager);
};
......
// Copyright 2014 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 CC_SURFACES_SURFACE_SEQUENCE_H_
#define CC_SURFACES_SURFACE_SEQUENCE_H_
namespace cc {
// A per-surface-namespace sequence number that's used to coordinate
// dependencies between frames. A sequence number may be satisfied once, and
// may be depended on once.
struct SurfaceSequence {
SurfaceSequence() : id_namespace(0u), sequence(0u) {}
SurfaceSequence(uint32_t id_namespace, uint32_t sequence)
: id_namespace(id_namespace), sequence(sequence) {}
uint32_t id_namespace;
uint32_t sequence;
};
inline bool operator==(const SurfaceSequence& a, const SurfaceSequence& b) {
return a.id_namespace == b.id_namespace && a.sequence == b.sequence;
}
inline bool operator!=(const SurfaceSequence& a, const SurfaceSequence& b) {
return !(a == b);
}
inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) {
if (a.id_namespace != b.id_namespace)
return a.id_namespace < b.id_namespace;
return a.sequence < b.sequence;
}
} // namespace cc
#endif // CC_SURFACES_SURFACE_SEQUENCE_H_
......@@ -370,16 +370,26 @@ void DelegatedFrameHost::SwapDelegatedFrame(
if (!surface_factory_) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
id_allocator_ = factory->CreateSurfaceIdAllocator();
id_allocator_ =
factory->GetContextFactory()->CreateSurfaceIdAllocator();
surface_factory_ =
make_scoped_ptr(new cc::SurfaceFactory(manager, this));
}
if (surface_id_.is_null() || frame_size != current_surface_size_ ||
frame_size_in_dip != current_frame_size_in_dip_) {
// TODO(jbauman): Wait to destroy this surface until the parent has
// finished using it.
if (!surface_id_.is_null())
surface_factory_->Destroy(surface_id_);
if (!surface_id_.is_null()) {
if (compositor) {
std::set<cc::SurfaceSequence> seq;
seq.insert(compositor->InsertSurfaceSequenceForNextFrame());
// Destruction of this surface needs to wait for compositors that
// have drawn using it to swap frames that don't reference it.
// TODO(jbauman): Handle cases where the compositor has been
// changed since the last draw.
surface_factory_->DestroyOnSequence(surface_id_, seq);
} else {
surface_factory_->Destroy(surface_id_);
}
}
surface_id_ = id_allocator_->GenerateId();
surface_factory_->Create(surface_id_, frame_size);
client_->GetLayer()->SetShowSurface(surface_id_, frame_size_in_dip);
......
......@@ -202,7 +202,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
scoped_ptr<SurfaceDisplayOutputSurface> output_surface(
new SurfaceDisplayOutputSurface(
manager, next_surface_id_namespace_++, context_provider));
manager, compositor->surface_id_allocator(), context_provider));
display_client->set_surface_output_surface(output_surface.get());
output_surface->set_display_client(display_client.get());
data->display_client = display_client.Pass();
......
......@@ -56,12 +56,12 @@ class GpuProcessTransportFactory
virtual bool DoesCreateTestContexts() override;
virtual cc::SharedBitmapManager* GetSharedBitmapManager() override;
virtual base::MessageLoopProxy* GetCompositorMessageLoop() override;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator()
override;
// ImageTransportFactory implementation.
virtual ui::ContextFactory* GetContextFactory() override;
virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() override;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator()
override;
virtual cc::SurfaceManager* GetSurfaceManager() override;
virtual GLHelper* GetGLHelper() override;
virtual void AddObserver(ImageTransportFactoryObserver* observer) override;
......
......@@ -72,7 +72,6 @@ class CONTENT_EXPORT ImageTransportFactory {
virtual ui::ContextFactory* GetContextFactory() = 0;
virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() = 0;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() = 0;
virtual cc::SurfaceManager* GetSurfaceManager() = 0;
// Gets a GLHelper instance, associated with the shared context. This
......
......@@ -15,14 +15,14 @@ namespace content {
SurfaceDisplayOutputSurface::SurfaceDisplayOutputSurface(
cc::SurfaceManager* surface_manager,
uint32_t surface_id_namespace,
cc::SurfaceIdAllocator* allocator,
const scoped_refptr<cc::ContextProvider>& context_provider)
: cc::OutputSurface(context_provider,
scoped_ptr<cc::SoftwareOutputDevice>()),
display_client_(NULL),
surface_manager_(surface_manager),
factory_(surface_manager, this),
allocator_(surface_id_namespace) {
allocator_(allocator) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
}
......@@ -47,7 +47,7 @@ void SurfaceDisplayOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
if (!surface_id_.is_null()) {
factory_.Destroy(surface_id_);
}
surface_id_ = allocator_.GenerateId();
surface_id_ = allocator_->GenerateId();
factory_.Create(surface_id_, frame_size);
display_size_ = frame_size;
display_client_->display()->Resize(surface_id_, frame_size);
......
......@@ -27,7 +27,7 @@ class SurfaceDisplayOutputSurface : public cc::OutputSurface,
// The underlying cc::Display and cc::SurfaceManager must outlive this class.
SurfaceDisplayOutputSurface(
cc::SurfaceManager* surface_manager,
uint32_t surface_id_namespace,
cc::SurfaceIdAllocator* allocator,
const scoped_refptr<cc::ContextProvider>& context_provider);
virtual ~SurfaceDisplayOutputSurface();
......@@ -54,7 +54,7 @@ class SurfaceDisplayOutputSurface : public cc::OutputSurface,
cc::SurfaceFactory factory_;
gfx::Size display_size_;
cc::SurfaceId surface_id_;
cc::SurfaceIdAllocator allocator_;
cc::SurfaceIdAllocator* allocator_;
DISALLOW_COPY_AND_ASSIGN(SurfaceDisplayOutputSurface);
};
......
......@@ -5,6 +5,7 @@
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "cc/output/context_provider.h"
#include "cc/surfaces/surface_manager.h"
#include "content/common/gpu/client/gl_helper.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "ui/compositor/compositor.h"
......@@ -13,7 +14,8 @@
namespace content {
NoTransportImageTransportFactory::NoTransportImageTransportFactory()
: context_factory_(new ui::InProcessContextFactory) {
: context_factory_(new ui::InProcessContextFactory),
surface_manager_(new cc::SurfaceManager) {
}
NoTransportImageTransportFactory::~NoTransportImageTransportFactory() {
......@@ -31,13 +33,8 @@ NoTransportImageTransportFactory::GetSharedSurfaceHandle() {
return gfx::GLSurfaceHandle();
}
scoped_ptr<cc::SurfaceIdAllocator>
NoTransportImageTransportFactory::CreateSurfaceIdAllocator() {
return scoped_ptr<cc::SurfaceIdAllocator>();
}
cc::SurfaceManager* NoTransportImageTransportFactory::GetSurfaceManager() {
return NULL;
return surface_manager_.get();
}
GLHelper* NoTransportImageTransportFactory::GetGLHelper() {
......
......@@ -24,8 +24,6 @@ class NoTransportImageTransportFactory : public ImageTransportFactory {
// ImageTransportFactory implementation.
virtual ui::ContextFactory* GetContextFactory() override;
virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() override;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator()
override;
virtual cc::SurfaceManager* GetSurfaceManager() override;
virtual GLHelper* GetGLHelper() override;
virtual void AddObserver(ImageTransportFactoryObserver* observer) override;
......@@ -38,6 +36,7 @@ class NoTransportImageTransportFactory : public ImageTransportFactory {
scoped_ptr<ui::ContextFactory> context_factory_;
scoped_refptr<cc::ContextProvider> context_provider_;
scoped_ptr<GLHelper> gl_helper_;
scoped_ptr<cc::SurfaceManager> surface_manager_;
ObserverList<ImageTransportFactoryObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(NoTransportImageTransportFactory);
......
......@@ -287,6 +287,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata)
IPC_STRUCT_TRAITS_MEMBER(selection_start)
IPC_STRUCT_TRAITS_MEMBER(selection_end)
IPC_STRUCT_TRAITS_MEMBER(latency_info)
IPC_STRUCT_TRAITS_MEMBER(satisfies_sequences)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData)
......
......@@ -6,6 +6,7 @@
#include "cc/output/output_surface.h"
#include "cc/resources/shared_bitmap_manager.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "ui/compositor/reflector.h"
......@@ -55,4 +56,9 @@ base::MessageLoopProxy* SurfaceContextFactory::GetCompositorMessageLoop() {
return nullptr;
}
scoped_ptr<cc::SurfaceIdAllocator>
SurfaceContextFactory::CreateSurfaceIdAllocator() {
return nullptr;
}
} // namespace mojo
......@@ -32,6 +32,8 @@ class SurfaceContextFactory : public ui::ContextFactory {
virtual bool DoesCreateTestContexts() override;
virtual cc::SharedBitmapManager* GetSharedBitmapManager() override;
virtual base::MessageLoopProxy* GetCompositorMessageLoop() override;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator()
override;
SurfaceBinding surface_binding_;
......
......@@ -109,6 +109,7 @@ source_set("test_support") {
deps = [
"//base/test:test_support",
"//cc",
"//cc/surfaces",
"//cc:test_support",
"//skia",
"//testing/gtest",
......
......@@ -20,6 +20,7 @@
#include "cc/layers/layer.h"
#include "cc/output/begin_frame_args.h"
#include "cc/output/context_provider.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/compositor_observer.h"
......@@ -68,12 +69,31 @@ namespace {} // namespace
namespace ui {
class SatisfySwapPromise : public cc::SwapPromise {
public:
explicit SatisfySwapPromise(uint32_t id) : id_(id) {}
private:
virtual void DidSwap(cc::CompositorFrameMetadata* metadata) OVERRIDE {
metadata->satisfies_sequences.push_back(id_);
}
virtual void DidNotSwap(DidNotSwapReason reason) OVERRIDE {
// TODO(jbauman): Send to the SurfaceManager immediately.
DCHECK(false);
}
virtual int64 TraceId() const OVERRIDE { return 0; }
uint32_t id_;
};
Compositor::Compositor(gfx::AcceleratedWidget widget,
ui::ContextFactory* context_factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: context_factory_(context_factory),
root_layer_(NULL),
widget_(widget),
surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()),
surface_sequence_number_(0),
compositor_thread_loop_(context_factory->GetCompositorMessageLoop()),
task_runner_(task_runner),
vsync_manager_(new CompositorVSyncManager()),
......@@ -406,6 +426,16 @@ void Compositor::SetLayerTreeDebugState(
host_->SetDebugState(debug_state);
}
cc::SurfaceSequence Compositor::InsertSurfaceSequenceForNextFrame() {
cc::SurfaceSequence sequence;
sequence.id_namespace = surface_id_allocator_->id_namespace();
sequence.sequence = ++surface_sequence_number_;
scoped_ptr<cc::SwapPromise> promise(
new SatisfySwapPromise(surface_sequence_number_));
host_->QueueSwapPromise(promise.Pass());
return sequence;
}
scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
if (!compositor_lock_) {
compositor_lock_ = new CompositorLock(this);
......
......@@ -14,6 +14,7 @@
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'<(DEPTH)/cc/cc.gyp:cc',
'<(DEPTH)/cc/cc.gyp:cc_surfaces',
'<(DEPTH)/gpu/gpu.gyp:command_buffer_common',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx',
......@@ -87,6 +88,7 @@
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/cc/cc.gyp:cc',
'<(DEPTH)/cc/cc.gyp:cc_surfaces',
'<(DEPTH)/cc/cc_tests.gyp:cc_test_support',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/testing/gtest.gyp:gtest',
......
......@@ -13,6 +13,7 @@
#include "base/observer_list.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "cc/surfaces/surface_sequence.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "third_party/skia/include/core/SkColor.h"
......@@ -37,6 +38,7 @@ class Layer;
class LayerTreeDebugState;
class LayerTreeHost;
class SharedBitmapManager;
class SurfaceIdAllocator;
}
namespace gfx {
......@@ -95,6 +97,9 @@ class COMPOSITOR_EXPORT ContextFactory {
// Gets the compositor message loop, or NULL if not using threaded
// compositing.
virtual base::MessageLoopProxy* GetCompositorMessageLoop() = 0;
// Creates a Surface ID allocator with a new namespace.
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() = 0;
};
// This class represents a lock on the compositor, that can be used to prevent
......@@ -266,6 +271,14 @@ class COMPOSITOR_EXPORT Compositor
return &layer_animator_collection_;
}
// Inserts a SurfaceSequence that will be satisfied on the next frame this
// compositor commits and swaps.
cc::SurfaceSequence InsertSurfaceSequenceForNextFrame();
cc::SurfaceIdAllocator* surface_id_allocator() {
return surface_id_allocator_.get();
}
private:
friend class base::RefCounted<Compositor>;
friend class CompositorLock;
......@@ -290,6 +303,8 @@ class COMPOSITOR_EXPORT Compositor
ObserverList<CompositorAnimationObserver> animation_observer_list_;
gfx::AcceleratedWidget widget_;
scoped_ptr<cc::SurfaceIdAllocator> surface_id_allocator_;
uint32_t surface_sequence_number_;
scoped_refptr<cc::Layer> root_web_layer_;
scoped_ptr<cc::LayerTreeHost> host_;
scoped_refptr<base::MessageLoopProxy> compositor_thread_loop_;
......
......@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/threading/thread.h"
#include "cc/output/output_surface.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/reflector.h"
......@@ -19,7 +20,8 @@
namespace ui {
InProcessContextFactory::InProcessContextFactory()
: shared_bitmap_manager_(new cc::TestSharedBitmapManager()) {
: shared_bitmap_manager_(new cc::TestSharedBitmapManager()),
next_surface_id_namespace_(1u) {
DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone)
<< "If running tests, ensure that main() is calling "
<< "gfx::GLSurface::InitializeOneOffForTests()";
......@@ -102,4 +104,10 @@ base::MessageLoopProxy* InProcessContextFactory::GetCompositorMessageLoop() {
return compositor_thread_->message_loop_proxy().get();
}
scoped_ptr<cc::SurfaceIdAllocator>
InProcessContextFactory::CreateSurfaceIdAllocator() {
return make_scoped_ptr(
new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
}
} // namespace ui
......@@ -40,12 +40,15 @@ class InProcessContextFactory : public ContextFactory {
virtual bool DoesCreateTestContexts() override;
virtual cc::SharedBitmapManager* GetSharedBitmapManager() override;
virtual base::MessageLoopProxy* GetCompositorMessageLoop() override;
virtual scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator()
override;
private:
scoped_ptr<base::Thread> compositor_thread_;
scoped_refptr<webkit::gpu::ContextProviderInProcess>
shared_main_thread_contexts_;
scoped_ptr<cc::SharedBitmapManager> shared_bitmap_manager_;
uint32_t next_surface_id_namespace_;
DISALLOW_COPY_AND_ASSIGN(InProcessContextFactory);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment