From c4967eface72bc99452d8a83800c7cdd19a872ee Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 18 Aug 2015 14:46:01 -0700 Subject: Revert of Re-land: cc: Use worker context for one-copy tile initialization. (patchset #29 id:560001 of https://codereview.chromium.org/1230203007/ ) Reason for revert: Sorry Dave. I'm reverting as this broke mandoline. To see the breakage build mandoline:all, and run with: mandoline --oopif-always-create-new-frame-tree http://phuang.github.io/iframe.html . We do have mandoline tests that run, but they run with the code path gfx::GLSurfaceTestSupport::InitializeOneOff(), which is why they likely still pass. I'll see about making the tests not run with that config. Original issue's description: > Re-land: cc: Use worker context for one-copy tile initialization. > > This moves management of staging resources to > OneCopyTileTaskWorkerPool class. This makes it possible > to use a worker context to issue and detect when copy > operations complete. > > BUG=490295 > TBR=jamesr@chromium.org, sky@chromium.org > CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel > > Committed: https://crrev.com/af0ab609b53c64ce43172be42e20e7ca8beab497 > Cr-Commit-Position: refs/heads/master@{#343947} TBR=jamesr@chromium.org,kbr@chromium.org,piman@chromium.org,primiano@chromium.org,vmiura@chromium.org,vmpstr@chromium.org,reveman@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=490295 Review URL: https://codereview.chromium.org/1298143003 Cr-Commit-Position: refs/heads/master@{#344042} --- cc/output/context_provider.h | 22 - cc/output/output_surface.cc | 21 +- cc/raster/gpu_tile_task_worker_pool.cc | 13 +- cc/raster/one_copy_tile_task_worker_pool.cc | 766 ++++++++------------- cc/raster/one_copy_tile_task_worker_pool.h | 127 ++-- cc/raster/tile_task_worker_pool_perftest.cc | 7 +- cc/raster/tile_task_worker_pool_unittest.cc | 6 +- cc/resources/resource_format.cc | 19 - cc/resources/resource_format.h | 2 - cc/resources/resource_pool.cc | 5 +- cc/resources/resource_pool.h | 5 +- cc/resources/resource_pool_unittest.cc | 13 +- cc/resources/resource_provider.cc | 156 ++++- cc/resources/resource_provider.h | 18 +- cc/resources/resource_provider_unittest.cc | 134 +++- cc/surfaces/display.cc | 3 + cc/surfaces/surface_display_output_surface.cc | 5 +- cc/surfaces/surface_display_output_surface.h | 3 +- .../surface_display_output_surface_unittest.cc | 3 +- cc/test/fake_output_surface.h | 8 +- cc/test/fake_resource_provider.h | 5 +- cc/test/layer_tree_pixel_resource_test.cc | 27 +- cc/test/layer_tree_pixel_resource_test.h | 4 +- cc/test/layer_tree_pixel_test.cc | 6 - cc/test/layer_tree_pixel_test.h | 2 - cc/test/layer_tree_test.cc | 10 +- cc/test/layer_tree_test.h | 3 +- cc/test/pixel_test.cc | 4 +- cc/test/test_in_process_context_provider.cc | 1 - cc/tiles/tile_manager.cc | 2 +- cc/trees/layer_tree_host_impl.cc | 39 +- cc/trees/layer_tree_host_impl.h | 4 +- cc/trees/layer_tree_host_pixeltest_tiles.cc | 1 - cc/trees/layer_tree_settings.cc | 3 +- cc/trees/layer_tree_settings.h | 1 - components/html_viewer/web_layer_tree_view_impl.cc | 10 +- .../browser_compositor_output_surface.cc | 8 +- .../compositor/browser_compositor_output_surface.h | 1 - .../gpu_browser_compositor_output_surface.cc | 2 - .../gpu_browser_compositor_output_surface.h | 1 - .../compositor/gpu_process_transport_factory.cc | 35 +- .../compositor/gpu_process_transport_factory.h | 1 - ...urfaceless_browser_compositor_output_surface.cc | 2 - ...surfaceless_browser_compositor_output_surface.h | 1 - .../offscreen_browser_compositor_output_surface.cc | 2 - .../offscreen_browser_compositor_output_surface.h | 1 - .../browser/compositor/reflector_impl_unittest.cc | 1 - content/browser/gpu/compositor_util.cc | 8 + .../renderer_host/compositor_impl_android.cc | 2 +- .../common/gpu/client/command_buffer_metrics.cc | 6 - content/common/gpu/client/command_buffer_metrics.h | 1 - content/renderer/gpu/render_widget_compositor.cc | 5 - gpu/command_buffer/build_gles2_cmd_buffer.py | 2 +- gpu/command_buffer/client/cmd_buffer_helper.cc | 3 +- gpu/command_buffer/service/query_manager.cc | 1 - mojo/cc/output_surface_mojo.cc | 3 +- mojo/cc/output_surface_mojo.h | 8 +- mojo/gpu/mojo_gles2_impl_autogen.cc | 3 +- ...2_call_visitor_chromium_miscellaneous_autogen.h | 1 - ui/compositor/test/in_process_context_factory.cc | 23 +- ui/compositor/test/in_process_context_provider.cc | 4 - ui/compositor/test/in_process_context_provider.h | 1 - 62 files changed, 820 insertions(+), 764 deletions(-) diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h index c024e02..aa4367d 100644 --- a/cc/output/context_provider.h +++ b/cc/output/context_provider.h @@ -7,7 +7,6 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" #include "cc/base/cc_export.h" #include "gpu/command_buffer/common/capabilities.h" @@ -27,27 +26,6 @@ struct ManagedMemoryPolicy; class ContextProvider : public base::RefCountedThreadSafe { public: - class ScopedContextLock { - public: - explicit ScopedContextLock(ContextProvider* context_provider) - : context_provider_(context_provider), - context_lock_(*context_provider_->GetLock()) { - // Allow current thread to bind to |context_provider|. - context_provider_->DetachFromThread(); - } - ~ScopedContextLock() { - // Allow a different thread to bind to |context_provider|. - context_provider_->DetachFromThread(); - } - - gpu::gles2::GLES2Interface* ContextGL() { - return context_provider_->ContextGL(); - } - - private: - ContextProvider* const context_provider_; - base::AutoLock context_lock_; - }; // Bind the 3d context to the current thread. This should be called before // accessing the contexts. Calling it more than once should have no effect. // Once this function has been called, the class should only be accessed diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc index 0786d66..a597a87 100644 --- a/cc/output/output_surface.cc +++ b/cc/output/output_surface.cc @@ -107,6 +107,10 @@ OutputSurface::~OutputSurface() { context_provider_->SetMemoryPolicyChangedCallback( ContextProvider::MemoryPolicyChangedCallback()); } + if (worker_context_provider_.get()) { + worker_context_provider_->SetLostContextCallback( + ContextProvider::LostContextCallback()); + } } bool OutputSurface::HasExternalStencilTest() const { @@ -130,8 +134,14 @@ bool OutputSurface::BindToClient(OutputSurfaceClient* client) { if (success && worker_context_provider_.get()) { success = worker_context_provider_->BindToCurrentThread(); - if (success) + if (success) { worker_context_provider_->SetupLock(); + // The destructor resets the context lost callback, so base::Unretained + // is safe, as long as the worker threads stop using the context before + // the output surface is destroyed. + worker_context_provider_->SetLostContextCallback(base::Bind( + &OutputSurface::DidLoseOutputSurface, base::Unretained(this))); + } } if (!success) @@ -207,7 +217,11 @@ void OutputSurface::SetWorkerContextShouldAggressivelyFreeResources( "OutputSurface::SetWorkerContextShouldAggressivelyFreeResources", "aggressively_free_resources", aggressively_free_resources); if (auto* context_provider = worker_context_provider()) { - ContextProvider::ScopedContextLock scoped_context(context_provider); + // The context lock must be held while accessing the worker context. + base::AutoLock context_lock(*context_provider->GetLock()); + + // Allow context to bind to current thread. + context_provider->DetachFromThread(); if (aggressively_free_resources) { context_provider->DeleteCachedResources(); @@ -217,6 +231,9 @@ void OutputSurface::SetWorkerContextShouldAggressivelyFreeResources( context_support->SetAggressivelyFreeResources( aggressively_free_resources); } + + // Allow context to bind to other threads. + context_provider->DetachFromThread(); } } diff --git a/cc/raster/gpu_tile_task_worker_pool.cc b/cc/raster/gpu_tile_task_worker_pool.cc index 2380455..3567308 100644 --- a/cc/raster/gpu_tile_task_worker_pool.cc +++ b/cc/raster/gpu_tile_task_worker_pool.cc @@ -46,9 +46,13 @@ class RasterBufferImpl : public RasterBuffer { ContextProvider* context_provider = rasterizer_->resource_provider() ->output_surface() ->worker_context_provider(); - DCHECK(context_provider); - ContextProvider::ScopedContextLock scoped_context(context_provider); + // The context lock must be held while accessing the context on a + // worker thread. + base::AutoLock context_lock(*context_provider->GetLock()); + + // Allow this worker thread to bind to context_provider. + context_provider->DetachFromThread(); gfx::Rect playback_rect = raster_full_rect; if (resource_has_previous_content_) { @@ -63,7 +67,10 @@ class RasterBufferImpl : public RasterBuffer { playback_rect, scale); // Barrier to sync worker context output to cc context. - scoped_context.ContextGL()->OrderingBarrierCHROMIUM(); + context_provider->ContextGL()->OrderingBarrierCHROMIUM(); + + // Allow compositor thread to bind to context_provider. + context_provider->DetachFromThread(); } private: diff --git a/cc/raster/one_copy_tile_task_worker_pool.cc b/cc/raster/one_copy_tile_task_worker_pool.cc index d0f1713..2d6f644 100644 --- a/cc/raster/one_copy_tile_task_worker_pool.cc +++ b/cc/raster/one_copy_tile_task_worker_pool.cc @@ -8,21 +8,17 @@ #include #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" -#include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" #include "cc/debug/traced_value.h" #include "cc/raster/raster_buffer.h" #include "cc/resources/platform_color.h" -#include "cc/resources/resource_format.h" -#include "cc/resources/resource_util.h" +#include "cc/resources/resource_pool.h" #include "cc/resources/scoped_resource.h" -#include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "ui/gfx/buffer_format_util.h" +#include "ui/gfx/gpu_memory_buffer.h" namespace cc { namespace { @@ -31,15 +27,49 @@ class RasterBufferImpl : public RasterBuffer { public: RasterBufferImpl(OneCopyTileTaskWorkerPool* worker_pool, ResourceProvider* resource_provider, + ResourcePool* resource_pool, ResourceFormat resource_format, - const Resource* resource, + const Resource* output_resource, uint64_t previous_content_id) : worker_pool_(worker_pool), - resource_(resource), - lock_(resource_provider, resource->id()), - previous_content_id_(previous_content_id) {} + resource_provider_(resource_provider), + resource_pool_(resource_pool), + output_resource_(output_resource), + raster_content_id_(0), + sequence_(0) { + if (worker_pool->have_persistent_gpu_memory_buffers() && + previous_content_id) { + raster_resource_ = + resource_pool->TryAcquireResourceWithContentId(previous_content_id); + } + if (raster_resource_) { + raster_content_id_ = previous_content_id; + DCHECK_EQ(resource_format, raster_resource_->format()); + DCHECK_EQ(output_resource->size().ToString(), + raster_resource_->size().ToString()); + } else { + raster_resource_ = resource_pool->AcquireResource(output_resource->size(), + resource_format); + } + + lock_.reset(new ResourceProvider::ScopedWriteLockGpuMemoryBuffer( + resource_provider_, raster_resource_->id())); + } - ~RasterBufferImpl() override {} + ~RasterBufferImpl() override { + // Release write lock in case a copy was never scheduled. + lock_.reset(); + + // Make sure any scheduled copy operations are issued before we release the + // raster resource. + if (sequence_) + worker_pool_->AdvanceLastIssuedCopyTo(sequence_); + + // Return resources to pool so they can be used by another RasterBuffer + // instance. + resource_pool_->ReleaseResource(raster_resource_.Pass(), + raster_content_id_); + } // Overridden from RasterBuffer: void Playback(const RasterSource* raster_source, @@ -48,117 +78,55 @@ class RasterBufferImpl : public RasterBuffer { uint64_t new_content_id, float scale, bool include_images) override { - worker_pool_->PlaybackAndCopyOnWorkerThread( - resource_, &lock_, raster_source, raster_full_rect, raster_dirty_rect, - scale, include_images, previous_content_id_, new_content_id); + // If there's a raster_content_id_, we are reusing a resource with that + // content id. + bool reusing_raster_resource = raster_content_id_ != 0; + sequence_ = worker_pool_->PlaybackAndScheduleCopyOnWorkerThread( + reusing_raster_resource, lock_.Pass(), raster_resource_.get(), + output_resource_, raster_source, raster_full_rect, raster_dirty_rect, + scale, include_images); + // Store the content id of the resource to return to the pool. + raster_content_id_ = new_content_id; } private: OneCopyTileTaskWorkerPool* worker_pool_; - const Resource* resource_; - ResourceProvider::ScopedWriteLockGL lock_; - uint64_t previous_content_id_; + ResourceProvider* resource_provider_; + ResourcePool* resource_pool_; + const Resource* output_resource_; + uint64_t raster_content_id_; + scoped_ptr raster_resource_; + scoped_ptr lock_; + CopySequenceNumber sequence_; DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); }; -// Delay between checking for query result to be available. -const int kCheckForQueryResultAvailableTickRateMs = 1; +// Number of in-flight copy operations to allow. +const int kMaxCopyOperations = 32; + +// Delay been checking for copy operations to complete. +const int kCheckForCompletedCopyOperationsTickRateMs = 1; -// Number of attempts to allow before we perform a check that will wait for -// query to complete. -const int kMaxCheckForQueryResultAvailableAttempts = 256; +// Number of failed attempts to allow before we perform a check that will +// wait for copy operations to complete if needed. +const int kFailedAttemptsBeforeWaitIfNeeded = 256; // 4MiB is the size of 4 512x512 tiles, which has proven to be a good // default batch size for copy operations. const int kMaxBytesPerCopyOperation = 1024 * 1024 * 4; -// Delay before a staging buffer might be released. -const int kStagingBufferExpirationDelayMs = 1000; - -bool CheckForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) { - unsigned complete = 1; - gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); - return !!complete; -} - -void WaitForQueryResult(gpu::gles2::GLES2Interface* gl, unsigned query_id) { - TRACE_EVENT0("cc", "WaitForQueryResult"); - - int attempts_left = kMaxCheckForQueryResultAvailableAttempts; - while (attempts_left--) { - if (CheckForQueryResult(gl, query_id)) - break; - - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( - kCheckForQueryResultAvailableTickRateMs)); - } - - unsigned result = 0; - gl->GetQueryObjectuivEXT(query_id, GL_QUERY_RESULT_EXT, &result); -} - } // namespace -OneCopyTileTaskWorkerPool::StagingBuffer::StagingBuffer(const gfx::Size& size) - : size(size), texture_id(0), image_id(0), query_id(0), content_id(0) {} - -OneCopyTileTaskWorkerPool::StagingBuffer::~StagingBuffer() { - DCHECK_EQ(texture_id, 0u); - DCHECK_EQ(image_id, 0u); - DCHECK_EQ(query_id, 0u); +OneCopyTileTaskWorkerPool::CopyOperation::CopyOperation( + scoped_ptr src_write_lock, + const Resource* src, + const Resource* dst, + const gfx::Rect& rect) + : src_write_lock(src_write_lock.Pass()), src(src), dst(dst), rect(rect) { } -void OneCopyTileTaskWorkerPool::StagingBuffer::DestroyGLResources( - gpu::gles2::GLES2Interface* gl) { - if (query_id) { - gl->DeleteQueriesEXT(1, &query_id); - query_id = 0; - } - if (image_id) { - gl->DestroyImageCHROMIUM(image_id); - image_id = 0; - } - if (texture_id) { - gl->DeleteTextures(1, &texture_id); - texture_id = 0; - } -} - -void OneCopyTileTaskWorkerPool::StagingBuffer::OnMemoryDump( - base::trace_event::ProcessMemoryDump* pmd, - ResourceFormat format, - bool in_free_list) const { - if (!gpu_memory_buffer) - return; - - gfx::GpuMemoryBufferId buffer_id = gpu_memory_buffer->GetId(); - std::string buffer_dump_name = - base::StringPrintf("cc/one_copy/staging_memory/buffer_%d", buffer_id.id); - base::trace_event::MemoryAllocatorDump* buffer_dump = - pmd->CreateAllocatorDump(buffer_dump_name); - - uint64_t buffer_size_in_bytes = - ResourceUtil::UncheckedSizeInBytes(size, format); - buffer_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - buffer_size_in_bytes); - buffer_dump->AddScalar("free_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - in_free_list ? buffer_size_in_bytes : 0); - - // Emit an ownership edge towards a global allocator dump node. - const uint64 tracing_process_id = - base::trace_event::MemoryDumpManager::GetInstance() - ->GetTracingProcessId(); - base::trace_event::MemoryAllocatorDumpGuid shared_buffer_guid = - gfx::GetGpuMemoryBufferGUIDForTracing(tracing_process_id, buffer_id); - pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); - - // By creating an edge with a higher |importance| (w.r.t. browser-side dumps) - // the tracing UI will account the effective size of the buffer to the child. - const int kImportance = 2; - pmd->AddOwnershipEdge(buffer_dump->guid(), shared_buffer_guid, kImportance); +OneCopyTileTaskWorkerPool::CopyOperation::~CopyOperation() { } // static @@ -167,49 +135,51 @@ scoped_ptr OneCopyTileTaskWorkerPool::Create( TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, + ResourcePool* resource_pool, int max_copy_texture_chromium_size, - bool use_persistent_gpu_memory_buffers, - int max_staging_buffers) { + bool have_persistent_gpu_memory_buffers) { return make_scoped_ptr(new OneCopyTileTaskWorkerPool( - task_runner, task_graph_runner, resource_provider, - max_copy_texture_chromium_size, use_persistent_gpu_memory_buffers, - max_staging_buffers)); + task_runner, task_graph_runner, context_provider, resource_provider, + resource_pool, max_copy_texture_chromium_size, + have_persistent_gpu_memory_buffers)); } OneCopyTileTaskWorkerPool::OneCopyTileTaskWorkerPool( base::SequencedTaskRunner* task_runner, TaskGraphRunner* task_graph_runner, + ContextProvider* context_provider, ResourceProvider* resource_provider, + ResourcePool* resource_pool, int max_copy_texture_chromium_size, - bool use_persistent_gpu_memory_buffers, - int max_staging_buffers) + bool have_persistent_gpu_memory_buffers) : task_runner_(task_runner), task_graph_runner_(task_graph_runner), namespace_token_(task_graph_runner->GetNamespaceToken()), + context_provider_(context_provider), resource_provider_(resource_provider), + resource_pool_(resource_pool), max_bytes_per_copy_operation_( max_copy_texture_chromium_size ? std::min(kMaxBytesPerCopyOperation, max_copy_texture_chromium_size) : kMaxBytesPerCopyOperation), - use_persistent_gpu_memory_buffers_(use_persistent_gpu_memory_buffers), + have_persistent_gpu_memory_buffers_(have_persistent_gpu_memory_buffers), + last_issued_copy_operation_(0), + last_flushed_copy_operation_(0), + lock_(), + copy_operation_count_cv_(&lock_), bytes_scheduled_since_last_flush_(0), - max_staging_buffers_(max_staging_buffers), - staging_buffer_expiration_delay_( - base::TimeDelta::FromMilliseconds(kStagingBufferExpirationDelayMs)), - reduce_memory_usage_pending_(false), + issued_copy_operation_count_(0), + next_copy_operation_sequence_(1), + check_for_completed_copy_operations_pending_(false), + shutdown_(false), weak_ptr_factory_(this), task_set_finished_weak_ptr_factory_(this) { - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, base::ThreadTaskRunnerHandle::Get()); - reduce_memory_usage_callback_ = - base::Bind(&OneCopyTileTaskWorkerPool::ReduceMemoryUsage, - weak_ptr_factory_.GetWeakPtr()); + DCHECK(context_provider_); } OneCopyTileTaskWorkerPool::~OneCopyTileTaskWorkerPool() { - base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( - this); + DCHECK_EQ(pending_copy_operations_.size(), 0u); } TileTaskRunner* OneCopyTileTaskWorkerPool::AsTileTaskRunner() { @@ -223,21 +193,28 @@ void OneCopyTileTaskWorkerPool::SetClient(TileTaskRunnerClient* client) { void OneCopyTileTaskWorkerPool::Shutdown() { TRACE_EVENT0("cc", "OneCopyTileTaskWorkerPool::Shutdown"); + { + base::AutoLock lock(lock_); + + shutdown_ = true; + copy_operation_count_cv_.Signal(); + } + TaskGraph empty; task_graph_runner_->ScheduleTasks(namespace_token_, &empty); task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); - - base::AutoLock lock(lock_); - - if (buffers_.empty()) - return; - - ReleaseBuffersNotUsedSince(base::TimeTicks() + base::TimeDelta::Max()); } void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { TRACE_EVENT0("cc", "OneCopyTileTaskWorkerPool::ScheduleTasks"); +#if DCHECK_IS_ON() + { + base::AutoLock lock(lock_); + DCHECK(!shutdown_); + } +#endif + if (tasks_pending_.none()) TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); @@ -262,6 +239,8 @@ void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { task_set_finished_weak_ptr_factory_.GetWeakPtr(), task_set)); } + resource_pool_->CheckBusyResources(false); + for (TileTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); it != queue->items.end(); ++it) { const TileTaskQueue::Item& item = *it; @@ -288,19 +267,14 @@ void OneCopyTileTaskWorkerPool::ScheduleTasks(TileTaskQueue* queue) { } ScheduleTasksOnOriginThread(this, &graph_); - - // Barrier to sync any new resources to the worker context. - resource_provider_->output_surface() - ->context_provider() - ->ContextGL() - ->OrderingBarrierCHROMIUM(); - task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); std::copy(new_task_set_finished_tasks, new_task_set_finished_tasks + kNumberOfTaskSets, task_set_finished_tasks_); + resource_pool_->ReduceResourceUsage(); + TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", "state", StateAsValue()); } @@ -339,9 +313,10 @@ scoped_ptr OneCopyTileTaskWorkerPool::AcquireBufferForRaster( // TODO(danakj): If resource_content_id != 0, we only need to copy/upload // the dirty rect. DCHECK_EQ(resource->format(), resource_provider_->best_texture_format()); - return make_scoped_ptr(new RasterBufferImpl( - this, resource_provider_, resource_provider_->best_texture_format(), - resource, previous_content_id)); + return make_scoped_ptr( + new RasterBufferImpl(this, resource_provider_, resource_pool_, + resource_provider_->best_texture_format(), resource, + previous_content_id)); } void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster( @@ -349,375 +324,238 @@ void OneCopyTileTaskWorkerPool::ReleaseBufferForRaster( // Nothing to do here. RasterBufferImpl destructor cleans up after itself. } -void OneCopyTileTaskWorkerPool::PlaybackAndCopyOnWorkerThread( - const Resource* resource, - const ResourceProvider::ScopedWriteLockGL* resource_lock, +CopySequenceNumber +OneCopyTileTaskWorkerPool::PlaybackAndScheduleCopyOnWorkerThread( + bool reusing_raster_resource, + scoped_ptr + raster_resource_write_lock, + const Resource* raster_resource, + const Resource* output_resource, const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, float scale, - bool include_images, - uint64_t previous_content_id, - uint64_t new_content_id) { - base::AutoLock lock(lock_); - - scoped_ptr staging_buffer = - AcquireStagingBuffer(resource, previous_content_id); - DCHECK(staging_buffer); - - { - base::AutoUnlock unlock(lock_); - - // Allocate GpuMemoryBuffer if necessary. - if (!staging_buffer->gpu_memory_buffer) { - staging_buffer->gpu_memory_buffer = - resource_provider_->gpu_memory_buffer_manager() - ->AllocateGpuMemoryBuffer( - staging_buffer->size, - BufferFormat(resource_provider_->best_texture_format()), - use_persistent_gpu_memory_buffers_ - ? gfx::BufferUsage::PERSISTENT_MAP - : gfx::BufferUsage::MAP); - DCHECK_EQ(gfx::NumberOfPlanesForBufferFormat( - staging_buffer->gpu_memory_buffer->GetFormat()), - 1u); - } + bool include_images) { + gfx::GpuMemoryBuffer* gpu_memory_buffer = + raster_resource_write_lock->GetGpuMemoryBuffer(); + if (gpu_memory_buffer) { + DCHECK_EQ( + 1u, gfx::NumberOfPlanesForBufferFormat(gpu_memory_buffer->GetFormat())); + void* data = NULL; + bool rv = gpu_memory_buffer->Map(&data); + DCHECK(rv); + int stride; + gpu_memory_buffer->GetStride(&stride); + // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides. + DCHECK_GE(stride, 0); gfx::Rect playback_rect = raster_full_rect; - if (use_persistent_gpu_memory_buffers_ && previous_content_id) { - // Reduce playback rect to dirty region if the content id of the staging - // buffer matches the prevous content id. - if (previous_content_id == staging_buffer->content_id) - playback_rect.Intersect(raster_dirty_rect); - } - - if (staging_buffer->gpu_memory_buffer) { - void* data = nullptr; - bool rv = staging_buffer->gpu_memory_buffer->Map(&data); - DCHECK(rv); - int stride; - staging_buffer->gpu_memory_buffer->GetStride(&stride); - // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides. - DCHECK_GE(stride, 0); - - DCHECK(!playback_rect.IsEmpty()) - << "Why are we rastering a tile that's not dirty?"; - TileTaskWorkerPool::PlaybackToMemory( - data, resource_provider_->best_texture_format(), staging_buffer->size, - static_cast(stride), raster_source, raster_full_rect, - playback_rect, scale, include_images); - staging_buffer->gpu_memory_buffer->Unmap(); - staging_buffer->content_id = new_content_id; + if (reusing_raster_resource) { + playback_rect.Intersect(raster_dirty_rect); } + DCHECK(!playback_rect.IsEmpty()) + << "Why are we rastering a tile that's not dirty?"; + TileTaskWorkerPool::PlaybackToMemory( + data, raster_resource->format(), raster_resource->size(), + static_cast(stride), raster_source, raster_full_rect, + playback_rect, scale, include_images); + gpu_memory_buffer->Unmap(); } - ContextProvider* context_provider = - resource_provider_->output_surface()->worker_context_provider(); - DCHECK(context_provider); + base::AutoLock lock(lock_); - { - ContextProvider::ScopedContextLock scoped_context(context_provider); - - gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); - DCHECK(gl); - - unsigned image_target = resource_provider_->GetImageTextureTarget( - resource_provider_->best_texture_format()); - - // Create and bind staging texture. - if (!staging_buffer->texture_id) { - gl->GenTextures(1, &staging_buffer->texture_id); - gl->BindTexture(image_target, staging_buffer->texture_id); - gl->TexParameteri(image_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri(image_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri(image_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(image_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } else { - gl->BindTexture(image_target, staging_buffer->texture_id); - } + CopySequenceNumber sequence = 0; + int bytes_per_row = (BitsPerPixel(raster_resource->format()) * + raster_resource->size().width()) / + 8; + int chunk_size_in_rows = + std::max(1, max_bytes_per_copy_operation_ / bytes_per_row); + // Align chunk size to 4. Required to support compressed texture formats. + chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4); + int y = 0; + int height = raster_resource->size().height(); + while (y < height) { + int failed_attempts = 0; + while ((pending_copy_operations_.size() + issued_copy_operation_count_) >= + kMaxCopyOperations) { + // Ignore limit when shutdown is set. + if (shutdown_) + break; - // Create and bind image. - if (!staging_buffer->image_id) { - if (staging_buffer->gpu_memory_buffer) { - staging_buffer->image_id = gl->CreateImageCHROMIUM( - staging_buffer->gpu_memory_buffer->AsClientBuffer(), - staging_buffer->size.width(), staging_buffer->size.height(), - GLInternalFormat(resource_provider_->best_texture_format())); - gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); - } - } else { - gl->ReleaseTexImage2DCHROMIUM(image_target, staging_buffer->image_id); - gl->BindTexImage2DCHROMIUM(image_target, staging_buffer->image_id); - } + ++failed_attempts; - // Unbind staging texture. - gl->BindTexture(image_target, 0); - - if (resource_provider_->use_sync_query()) { - if (!staging_buffer->query_id) - gl->GenQueriesEXT(1, &staging_buffer->query_id); - -#if defined(OS_CHROMEOS) - // TODO(reveman): This avoids a performance problem on some ChromeOS - // devices. This needs to be removed to support native GpuMemoryBuffer - // implementations. crbug.com/436314 - gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, staging_buffer->query_id); -#else - gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, - staging_buffer->query_id); -#endif - } + // Schedule a check that will also wait for operations to complete + // after too many failed attempts. + bool wait_if_needed = failed_attempts > kFailedAttemptsBeforeWaitIfNeeded; + + // Schedule a check for completed copy operations if too many operations + // are currently in-flight. + ScheduleCheckForCompletedCopyOperationsWithLockAcquired(wait_if_needed); - int bytes_per_row = - (BitsPerPixel(resource_provider_->best_texture_format()) * - resource->size().width()) / - 8; - int chunk_size_in_rows = - std::max(1, max_bytes_per_copy_operation_ / bytes_per_row); - // Align chunk size to 4. Required to support compressed texture formats. - chunk_size_in_rows = MathUtil::UncheckedRoundUp(chunk_size_in_rows, 4); - int y = 0; - int height = resource->size().height(); - while (y < height) { - // Copy at most |chunk_size_in_rows|. - int rows_to_copy = std::min(chunk_size_in_rows, height - y); - DCHECK_GT(rows_to_copy, 0); - - gl->CopySubTextureCHROMIUM(GL_TEXTURE_2D, staging_buffer->texture_id, - resource_lock->texture_id(), 0, y, 0, y, - resource->size().width(), rows_to_copy, false, - false, false); - y += rows_to_copy; - - // Increment |bytes_scheduled_since_last_flush_| by the amount of memory - // used for this copy operation. - bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row; - - if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) { - gl->ShallowFlushCHROMIUM(); - bytes_scheduled_since_last_flush_ = 0; + { + TRACE_EVENT0("cc", "WaitingForCopyOperationsToComplete"); + + // Wait for in-flight copy operations to drop below limit. + copy_operation_count_cv_.Wait(); } } - if (resource_provider_->use_sync_query()) { -#if defined(OS_CHROMEOS) - gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); -#else - gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); -#endif + // There may be more work available, so wake up another worker thread. + copy_operation_count_cv_.Signal(); + + // Copy at most |chunk_size_in_rows|. + int rows_to_copy = std::min(chunk_size_in_rows, height - y); + DCHECK_GT(rows_to_copy, 0); + + // |raster_resource_write_lock| is passed to the first copy operation as it + // needs to be released before we can issue a copy. + pending_copy_operations_.push_back(make_scoped_ptr(new CopyOperation( + raster_resource_write_lock.Pass(), raster_resource, output_resource, + gfx::Rect(0, y, raster_resource->size().width(), rows_to_copy)))); + y += rows_to_copy; + + // Acquire a sequence number for this copy operation. + sequence = next_copy_operation_sequence_++; + + // Increment |bytes_scheduled_since_last_flush_| by the amount of memory + // used for this copy operation. + bytes_scheduled_since_last_flush_ += rows_to_copy * bytes_per_row; + + // Post task that will advance last flushed copy operation to |sequence| + // when |bytes_scheduled_since_last_flush_| has reached + // |max_bytes_per_copy_operation_|. + if (bytes_scheduled_since_last_flush_ >= max_bytes_per_copy_operation_) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo, + weak_ptr_factory_.GetWeakPtr(), sequence)); + bytes_scheduled_since_last_flush_ = 0; } - - // Barrier to sync worker context output to cc context. - gl->OrderingBarrierCHROMIUM(); } - staging_buffer->last_usage = base::TimeTicks::Now(); - busy_buffers_.push_back(staging_buffer.Pass()); - - ScheduleReduceMemoryUsage(); + return sequence; } -bool OneCopyTileTaskWorkerPool::OnMemoryDump( - const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) { - base::AutoLock lock(lock_); - - for (const auto& buffer : buffers_) { - buffer->OnMemoryDump(pmd, resource_provider_->best_texture_format(), - std::find(free_buffers_.begin(), free_buffers_.end(), - buffer) != free_buffers_.end()); - } +void OneCopyTileTaskWorkerPool::AdvanceLastIssuedCopyTo( + CopySequenceNumber sequence) { + if (last_issued_copy_operation_ >= sequence) + return; - return true; + IssueCopyOperations(sequence - last_issued_copy_operation_); + last_issued_copy_operation_ = sequence; } -scoped_ptr -OneCopyTileTaskWorkerPool::AcquireStagingBuffer(const Resource* resource, - uint64_t previous_content_id) { - lock_.AssertAcquired(); +void OneCopyTileTaskWorkerPool::AdvanceLastFlushedCopyTo( + CopySequenceNumber sequence) { + if (last_flushed_copy_operation_ >= sequence) + return; - scoped_ptr staging_buffer; + AdvanceLastIssuedCopyTo(sequence); - ContextProvider* context_provider = - resource_provider_->output_surface()->worker_context_provider(); - DCHECK(context_provider); + // Flush all issued copy operations. + context_provider_->ContextGL()->ShallowFlushCHROMIUM(); + last_flushed_copy_operation_ = last_issued_copy_operation_; +} - ContextProvider::ScopedContextLock scoped_context(context_provider); +void OneCopyTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set) { + TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::OnTaskSetFinished", "task_set", + task_set); - gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); - DCHECK(gl); + DCHECK(tasks_pending_[task_set]); + tasks_pending_[task_set] = false; + if (tasks_pending_.any()) { + TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", + "state", StateAsValue()); + } else { + TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); + } + client_->DidFinishRunningTileTasks(task_set); +} - // Check if any busy buffers have become available. - if (resource_provider_->use_sync_query()) { - while (!busy_buffers_.empty()) { - if (!CheckForQueryResult(gl, busy_buffers_.front()->query_id)) - break; +void OneCopyTileTaskWorkerPool::IssueCopyOperations(int64 count) { + TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::IssueCopyOperations", "count", + count); - free_buffers_.push_back(busy_buffers_.take_front()); - } - } + CopyOperation::Deque copy_operations; - // Wait for number of non-free buffers to become less than the limit. - while ((buffers_.size() - free_buffers_.size()) >= max_staging_buffers_) { - // Stop when there are no more busy buffers to wait for. - if (busy_buffers_.empty()) - break; + { + base::AutoLock lock(lock_); - if (resource_provider_->use_sync_query()) { - WaitForQueryResult(gl, busy_buffers_.front()->query_id); - free_buffers_.push_back(busy_buffers_.take_front()); - } else { - // Fall-back to glFinish if CHROMIUM_sync_query is not available. - gl->Finish(); - while (!busy_buffers_.empty()) - free_buffers_.push_back(busy_buffers_.take_front()); + for (int64 i = 0; i < count; ++i) { + DCHECK(!pending_copy_operations_.empty()); + copy_operations.push_back(pending_copy_operations_.take_front()); } - } - // Find a staging buffer that allows us to perform partial raster when - // using persistent GpuMemoryBuffers. - if (use_persistent_gpu_memory_buffers_ && previous_content_id) { - StagingBufferDeque::iterator it = - std::find_if(free_buffers_.begin(), free_buffers_.end(), - [previous_content_id](const StagingBuffer* buffer) { - return buffer->content_id == previous_content_id; - }); - if (it != free_buffers_.end()) - staging_buffer = free_buffers_.take(it); + // Increment |issued_copy_operation_count_| to reflect the transition of + // copy operations from "pending" to "issued" state. + issued_copy_operation_count_ += copy_operations.size(); } - // Find staging buffer of correct size. - if (!staging_buffer) { - StagingBufferDeque::iterator it = - std::find_if(free_buffers_.begin(), free_buffers_.end(), - [resource](const StagingBuffer* buffer) { - return buffer->size == resource->size(); - }); - if (it != free_buffers_.end()) - staging_buffer = free_buffers_.take(it); - } + while (!copy_operations.empty()) { + scoped_ptr copy_operation = copy_operations.take_front(); - // Create new staging buffer if necessary. - if (!staging_buffer) { - staging_buffer = make_scoped_ptr(new StagingBuffer(resource->size())); - buffers_.insert(staging_buffer.get()); - } + // Remove the write lock. + copy_operation->src_write_lock.reset(); - // Release enough free buffers to stay within the limit. - while (buffers_.size() > max_staging_buffers_) { - if (free_buffers_.empty()) - break; - - free_buffers_.front()->DestroyGLResources(gl); - buffers_.erase(free_buffers_.front()); - free_buffers_.take_front(); + // Copy contents of source resource to destination resource. + resource_provider_->CopyResource(copy_operation->src->id(), + copy_operation->dst->id(), + copy_operation->rect); } - - return staging_buffer.Pass(); -} - -base::TimeTicks OneCopyTileTaskWorkerPool::GetUsageTimeForLRUBuffer() { - lock_.AssertAcquired(); - - if (!free_buffers_.empty()) - return free_buffers_.front()->last_usage; - - if (!busy_buffers_.empty()) - return busy_buffers_.front()->last_usage; - - return base::TimeTicks(); } -void OneCopyTileTaskWorkerPool::ScheduleReduceMemoryUsage() { +void OneCopyTileTaskWorkerPool:: + ScheduleCheckForCompletedCopyOperationsWithLockAcquired( + bool wait_if_needed) { lock_.AssertAcquired(); - if (reduce_memory_usage_pending_) + if (check_for_completed_copy_operations_pending_) return; - reduce_memory_usage_pending_ = true; + base::TimeTicks now = base::TimeTicks::Now(); - // Schedule a call to ReduceMemoryUsage at the time when the LRU buffer - // should be released. - base::TimeTicks reduce_memory_usage_time = - GetUsageTimeForLRUBuffer() + staging_buffer_expiration_delay_; - task_runner_->PostDelayedTask( - FROM_HERE, reduce_memory_usage_callback_, - reduce_memory_usage_time - base::TimeTicks::Now()); -} - -void OneCopyTileTaskWorkerPool::ReduceMemoryUsage() { - base::AutoLock lock(lock_); - - reduce_memory_usage_pending_ = false; + // Schedule a check for completed copy operations as soon as possible but + // don't allow two consecutive checks to be scheduled to run less than the + // tick rate apart. + base::TimeTicks next_check_for_completed_copy_operations_time = + std::max(last_check_for_completed_copy_operations_time_ + + base::TimeDelta::FromMilliseconds( + kCheckForCompletedCopyOperationsTickRateMs), + now); - if (free_buffers_.empty() && busy_buffers_.empty()) - return; - - base::TimeTicks current_time = base::TimeTicks::Now(); - ReleaseBuffersNotUsedSince(current_time - staging_buffer_expiration_delay_); - - if (free_buffers_.empty() && busy_buffers_.empty()) - return; - - reduce_memory_usage_pending_ = true; - - // Schedule another call to ReduceMemoryUsage at the time when the next - // buffer should be released. - base::TimeTicks reduce_memory_usage_time = - GetUsageTimeForLRUBuffer() + staging_buffer_expiration_delay_; - task_runner_->PostDelayedTask(FROM_HERE, reduce_memory_usage_callback_, - reduce_memory_usage_time - current_time); + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations, + weak_ptr_factory_.GetWeakPtr(), wait_if_needed), + next_check_for_completed_copy_operations_time - now); + + last_check_for_completed_copy_operations_time_ = + next_check_for_completed_copy_operations_time; + check_for_completed_copy_operations_pending_ = true; } -void OneCopyTileTaskWorkerPool::ReleaseBuffersNotUsedSince( - base::TimeTicks time) { - lock_.AssertAcquired(); +void OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations( + bool wait_if_needed) { + TRACE_EVENT1("cc", + "OneCopyTileTaskWorkerPool::CheckForCompletedCopyOperations", + "wait_if_needed", wait_if_needed); - ContextProvider* context_provider = - resource_provider_->output_surface()->worker_context_provider(); - DCHECK(context_provider); + resource_pool_->CheckBusyResources(wait_if_needed); { - ContextProvider::ScopedContextLock scoped_context(context_provider); - - gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); - DCHECK(gl); - - // Note: Front buffer is guaranteed to be LRU so we can stop releasing - // buffers as soon as we find a buffer that has been used since |time|. - while (!free_buffers_.empty()) { - if (free_buffers_.front()->last_usage > time) - return; - - free_buffers_.front()->DestroyGLResources(gl); - buffers_.erase(free_buffers_.front()); - free_buffers_.take_front(); - } + base::AutoLock lock(lock_); - while (!busy_buffers_.empty()) { - if (busy_buffers_.front()->last_usage > time) - return; + DCHECK(check_for_completed_copy_operations_pending_); + check_for_completed_copy_operations_pending_ = false; - busy_buffers_.front()->DestroyGLResources(gl); - buffers_.erase(busy_buffers_.front()); - busy_buffers_.take_front(); - } - } -} + // The number of busy resources in the pool reflects the number of issued + // copy operations that have not yet completed. + issued_copy_operation_count_ = resource_pool_->busy_resource_count(); -void OneCopyTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set) { - TRACE_EVENT1("cc", "OneCopyTileTaskWorkerPool::OnTaskSetFinished", "task_set", - task_set); - - DCHECK(tasks_pending_[task_set]); - tasks_pending_[task_set] = false; - if (tasks_pending_.any()) { - TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, "running", - "state", StateAsValue()); - } else { - TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); + // There may be work blocked on too many in-flight copy operations, so wake + // up a worker thread. + copy_operation_count_cv_.Signal(); } - client_->DidFinishRunningTileTasks(task_set); } scoped_refptr @@ -738,14 +576,20 @@ OneCopyTileTaskWorkerPool::StateAsValue() const { void OneCopyTileTaskWorkerPool::StagingStateAsValueInto( base::trace_event::TracedValue* staging_state) const { - base::AutoLock lock(lock_); - - staging_state->SetInteger("staging_buffer_count", - static_cast(buffers_.size())); - staging_state->SetInteger("busy_count", - static_cast(busy_buffers_.size())); - staging_state->SetInteger("free_count", - static_cast(free_buffers_.size())); + staging_state->SetInteger( + "staging_resource_count", + static_cast(resource_pool_->total_resource_count())); + staging_state->SetInteger( + "bytes_used_for_staging_resources", + static_cast(resource_pool_->total_memory_usage_bytes())); + staging_state->SetInteger( + "pending_copy_count", + static_cast(resource_pool_->total_resource_count() - + resource_pool_->acquired_resource_count())); + staging_state->SetInteger( + "bytes_pending_copy", + static_cast(resource_pool_->total_memory_usage_bytes() - + resource_pool_->acquired_memory_usage_bytes())); } } // namespace cc diff --git a/cc/raster/one_copy_tile_task_worker_pool.h b/cc/raster/one_copy_tile_task_worker_pool.h index 851f1b4..4e050b4 100644 --- a/cc/raster/one_copy_tile_task_worker_pool.h +++ b/cc/raster/one_copy_tile_task_worker_pool.h @@ -5,12 +5,8 @@ #ifndef CC_RASTER_ONE_COPY_TILE_TASK_WORKER_POOL_H_ #define CC_RASTER_ONE_COPY_TILE_TASK_WORKER_POOL_H_ -#include - #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" -#include "base/time/time.h" -#include "base/trace_event/memory_dump_provider.h" #include "base/values.h" #include "cc/base/scoped_ptr_deque.h" #include "cc/output/context_provider.h" @@ -25,20 +21,15 @@ class TracedValue; } } -namespace gpu { -namespace gles2 { -class GLES2Interface; -} -} - namespace cc { class ResourcePool; +class ScopedResource; + +typedef int64 CopySequenceNumber; -class CC_EXPORT OneCopyTileTaskWorkerPool - : public TileTaskWorkerPool, - public TileTaskRunner, - public TileTaskClient, - public base::trace_event::MemoryDumpProvider { +class CC_EXPORT OneCopyTileTaskWorkerPool : public TileTaskWorkerPool, + public TileTaskRunner, + public TileTaskClient { public: ~OneCopyTileTaskWorkerPool() override; @@ -47,9 +38,9 @@ class CC_EXPORT OneCopyTileTaskWorkerPool TaskGraphRunner* task_graph_runner, ContextProvider* context_provider, ResourceProvider* resource_provider, + ResourcePool* resource_pool, int max_copy_texture_chromium_size, - bool use_persistent_gpu_memory_buffers, - int max_staging_buffers); + bool have_persistent_gpu_memory_buffers); // Overridden from TileTaskWorkerPool: TileTaskRunner* AsTileTaskRunner() override; @@ -69,57 +60,61 @@ class CC_EXPORT OneCopyTileTaskWorkerPool uint64_t previous_content_id) override; void ReleaseBufferForRaster(scoped_ptr buffer) override; - // Overridden from base::trace_event::MemoryDumpProvider: - bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* pmd) override; - - // Playback raster source and copy result into |resource|. - void PlaybackAndCopyOnWorkerThread( - const Resource* resource, - const ResourceProvider::ScopedWriteLockGL* resource_lock, + // Playback raster source and schedule copy of |raster_resource| resource to + // |output_resource|. Returns a non-zero sequence number for this copy + // operation. + CopySequenceNumber PlaybackAndScheduleCopyOnWorkerThread( + bool reusing_raster_resource, + scoped_ptr + raster_resource_write_lock, + const Resource* raster_resource, + const Resource* output_resource, const RasterSource* raster_source, const gfx::Rect& raster_full_rect, const gfx::Rect& raster_dirty_rect, float scale, - bool include_images, - uint64_t resource_content_id, - uint64_t previous_content_id); + bool include_images); + + // Issues copy operations until |sequence| has been processed. This will + // return immediately if |sequence| has already been processed. + void AdvanceLastIssuedCopyTo(CopySequenceNumber sequence); + + bool have_persistent_gpu_memory_buffers() const { + return have_persistent_gpu_memory_buffers_; + } protected: OneCopyTileTaskWorkerPool(base::SequencedTaskRunner* task_runner, TaskGraphRunner* task_graph_runner, + ContextProvider* context_provider, ResourceProvider* resource_provider, + ResourcePool* resource_pool, int max_copy_texture_chromium_size, - bool use_persistent_gpu_memory_buffers, - int max_staging_buffers); + bool have_persistent_gpu_memory_buffers); private: - struct StagingBuffer { - explicit StagingBuffer(const gfx::Size& size); - ~StagingBuffer(); - - void DestroyGLResources(gpu::gles2::GLES2Interface* gl); - void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, - ResourceFormat format, - bool is_free) const; - - const gfx::Size size; - scoped_ptr gpu_memory_buffer; - base::TimeTicks last_usage; - unsigned texture_id; - unsigned image_id; - unsigned query_id; - uint64_t content_id; + struct CopyOperation { + typedef ScopedPtrDeque Deque; + + CopyOperation(scoped_ptr + src_write_lock, + const Resource* src, + const Resource* dst, + const gfx::Rect& rect); + ~CopyOperation(); + + scoped_ptr src_write_lock; + const Resource* src; + const Resource* dst; + const gfx::Rect rect; }; - scoped_ptr AcquireStagingBuffer(const Resource* resource, - uint64_t previous_content_id); - base::TimeTicks GetUsageTimeForLRUBuffer(); - void ScheduleReduceMemoryUsage(); - void ReduceMemoryUsage(); - void ReleaseBuffersNotUsedSince(base::TimeTicks time); - void OnTaskSetFinished(TaskSet task_set); + void AdvanceLastFlushedCopyTo(CopySequenceNumber sequence); + void IssueCopyOperations(int64 count); + void ScheduleCheckForCompletedCopyOperationsWithLockAcquired( + bool wait_if_needed); + void CheckForCompletedCopyOperations(bool wait_if_needed); scoped_refptr StateAsValue() const; void StagingStateAsValueInto( @@ -129,29 +124,31 @@ class CC_EXPORT OneCopyTileTaskWorkerPool TaskGraphRunner* task_graph_runner_; const NamespaceToken namespace_token_; TileTaskRunnerClient* client_; - ResourceProvider* const resource_provider_; + ContextProvider* context_provider_; + ResourceProvider* resource_provider_; + ResourcePool* resource_pool_; const int max_bytes_per_copy_operation_; - const bool use_persistent_gpu_memory_buffers_; + const bool have_persistent_gpu_memory_buffers_; TaskSetCollection tasks_pending_; scoped_refptr task_set_finished_tasks_[kNumberOfTaskSets]; + CopySequenceNumber last_issued_copy_operation_; + CopySequenceNumber last_flushed_copy_operation_; // Task graph used when scheduling tasks and vector used to gather // completed tasks. TaskGraph graph_; Task::Vector completed_tasks_; - mutable base::Lock lock_; + base::Lock lock_; // |lock_| must be acquired when accessing the following members. - using StagingBufferSet = std::set; - StagingBufferSet buffers_; - using StagingBufferDeque = ScopedPtrDeque; - StagingBufferDeque free_buffers_; - StagingBufferDeque busy_buffers_; + base::ConditionVariable copy_operation_count_cv_; int bytes_scheduled_since_last_flush_; - size_t max_staging_buffers_; - const base::TimeDelta staging_buffer_expiration_delay_; - bool reduce_memory_usage_pending_; - base::Closure reduce_memory_usage_callback_; + size_t issued_copy_operation_count_; + CopyOperation::Deque pending_copy_operations_; + CopySequenceNumber next_copy_operation_sequence_; + bool check_for_completed_copy_operations_pending_; + base::TimeTicks last_check_for_completed_copy_operations_time_; + bool shutdown_; base::WeakPtrFactory weak_ptr_factory_; // "raster finished" tasks need their own factory as they need to be diff --git a/cc/raster/tile_task_worker_pool_perftest.cc b/cc/raster/tile_task_worker_pool_perftest.cc index 1262ace..b49c498 100644 --- a/cc/raster/tile_task_worker_pool_perftest.cc +++ b/cc/raster/tile_task_worker_pool_perftest.cc @@ -265,11 +265,13 @@ class TileTaskWorkerPoolPerfTest break; case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY: Create3dOutputSurfaceAndResourceProvider(); + staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(), + GL_TEXTURE_2D); tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create( task_runner_.get(), task_graph_runner_.get(), context_provider_.get(), resource_provider_.get(), - std::numeric_limits::max(), false, - std::numeric_limits::max()); + staging_resource_pool_.get(), std::numeric_limits::max(), + false); break; case TILE_TASK_WORKER_POOL_TYPE_GPU: Create3dOutputSurfaceAndResourceProvider(); @@ -429,6 +431,7 @@ class TileTaskWorkerPoolPerfTest return std::string(); } + scoped_ptr staging_resource_pool_; scoped_ptr tile_task_worker_pool_; TestGpuMemoryBufferManager gpu_memory_buffer_manager_; TestSharedBitmapManager shared_bitmap_manager_; diff --git a/cc/raster/tile_task_worker_pool_unittest.cc b/cc/raster/tile_task_worker_pool_unittest.cc index bf2a82a..6038b00 100644 --- a/cc/raster/tile_task_worker_pool_unittest.cc +++ b/cc/raster/tile_task_worker_pool_unittest.cc @@ -41,7 +41,6 @@ namespace { const size_t kMaxTransferBufferUsageBytes = 10000U; const size_t kMaxBytesPerCopyOperation = 1000U; -const size_t kMaxStagingBuffers = 32U; // A resource of this dimension^2 * 4 must be greater than the above transfer // buffer constant. @@ -166,10 +165,12 @@ class TileTaskWorkerPoolTest break; case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY: Create3dOutputSurfaceAndResourceProvider(); + staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(), + GL_TEXTURE_2D); tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create( base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_, context_provider_.get(), resource_provider_.get(), - kMaxBytesPerCopyOperation, false, kMaxStagingBuffers); + staging_resource_pool_.get(), kMaxBytesPerCopyOperation, false); break; case TILE_TASK_WORKER_POOL_TYPE_GPU: Create3dOutputSurfaceAndResourceProvider(); @@ -331,6 +332,7 @@ class TileTaskWorkerPoolTest FakeOutputSurfaceClient output_surface_client_; scoped_ptr output_surface_; scoped_ptr resource_provider_; + scoped_ptr staging_resource_pool_; scoped_ptr tile_task_worker_pool_; TestGpuMemoryBufferManager gpu_memory_buffer_manager_; TestSharedBitmapManager shared_bitmap_manager_; diff --git a/cc/resources/resource_format.cc b/cc/resources/resource_format.cc index c62ae93..ce9fe7d 100644 --- a/cc/resources/resource_format.cc +++ b/cc/resources/resource_format.cc @@ -87,23 +87,4 @@ GLenum GLInternalFormat(ResourceFormat format) { return GLDataFormat(format); } -gfx::BufferFormat BufferFormat(ResourceFormat format) { - switch (format) { - case RGBA_8888: - return gfx::BufferFormat::RGBA_8888; - case BGRA_8888: - return gfx::BufferFormat::BGRA_8888; - case RGBA_4444: - return gfx::BufferFormat::RGBA_4444; - case ALPHA_8: - case LUMINANCE_8: - case RGB_565: - case ETC1: - case RED_8: - break; - } - NOTREACHED(); - return gfx::BufferFormat::RGBA_8888; -} - } // namespace cc diff --git a/cc/resources/resource_format.h b/cc/resources/resource_format.h index 79b815f..d910bb0 100644 --- a/cc/resources/resource_format.h +++ b/cc/resources/resource_format.h @@ -8,7 +8,6 @@ #include "base/logging.h" #include "cc/base/cc_export.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/gpu_memory_buffer.h" // TODO(prashant.n): Including third_party/khronos/GLES2/gl2.h causes // redefinition errors as macros/functions defined in it conflict with @@ -36,7 +35,6 @@ CC_EXPORT int BitsPerPixel(ResourceFormat format); CC_EXPORT GLenum GLDataType(ResourceFormat format); CC_EXPORT GLenum GLDataFormat(ResourceFormat format); CC_EXPORT GLenum GLInternalFormat(ResourceFormat format); -CC_EXPORT gfx::BufferFormat BufferFormat(ResourceFormat format); } // namespace cc diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index e0e5af3..cdcaa4d 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc @@ -191,12 +191,15 @@ void ResourcePool::DeleteResource(ScopedResource* resource) { delete resource; } -void ResourcePool::CheckBusyResources() { +void ResourcePool::CheckBusyResources(bool wait_if_needed) { ResourceList::iterator it = busy_resources_.begin(); while (it != busy_resources_.end()) { ScopedResource* resource = it->resource; + if (wait_if_needed) + resource_provider_->WaitReadLockIfNeeded(resource->id()); + if (resource_provider_->CanLockForWrite(resource->id())) { DidFinishUsingResource(resource, it->content_id); it = busy_resources_.erase(it); diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index e87e217..e577826 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h @@ -41,7 +41,10 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { size_t max_resource_count); void ReduceResourceUsage(); - void CheckBusyResources(); + // This might block if |wait_if_needed| is true and one of the currently + // busy resources has a read lock fence that needs to be waited upon before + // it can be locked for write again. + void CheckBusyResources(bool wait_if_needed); size_t total_memory_usage_bytes() const { return memory_usage_bytes_; } size_t acquired_memory_usage_bytes() const { diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc index f280f49..035b19e 100644 --- a/cc/resources/resource_pool_unittest.cc +++ b/cc/resources/resource_pool_unittest.cc @@ -71,7 +71,8 @@ TEST_F(ResourcePoolTest, AccountingSingleResource) { EXPECT_EQ(1u, resource_pool_->total_resource_count()); EXPECT_EQ(1u, resource_pool_->busy_resource_count()); - resource_pool_->CheckBusyResources(); + bool wait_if_needed = false; + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes()); EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes()); EXPECT_EQ(1u, resource_pool_->total_resource_count()); @@ -95,25 +96,26 @@ TEST_F(ResourcePoolTest, SimpleResourceReuse) { gfx::Size size(100, 100); ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; scoped_ptr resource = resource_pool_->AcquireResource(size, format); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(1u, resource_provider_->num_resources()); // Same size/format should re-use resource. resource = resource_pool_->AcquireResource(size, format); EXPECT_EQ(1u, resource_provider_->num_resources()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(1u, resource_provider_->num_resources()); // Different size/format should alloate new resource. resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8); EXPECT_EQ(2u, resource_provider_->num_resources()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(2u, resource_provider_->num_resources()); } @@ -125,6 +127,7 @@ TEST_F(ResourcePoolTest, LostResource) { gfx::Size size(100, 100); ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; scoped_ptr resource = resource_pool_->AcquireResource(size, format); @@ -132,7 +135,7 @@ TEST_F(ResourcePoolTest, LostResource) { resource_provider_->LoseResourceForTesting(resource->id()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(0u, resource_provider_->num_resources()); } diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 6129b26..be282b9 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc @@ -33,6 +33,7 @@ #include "third_party/skia/include/gpu/GrTextureProvider.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/trace_util.h" using gpu::gles2::GLES2Interface; @@ -117,6 +118,25 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) { return kSkia8888_GrPixelConfig; } +gfx::BufferFormat ToGpuMemoryBufferFormat(ResourceFormat format) { + switch (format) { + case RGBA_8888: + return gfx::BufferFormat::RGBA_8888; + case BGRA_8888: + return gfx::BufferFormat::BGRA_8888; + case RGBA_4444: + return gfx::BufferFormat::RGBA_4444; + case ALPHA_8: + case LUMINANCE_8: + case RGB_565: + case ETC1: + case RED_8: + break; + } + NOTREACHED(); + return gfx::BufferFormat::RGBA_8888; +} + class ScopedSetActiveTexture { public: ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit) @@ -187,6 +207,46 @@ class BufferIdAllocator : public IdAllocator { DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator); }; +// Query object based fence implementation used to detect completion of copy +// texture operations. Fence has passed when query result is available. +class CopyTextureFence : public ResourceProvider::Fence { + public: + CopyTextureFence(gpu::gles2::GLES2Interface* gl, unsigned query_id) + : gl_(gl), query_id_(query_id) {} + + // Overridden from ResourceProvider::Fence: + void Set() override {} + bool HasPassed() override { + unsigned available = 1; + gl_->GetQueryObjectuivEXT( + query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); + if (!available) + return false; + + ProcessResult(); + return true; + } + void Wait() override { + // ProcessResult() will wait for result to become available. + ProcessResult(); + } + + private: + ~CopyTextureFence() override {} + + void ProcessResult() { + unsigned time_elapsed_us = 0; + gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &time_elapsed_us); + UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us, + 0, 256000, 50); + } + + gpu::gles2::GLES2Interface* gl_; + unsigned query_id_; + + DISALLOW_COPY_AND_ASSIGN(CopyTextureFence); +}; + // Generates process-unique IDs to use for tracing a ResourceProvider's // resources. base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id; @@ -342,12 +402,13 @@ scoped_ptr ResourceProvider::Create( int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector& use_image_texture_targets) { scoped_ptr resource_provider(new ResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, blocking_main_thread_task_runner, highp_threshold_min, use_rgba_4444_texture_format, id_allocation_chunk_size, - use_image_texture_targets)); + use_persistent_map_for_gpu_memory_buffers, use_image_texture_targets)); resource_provider->Initialize(); return resource_provider; } @@ -938,9 +999,13 @@ gfx::GpuMemoryBuffer* ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { if (gpu_memory_buffer_) return gpu_memory_buffer_; + gfx::BufferUsage usage = + resource_provider_->use_persistent_map_for_gpu_memory_buffers() + ? gfx::BufferUsage::PERSISTENT_MAP + : gfx::BufferUsage::MAP; scoped_ptr gpu_memory_buffer = gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( - size_, BufferFormat(format_), gfx::BufferUsage::MAP); + size_, ToGpuMemoryBufferFormat(format_), usage); gpu_memory_buffer_ = gpu_memory_buffer.release(); return gpu_memory_buffer_; } @@ -1032,6 +1097,7 @@ ResourceProvider::ResourceProvider( int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector& use_image_texture_targets) : output_surface_(output_surface), shared_bitmap_manager_(shared_bitmap_manager), @@ -1053,6 +1119,8 @@ ResourceProvider::ResourceProvider( use_rgba_4444_texture_format_(use_rgba_4444_texture_format), id_allocation_chunk_size_(id_allocation_chunk_size), use_sync_query_(false), + use_persistent_map_for_gpu_memory_buffers_( + use_persistent_map_for_gpu_memory_buffers), use_image_texture_targets_(use_image_texture_targets), tracing_id_(g_next_resource_provider_tracing_id.GetNext()) { DCHECK(output_surface_->HasClient()); @@ -1788,6 +1856,79 @@ void ResourceProvider::BindImageForSampling(Resource* resource) { resource->dirty_image = false; } +void ResourceProvider::CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect) { + TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); + + Resource* source_resource = GetResource(source_id); + DCHECK(!source_resource->lock_for_read_count); + DCHECK(source_resource->origin == Resource::INTERNAL); + DCHECK_EQ(source_resource->exported_count, 0); + DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type); + LazyAllocate(source_resource); + + Resource* dest_resource = GetResource(dest_id); + DCHECK(!dest_resource->locked_for_write); + DCHECK(!dest_resource->lock_for_read_count); + DCHECK(dest_resource->origin == Resource::INTERNAL); + DCHECK_EQ(dest_resource->exported_count, 0); + DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, dest_resource->type); + LazyAllocate(dest_resource); + + DCHECK_EQ(source_resource->type, dest_resource->type); + DCHECK_EQ(source_resource->format, dest_resource->format); + DCHECK(source_resource->size == dest_resource->size); + DCHECK(gfx::Rect(dest_resource->size).Contains(rect)); + + GLES2Interface* gl = ContextGL(); + DCHECK(gl); + if (source_resource->image_id && source_resource->dirty_image) { + gl->BindTexture(source_resource->target, source_resource->gl_id); + BindImageForSampling(source_resource); + } + if (use_sync_query_) { + if (!source_resource->gl_read_lock_query_id) + gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id); +#if defined(OS_CHROMEOS) + // TODO(reveman): This avoids a performance problem on some ChromeOS + // devices. This needs to be removed to support native GpuMemoryBuffer + // implementations. crbug.com/436314 + gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, + source_resource->gl_read_lock_query_id); +#else + gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, + source_resource->gl_read_lock_query_id); +#endif + } + DCHECK(!dest_resource->image_id); + dest_resource->allocated = true; + gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id, + dest_resource->gl_id, rect.x(), rect.y(), rect.x(), + rect.y(), rect.width(), rect.height(), + false, false, false); + if (source_resource->gl_read_lock_query_id) { + // End query and create a read lock fence that will prevent access to +// source resource until CopySubTextureCHROMIUM command has completed. +#if defined(OS_CHROMEOS) + gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); +#else + gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); +#endif + source_resource->read_lock_fence = make_scoped_refptr( + new CopyTextureFence(gl, source_resource->gl_read_lock_query_id)); + } else { + // Create a SynchronousFence when CHROMIUM_sync_query extension is missing. + // Try to use one synchronous fence for as many CopyResource operations as + // possible as that reduce the number of times we have to synchronize with + // the GL. + if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized()) + synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl)); + source_resource->read_lock_fence = synchronous_fence_; + source_resource->read_lock_fence->Set(); + } +} + void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { Resource* resource = GetResource(id); DCHECK_EQ(resource->exported_count, 0); @@ -1803,6 +1944,15 @@ void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { resource->mailbox.set_sync_point(0); } +void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) { + Resource* resource = GetResource(id); + DCHECK_EQ(resource->exported_count, 0); + if (!resource->read_lock_fence.get()) + return; + + resource->read_lock_fence->Wait(); +} + GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) { GLint active_unit = 0; gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); @@ -1810,7 +1960,7 @@ GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) { } GLenum ResourceProvider::GetImageTextureTarget(ResourceFormat format) { - gfx::BufferFormat buffer_format = BufferFormat(format); + gfx::BufferFormat buffer_format = ToGpuMemoryBufferFormat(format); DCHECK_GT(use_image_texture_targets_.size(), static_cast(buffer_format)); return use_image_texture_targets_[static_cast(buffer_format)]; diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 8b7ccd8..324df1b 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h @@ -35,7 +35,6 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/geometry/size.h" -#include "ui/gfx/gpu_memory_buffer.h" class GrContext; @@ -47,6 +46,7 @@ class GLES2Interface; } namespace gfx { +class GpuMemoryBuffer; class Rect; class Vector2d; } @@ -88,6 +88,7 @@ class CC_EXPORT ResourceProvider int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector& use_image_texture_targets); ~ResourceProvider() override; @@ -103,8 +104,8 @@ class CC_EXPORT ResourceProvider } ResourceFormat yuv_resource_format() const { return yuv_resource_format_; } bool use_sync_query() const { return use_sync_query_; } - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() { - return gpu_memory_buffer_manager_; + bool use_persistent_map_for_gpu_memory_buffers() const { + return use_persistent_map_for_gpu_memory_buffers_; } size_t num_resources() const { return resources_.size(); } @@ -426,8 +427,15 @@ class CC_EXPORT ResourceProvider // Indicates if we can currently lock this resource for write. bool CanLockForWrite(ResourceId id); + // Copy |rect| pixels from source to destination. + void CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect); + void WaitSyncPointIfNeeded(ResourceId id); + void WaitReadLockIfNeeded(ResourceId id); + static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl); OutputSurface* output_surface() { return output_surface_; } @@ -450,6 +458,7 @@ class CC_EXPORT ResourceProvider int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector& use_image_texture_targets); void Initialize(); @@ -605,6 +614,9 @@ class CC_EXPORT ResourceProvider scoped_ptr buffer_id_allocator_; bool use_sync_query_; + bool use_persistent_map_for_gpu_memory_buffers_; + // Fence used for CopyResource if CHROMIUM_sync_query is not supported. + scoped_refptr synchronous_fence_; std::vector use_image_texture_targets_; // A process-unique ID used for disambiguating memory dumps from different diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 7c65b73..4a02e82 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc @@ -422,11 +422,11 @@ class ResourceProviderTest resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_); + false, 1, false, use_image_texture_targets_); child_resource_provider_ = ResourceProvider::Create( child_output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_); + false, 1, false, use_image_texture_targets_); } ResourceProviderTest() : ResourceProviderTest(true) {} @@ -1378,7 +1378,7 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) { scoped_ptr child_resource_provider(ResourceProvider::Create( child_output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -1863,7 +1863,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr child_resource_provider( ResourceProvider::Create(child_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); scoped_ptr parent_context_owned( new TextureStateTrackingContext); @@ -1877,7 +1877,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr parent_resource_provider( ResourceProvider::Create(parent_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2509,7 +2509,7 @@ TEST_P(ResourceProviderTest, ScopedSampler) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2592,7 +2592,7 @@ TEST_P(ResourceProviderTest, ManagedResource) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2640,7 +2640,7 @@ TEST_P(ResourceProviderTest, TextureWrapMode) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2691,7 +2691,7 @@ TEST_P(ResourceProviderTest, TextureHint) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2757,7 +2757,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); uint32 release_sync_point = 0; bool lost_resource = false; @@ -2806,7 +2806,8 @@ class ResourceProviderTestTextureMailboxGLFilters scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager, - main_thread_task_runner, 0, false, 1, use_image_texture_targets_)); + main_thread_task_runner, 0, false, 1, false, + use_image_texture_targets_)); unsigned texture_id = 1; uint32 sync_point = 30; @@ -2949,7 +2950,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 30; @@ -3019,7 +3020,7 @@ TEST_P(ResourceProviderTest, scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 30; @@ -3073,7 +3074,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 0; @@ -3194,7 +3195,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3269,7 +3270,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3325,7 +3326,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3380,7 +3381,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3423,7 +3424,7 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3466,7 +3467,7 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id)); @@ -3507,7 +3508,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3568,6 +3569,89 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { .RetiresOnSaturation(); } +TEST_P(ResourceProviderTest, CopyResource_GLTexture) { + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) + return; + scoped_ptr context_owned( + new StrictMock); + AllocationTrackingContext3D* context = context_owned.get(); + context_owned->set_support_sync_query(true); + + FakeOutputSurfaceClient output_surface_client; + scoped_ptr output_surface( + FakeOutputSurface::Create3d(context_owned.Pass())); + ASSERT_TRUE(output_surface->BindToClient(&output_surface_client)); + + const int kWidth = 2; + const int kHeight = 2; + gfx::Size size(kWidth, kHeight); + ResourceFormat format = RGBA_8888; + ResourceId source_id = 0; + ResourceId dest_id = 0; + const unsigned kSourceTextureId = 123u; + const unsigned kDestTextureId = 321u; + const unsigned kImageId = 234u; + + scoped_ptr resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, + std::vector(static_cast(gfx::BufferFormat::LAST) + 1, + GL_TEXTURE_2D))); + + source_id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kSourceTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) + .WillOnce(Return(kImageId)) + .RetiresOnSaturation(); + { + ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( + resource_provider.get(), source_id); + EXPECT_TRUE(lock.GetGpuMemoryBuffer()); + } + Mock::VerifyAndClearExpectations(context); + + dest_id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kDestTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId)) + .Times(2) + .RetiresOnSaturation(); + EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) + .Times(1) + .RetiresOnSaturation(); + resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size)); + Mock::VerifyAndClearExpectations(context); + + EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, RetireTextureId(kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, RetireTextureId(kDestTextureId)) + .Times(1) + .RetiresOnSaturation(); + resource_provider->DeleteResource(source_id); + resource_provider->DeleteResource(dest_id); +} + TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; @@ -3585,7 +3669,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { gfx::Size size(4, 4); scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); int texture_id = 123; @@ -3617,7 +3701,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { gfx::Size size(4, 4); scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); int texture_id = 123; uint8_t pixels[8]; @@ -3674,7 +3758,7 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { size_t kTextureAllocationChunkSize = 1; scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - kTextureAllocationChunkSize, + kTextureAllocationChunkSize, false, ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource( @@ -3691,7 +3775,7 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { size_t kTextureAllocationChunkSize = 8; scoped_ptr resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - kTextureAllocationChunkSize, + kTextureAllocationChunkSize, false, ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource( diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index 6ad178df..6bb12dc 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc @@ -102,10 +102,13 @@ void Display::InitializeRenderer() { if (resource_provider_) return; + // Display does not use GpuMemoryBuffers, so persistent map is not relevant. + bool use_persistent_map_for_gpu_memory_buffers = false; scoped_ptr resource_provider = ResourceProvider::Create( output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_, nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures, settings_.texture_id_allocation_chunk_size, + use_persistent_map_for_gpu_memory_buffers, std::vector(static_cast(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D)); if (!resource_provider) diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc index 6a2779d..e21d15d 100644 --- a/cc/surfaces/surface_display_output_surface.cc +++ b/cc/surfaces/surface_display_output_surface.cc @@ -17,9 +17,8 @@ namespace cc { SurfaceDisplayOutputSurface::SurfaceDisplayOutputSurface( SurfaceManager* surface_manager, SurfaceIdAllocator* allocator, - const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider) - : OutputSurface(context_provider, worker_context_provider), + const scoped_refptr& context_provider) + : OutputSurface(context_provider), display_client_(NULL), factory_(surface_manager, this), allocator_(allocator) { diff --git a/cc/surfaces/surface_display_output_surface.h b/cc/surfaces/surface_display_output_surface.h index 2cdaadc..c11bb86 100644 --- a/cc/surfaces/surface_display_output_surface.h +++ b/cc/surfaces/surface_display_output_surface.h @@ -27,8 +27,7 @@ class CC_SURFACES_EXPORT SurfaceDisplayOutputSurface SurfaceDisplayOutputSurface( SurfaceManager* surface_manager, SurfaceIdAllocator* allocator, - const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider); + const scoped_refptr& context_provider); ~SurfaceDisplayOutputSurface() override; void set_display_client(OnscreenDisplayClient* display_client) { diff --git a/cc/surfaces/surface_display_output_surface_unittest.cc b/cc/surfaces/surface_display_output_surface_unittest.cc index daabafe..922dd9e 100644 --- a/cc/surfaces/surface_display_output_surface_unittest.cc +++ b/cc/surfaces/surface_display_output_surface_unittest.cc @@ -60,8 +60,7 @@ class SurfaceDisplayOutputSurfaceTest : public testing::Test { context_provider_(TestContextProvider::Create()), surface_display_output_surface_(&surface_manager_, &allocator_, - context_provider_, - nullptr) { + context_provider_) { output_surface_ = display_client_.output_surface(); display_client_.set_surface_output_surface( &surface_display_output_surface_); diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 066f027..a682177 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -60,15 +60,13 @@ class FakeOutputSurface : public OutputSurface { static scoped_ptr CreateDelegating3d( scoped_refptr context_provider) { - return make_scoped_ptr(new FakeOutputSurface( - context_provider, TestContextProvider::Create(), true)); + return make_scoped_ptr(new FakeOutputSurface(context_provider, true)); } static scoped_ptr CreateDelegating3d( scoped_ptr context) { - return make_scoped_ptr( - new FakeOutputSurface(TestContextProvider::Create(context.Pass()), - TestContextProvider::Create(), true)); + return make_scoped_ptr(new FakeOutputSurface( + TestContextProvider::Create(context.Pass()), true)); } static scoped_ptr CreateDelegatingSoftware( diff --git a/cc/test/fake_resource_provider.h b/cc/test/fake_resource_provider.h index e954d26..2295a4f 100644 --- a/cc/test/fake_resource_provider.h +++ b/cc/test/fake_resource_provider.h @@ -17,6 +17,7 @@ class FakeResourceProvider : public ResourceProvider { SharedBitmapManager* shared_bitmap_manager) { scoped_ptr provider(new FakeResourceProvider( output_surface, shared_bitmap_manager, nullptr, nullptr, 0, false, 1, + false, std::vector(static_cast(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D))); provider->Initialize(); @@ -29,7 +30,7 @@ class FakeResourceProvider : public ResourceProvider { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { scoped_ptr provider(new FakeResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, - nullptr, 0, false, 1, + nullptr, 0, false, 1, false, std::vector(static_cast(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D))); provider->Initialize(); @@ -44,6 +45,7 @@ class FakeResourceProvider : public ResourceProvider { int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector& use_image_texture_targets) : ResourceProvider(output_surface, shared_bitmap_manager, @@ -52,6 +54,7 @@ class FakeResourceProvider : public ResourceProvider { highp_threshold_min, use_rgba_4444_texture_format, id_allocation_chunk_size, + use_persistent_map_for_gpu_memory_buffers, use_image_texture_targets) {} }; diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc index 3b52487..bc323f1 100644 --- a/cc/test/layer_tree_pixel_resource_test.cc +++ b/cc/test/layer_tree_pixel_resource_test.cc @@ -45,7 +45,8 @@ bool IsTestCaseSupported(PixelResourceTestCase test_case) { LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest( PixelResourceTestCase test_case) - : draw_texture_target_(GL_INVALID_VALUE), + : staging_texture_target_(GL_INVALID_VALUE), + draw_texture_target_(GL_INVALID_VALUE), resource_pool_option_(BITMAP_TILE_TASK_WORKER_POOL), initialized_(false), test_case_(test_case) { @@ -53,10 +54,12 @@ LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest( } LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest() - : draw_texture_target_(GL_INVALID_VALUE), + : staging_texture_target_(GL_INVALID_VALUE), + draw_texture_target_(GL_INVALID_VALUE), resource_pool_option_(BITMAP_TILE_TASK_WORKER_POOL), initialized_(false), - test_case_(SOFTWARE) {} + test_case_(SOFTWARE) { +} void LayerTreeHostPixelResourceTest::InitializeFromTestCase( PixelResourceTestCase test_case) { @@ -65,46 +68,55 @@ void LayerTreeHostPixelResourceTest::InitializeFromTestCase( switch (test_case) { case SOFTWARE: test_type_ = PIXEL_TEST_SOFTWARE; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_INVALID_VALUE; resource_pool_option_ = BITMAP_TILE_TASK_WORKER_POOL; return; case GL_GPU_RASTER_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = GPU_TILE_TASK_WORKER_POOL; return; case GL_ONE_COPY_2D_STAGING_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_TEXTURE_2D; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = ONE_COPY_TILE_TASK_WORKER_POOL; return; case GL_ONE_COPY_RECT_STAGING_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_TEXTURE_RECTANGLE_ARB; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = ONE_COPY_TILE_TASK_WORKER_POOL; return; case GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_TEXTURE_EXTERNAL_OES; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = ONE_COPY_TILE_TASK_WORKER_POOL; return; case GL_ZERO_COPY_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = ZERO_COPY_TILE_TASK_WORKER_POOL; return; case GL_ZERO_COPY_RECT_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_TEXTURE_RECTANGLE_ARB; resource_pool_option_ = ZERO_COPY_TILE_TASK_WORKER_POOL; return; case GL_ZERO_COPY_EXTERNAL_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_TEXTURE_EXTERNAL_OES; resource_pool_option_ = ZERO_COPY_TILE_TASK_WORKER_POOL; return; case GL_ASYNC_UPLOAD_2D_DRAW: test_type_ = PIXEL_TEST_GL; + staging_texture_target_ = GL_INVALID_VALUE; draw_texture_target_ = GL_TEXTURE_2D; resource_pool_option_ = PIXEL_BUFFER_TILE_TASK_WORKER_POOL; return; @@ -115,7 +127,8 @@ void LayerTreeHostPixelResourceTest::InitializeFromTestCase( void LayerTreeHostPixelResourceTest::CreateResourceAndTileTaskWorkerPool( LayerTreeHostImpl* host_impl, scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool) { + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool) { base::SingleThreadTaskRunner* task_runner = proxy()->HasImplThread() ? proxy()->ImplThreadTaskRunner() : proxy()->MainThreadTaskRunner(); @@ -127,7 +140,6 @@ void LayerTreeHostPixelResourceTest::CreateResourceAndTileTaskWorkerPool( ResourceProvider* resource_provider = host_impl->resource_provider(); size_t max_transfer_buffer_usage_bytes = 1024u * 1024u * 60u; int max_bytes_per_copy_operation = 1024 * 1024; - int max_staging_buffers = 32; switch (resource_pool_option_) { case BITMAP_TILE_TASK_WORKER_POOL: @@ -165,12 +177,15 @@ void LayerTreeHostPixelResourceTest::CreateResourceAndTileTaskWorkerPool( EXPECT_TRUE(context_provider); EXPECT_EQ(PIXEL_TEST_GL, test_type_); EXPECT_TRUE(host_impl->GetRendererCapabilities().using_image); + // We need to create a staging resource pool when using copy rasterizer. + *staging_resource_pool = + ResourcePool::Create(resource_provider, staging_texture_target_); *resource_pool = ResourcePool::Create(resource_provider, draw_texture_target_); *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create( task_runner, task_graph_runner(), context_provider, resource_provider, - max_bytes_per_copy_operation, false, max_staging_buffers); + staging_resource_pool->get(), max_bytes_per_copy_operation, false); break; case PIXEL_BUFFER_TILE_TASK_WORKER_POOL: EXPECT_TRUE(context_provider); diff --git a/cc/test/layer_tree_pixel_resource_test.h b/cc/test/layer_tree_pixel_resource_test.h index 8c3242a..16b7ca9 100644 --- a/cc/test/layer_tree_pixel_resource_test.h +++ b/cc/test/layer_tree_pixel_resource_test.h @@ -38,7 +38,8 @@ class LayerTreeHostPixelResourceTest : public LayerTreePixelTest { void CreateResourceAndTileTaskWorkerPool( LayerTreeHostImpl* host_impl, scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool) override; + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool) override; void RunPixelResourceTest(scoped_refptr content_root, base::FilePath file_name); @@ -52,6 +53,7 @@ class LayerTreeHostPixelResourceTest : public LayerTreePixelTest { }; protected: + unsigned staging_texture_target_; unsigned draw_texture_target_; TileTaskWorkerPoolOption resource_pool_option_; bool initialized_; diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 77399b9..c145735 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc @@ -381,10 +381,4 @@ void LayerTreePixelTest::CopyBitmapToTextureMailboxAsTexture( texture_id)); } -void LayerTreePixelTest::Finish() { - scoped_ptr context = CreateTestInProcessContext(); - GLES2Interface* gl = context->GetImplementation(); - gl->Finish(); -} - } // namespace cc diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h index fcaf1b4..f2352b0 100644 --- a/cc/test/layer_tree_pixel_test.h +++ b/cc/test/layer_tree_pixel_test.h @@ -91,8 +91,6 @@ class LayerTreePixelTest : public LayerTreeTest { uint32 sync_point, bool lost_resource); - void Finish(); - void set_enlarge_texture_amount(const gfx::Vector2d& enlarge_texture_amount) { enlarge_texture_amount_ = enlarge_texture_amount; } diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index c426bc1..a866ac1 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -107,9 +107,10 @@ DrawResult TestHooks::PrepareToDrawOnThread( void TestHooks::CreateResourceAndTileTaskWorkerPool( LayerTreeHostImpl* host_impl, scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool) { + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool) { host_impl->LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( - tile_task_worker_pool, resource_pool); + tile_task_worker_pool, resource_pool, staging_resource_pool); } // Adapts ThreadProxy for test. Injects test hooks for testing. @@ -302,9 +303,10 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl { void CreateResourceAndTileTaskWorkerPool( scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool) override { + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool) override { test_hooks_->CreateResourceAndTileTaskWorkerPool( - this, tile_task_worker_pool, resource_pool); + this, tile_task_worker_pool, resource_pool, staging_resource_pool); } void WillBeginImplFrame(const BeginFrameArgs& args) override { diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 9f6d369..828850c 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -55,7 +55,8 @@ class TestHooks : public AnimationDelegate { virtual void CreateResourceAndTileTaskWorkerPool( LayerTreeHostImpl* host_impl, scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool); + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool); virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, const BeginFrameArgs& args) {} virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {} diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc index d76da9f..32f32d3 100644 --- a/cc/test/pixel_test.cc +++ b/cc/test/pixel_test.cc @@ -136,7 +136,7 @@ void PixelTest::SetUpGLRenderer(bool use_skia_gpu_backend, resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, settings_.use_image_texture_targets); + false, 1, false, settings_.use_image_texture_targets); texture_mailbox_deleter_ = make_scoped_ptr( new TextureMailboxDeleter(base::ThreadTaskRunnerHandle::Get())); @@ -177,7 +177,7 @@ void PixelTest::SetUpSoftwareRenderer() { resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, settings_.use_image_texture_targets); + false, 1, false, settings_.use_image_texture_targets); renderer_ = SoftwareRenderer::Create(this, &settings_.renderer_settings, output_surface_.get(), resource_provider_.get()); diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc index 79d53d2..efbbeec 100644 --- a/cc/test/test_in_process_context_provider.cc +++ b/cc/test/test_in_process_context_provider.cc @@ -142,7 +142,6 @@ TestInProcessContextProvider::ContextCapabilities() { ContextProvider::Capabilities capabilities; capabilities.gpu.image = true; capabilities.gpu.texture_rectangle = true; - capabilities.gpu.sync_query = true; switch (PlatformColor::Format()) { case PlatformColor::SOURCE_FORMAT_RGBA8: diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index cc77587..f90faa0 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc @@ -494,7 +494,7 @@ void TileManager::AssignGpuMemoryToTiles( // or deleted. If this operation becomes expensive too, only do this after // some resource(s) was returned. Note that in that case, one also need to // invalidate when releasing some resource from the pool. - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(false); // Now give memory out to the tiles until we're out, and build // the needs-to-be-rasterized queue. diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0b235b6..1b72a04 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -153,6 +153,11 @@ size_t GetMaxTransferBufferUsageBytes( max_transfer_buffer_usage_bytes); } +size_t GetMaxStagingResourceCount() { + // Upper bound for number of staging resource to allow. + return 32; +} + size_t GetDefaultMemoryAllocationLimit() { // TODO(ccameron): (http://crbug.com/137094) This 64MB default is a straggler // from the old texture manager and is just to give us a default memory @@ -1230,7 +1235,7 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( 100); DCHECK(resource_pool_); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(false); // Soft limit is used for resource pool such that memory returns to soft // limit after going over. resource_pool_->SetResourceUsageLimits( @@ -1238,6 +1243,15 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( unused_memory_limit_in_bytes, global_tile_state_.num_resources_limit); + // Release all staging resources when invisible. + if (staging_resource_pool_) { + staging_resource_pool_->CheckBusyResources(false); + staging_resource_pool_->SetResourceUsageLimits( + std::numeric_limits::max(), + std::numeric_limits::max(), + visible_ ? GetMaxStagingResourceCount() : 0); + } + DidModifyTilePriorities(); } @@ -1451,7 +1465,7 @@ void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) { // In OOM, we now might be able to release more resources that were held // because they were exported. if (resource_pool_) { - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(false); resource_pool_->ReduceResourceUsage(); } // If we're not visible, we likely released resources, so we want to @@ -2062,7 +2076,8 @@ void LayerTreeHostImpl::CreateAndSetRenderer() { } void LayerTreeHostImpl::CreateTileManagerResources() { - CreateResourceAndTileTaskWorkerPool(&tile_task_worker_pool_, &resource_pool_); + CreateResourceAndTileTaskWorkerPool(&tile_task_worker_pool_, &resource_pool_, + &staging_resource_pool_); // TODO(vmpstr): Initialize tile task limit at ctor time. tile_manager_->SetResources( resource_pool_.get(), tile_task_worker_pool_->AsTileTaskRunner(), @@ -2073,7 +2088,8 @@ void LayerTreeHostImpl::CreateTileManagerResources() { void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool) { + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool) { DCHECK(GetTaskRunner()); // TODO(vmpstr): Make this a DCHECK (or remove) when crbug.com/419086 is // resolved. @@ -2122,6 +2138,13 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( } if (settings_.use_one_copy) { + // Synchronous single-threaded mode depends on tiles being ready to + // draw when raster is complete. Therefore, it must use one of zero + // copy, software raster, or GPU raster. + DCHECK(!is_synchronous_single_threaded_); + + // We need to create a staging resource pool when using copy rasterizer. + *staging_resource_pool = ResourcePool::Create(resource_provider_.get()); *resource_pool = ResourcePool::Create(resource_provider_.get(), GL_TEXTURE_2D); @@ -2131,9 +2154,9 @@ void LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool( *tile_task_worker_pool = OneCopyTileTaskWorkerPool::Create( GetTaskRunner(), task_graph_runner, context_provider, - resource_provider_.get(), max_copy_texture_chromium_size, - settings_.use_persistent_map_for_gpu_memory_buffers, - settings_.max_staging_buffers); + resource_provider_.get(), staging_resource_pool_.get(), + max_copy_texture_chromium_size, + settings_.use_persistent_map_for_gpu_memory_buffers); return; } @@ -2176,6 +2199,7 @@ void LayerTreeHostImpl::PostFrameTimingEvents( void LayerTreeHostImpl::CleanUpTileManager() { tile_manager_->FinishTasksAndCleanUp(); resource_pool_ = nullptr; + staging_resource_pool_ = nullptr; tile_task_worker_pool_ = nullptr; single_thread_synchronous_task_graph_runner_ = nullptr; } @@ -2209,6 +2233,7 @@ bool LayerTreeHostImpl::InitializeRenderer( settings_.renderer_settings.highp_threshold_min, settings_.renderer_settings.use_rgba_4444_textures, settings_.renderer_settings.texture_id_allocation_chunk_size, + settings_.use_persistent_map_for_gpu_memory_buffers, settings_.use_image_texture_targets); CreateAndSetRenderer(); diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 144ca92..893b42a 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -560,7 +560,8 @@ class CC_EXPORT LayerTreeHostImpl virtual void CreateResourceAndTileTaskWorkerPool( scoped_ptr* tile_task_worker_pool, - scoped_ptr* resource_pool); + scoped_ptr* resource_pool, + scoped_ptr* staging_resource_pool); bool prepare_tiles_needed() const { return tile_priorities_dirty_; } @@ -713,6 +714,7 @@ class CC_EXPORT LayerTreeHostImpl bool tree_resources_for_gpu_rasterization_dirty_; scoped_ptr tile_task_worker_pool_; scoped_ptr resource_pool_; + scoped_ptr staging_resource_pool_; scoped_ptr renderer_; GlobalStateThatImpactsTilePriority global_tile_state_; diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc index e4f52cd..a8d7b32 100644 --- a/cc/trees/layer_tree_host_pixeltest_tiles.cc +++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc @@ -161,7 +161,6 @@ class LayerTreeHostTilesTestPartialInvalidation // only re-raster the stuff in the rect. If it doesn't do partial raster // it would re-raster the whole thing instead. client_.set_blue_top(false); - Finish(); picture_layer_->SetNeedsDisplayRect(gfx::Rect(50, 50, 100, 100)); // Add a copy request to see what happened! diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index 9d0dcb8..801dc6d 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc @@ -74,8 +74,7 @@ LayerTreeSettings::LayerTreeSettings() gather_pixel_refs(false), use_compositor_animation_timelines(false), invert_viewport_scroll_order(false), - wait_for_beginframe_interval(true), - max_staging_buffers(32) {} + wait_for_beginframe_interval(true) {} LayerTreeSettings::~LayerTreeSettings() {} diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index af9374c..dbc9004 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h @@ -89,7 +89,6 @@ class CC_EXPORT LayerTreeSettings { bool use_compositor_animation_timelines; bool invert_viewport_scroll_order; bool wait_for_beginframe_interval; - int max_staging_buffers; LayerTreeDebugState initial_debug_state; diff --git a/components/html_viewer/web_layer_tree_view_impl.cc b/components/html_viewer/web_layer_tree_view_impl.cc index 8acb806..9d54f7e 100644 --- a/components/html_viewer/web_layer_tree_view_impl.cc +++ b/components/html_viewer/web_layer_tree_view_impl.cc @@ -63,16 +63,12 @@ WebLayerTreeViewImpl::WebLayerTreeViewImpl( if (surface && gpu_service) { mojo::CommandBufferPtr cb; - mojo::CommandBufferPtr worker_cb; gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb)); - gpu_service->CreateOffscreenGLES2Context(GetProxy(&worker_cb)); scoped_refptr context_provider( new mojo::ContextProviderMojo(cb.PassInterface().PassHandle())); - scoped_refptr worker_context_provider( - new mojo::ContextProviderMojo(worker_cb.PassInterface().PassHandle())); - output_surface_.reset(new mojo::OutputSurfaceMojo( - this, context_provider, worker_context_provider, - surface.PassInterface().PassHandle())); + output_surface_.reset( + new mojo::OutputSurfaceMojo(this, context_provider, + surface.PassInterface().PassHandle())); } layer_tree_host_->SetLayerTreeHostClientReady(); } diff --git a/content/browser/compositor/browser_compositor_output_surface.cc b/content/browser/compositor/browser_compositor_output_surface.cc index bdf3a1b..0e014c9 100644 --- a/content/browser/compositor/browser_compositor_output_surface.cc +++ b/content/browser/compositor/browser_compositor_output_surface.cc @@ -17,16 +17,14 @@ namespace content { BrowserCompositorOutputSurface::BrowserCompositorOutputSurface( const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) - : OutputSurface(context_provider, worker_context_provider), + : OutputSurface(context_provider), vsync_manager_(vsync_manager), reflector_(nullptr), - use_begin_frame_scheduling_( - base::CommandLine::ForCurrentProcess() - ->HasSwitch(cc::switches::kEnableBeginFrameScheduling)) { + use_begin_frame_scheduling_(base::CommandLine::ForCurrentProcess()-> + HasSwitch(cc::switches::kEnableBeginFrameScheduling)) { overlay_candidate_validator_ = overlay_candidate_validator.Pass(); Initialize(); } diff --git a/content/browser/compositor/browser_compositor_output_surface.h b/content/browser/compositor/browser_compositor_output_surface.h index f5da02d..f582776 100644 --- a/content/browser/compositor/browser_compositor_output_surface.h +++ b/content/browser/compositor/browser_compositor_output_surface.h @@ -56,7 +56,6 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface // Constructor used by the accelerated implementation. BrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc index 70725a2..81da36d 100644 --- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc @@ -17,12 +17,10 @@ namespace content { GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) : BrowserCompositorOutputSurface(context, - worker_context, vsync_manager, overlay_candidate_validator.Pass()), #if defined(OS_MACOSX) diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.h b/content/browser/compositor/gpu_browser_compositor_output_surface.h index 7b4f242..3bc2a3a 100644 --- a/content/browser/compositor/gpu_browser_compositor_output_surface.h +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.h @@ -26,7 +26,6 @@ class GpuBrowserCompositorOutputSurface public: GpuBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 4c0b363..86853c8 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -241,13 +241,6 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( scoped_refptr context_provider; if (create_gpu_output_surface) { - // Try to reuse existing worker context provider. - if (shared_worker_context_provider_) { - base::AutoLock lock(*shared_worker_context_provider_->GetLock()); - if (shared_worker_context_provider_->ContextGL() - ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) - shared_worker_context_provider_ = nullptr; - } scoped_refptr gpu_channel_host = BrowserGpuChannelHostFactory::instance()->GetGpuChannel(); if (gpu_channel_host.get()) { @@ -257,24 +250,12 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( BROWSER_COMPOSITOR_ONSCREEN_CONTEXT); if (context_provider && !context_provider->BindToCurrentThread()) context_provider = nullptr; - if (!shared_worker_context_provider_) { - shared_worker_context_provider_ = ContextProviderCommandBuffer::Create( - GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, - 0), - BROWSER_WORKER_CONTEXT); - if (shared_worker_context_provider_ && - !shared_worker_context_provider_->BindToCurrentThread()) - shared_worker_context_provider_ = nullptr; - } } - bool created_gpu_browser_compositor = - !!context_provider && !!shared_worker_context_provider_; - UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", - created_gpu_browser_compositor); + !!context_provider.get()); - if (!created_gpu_browser_compositor) { + if (!context_provider) { // Try again. CauseForGpuLaunch cause = CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; @@ -297,8 +278,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( context_provider->ContextCapabilities(); if (!data->surface_id) { surface = make_scoped_ptr(new OffscreenBrowserCompositorOutputSurface( - context_provider, shared_worker_context_provider_, - compositor->vsync_manager(), + context_provider, compositor->vsync_manager(), scoped_ptr())); } else if (capabilities.gpu.surfaceless) { GLenum target = GL_TEXTURE_2D; @@ -309,15 +289,13 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( #endif surface = make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface( - context_provider, shared_worker_context_provider_, - data->surface_id, compositor->vsync_manager(), + context_provider, data->surface_id, compositor->vsync_manager(), CreateOverlayCandidateValidator(compositor->widget()), target, format, BrowserGpuMemoryBufferManager::current())); } else { if (!surface) { surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( - context_provider, shared_worker_context_provider_, - compositor->vsync_manager(), + context_provider, compositor->vsync_manager(), CreateOverlayCandidateValidator(compositor->widget()))); } } @@ -348,8 +326,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( scoped_ptr output_surface( new cc::SurfaceDisplayOutputSurface( - manager, compositor->surface_id_allocator(), context_provider, - shared_worker_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()); display_client->display()->Resize(compositor->size()); diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h index 564b3cd..c16b36e 100644 --- a/content/browser/compositor/gpu_process_transport_factory.h +++ b/content/browser/compositor/gpu_process_transport_factory.h @@ -102,7 +102,6 @@ class GpuProcessTransportFactory uint32_t next_surface_id_namespace_; scoped_ptr task_graph_runner_; scoped_ptr raster_thread_; - scoped_refptr shared_worker_context_provider_; #if defined(OS_WIN) scoped_ptr software_backing_; diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc index 60dc778..62b1aae 100644 --- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc +++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc @@ -19,7 +19,6 @@ namespace content { GpuSurfacelessBrowserCompositorOutputSurface:: GpuSurfacelessBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, int surface_id, const scoped_refptr& vsync_manager, scoped_ptr @@ -28,7 +27,6 @@ GpuSurfacelessBrowserCompositorOutputSurface:: unsigned int internalformat, BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager) : GpuBrowserCompositorOutputSurface(context, - worker_context, vsync_manager, overlay_candidate_validator.Pass()), internalformat_(internalformat), diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h index ed5618d..27bb335 100644 --- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h +++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h @@ -18,7 +18,6 @@ class GpuSurfacelessBrowserCompositorOutputSurface public: GpuSurfacelessBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, int surface_id, const scoped_refptr& vsync_manager, scoped_ptr diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc index da972c7..599f553 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc @@ -30,12 +30,10 @@ namespace content { OffscreenBrowserCompositorOutputSurface:: OffscreenBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) : BrowserCompositorOutputSurface(context, - worker_context, vsync_manager, overlay_candidate_validator.Pass()), fbo_(0), diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/content/browser/compositor/offscreen_browser_compositor_output_surface.h index c9e32e7..67fc224 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.h +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.h @@ -23,7 +23,6 @@ class OffscreenBrowserCompositorOutputSurface public: OffscreenBrowserCompositorOutputSurface( const scoped_refptr& context, - const scoped_refptr& worker_context, const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc index 3377b8a..ce9fbb9 100644 --- a/content/browser/compositor/reflector_impl_unittest.cc +++ b/content/browser/compositor/reflector_impl_unittest.cc @@ -74,7 +74,6 @@ class TestOutputSurface : public BrowserCompositorOutputSurface { const scoped_refptr& context_provider, const scoped_refptr& vsync_manager) : BrowserCompositorOutputSurface(context_provider, - nullptr, vsync_manager, CreateTestValidatorOzone().Pass()) {} diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 9646b8f..342aafb 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc @@ -242,6 +242,14 @@ bool IsOneCopyUploadEnabled() { bool IsZeroCopyUploadEnabled() { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + // Single-threaded mode in the renderer process (for layout tests) is + // synchronous, which depends on tiles being ready to draw when raster is + // complete. Therefore, it must use one of zero copy, software raster, or + // GPU raster. So we force zero-copy on for the case where software/GPU raster + // is not used. + // TODO(reveman): One-copy can work with sync compositing: crbug.com/490295. + if (command_line.HasSwitch(switches::kDisableThreadedCompositing)) + return true; return command_line.HasSwitch(switches::kEnableZeroCopy); } diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index b5ee3fa..d5bb4b7 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -673,7 +673,7 @@ void CompositorImpl::CreateOutputSurface() { base::ThreadTaskRunnerHandle::Get())); scoped_ptr surface_output_surface( new cc::SurfaceDisplayOutputSurface( - manager, surface_id_allocator_.get(), context_provider, nullptr)); + manager, surface_id_allocator_.get(), context_provider)); display_client_->set_surface_output_surface(surface_output_surface.get()); surface_output_surface->set_display_client(display_client_.get()); diff --git a/content/common/gpu/client/command_buffer_metrics.cc b/content/common/gpu/client/command_buffer_metrics.cc index 5065ca5..d16f276 100644 --- a/content/common/gpu/client/command_buffer_metrics.cc +++ b/content/common/gpu/client/command_buffer_metrics.cc @@ -79,10 +79,6 @@ void RecordContextLost(CommandBufferContextType type, UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BrowserMainThread", reason, CONTEXT_LOST_REASON_MAX_ENUM); break; - case BROWSER_WORKER_CONTEXT: - UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BrowserWorker", reason, - CONTEXT_LOST_REASON_MAX_ENUM); - break; case RENDER_COMPOSITOR_CONTEXT: UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.RenderCompositor", reason, CONTEXT_LOST_REASON_MAX_ENUM); @@ -124,8 +120,6 @@ std::string CommandBufferContextTypeToString(CommandBufferContextType type) { return "Compositor"; case BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT: return "Offscreen-MainThread"; - case BROWSER_WORKER_CONTEXT: - return "CompositorWorker"; case RENDER_COMPOSITOR_CONTEXT: return "RenderCompositor"; case RENDER_WORKER_CONTEXT: diff --git a/content/common/gpu/client/command_buffer_metrics.h b/content/common/gpu/client/command_buffer_metrics.h index 0b4790c..e198d85 100644 --- a/content/common/gpu/client/command_buffer_metrics.h +++ b/content/common/gpu/client/command_buffer_metrics.h @@ -14,7 +14,6 @@ namespace content { enum CommandBufferContextType { BROWSER_COMPOSITOR_ONSCREEN_CONTEXT, BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT, - BROWSER_WORKER_CONTEXT, RENDER_COMPOSITOR_CONTEXT, RENDER_WORKER_CONTEXT, RENDERER_MAINTHREAD_CONTEXT, diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 705937a..f69dc63 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -470,11 +470,6 @@ void RenderWidgetCompositor::Initialize() { settings.use_external_begin_frame_source = false; } - settings.max_staging_buffers = 32; - // Use 1/4th of staging buffers on low-end devices. - if (base::SysInfo::IsLowEndDevice()) - settings.max_staging_buffers /= 4; - scoped_refptr compositor_thread_task_runner = compositor_deps_->GetCompositorImplThreadTaskRunner(); scoped_refptr diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index d6157af..ed7a323 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -3988,7 +3988,7 @@ _FUNCTION_INFO = { 'OrderingBarrierCHROMIUM': { 'impl_func': False, 'gen_cmd': False, - 'extension': "CHROMIUM_miscellaneous", + 'extension': True, 'chromium': True, 'client_test': False, }, diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 2750903..b6306d7 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -198,8 +198,7 @@ bool CommandBufferHelper::Finish() { if (put_ == get_offset()) { return true; } - DCHECK(HaveRingBuffer() || - error::IsError(command_buffer_->GetLastState().error)); + DCHECK(HaveRingBuffer()); Flush(); if (!WaitForGetOffsetInRange(put_, put_)) return false; diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc index a269f35..49f111f 100644 --- a/gpu/command_buffer/service/query_manager.cc +++ b/gpu/command_buffer/service/query_manager.cc @@ -785,7 +785,6 @@ QueryManager::~QueryManager() { } void QueryManager::Destroy(bool have_context) { - active_queries_.clear(); pending_queries_.clear(); pending_transfer_queries_.clear(); active_queries_.clear(); diff --git a/mojo/cc/output_surface_mojo.cc b/mojo/cc/output_surface_mojo.cc index 76f5b49..21f509f 100644 --- a/mojo/cc/output_surface_mojo.cc +++ b/mojo/cc/output_surface_mojo.cc @@ -15,9 +15,8 @@ namespace mojo { OutputSurfaceMojo::OutputSurfaceMojo( OutputSurfaceMojoClient* client, const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider, ScopedMessagePipeHandle surface_handle) - : cc::OutputSurface(context_provider, worker_context_provider), + : cc::OutputSurface(context_provider), output_surface_mojo_client_(client), surface_handle_(surface_handle.Pass()), id_namespace_(0u), diff --git a/mojo/cc/output_surface_mojo.h b/mojo/cc/output_surface_mojo.h index 82df5b8..e8f8737 100644 --- a/mojo/cc/output_surface_mojo.h +++ b/mojo/cc/output_surface_mojo.h @@ -21,11 +21,9 @@ class OutputSurfaceMojoClient { class OutputSurfaceMojo : public cc::OutputSurface { public: - OutputSurfaceMojo( - OutputSurfaceMojoClient* client, - const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider, - ScopedMessagePipeHandle surface_handle); + OutputSurfaceMojo(OutputSurfaceMojoClient* client, + const scoped_refptr& context_provider, + ScopedMessagePipeHandle surface_handle); // cc::OutputSurface implementation. void SwapBuffers(cc::CompositorFrame* frame) override; diff --git a/mojo/gpu/mojo_gles2_impl_autogen.cc b/mojo/gpu/mojo_gles2_impl_autogen.cc index 0aec3a9..a61befb 100644 --- a/mojo/gpu/mojo_gles2_impl_autogen.cc +++ b/mojo/gpu/mojo_gles2_impl_autogen.cc @@ -825,8 +825,7 @@ void MojoGLES2Impl::ShallowFlushCHROMIUM() { glShallowFlushCHROMIUM(); } void MojoGLES2Impl::OrderingBarrierCHROMIUM() { - MojoGLES2MakeCurrent(context_); - glOrderingBarrierCHROMIUM(); + NOTREACHED() << "Unimplemented OrderingBarrierCHROMIUM."; } void MojoGLES2Impl::StencilFunc(GLenum func, GLint ref, GLuint mask) { MojoGLES2MakeCurrent(context_); diff --git a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_miscellaneous_autogen.h b/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_miscellaneous_autogen.h index b1455d5..ff7dabe 100644 --- a/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_miscellaneous_autogen.h +++ b/third_party/mojo/src/mojo/public/c/gles2/gles2_call_visitor_chromium_miscellaneous_autogen.h @@ -9,4 +9,3 @@ // DO NOT EDIT! VISIT_GL_CALL(ShallowFlushCHROMIUM, void, (), ()) -VISIT_GL_CALL(OrderingBarrierCHROMIUM, void, (), ()) diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 942947d..13ddd90 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc @@ -41,11 +41,9 @@ class FakeReflector : public Reflector { // GL surface. class DirectOutputSurface : public cc::OutputSurface { public: - DirectOutputSurface( - const scoped_refptr& context_provider, - const scoped_refptr& worker_context_provider) - : cc::OutputSurface(context_provider, worker_context_provider), - weak_ptr_factory_(this) {} + explicit DirectOutputSurface( + const scoped_refptr& context_provider) + : cc::OutputSurface(context_provider), weak_ptr_factory_(this) {} ~DirectOutputSurface() override {} @@ -112,19 +110,16 @@ void InProcessContextFactory::CreateOutputSurface( InProcessContextProvider::Create(attribs, &gpu_memory_buffer_manager_, &image_factory_, compositor->widget(), "UICompositor"); - scoped_refptr worker_context_provider = - InProcessContextProvider::CreateOffscreen(&gpu_memory_buffer_manager_, - &image_factory_); scoped_ptr real_output_surface; if (use_test_surface_) { bool flipped_output_surface = false; real_output_surface = make_scoped_ptr(new cc::PixelTestOutputSurface( - context_provider, worker_context_provider, flipped_output_surface)); + context_provider, flipped_output_surface)); } else { - real_output_surface = make_scoped_ptr( - new DirectOutputSurface(context_provider, worker_context_provider)); + real_output_surface = + make_scoped_ptr(new DirectOutputSurface(context_provider)); } if (surface_manager_) { @@ -134,9 +129,9 @@ void InProcessContextFactory::CreateOutputSurface( GetSharedBitmapManager(), GetGpuMemoryBufferManager(), compositor->GetRendererSettings(), compositor->task_runner())); scoped_ptr surface_output_surface( - new cc::SurfaceDisplayOutputSurface( - surface_manager_, compositor->surface_id_allocator(), - context_provider, worker_context_provider)); + new cc::SurfaceDisplayOutputSurface(surface_manager_, + compositor->surface_id_allocator(), + context_provider)); display_client->set_surface_output_surface(surface_output_surface.get()); surface_output_surface->set_display_client(display_client.get()); diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc index 76cd19d..c5f950f 100644 --- a/ui/compositor/test/in_process_context_provider.cc +++ b/ui/compositor/test/in_process_context_provider.cc @@ -122,10 +122,6 @@ bool InProcessContextProvider::BindToCurrentThread() { return true; } -void InProcessContextProvider::DetachFromThread() { - context_thread_checker_.DetachFromThread(); -} - cc::ContextProvider::Capabilities InProcessContextProvider::ContextCapabilities() { DCHECK(context_thread_checker_.CalledOnValidThread()); diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h index 0f5f35f..bc3e494 100644 --- a/ui/compositor/test/in_process_context_provider.h +++ b/ui/compositor/test/in_process_context_provider.h @@ -49,7 +49,6 @@ class InProcessContextProvider : public cc::ContextProvider { // cc::ContextProvider: bool BindToCurrentThread() override; - void DetachFromThread() override; Capabilities ContextCapabilities() override; gpu::gles2::GLES2Interface* ContextGL() override; gpu::ContextSupport* ContextSupport() override; -- cgit v1.1