diff options
27 files changed, 270 insertions, 31 deletions
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h index e9dd706..a6fe2d4 100644 --- a/cc/output/compositor_frame_metadata.h +++ b/cc/output/compositor_frame_metadata.h @@ -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 diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index d58ed4c..4d32d72 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.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_, ¤t_frame_->metadata.satisfies_sequences); } void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) { diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index 718fef4..0df5c17 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h @@ -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_; diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index ab7186a..dcf1130 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc @@ -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); } diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h index 2516015..3eb4f43 100644 --- a/cc/surfaces/surface_factory.h +++ b/cc/surfaces/surface_factory.h @@ -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_; diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index 5cb83fe..ba2a888 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc @@ -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 diff --git a/cc/surfaces/surface_id_allocator.h b/cc/surfaces/surface_id_allocator.h index d410f06..96a241f 100644 --- a/cc/surfaces/surface_id_allocator.h +++ b/cc/surfaces/surface_id_allocator.h @@ -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_; diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index 1e3699d..920f464 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc @@ -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); diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h index 7515be5..66db9d9 100644 --- a/cc/surfaces/surface_manager.h +++ b/cc/surfaces/surface_manager.h @@ -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); }; diff --git a/cc/surfaces/surface_sequence.h b/cc/surfaces/surface_sequence.h new file mode 100644 index 0000000..4c99e45 --- /dev/null +++ b/cc/surfaces/surface_sequence.h @@ -0,0 +1,38 @@ +// 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_ diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc index 9df4600..9a26d42 100644 --- a/content/browser/compositor/delegated_frame_host.cc +++ b/content/browser/compositor/delegated_frame_host.cc @@ -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); diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 36b3e0c..abdbdb2 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -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(); diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h index cb78094..abed2f8 100644 --- a/content/browser/compositor/gpu_process_transport_factory.h +++ b/content/browser/compositor/gpu_process_transport_factory.h @@ -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; diff --git a/content/browser/compositor/image_transport_factory.h b/content/browser/compositor/image_transport_factory.h index c3af76a..4b5dec1 100644 --- a/content/browser/compositor/image_transport_factory.h +++ b/content/browser/compositor/image_transport_factory.h @@ -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 diff --git a/content/browser/compositor/surface_display_output_surface.cc b/content/browser/compositor/surface_display_output_surface.cc index c1a09f8f..2f06581 100644 --- a/content/browser/compositor/surface_display_output_surface.cc +++ b/content/browser/compositor/surface_display_output_surface.cc @@ -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); diff --git a/content/browser/compositor/surface_display_output_surface.h b/content/browser/compositor/surface_display_output_surface.h index 3549ad2..ac1a3e2 100644 --- a/content/browser/compositor/surface_display_output_surface.h +++ b/content/browser/compositor/surface_display_output_surface.h @@ -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); }; diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.cc b/content/browser/compositor/test/no_transport_image_transport_factory.cc index 524223f..808d297 100644 --- a/content/browser/compositor/test/no_transport_image_transport_factory.cc +++ b/content/browser/compositor/test/no_transport_image_transport_factory.cc @@ -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() { diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.h b/content/browser/compositor/test/no_transport_image_transport_factory.h index 6bcca6f..67ba4ec 100644 --- a/content/browser/compositor/test/no_transport_image_transport_factory.h +++ b/content/browser/compositor/test/no_transport_image_transport_factory.h @@ -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); diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index d51f7af..b29fdc6 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h @@ -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) diff --git a/mojo/aura/surface_context_factory.cc b/mojo/aura/surface_context_factory.cc index 1e56029..9f1e77a 100644 --- a/mojo/aura/surface_context_factory.cc +++ b/mojo/aura/surface_context_factory.cc @@ -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 diff --git a/mojo/aura/surface_context_factory.h b/mojo/aura/surface_context_factory.h index dc0e8d0..cc9aba3 100644 --- a/mojo/aura/surface_context_factory.h +++ b/mojo/aura/surface_context_factory.h @@ -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_; diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index ada7f9e..38b79ad 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn @@ -109,6 +109,7 @@ source_set("test_support") { deps = [ "//base/test:test_support", "//cc", + "//cc/surfaces", "//cc:test_support", "//skia", "//testing/gtest", diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 1b6f342..4d07e1e 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -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); diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp index 4a1437e..76cb687 100644 --- a/ui/compositor/compositor.gyp +++ b/ui/compositor/compositor.gyp @@ -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', diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index d808f62..bd96541 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -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_; diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index fa2380f..d815a5c 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc @@ -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 diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 56f2d7e..6100edb 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h @@ -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); }; |