From edc0c2c7a7de29978b3c25d6f80ccee88aa00125 Mon Sep 17 00:00:00 2001 From: fsamuel Date: Fri, 18 Nov 2016 14:28:04 -0800 Subject: [PATCH] Add InProcessContextProvider and update InProcessCommandBuffer The Mus-Gpu Display Compositor will use an InProcessContextProvider and InProcessCommandBuffer in place of SurfacesContextProvider, GpuChannelHost, and CommandBufferProxyImpl to avoid the IPC overhead of those classes. This CL introduces InProcessContextProvider and allows InProcessCommandBuffer to coexist with GpuCommandBufferStubs on the same thread. In particular, when an InProcessCommandBuffer hits a sync token, it will now get descheduled if specified by InProcessCommandBuffer::Service until the token is passed. At that point, it will finish the flush and run all the operations that have been queued up since the command buffer was descheduled. This enables other command buffers on the same thread to make progress. BUG=661278 CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel Review-Url: https://codereview.chromium.org/2498053004 Cr-Commit-Position: refs/heads/master@{#433313} --- .../aw_render_thread_context_provider.cc | 2 +- .../browser/deferred_gpu_command_service.cc | 4 + .../browser/deferred_gpu_command_service.h | 1 + blimp/client/app/BUILD.gn | 1 + .../app/compositor/browser_compositor.cc | 21 +- .../app/compositor/browser_compositor.h | 2 + blimp/client/support/compositor/BUILD.gn | 1 + .../compositor/blimp_context_provider.cc | 6 +- .../compositor/blimp_context_provider.h | 5 +- .../compositor_dependencies_impl.cc | 3 +- blimp/client/test/compositor/BUILD.gn | 1 + .../test_blimp_embedder_compositor.cc | 3 +- cc/BUILD.gn | 5 + cc/DEPS | 14 + cc/output/in_process_context_provider.cc | 165 ++++++++ cc/output/in_process_context_provider.h | 84 ++++ cc/test/test_in_process_context_provider.cc | 2 +- chrome/test/BUILD.gn | 1 + chrome/test/base/chrome_unit_test_suite.cc | 5 + chrome/test/base/interactive_ui_tests_main.cc | 5 + .../display_compositor/gl_helper_benchmark.cc | 20 +- .../display_compositor/gl_helper_unittest.cc | 20 +- .../yuv_readback_unittest.cc | 21 +- .../render_widget_host_view_mac_unittest.mm | 3 + gpu/ipc/BUILD.gn | 4 + .../client/gpu_in_process_context_tests.cc | 21 +- gpu/ipc/gl_in_process_context.cc | 26 +- gpu/ipc/gl_in_process_context.h | 11 +- gpu/ipc/gpu_in_process_thread_service.cc | 69 ++++ gpu/ipc/gpu_in_process_thread_service.h | 55 +++ gpu/ipc/in_process_command_buffer.cc | 368 ++++++++++++------ gpu/ipc/in_process_command_buffer.h | 104 +++-- gpu/ipc/service/gpu_channel_manager.h | 14 +- .../test/in_process_context_factory.cc | 58 ++- .../test/in_process_context_factory.h | 10 +- .../test/in_process_context_provider.cc | 6 +- .../test/in_process_context_provider.h | 7 +- ui/views/BUILD.gn | 1 + ui/views/DEPS | 3 + ui/views/views_test_suite.cc | 6 + 40 files changed, 915 insertions(+), 243 deletions(-) create mode 100644 cc/output/in_process_context_provider.cc create mode 100644 cc/output/in_process_context_provider.h create mode 100644 gpu/ipc/gpu_in_process_thread_service.cc create mode 100644 gpu/ipc/gpu_in_process_thread_service.h diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc index eae532d14d4e25..563bce645e6241 100644 --- a/android_webview/browser/aw_render_thread_context_provider.cc +++ b/android_webview/browser/aw_render_thread_context_provider.cc @@ -62,7 +62,7 @@ AwRenderThreadContextProvider::AwRenderThreadContextProvider( limits.min_transfer_buffer_size = 64 * 1024; context_.reset(gpu::GLInProcessContext::Create( - service, surface, surface->IsOffscreen(), gfx::kNullAcceleratedWidget, + service, surface, surface->IsOffscreen(), gpu::kNullSurfaceHandle, nullptr /* share_context */, attributes, limits, nullptr, nullptr, nullptr)); diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc index cd4e85dc201942..6f0a146a90b179 100644 --- a/android_webview/browser/deferred_gpu_command_service.cc +++ b/android_webview/browser/deferred_gpu_command_service.cc @@ -209,4 +209,8 @@ void DeferredGpuCommandService::Release() const { base::RefCountedThreadSafe::Release(); } +bool DeferredGpuCommandService::BlockThreadOnWaitSyncToken() const { + return true; +} + } // namespace android_webview diff --git a/android_webview/browser/deferred_gpu_command_service.h b/android_webview/browser/deferred_gpu_command_service.h index 6d93804ee437e8..8a0ef8cde86fba 100644 --- a/android_webview/browser/deferred_gpu_command_service.h +++ b/android_webview/browser/deferred_gpu_command_service.h @@ -63,6 +63,7 @@ class DeferredGpuCommandService void AddRef() const override; void Release() const override; + bool BlockThreadOnWaitSyncToken() const override; protected: ~DeferredGpuCommandService() override; diff --git a/blimp/client/app/BUILD.gn b/blimp/client/app/BUILD.gn index b98da8137f5b92..586043c36b8521 100644 --- a/blimp/client/app/BUILD.gn +++ b/blimp/client/app/BUILD.gn @@ -34,6 +34,7 @@ source_set("app") { "//cc/surfaces", "//components/safe_json", "//components/url_formatter", + "//gpu/ipc/common", "//skia", "//ui/events", "//ui/gfx/geometry", diff --git a/blimp/client/app/compositor/browser_compositor.cc b/blimp/client/app/compositor/browser_compositor.cc index 9aa4811f00fa3a..446715ea279ba7 100644 --- a/blimp/client/app/compositor/browser_compositor.cc +++ b/blimp/client/app/compositor/browser_compositor.cc @@ -8,6 +8,10 @@ #include "blimp/client/support/compositor/blimp_context_provider.h" #include "cc/output/context_provider.h" +#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) +#include "gpu/ipc/common/gpu_surface_tracker.h" +#endif + namespace blimp { namespace client { @@ -15,14 +19,27 @@ BrowserCompositor::BrowserCompositor( CompositorDependencies* compositor_dependencies) : BlimpEmbedderCompositor(compositor_dependencies) {} -BrowserCompositor::~BrowserCompositor() = default; +BrowserCompositor::~BrowserCompositor() { +#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) + if (surface_handle_ != gpu::kNullSurfaceHandle) + gpu::GpuSurfaceTracker::Get()->RemoveSurface(surface_handle_); +#endif +} void BrowserCompositor::SetAcceleratedWidget(gfx::AcceleratedWidget widget) { scoped_refptr provider; if (widget != gfx::kNullAcceleratedWidget) { + DCHECK_EQ(gpu::kNullSurfaceHandle, surface_handle_); +#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) + surface_handle_ = + gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(widget); +#else + surface_handle_ = widget; +#endif provider = BlimpContextProvider::Create( - widget, compositor_dependencies()->GetGpuMemoryBufferManager()); + surface_handle_, + compositor_dependencies()->GetGpuMemoryBufferManager()); } SetContextProvider(std::move(provider)); diff --git a/blimp/client/app/compositor/browser_compositor.h b/blimp/client/app/compositor/browser_compositor.h index f3687f94120f74..9881d7c3587b93 100644 --- a/blimp/client/app/compositor/browser_compositor.h +++ b/blimp/client/app/compositor/browser_compositor.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "blimp/client/support/compositor/blimp_embedder_compositor.h" +#include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/native_widget_types.h" namespace blimp { @@ -37,6 +38,7 @@ class BrowserCompositor : public BlimpEmbedderCompositor { // BlimpEmbedderCompositor implementation. void DidReceiveCompositorFrameAck() override; + gpu::SurfaceHandle surface_handle_ = gpu::kNullSurfaceHandle; base::Closure did_complete_swap_buffers_; private: diff --git a/blimp/client/support/compositor/BUILD.gn b/blimp/client/support/compositor/BUILD.gn index 0a4a732516e20f..619761febbef67 100644 --- a/blimp/client/support/compositor/BUILD.gn +++ b/blimp/client/support/compositor/BUILD.gn @@ -28,6 +28,7 @@ source_set("compositor") { "//gpu/command_buffer/client:gles2_c_lib", "//gpu/command_buffer/client:gles2_implementation", "//gpu/ipc:gl_in_process_context", + "//gpu/ipc/common", "//ui/gl", ] diff --git a/blimp/client/support/compositor/blimp_context_provider.cc b/blimp/client/support/compositor/blimp_context_provider.cc index c1b63eb974a701..3f45247f282742 100644 --- a/blimp/client/support/compositor/blimp_context_provider.cc +++ b/blimp/client/support/compositor/blimp_context_provider.cc @@ -22,13 +22,13 @@ namespace client { // static scoped_refptr BlimpContextProvider::Create( - gfx::AcceleratedWidget widget, + gpu::SurfaceHandle widget, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { return new BlimpContextProvider(widget, gpu_memory_buffer_manager); } BlimpContextProvider::BlimpContextProvider( - gfx::AcceleratedWidget widget, + gpu::SurfaceHandle widget, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { context_thread_checker_.DetachFromThread(); @@ -45,7 +45,7 @@ BlimpContextProvider::BlimpContextProvider( context_.reset(gpu::GLInProcessContext::Create( nullptr /* service */, nullptr /* surface */, - widget == gfx::kNullAcceleratedWidget /* is_offscreen */, widget, + widget == gpu::kNullSurfaceHandle /* is_offscreen */, widget, nullptr /* share_context */, attribs_for_gles2, gpu::SharedMemoryLimits(), gpu_memory_buffer_manager, nullptr /* memory_limits */, base::ThreadTaskRunnerHandle::Get())); diff --git a/blimp/client/support/compositor/blimp_context_provider.h b/blimp/client/support/compositor/blimp_context_provider.h index 3d0206dd48d701..98fc1fd21cfb61 100644 --- a/blimp/client/support/compositor/blimp_context_provider.h +++ b/blimp/client/support/compositor/blimp_context_provider.h @@ -13,6 +13,7 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "cc/output/context_provider.h" +#include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/gl_in_process_context.h" #include "ui/gl/gl_surface.h" @@ -27,7 +28,7 @@ namespace client { class BlimpContextProvider : public cc::ContextProvider { public: static scoped_refptr Create( - gfx::AcceleratedWidget widget, + gpu::SurfaceHandle widget, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); // cc::ContextProvider implementation. @@ -44,7 +45,7 @@ class BlimpContextProvider : public cc::ContextProvider { const LostContextCallback& lost_context_callback) override; protected: - BlimpContextProvider(gfx::AcceleratedWidget widget, + BlimpContextProvider(gpu::SurfaceHandle widget, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); ~BlimpContextProvider() override; diff --git a/blimp/client/support/compositor/compositor_dependencies_impl.cc b/blimp/client/support/compositor/compositor_dependencies_impl.cc index b85aad9c4baabc..377be1aca745b5 100644 --- a/blimp/client/support/compositor/compositor_dependencies_impl.cc +++ b/blimp/client/support/compositor/compositor_dependencies_impl.cc @@ -10,6 +10,7 @@ #include "cc/output/context_provider.h" #include "cc/surfaces/surface_manager.h" #include "cc/trees/layer_tree_settings.h" +#include "gpu/ipc/common/surface_handle.h" namespace blimp { namespace client { @@ -38,7 +39,7 @@ cc::FrameSinkId CompositorDependenciesImpl::AllocateFrameSinkId() { void CompositorDependenciesImpl::GetContextProviders( const CompositorDependencies::ContextProviderCallback& callback) { scoped_refptr compositor_context = - BlimpContextProvider::Create(gfx::kNullAcceleratedWidget, + BlimpContextProvider::Create(gpu::kNullSurfaceHandle, gpu_memory_buffer_manager_.get()); // TODO(khushalsagar): Make a worker context and bind to the current thread. diff --git a/blimp/client/test/compositor/BUILD.gn b/blimp/client/test/compositor/BUILD.gn index 59eb7de1331f16..d399460b153567 100644 --- a/blimp/client/test/compositor/BUILD.gn +++ b/blimp/client/test/compositor/BUILD.gn @@ -17,6 +17,7 @@ source_set("compositor") { deps = [ "//cc:test_support", "//cc/proto", + "//gpu/ipc/common", ] public_deps = [ diff --git a/blimp/client/test/compositor/test_blimp_embedder_compositor.cc b/blimp/client/test/compositor/test_blimp_embedder_compositor.cc index 94b216d2c35dcf..0061f5dff40b5a 100644 --- a/blimp/client/test/compositor/test_blimp_embedder_compositor.cc +++ b/blimp/client/test/compositor/test_blimp_embedder_compositor.cc @@ -12,6 +12,7 @@ #include "cc/layers/layer.h" #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" +#include "gpu/ipc/common/surface_handle.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/native_widget_types.h" @@ -22,7 +23,7 @@ TestBlimpEmbedderCompositor::TestBlimpEmbedderCompositor( CompositorDependencies* compositor_dependencies) : BlimpEmbedderCompositor(compositor_dependencies) { SetContextProvider(BlimpContextProvider::Create( - gfx::kNullAcceleratedWidget, + gpu::kNullSurfaceHandle, compositor_dependencies->GetGpuMemoryBufferManager())); } diff --git a/cc/BUILD.gn b/cc/BUILD.gn index a3622218d6a8fc..5c13d6ea780e59 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -244,6 +244,8 @@ component("cc") { "output/gl_renderer.h", "output/gl_renderer_draw_cache.cc", "output/gl_renderer_draw_cache.h", + "output/in_process_context_provider.cc", + "output/in_process_context_provider.h", "output/latency_info_swap_promise.cc", "output/latency_info_swap_promise.h", "output/layer_quad.cc", @@ -584,7 +586,10 @@ component("cc") { "//cc/proto", "//cc/surfaces:surface_id", "//gpu", + "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/client:gles2_interface", + "//gpu/ipc:gl_in_process_context", + "//gpu/skia_bindings:skia_bindings", "//media", "//third_party/libyuv", "//ui/events:events_base", diff --git a/cc/DEPS b/cc/DEPS index c41afd289ce80a..bbab8316a1074d 100644 --- a/cc/DEPS +++ b/cc/DEPS @@ -22,3 +22,17 @@ include_rules = [ "+ui/gl", "-cc/blink", ] + +specific_include_rules = { + "in_process_context_provider\.cc": [ + "+gpu/command_buffer/client", + "+gpu/command_buffer/common", + "+gpu/command_buffer/service", + "+gpu/ipc", + "+gpu/skia_bindings", + ], + "in_process_context_provider\.h": [ + "+gpu/command_buffer/common", + "+gpu/ipc", + ], +} diff --git a/cc/output/in_process_context_provider.cc b/cc/output/in_process_context_provider.cc new file mode 100644 index 00000000000000..999b7c7b51c7cb --- /dev/null +++ b/cc/output/in_process_context_provider.cc @@ -0,0 +1,165 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/output/in_process_context_provider.h" + +#include + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "cc/resources/platform_color.h" +#include "gpu/GLES2/gl2extchromium.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/framebuffer_completeness_cache.h" +#include "gpu/command_buffer/service/gpu_preferences.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/shader_translator_cache.h" +#include "gpu/command_buffer/service/sync_point_manager.h" +#include "gpu/ipc/common/surface_handle.h" +#include "gpu/ipc/gl_in_process_context.h" +#include "gpu/ipc/gpu_in_process_thread_service.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "gpu/skia_bindings/grcontext_for_gles2_interface.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" +#include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_share_group.h" + +namespace cc { + +namespace { + +gpu::gles2::ContextCreationAttribHelper CreateAttributes() { + gpu::gles2::ContextCreationAttribHelper attributes; + attributes.alpha_size = -1; + attributes.depth_size = 0; + attributes.stencil_size = 0; + attributes.samples = 0; + attributes.sample_buffers = 0; + attributes.fail_if_major_perf_caveat = false; + attributes.bind_generates_resource = false; + return attributes; +} + +std::unique_ptr CreateInProcessContext( + scoped_refptr service, + const gpu::gles2::ContextCreationAttribHelper& attributes, + gpu::SurfaceHandle widget, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + gpu::ImageFactory* image_factory, + const gpu::SharedMemoryLimits& limits, + gpu::GLInProcessContext* shared_context) { + const bool is_offscreen = widget == gpu::kNullSurfaceHandle; + return base::WrapUnique(gpu::GLInProcessContext::Create( + service, nullptr, is_offscreen, widget, shared_context, attributes, + limits, gpu_memory_buffer_manager, image_factory, + base::ThreadTaskRunnerHandle::Get())); +} + +} // namespace + +InProcessContextProvider::InProcessContextProvider( + scoped_refptr service, + gpu::SurfaceHandle widget, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + gpu::ImageFactory* image_factory, + const gpu::SharedMemoryLimits& limits, + InProcessContextProvider* shared_context) + : attributes_(CreateAttributes()), + context_(CreateInProcessContext( + service, + attributes_, + widget, + gpu_memory_buffer_manager, + image_factory, + limits, + (shared_context ? shared_context->context_.get() : nullptr))) { + cache_controller_.reset(new ContextCacheController( + context_->GetImplementation(), base::ThreadTaskRunnerHandle::Get())); +} + +InProcessContextProvider::~InProcessContextProvider() = default; + +bool InProcessContextProvider::BindToCurrentThread() { + return !!context_; +} + +gpu::gles2::GLES2Interface* InProcessContextProvider::ContextGL() { + return context_->GetImplementation(); +} + +gpu::ContextSupport* InProcessContextProvider::ContextSupport() { + return context_->GetImplementation(); +} + +class GrContext* InProcessContextProvider::GrContext() { + if (gr_context_) + return gr_context_->get(); + + gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(ContextGL())); + return gr_context_->get(); +} + +ContextCacheController* InProcessContextProvider::CacheController() { + return cache_controller_.get(); +} + +void InProcessContextProvider::InvalidateGrContext(uint32_t state) { + if (gr_context_) + gr_context_->ResetContext(state); +} + +base::Lock* InProcessContextProvider::GetLock() { + return &context_lock_; +} + +gpu::Capabilities InProcessContextProvider::ContextCapabilities() { + gpu::Capabilities capabilities; + capabilities.texture_rectangle = true; + capabilities.sync_query = true; + switch (PlatformColor::Format()) { + case PlatformColor::SOURCE_FORMAT_RGBA8: + capabilities.texture_format_bgra8888 = false; + break; + case PlatformColor::SOURCE_FORMAT_BGRA8: + capabilities.texture_format_bgra8888 = true; + break; + } + return capabilities; +} + +void InProcessContextProvider::SetLostContextCallback( + const LostContextCallback& lost_context_callback) { + // This code lives in the GPU process and so this would go away + // if the context is lost? +} + +uint32_t InProcessContextProvider::GetCopyTextureInternalFormat() { + if (attributes_.alpha_size > 0) + return GL_RGBA; + DCHECK_NE(attributes_.red_size, 0); + DCHECK_NE(attributes_.green_size, 0); + DCHECK_NE(attributes_.blue_size, 0); + return GL_RGB; +} + +void InProcessContextProvider::SetSwapBuffersCompletionCallback( + const gpu::InProcessCommandBuffer::SwapBuffersCompletionCallback& + callback) { + context_->SetSwapBuffersCompletionCallback(callback); +} + +void InProcessContextProvider::SetUpdateVSyncParametersCallback( + const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& + callback) { + context_->SetUpdateVSyncParametersCallback(callback); +} + +} // namespace cc diff --git a/cc/output/in_process_context_provider.h b/cc/output/in_process_context_provider.h new file mode 100644 index 00000000000000..e42c094797d08b --- /dev/null +++ b/cc/output/in_process_context_provider.h @@ -0,0 +1,84 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_OUTPUT_IN_PROCESS_CONTEXT_PROVIDER_H_ +#define CC_OUTPUT_IN_PROCESS_CONTEXT_PROVIDER_H_ + +#include + +#include + +#include "base/synchronization/lock.h" +#include "cc/output/context_cache_controller.h" +#include "cc/output/context_provider.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "ui/gfx/native_widget_types.h" + +class GrContext; + +namespace gpu { +class GLInProcessContext; +class GpuMemoryBufferManager; +class ImageFactory; +struct SharedMemoryLimits; +class SyncPointManager; +namespace gles2 { +class MailboxManager; +} +} + +namespace skia_bindings { +class GrContextForGLES2Interface; +} + +namespace cc { + +class InProcessContextProvider : public ContextProvider { + public: + InProcessContextProvider( + scoped_refptr service, + gpu::SurfaceHandle widget, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + gpu::ImageFactory* image_factory, + const gpu::SharedMemoryLimits& limits, + InProcessContextProvider* shared_context); + + bool BindToCurrentThread() override; + gpu::gles2::GLES2Interface* ContextGL() override; + gpu::ContextSupport* ContextSupport() override; + class GrContext* GrContext() override; + ContextCacheController* CacheController() override; + void InvalidateGrContext(uint32_t state) override; + base::Lock* GetLock() override; + gpu::Capabilities ContextCapabilities() override; + void SetLostContextCallback( + const LostContextCallback& lost_context_callback) override; + + uint32_t GetCopyTextureInternalFormat(); + + void SetSwapBuffersCompletionCallback( + const gpu::InProcessCommandBuffer::SwapBuffersCompletionCallback& + callback); + + void SetUpdateVSyncParametersCallback( + const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& + callback); + + protected: + friend class base::RefCountedThreadSafe; + ~InProcessContextProvider() override; + + private: + const gpu::gles2::ContextCreationAttribHelper attributes_; + + base::Lock context_lock_; + std::unique_ptr context_; + std::unique_ptr gr_context_; + std::unique_ptr cache_controller_; +}; + +} // namespace cc + +#endif // CC_OUTPUT_IN_PROCESS_CONTEXT_PROVIDER_H_ diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc index 4621eb7f59b3eb..042be7cf124481 100644 --- a/cc/test/test_in_process_context_provider.cc +++ b/cc/test/test_in_process_context_provider.cc @@ -45,7 +45,7 @@ std::unique_ptr CreateTestInProcessContext( std::unique_ptr context = base::WrapUnique(gpu::GLInProcessContext::Create( - nullptr, nullptr, is_offscreen, gfx::kNullAcceleratedWidget, + nullptr, nullptr, is_offscreen, gpu::kNullSurfaceHandle, shared_context, attribs, gpu::SharedMemoryLimits(), gpu_memory_buffer_manager, image_factory, std::move(task_runner))); diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 281eb147e3346d..c363d3e2c6ded2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -124,6 +124,7 @@ static_library("test_support") { "//content/public/app:both", "//content/test:test_support", "//extensions/features", + "//gpu/ipc/service", "//net", "//net:test_support", "//printing/features", diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc index 5e1665860f2fde..6fa025725e8a1e 100644 --- a/chrome/test/base/chrome_unit_test_suite.cc +++ b/chrome/test/base/chrome_unit_test_suite.cc @@ -20,6 +20,7 @@ #include "components/update_client/update_query_params.h" #include "content/public/common/content_paths.h" #include "extensions/features/features.h" +#include "gpu/ipc/service/image_transport_surface.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_handle.h" @@ -147,6 +148,10 @@ void ChromeUnitTestSuite::InitializeProviders() { gl::GLSurfaceTestSupport::InitializeOneOff(); +#if defined(OS_MACOSX) + gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true); +#endif + update_client::UpdateQueryParams::SetDelegate( ChromeUpdateQueryParamsDelegate::GetInstance()); } diff --git a/chrome/test/base/interactive_ui_tests_main.cc b/chrome/test/base/interactive_ui_tests_main.cc index b84939fc25c5c5..c2491cf2b4ce2e 100644 --- a/chrome/test/base/interactive_ui_tests_main.cc +++ b/chrome/test/base/interactive_ui_tests_main.cc @@ -8,6 +8,7 @@ #include "chrome/test/base/chrome_test_suite.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" +#include "gpu/ipc/service/image_transport_surface.h" #include "ui/base/test/ui_controls.h" #if defined(USE_AURA) @@ -37,6 +38,10 @@ class InteractiveUITestSuite : public ChromeTestSuite { void Initialize() override { ChromeTestSuite::Initialize(); +#if defined(OS_MACOSX) + gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true); +#endif + // Only allow ui_controls to be used in interactive_ui_tests, since they // depend on focus and can't be sharded. ui_controls::EnableUIControls(); diff --git a/components/display_compositor/gl_helper_benchmark.cc b/components/display_compositor/gl_helper_benchmark.cc index 38e009fc61cab1..674e4fd18bd846 100644 --- a/components/display_compositor/gl_helper_benchmark.cc +++ b/components/display_compositor/gl_helper_benchmark.cc @@ -67,16 +67,16 @@ class GLHelperBenchmark : public testing::Test { attributes.bind_generates_resource = false; attributes.gpu_preference = gl::PreferDiscreteGpu; - context_.reset(gpu::GLInProcessContext::Create( - nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gfx::kNullAcceleratedWidget, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get())); + context_.reset( + gpu::GLInProcessContext::Create(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + base::ThreadTaskRunnerHandle::Get())); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation(); diff --git a/components/display_compositor/gl_helper_unittest.cc b/components/display_compositor/gl_helper_unittest.cc index b70e9211d8f8b5..73a837dfd0e2f2 100644 --- a/components/display_compositor/gl_helper_unittest.cc +++ b/components/display_compositor/gl_helper_unittest.cc @@ -67,16 +67,16 @@ class GLHelperTest : public testing::Test { attributes.sample_buffers = 1; attributes.bind_generates_resource = false; - context_.reset(gpu::GLInProcessContext::Create( - nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gfx::kNullAcceleratedWidget, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get())); + context_.reset( + gpu::GLInProcessContext::Create(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + base::ThreadTaskRunnerHandle::Get())); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation(); diff --git a/components/display_compositor/yuv_readback_unittest.cc b/components/display_compositor/yuv_readback_unittest.cc index 29cc498f3a84a4..fe595e3364a996 100644 --- a/components/display_compositor/yuv_readback_unittest.cc +++ b/components/display_compositor/yuv_readback_unittest.cc @@ -13,6 +13,7 @@ #include "components/display_compositor/gl_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/gl_in_process_context.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" @@ -40,16 +41,16 @@ class YUVReadbackTest : public testing::Test { attributes.sample_buffers = 1; attributes.bind_generates_resource = false; - context_.reset(gpu::GLInProcessContext::Create( - nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gfx::kNullAcceleratedWidget, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get())); + context_.reset( + gpu::GLInProcessContext::Create(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + base::ThreadTaskRunnerHandle::Get())); gl_ = context_->GetImplementation(); gpu::ContextSupport* support = context_->GetImplementation(); diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 47757f1d382feb..5f533eafb1b70d 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -34,6 +34,7 @@ #include "content/public/test/test_utils.h" #include "content/test/test_render_view_host.h" #include "gpu/ipc/common/gpu_messages.h" +#include "gpu/ipc/service/image_transport_surface.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" @@ -254,6 +255,8 @@ void GenerateCompositionRectArray(const gfx::Point& origin, void SetUp() override { RenderViewHostImplTestHarness::SetUp(); + gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true); + // TestRenderViewHost's destruction assumes that its view is a // TestRenderWidgetHostView, so store its view and reset it back to the // stored view in |TearDown()|. diff --git a/gpu/ipc/BUILD.gn b/gpu/ipc/BUILD.gn index a30ffdcfa984ac..5c03cf515ff207 100644 --- a/gpu/ipc/BUILD.gn +++ b/gpu/ipc/BUILD.gn @@ -19,6 +19,8 @@ group("command_buffer") { source_set("command_buffer_sources") { visibility = [ "//gpu/*" ] sources = [ + "gpu_in_process_thread_service.cc", + "gpu_in_process_thread_service.h", "in_process_command_buffer.cc", "in_process_command_buffer.h", ] @@ -31,6 +33,8 @@ source_set("command_buffer_sources") { "//gpu/command_buffer/common:common_sources", "//gpu/command_buffer/service:service_sources", "//gpu/config:config_sources", + "//gpu/ipc/client:ipc_client_sources", + "//gpu/ipc/service:ipc_service_sources", "//ui/gfx", "//ui/gl", "//ui/gl/init", diff --git a/gpu/ipc/client/gpu_in_process_context_tests.cc b/gpu/ipc/client/gpu_in_process_context_tests.cc index fdce1c024d4100..7562908be44476 100644 --- a/gpu/ipc/client/gpu_in_process_context_tests.cc +++ b/gpu/ipc/client/gpu_in_process_context_tests.cc @@ -12,6 +12,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/ipc/common/surface_handle.h" #include "gpu/ipc/gl_in_process_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_surface.h" @@ -32,16 +33,16 @@ class ContextTestBase : public testing::Test { attributes.sample_buffers = 1; attributes.bind_generates_resource = false; - context_.reset(gpu::GLInProcessContext::Create( - nullptr, /* service */ - nullptr, /* surface */ - true, /* offscreen */ - gfx::kNullAcceleratedWidget, /* window */ - nullptr, /* share_context */ - attributes, gpu::SharedMemoryLimits(), - nullptr, /* gpu_memory_buffer_manager */ - nullptr, /* image_factory */ - base::ThreadTaskRunnerHandle::Get())); + context_.reset( + gpu::GLInProcessContext::Create(nullptr, /* service */ + nullptr, /* surface */ + true, /* offscreen */ + gpu::kNullSurfaceHandle, /* window */ + nullptr, /* share_context */ + attributes, gpu::SharedMemoryLimits(), + nullptr, /* gpu_memory_buffer_manager */ + nullptr, /* image_factory */ + base::ThreadTaskRunnerHandle::Get())); gl_ = context_->GetImplementation(); context_support_ = context_->GetImplementation(); } diff --git a/gpu/ipc/gl_in_process_context.cc b/gpu/ipc/gl_in_process_context.cc index 16a1cb165000be..7d734002a918e5 100644 --- a/gpu/ipc/gl_in_process_context.cc +++ b/gpu/ipc/gl_in_process_context.cc @@ -54,7 +54,7 @@ class GLInProcessContextImpl bool Initialize(scoped_refptr surface, bool is_offscreen, GLInProcessContext* share_context, - gfx::AcceleratedWidget window, + SurfaceHandle window, const gpu::gles2::ContextCreationAttribHelper& attribs, const scoped_refptr& service, const SharedMemoryLimits& mem_limits, @@ -64,6 +64,12 @@ class GLInProcessContextImpl // GLInProcessContext implementation: gles2::GLES2Implementation* GetImplementation() override; + void SetSwapBuffersCompletionCallback( + const gpu::InProcessCommandBuffer::SwapBuffersCompletionCallback& + callback) override; + void SetUpdateVSyncParametersCallback( + const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& + callback) override; void SetLock(base::Lock* lock) override; private: @@ -88,6 +94,18 @@ gles2::GLES2Implementation* GLInProcessContextImpl::GetImplementation() { return gles2_implementation_.get(); } +void GLInProcessContextImpl::SetSwapBuffersCompletionCallback( + const gpu::InProcessCommandBuffer::SwapBuffersCompletionCallback& + callback) { + command_buffer_->SetSwapBuffersCompletionCallback(callback); +} + +void GLInProcessContextImpl::SetUpdateVSyncParametersCallback( + const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& + callback) { + command_buffer_->SetUpdateVSyncParametersCallback(callback); +} + void GLInProcessContextImpl::SetLock(base::Lock* lock) { NOTREACHED(); } @@ -96,7 +114,7 @@ bool GLInProcessContextImpl::Initialize( scoped_refptr surface, bool is_offscreen, GLInProcessContext* share_context, - gfx::AcceleratedWidget window, + SurfaceHandle window, const gles2::ContextCreationAttribHelper& attribs, const scoped_refptr& service, const SharedMemoryLimits& mem_limits, @@ -183,7 +201,7 @@ GLInProcessContext* GLInProcessContext::Create( scoped_refptr service, scoped_refptr surface, bool is_offscreen, - gfx::AcceleratedWidget window, + SurfaceHandle window, GLInProcessContext* share_context, const ::gpu::gles2::ContextCreationAttribHelper& attribs, const SharedMemoryLimits& memory_limits, @@ -196,7 +214,7 @@ GLInProcessContext* GLInProcessContext::Create( if (surface) { DCHECK_EQ(surface->IsOffscreen(), is_offscreen); - DCHECK_EQ(gfx::kNullAcceleratedWidget, window); + DCHECK_EQ(kNullSurfaceHandle, window); } std::unique_ptr context(new GLInProcessContextImpl); diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h index e03363f3acad48..83aeb09cb1cefc 100644 --- a/gpu/ipc/gl_in_process_context.h +++ b/gpu/ipc/gl_in_process_context.h @@ -28,6 +28,7 @@ class SurfaceTexture; #endif namespace gpu { +class InProcessCommandBuffer; struct SharedMemoryLimits; namespace gles2 { @@ -50,7 +51,7 @@ class GL_IN_PROCESS_CONTEXT_EXPORT GLInProcessContext { scoped_refptr service, scoped_refptr surface, bool is_offscreen, - gfx::AcceleratedWidget window, + SurfaceHandle window, GLInProcessContext* share_context, const gpu::gles2::ContextCreationAttribHelper& attribs, const SharedMemoryLimits& memory_limits, @@ -63,6 +64,14 @@ class GL_IN_PROCESS_CONTEXT_EXPORT GLInProcessContext { virtual gles2::GLES2Implementation* GetImplementation() = 0; virtual void SetLock(base::Lock* lock) = 0; + + virtual void SetSwapBuffersCompletionCallback( + const gpu::InProcessCommandBuffer::SwapBuffersCompletionCallback& + callback) = 0; + + virtual void SetUpdateVSyncParametersCallback( + const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback& + callback) = 0; }; } // namespace gpu diff --git a/gpu/ipc/gpu_in_process_thread_service.cc b/gpu/ipc/gpu_in_process_thread_service.cc new file mode 100644 index 00000000000000..b21b864e3b1c6e --- /dev/null +++ b/gpu/ipc/gpu_in_process_thread_service.cc @@ -0,0 +1,69 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/ipc/gpu_in_process_thread_service.h" + +#include "base/lazy_instance.h" +#include "base/threading/thread_task_runner_handle.h" + +namespace gpu { + +GpuInProcessThreadService::GpuInProcessThreadService( + scoped_refptr task_runner, + gpu::SyncPointManager* sync_point_manager, + gpu::gles2::MailboxManager* mailbox_manager, + scoped_refptr share_group) + : gpu::InProcessCommandBuffer::Service(mailbox_manager, share_group), + task_runner_(task_runner), + sync_point_manager_(sync_point_manager) {} + +void GpuInProcessThreadService::ScheduleTask(const base::Closure& task) { + task_runner_->PostTask(FROM_HERE, task); +} + +void GpuInProcessThreadService::ScheduleDelayedWork(const base::Closure& task) { + task_runner_->PostDelayedTask(FROM_HERE, task, + base::TimeDelta::FromMilliseconds(2)); +} +bool GpuInProcessThreadService::UseVirtualizedGLContexts() { + return true; +} + +scoped_refptr +GpuInProcessThreadService::shader_translator_cache() { + if (!shader_translator_cache_) { + shader_translator_cache_ = make_scoped_refptr( + new gpu::gles2::ShaderTranslatorCache(gpu_preferences())); + } + return shader_translator_cache_; +} + +scoped_refptr +GpuInProcessThreadService::framebuffer_completeness_cache() { + if (!framebuffer_completeness_cache_.get()) { + framebuffer_completeness_cache_ = + make_scoped_refptr(new gpu::gles2::FramebufferCompletenessCache); + } + return framebuffer_completeness_cache_; +} + +gpu::SyncPointManager* GpuInProcessThreadService::sync_point_manager() { + return sync_point_manager_; +} + +void GpuInProcessThreadService::AddRef() const { + base::RefCountedThreadSafe::AddRef(); +} + +void GpuInProcessThreadService::Release() const { + base::RefCountedThreadSafe::Release(); +} + +bool GpuInProcessThreadService::BlockThreadOnWaitSyncToken() const { + return false; +} + +GpuInProcessThreadService::~GpuInProcessThreadService() {} + +} // namespace gpu diff --git a/gpu/ipc/gpu_in_process_thread_service.h b/gpu/ipc/gpu_in_process_thread_service.h new file mode 100644 index 00000000000000..52e8b489566f77 --- /dev/null +++ b/gpu/ipc/gpu_in_process_thread_service.h @@ -0,0 +1,55 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_IPC_GPU_IN_PROCESS_THREAD_SERVICE_H_ +#define GPU_IPC_GPU_IN_PROCESS_THREAD_SERVICE_H_ + +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "ui/gl/gl_share_group.h" + +namespace gpu { + +// Default Service class when a null service is used. +class GpuInProcessThreadService + : public gpu::InProcessCommandBuffer::Service, + public base::RefCountedThreadSafe { + public: + GpuInProcessThreadService( + scoped_refptr task_runner, + gpu::SyncPointManager* sync_point_manager, + gpu::gles2::MailboxManager* mailbox_manager, + scoped_refptr share_group); + + // gpu::InProcessCommandBuffer::Service implementation. + void ScheduleTask(const base::Closure& task) override; + void ScheduleDelayedWork(const base::Closure& task) override; + bool UseVirtualizedGLContexts() override; + scoped_refptr shader_translator_cache() + override; + scoped_refptr + framebuffer_completeness_cache() override; + gpu::SyncPointManager* sync_point_manager() override; + void AddRef() const override; + void Release() const override; + bool BlockThreadOnWaitSyncToken() const override; + + private: + friend class base::RefCountedThreadSafe; + + ~GpuInProcessThreadService() override; + + scoped_refptr task_runner_; + + gpu::SyncPointManager* sync_point_manager_; // Non-owning. + scoped_refptr shader_translator_cache_; + scoped_refptr + framebuffer_completeness_cache_; + + DISALLOW_COPY_AND_ASSIGN(GpuInProcessThreadService); +}; + +} // namespace gpu + +#endif // GPU_IPC_GPU_IN_PROCESS_THREAD_SERVICE_H_ diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 54c0f0d3ebd463..9ed647621779c9 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc @@ -17,6 +17,7 @@ #include "base/lazy_instance.h" #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/numerics/safe_conversions.h" #include "base/sequence_checker.h" @@ -40,6 +41,8 @@ #include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" +#include "gpu/ipc/gpu_in_process_thread_service.h" +#include "gpu/ipc/service/image_transport_surface.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" @@ -52,6 +55,10 @@ #include "base/process/process_handle.h" #endif +#if defined(OS_MACOSX) +#include "gpu/ipc/client/gpu_process_hosted_ca_layer_tree_params.h" +#endif + namespace gpu { namespace { @@ -66,27 +73,27 @@ static void RunTaskWithResult(base::Callback task, completion->Signal(); } -struct ScopedOrderNumberProcessor { - ScopedOrderNumberProcessor(SyncPointOrderData* order_data, uint32_t order_num) - : order_data_(order_data), order_num_(order_num) { - order_data_->BeginProcessingOrderNumber(order_num_); +class GpuInProcessThreadHolder : public base::Thread { + public: + GpuInProcessThreadHolder() + : base::Thread("GpuThread"), + sync_point_manager_(new SyncPointManager(false)) { + Start(); } - ~ScopedOrderNumberProcessor() { - order_data_->FinishProcessingOrderNumber(order_num_); + ~GpuInProcessThreadHolder() override { Stop(); } + + const scoped_refptr& GetGpuThreadService() { + if (!gpu_thread_service_) { + gpu_thread_service_ = new GpuInProcessThreadService( + task_runner(), sync_point_manager_.get(), nullptr, nullptr); + } + return gpu_thread_service_; } private: - SyncPointOrderData* order_data_; - uint32_t order_num_; -}; - -struct GpuInProcessThreadHolder { - GpuInProcessThreadHolder() - : sync_point_manager(new SyncPointManager(false)), - gpu_thread(new GpuInProcessThread(sync_point_manager.get())) {} - std::unique_ptr sync_point_manager; - scoped_refptr gpu_thread; + std::unique_ptr sync_point_manager_; + scoped_refptr gpu_thread_service_; }; base::LazyInstance g_default_service = @@ -141,7 +148,7 @@ scoped_refptr GetInitialService( // ThreadTaskRunnerHandle, which will re-add a new task to the, AtExitManager, // which causes a deadlock because it's already locked. base::ThreadTaskRunnerHandle::IsSet(); - return g_default_service.Get().gpu_thread; + return g_default_service.Get().GetGpuThreadService(); } } // anonyous namespace @@ -153,6 +160,13 @@ InProcessCommandBuffer::Service::Service(const GpuPreferences& gpu_preferences) : gpu_preferences_(gpu_preferences), gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {} +InProcessCommandBuffer::Service::Service( + gpu::gles2::MailboxManager* mailbox_manager, + scoped_refptr share_group) + : gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()), + mailbox_manager_(mailbox_manager), + share_group_(share_group) {} + InProcessCommandBuffer::Service::~Service() {} const gpu::GpuPreferences& InProcessCommandBuffer::Service::gpu_preferences() { @@ -251,7 +265,7 @@ void InProcessCommandBuffer::PumpCommandsOnGpuThread() { bool InProcessCommandBuffer::Initialize( scoped_refptr surface, bool is_offscreen, - gfx::AcceleratedWidget window, + SurfaceHandle window, const gles2::ContextCreationAttribHelper& attribs, InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, @@ -286,8 +300,8 @@ bool InProcessCommandBuffer::Initialize( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); bool result = false; - QueueTask( - base::Bind(&RunTaskWithResult, init_task, &result, &completion)); + QueueTask(true, base::Bind(&RunTaskWithResult, init_task, &result, + &completion)); completion.Wait(); gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; @@ -320,14 +334,17 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( bool bind_generates_resource = false; scoped_refptr feature_info = new gles2::FeatureInfo(service_->gpu_driver_bug_workarounds()); - decoder_.reset(gles2::GLES2Decoder::Create( + + context_group_ = params.context_group ? params.context_group->decoder_->GetContextGroup() : new gles2::ContextGroup( service_->gpu_preferences(), service_->mailbox_manager(), NULL, service_->shader_translator_cache(), service_->framebuffer_completeness_cache(), feature_info, - bind_generates_resource, nullptr, nullptr))); + bind_generates_resource, nullptr, nullptr); + + decoder_.reset(gles2::GLES2Decoder::Create(context_group_.get())); executor_.reset(new CommandExecutor(command_buffer.get(), decoder_.get(), decoder_.get())); @@ -338,10 +355,18 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( decoder_->set_engine(executor_.get()); if (!surface_.get()) { - if (params.is_offscreen) + if (params.is_offscreen) { surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); - else - surface_ = gl::init::CreateViewGLSurface(params.window); + } else { + surface_ = ImageTransportSurface::CreateNativeSurface( + gpu_thread_weak_ptr_factory_.GetWeakPtr(), params.window, + gl::GLSurface::SURFACE_DEFAULT); + if (!surface_ || !surface_->Initialize(gl::GLSurface::SURFACE_DEFAULT)) { + surface_ = nullptr; + DLOG(ERROR) << "Failed to create surface."; + return false; + } + } } if (!surface_.get()) { @@ -444,8 +469,8 @@ void InProcessCommandBuffer::Destroy() { bool result = false; base::Callback destroy_task = base::Bind( &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this)); - QueueTask( - base::Bind(&RunTaskWithResult, destroy_task, &result, &completion)); + QueueTask(true, base::Bind(&RunTaskWithResult, destroy_task, &result, + &completion)); completion.Wait(); } @@ -468,6 +493,10 @@ bool InProcessCommandBuffer::DestroyOnGpuThread() { } gl_share_group_ = nullptr; + base::AutoLock lock(task_queue_lock_); + std::queue> empty; + task_queue_.swap(empty); + return true; } @@ -504,6 +533,42 @@ CommandBuffer::State InProcessCommandBuffer::GetStateFast() { return last_state_; } +void InProcessCommandBuffer::QueueTask(bool out_of_order, + const base::Closure& task) { + if (out_of_order) { + service_->ScheduleTask(task); + return; + } + // Release the |task_queue_lock_| before calling ScheduleTask because + // the callback may get called immediately and attempt to acquire the lock. + SyncPointManager* sync_manager = service_->sync_point_manager(); + uint32_t order_num = + sync_point_order_data_->GenerateUnprocessedOrderNumber(sync_manager); + { + base::AutoLock lock(task_queue_lock_); + task_queue_.push(base::MakeUnique(task, order_num)); + } + service_->ScheduleTask(base::Bind( + &InProcessCommandBuffer::ProcessTasksOnGpuThread, gpu_thread_weak_ptr_)); +} + +void InProcessCommandBuffer::ProcessTasksOnGpuThread() { + while (executor_->scheduled()) { + base::AutoLock lock(task_queue_lock_); + if (task_queue_.empty()) + break; + GpuTask* task = task_queue_.front().get(); + sync_point_order_data_->BeginProcessingOrderNumber(task->order_number); + task->callback.Run(); + if (!executor_->scheduled() && !service_->BlockThreadOnWaitSyncToken()) { + sync_point_order_data_->PauseProcessingOrderNumber(task->order_number); + return; + } + sync_point_order_data_->FinishProcessingOrderNumber(task->order_number); + task_queue_.pop(); + } +} + CommandBuffer::State InProcessCommandBuffer::GetLastState() { CheckSequencedThread(); return last_state_; @@ -515,28 +580,18 @@ int32_t InProcessCommandBuffer::GetLastToken() { return last_state_.token; } -void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset, - uint32_t order_num) { +void InProcessCommandBuffer::FlushOnGpuThread(int32_t put_offset) { CheckSequencedThread(); ScopedEvent handle_flush(&flush_event_); base::AutoLock lock(command_buffer_lock_); { - ScopedOrderNumberProcessor scoped_order_num(sync_point_order_data_.get(), - order_num); command_buffer_->Flush(put_offset); { // Update state before signaling the flush event. base::AutoLock lock(state_after_last_flush_lock_); state_after_last_flush_ = command_buffer_->GetLastState(); } - - // Currently the in process command buffer does not support being - // descheduled, if it does we would need to back off on calling the finish - // processing number function until the message is rescheduled and finished - // processing. This DCHECK is to enforce this. - DCHECK(error::IsError(state_after_last_flush_.error) || - put_offset == state_after_last_flush_.get_offset); } // If we've processed all pending commands but still have pending queries, @@ -578,13 +633,10 @@ void InProcessCommandBuffer::Flush(int32_t put_offset) { if (last_put_offset_ == put_offset) return; - SyncPointManager* sync_manager = service_->sync_point_manager(); - const uint32_t order_num = - sync_point_order_data_->GenerateUnprocessedOrderNumber(sync_manager); last_put_offset_ = put_offset; base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, - gpu_thread_weak_ptr_, put_offset, order_num); - QueueTask(task); + gpu_thread_weak_ptr_, put_offset); + QueueTask(false, task); flushed_fence_sync_release_ = next_fence_sync_release_ - 1; } @@ -596,8 +648,9 @@ void InProcessCommandBuffer::OrderingBarrier(int32_t put_offset) { void InProcessCommandBuffer::WaitForTokenInRange(int32_t start, int32_t end) { CheckSequencedThread(); while (!InRange(start, end, GetLastToken()) && - last_state_.error == gpu::error::kNoError) + last_state_.error == gpu::error::kNoError) { flush_event_.Wait(); + } } void InProcessCommandBuffer::WaitForGetOffsetInRange(int32_t start, @@ -623,7 +676,7 @@ void InProcessCommandBuffer::SetGetBuffer(int32_t shm_id) { base::Closure task = base::Bind(&InProcessCommandBuffer::SetGetBufferOnGpuThread, base::Unretained(this), shm_id, &completion); - QueueTask(task); + QueueTask(false, task); completion.Wait(); { @@ -655,7 +708,7 @@ void InProcessCommandBuffer::DestroyTransferBuffer(int32_t id) { base::Bind(&InProcessCommandBuffer::DestroyTransferBufferOnGpuThread, base::Unretained(this), id); - QueueTask(task); + QueueTask(false, task); } void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32_t id) { @@ -696,10 +749,6 @@ int32_t InProcessCommandBuffer::CreateImage(ClientBuffer buffer, gfx::GpuMemoryBufferHandle handle = ShareGpuMemoryBufferToGpuThread( gpu_memory_buffer->GetHandle(), &requires_sync_point); - SyncPointManager* sync_manager = service_->sync_point_manager(); - const uint32_t order_num = - sync_point_order_data_->GenerateUnprocessedOrderNumber(sync_manager); - uint64_t fence_sync = 0; if (requires_sync_point) { fence_sync = GenerateFenceSyncRelease(); @@ -708,12 +757,13 @@ int32_t InProcessCommandBuffer::CreateImage(ClientBuffer buffer, DCHECK_EQ(fence_sync - 1, flushed_fence_sync_release_); } - QueueTask(base::Bind( - &InProcessCommandBuffer::CreateImageOnGpuThread, base::Unretained(this), - new_id, handle, gfx::Size(base::checked_cast(width), - base::checked_cast(height)), - gpu_memory_buffer->GetFormat(), - base::checked_cast(internalformat), order_num, fence_sync)); + QueueTask(false, base::Bind(&InProcessCommandBuffer::CreateImageOnGpuThread, + base::Unretained(this), new_id, handle, + gfx::Size(base::checked_cast(width), + base::checked_cast(height)), + gpu_memory_buffer->GetFormat(), + base::checked_cast(internalformat), + fence_sync)); if (fence_sync) { flushed_fence_sync_release_ = fence_sync; @@ -733,10 +783,7 @@ void InProcessCommandBuffer::CreateImageOnGpuThread( const gfx::Size& size, gfx::BufferFormat format, uint32_t internalformat, - uint32_t order_num, uint64_t fence_sync) { - ScopedOrderNumberProcessor scoped_order_num(sync_point_order_data_.get(), - order_num); if (!decoder_) return; @@ -795,8 +842,8 @@ void InProcessCommandBuffer::CreateImageOnGpuThread( void InProcessCommandBuffer::DestroyImage(int32_t id) { CheckSequencedThread(); - QueueTask(base::Bind(&InProcessCommandBuffer::DestroyImageOnGpuThread, - base::Unretained(this), id)); + QueueTask(false, base::Bind(&InProcessCommandBuffer::DestroyImageOnGpuThread, + base::Unretained(this), id)); } void InProcessCommandBuffer::DestroyImageOnGpuThread(int32_t id) { @@ -850,6 +897,7 @@ bool InProcessCommandBuffer::WaitFenceSyncOnGpuThread( gpu::CommandBufferNamespace namespace_id, gpu::CommandBufferId command_buffer_id, uint64_t release) { + DCHECK(!waiting_for_sync_point_); gpu::SyncPointManager* sync_point_manager = service_->sync_point_manager(); DCHECK(sync_point_manager); @@ -860,28 +908,77 @@ bool InProcessCommandBuffer::WaitFenceSyncOnGpuThread( if (!release_state) return true; - if (!release_state->IsFenceSyncReleased(release)) { - // Use waitable event which is signalled when the release fence is released. - sync_point_client_->Wait( - release_state.get(), release, - base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&fence_sync_wait_event_))); - fence_sync_wait_event_.Wait(); + if (service_->BlockThreadOnWaitSyncToken()) { + if (!release_state->IsFenceSyncReleased(release)) { + // Use waitable event which is signalled when the release fence is + // released. + sync_point_client_->Wait( + release_state.get(), release, + base::Bind(&base::WaitableEvent::Signal, + base::Unretained(&fence_sync_wait_event_))); + fence_sync_wait_event_.Wait(); + } + + gles2::MailboxManager* mailbox_manager = + decoder_->GetContextGroup()->mailbox_manager(); + SyncToken sync_token(namespace_id, 0, command_buffer_id, release); + mailbox_manager->PullTextureUpdates(sync_token); + return true; + } + + if (release_state->IsFenceSyncReleased(release)) { + gles2::MailboxManager* mailbox_manager = + decoder_->GetContextGroup()->mailbox_manager(); + SyncToken sync_token(namespace_id, 0, command_buffer_id, release); + mailbox_manager->PullTextureUpdates(sync_token); + return true; } + waiting_for_sync_point_ = true; + sync_point_client_->Wait( + release_state.get(), release, + base::Bind(&InProcessCommandBuffer::OnWaitFenceSyncCompleted, + gpu_thread_weak_ptr_factory_.GetWeakPtr(), namespace_id, + command_buffer_id, release)); + + if (!waiting_for_sync_point_) + return true; + + executor_->SetScheduled(false); + return false; +} + +void InProcessCommandBuffer::OnWaitFenceSyncCompleted( + CommandBufferNamespace namespace_id, + CommandBufferId command_buffer_id, + uint64_t release) { + DCHECK(waiting_for_sync_point_); gles2::MailboxManager* mailbox_manager = decoder_->GetContextGroup()->mailbox_manager(); SyncToken sync_token(namespace_id, 0, command_buffer_id, release); mailbox_manager->PullTextureUpdates(sync_token); - return true; + waiting_for_sync_point_ = false; + executor_->SetScheduled(true); + QueueTask(false, base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, + gpu_thread_weak_ptr_, last_put_offset_)); } void InProcessCommandBuffer::DescheduleUntilFinishedOnGpuThread() { - NOTIMPLEMENTED(); + if (!service_->BlockThreadOnWaitSyncToken()) { + DCHECK(executor_->scheduled()); + DCHECK(executor_->HasPollingWork()); + + executor_->SetScheduled(false); + } } void InProcessCommandBuffer::RescheduleAfterFinishedOnGpuThread() { - NOTIMPLEMENTED(); + if (!service_->BlockThreadOnWaitSyncToken()) { + DCHECK(!executor_->scheduled()); + + executor_->SetScheduled(true); + ProcessTasksOnGpuThread(); + } } void InProcessCommandBuffer::SignalSyncTokenOnGpuThread( @@ -906,9 +1003,9 @@ void InProcessCommandBuffer::SignalSyncTokenOnGpuThread( void InProcessCommandBuffer::SignalQuery(unsigned query_id, const base::Closure& callback) { CheckSequencedThread(); - QueueTask(base::Bind(&InProcessCommandBuffer::SignalQueryOnGpuThread, - base::Unretained(this), query_id, - WrapCallback(callback))); + QueueTask(false, base::Bind(&InProcessCommandBuffer::SignalQueryOnGpuThread, + base::Unretained(this), query_id, + WrapCallback(callback))); } void InProcessCommandBuffer::SignalQueryOnGpuThread( @@ -964,9 +1061,10 @@ bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) { void InProcessCommandBuffer::SignalSyncToken(const SyncToken& sync_token, const base::Closure& callback) { CheckSequencedThread(); - QueueTask(base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, - base::Unretained(this), sync_token, - WrapCallback(callback))); + QueueTask( + true, + base::Bind(&InProcessCommandBuffer::SignalSyncTokenOnGpuThread, + base::Unretained(this), sync_token, WrapCallback(callback))); } bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( @@ -974,6 +1072,69 @@ bool InProcessCommandBuffer::CanWaitUnverifiedSyncToken( return sync_token->namespace_id() == GetNamespaceID(); } +#if defined(OS_WIN) +void InProcessCommandBuffer::DidCreateAcceleratedSurfaceChildWindow( + SurfaceHandle parent_window, + SurfaceHandle child_window) { + // TODO(fsamuel): Implement this. +} +#endif + +void InProcessCommandBuffer::DidSwapBuffersComplete( + SwapBuffersCompleteParams params) { +#if defined(OS_MACOSX) + gpu::GpuProcessHostedCALayerTreeParamsMac params_mac; + params_mac.ca_context_id = params.ca_context_id; + params_mac.fullscreen_low_power_ca_context_valid = + params.fullscreen_low_power_ca_context_valid; + params_mac.fullscreen_low_power_ca_context_id = + params.fullscreen_low_power_ca_context_id; + params_mac.io_surface.reset(IOSurfaceLookupFromMachPort(params.io_surface)); + params_mac.pixel_size = params.pixel_size; + params_mac.scale_factor = params.scale_factor; + params_mac.responses = std::move(params.in_use_responses); + gpu::GpuProcessHostedCALayerTreeParamsMac* mac_frame_ptr = ¶ms_mac; +#else + gpu::GpuProcessHostedCALayerTreeParamsMac* mac_frame_ptr = nullptr; +#endif + if (!swap_buffers_completion_callback_.is_null()) { + if (!ui::LatencyInfo::Verify( + params.latency_info, + "InProcessCommandBuffer::DidSwapBuffersComplete")) { + swap_buffers_completion_callback_.Run(std::vector(), + params.result, mac_frame_ptr); + } else { + swap_buffers_completion_callback_.Run(params.latency_info, params.result, + mac_frame_ptr); + } + } +} + +const gles2::FeatureInfo* InProcessCommandBuffer::GetFeatureInfo() const { + return context_group_->feature_info(); +} + +void InProcessCommandBuffer::SetLatencyInfoCallback( + const LatencyInfoCallback& callback) { + // TODO(fsamuel): Implement this. +} + +void InProcessCommandBuffer::UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) { + if (!update_vsync_parameters_completion_callback_.is_null()) + update_vsync_parameters_completion_callback_.Run(timebase, interval); +} + +void InProcessCommandBuffer::SetSwapBuffersCompletionCallback( + const SwapBuffersCompletionCallback& callback) { + swap_buffers_completion_callback_ = callback; +} + +void InProcessCommandBuffer::SetUpdateVSyncParametersCallback( + const UpdateVSyncParametersCallback& callback) { + update_vsync_parameters_completion_callback_ = callback; +} + gpu::error::Error InProcessCommandBuffer::GetLastError() { CheckSequencedThread(); return last_state_.error; @@ -1015,55 +1176,10 @@ base::Closure InProcessCommandBuffer::WrapCallback( return wrapped_callback; } -GpuInProcessThread::GpuInProcessThread(SyncPointManager* sync_point_manager) - : base::Thread("GpuThread"), sync_point_manager_(sync_point_manager) { - Start(); -} - -GpuInProcessThread::~GpuInProcessThread() { - Stop(); -} - -void GpuInProcessThread::AddRef() const { - base::RefCountedThreadSafe::AddRef(); -} -void GpuInProcessThread::Release() const { - base::RefCountedThreadSafe::Release(); -} - -void GpuInProcessThread::ScheduleTask(const base::Closure& task) { - task_runner()->PostTask(FROM_HERE, task); -} - -void GpuInProcessThread::ScheduleDelayedWork(const base::Closure& callback) { - // Match delay with GpuCommandBufferStub. - task_runner()->PostDelayedTask(FROM_HERE, callback, - base::TimeDelta::FromMilliseconds(2)); -} - -bool GpuInProcessThread::UseVirtualizedGLContexts() { - return false; -} +InProcessCommandBuffer::GpuTask::GpuTask(const base::Closure& callback, + uint32_t order_number) + : callback(callback), order_number(order_number) {} -scoped_refptr -GpuInProcessThread::shader_translator_cache() { - if (!shader_translator_cache_.get()) { - shader_translator_cache_ = - new gpu::gles2::ShaderTranslatorCache(gpu_preferences()); - } - return shader_translator_cache_; -} - -scoped_refptr -GpuInProcessThread::framebuffer_completeness_cache() { - if (!framebuffer_completeness_cache_.get()) - framebuffer_completeness_cache_ = - new gpu::gles2::FramebufferCompletenessCache; - return framebuffer_completeness_cache_; -} - -SyncPointManager* GpuInProcessThread::sync_point_manager() { - return sync_point_manager_; -} +InProcessCommandBuffer::GpuTask::~GpuTask() {} } // namespace gpu diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index ac4ef0238789e6..432c68bb72f4fa 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h @@ -25,9 +25,12 @@ #include "base/threading/thread.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/service/command_executor.h" +#include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/gpu_export.h" +#include "gpu/ipc/service/image_transport_surface_delegate.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/native_widget_types.h" #include "ui/gl/gl_surface.h" @@ -48,9 +51,11 @@ class Size; } namespace gpu { + class SyncPointClient; class SyncPointOrderData; class SyncPointManager; +struct GpuProcessHostedCALayerTreeParamsMac; namespace gles2 { struct ContextCreationAttribHelper; @@ -72,7 +77,8 @@ class TransferBufferManagerInterface; // However, the behavior for accessing one context (i.e. one instance of this // class) from different client threads is undefined. class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, - public GpuControl { + public GpuControl, + public ImageTransportSurfaceDelegate { public: class Service; explicit InProcessCommandBuffer(const scoped_refptr& service); @@ -83,7 +89,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // a new GLSurface. bool Initialize(scoped_refptr surface, bool is_offscreen, - gfx::AcceleratedWidget window, + SurfaceHandle window, const gles2::ContextCreationAttribHelper& attribs, InProcessCommandBuffer* share_group, GpuMemoryBufferManager* gpu_memory_buffer_manager, @@ -130,11 +136,38 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, const base::Closure& callback) override; bool CanWaitUnverifiedSyncToken(const SyncToken* sync_token) override; +// ImageTransportSurfaceDelegate implementation: +#if defined(OS_WIN) + void DidCreateAcceleratedSurfaceChildWindow( + SurfaceHandle parent_window, + SurfaceHandle child_window) override; +#endif + void DidSwapBuffersComplete(SwapBuffersCompleteParams params) override; + const gles2::FeatureInfo* GetFeatureInfo() const override; + void SetLatencyInfoCallback(const LatencyInfoCallback& callback) override; + void UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) override; + + using SwapBuffersCompletionCallback = base::Callback& latency_info, + gfx::SwapResult result, + const gpu::GpuProcessHostedCALayerTreeParamsMac* params_mac)>; + void SetSwapBuffersCompletionCallback( + const SwapBuffersCompletionCallback& callback); + + using UpdateVSyncParametersCallback = + base::Callback; + void SetUpdateVSyncParametersCallback( + const UpdateVSyncParametersCallback& callback); + // The serializer interface to the GPU service (i.e. thread). class Service { public: Service(); Service(const gpu::GpuPreferences& gpu_preferences); + Service(gpu::gles2::MailboxManager* mailbox_manager, + scoped_refptr share_group); + virtual ~Service(); virtual void AddRef() const = 0; @@ -158,19 +191,20 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, scoped_refptr share_group(); scoped_refptr mailbox_manager(); gpu::gles2::ProgramCache* program_cache(); + virtual bool BlockThreadOnWaitSyncToken() const = 0; - private: + protected: const GpuPreferences gpu_preferences_; const GpuDriverBugWorkarounds gpu_driver_bug_workarounds_; - scoped_refptr share_group_; scoped_refptr mailbox_manager_; + scoped_refptr share_group_; std::unique_ptr program_cache_; }; private: struct InitializeOnGpuThreadParams { bool is_offscreen; - gfx::AcceleratedWidget window; + SurfaceHandle window; const gles2::ContextCreationAttribHelper& attribs; gpu::Capabilities* capabilities; // Ouptut. InProcessCommandBuffer* context_group; @@ -178,7 +212,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, InitializeOnGpuThreadParams( bool is_offscreen, - gfx::AcceleratedWidget window, + SurfaceHandle window, const gles2::ContextCreationAttribHelper& attribs, gpu::Capabilities* capabilities, InProcessCommandBuffer* share_group, @@ -194,17 +228,21 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, bool InitializeOnGpuThread(const InitializeOnGpuThreadParams& params); void Destroy(); bool DestroyOnGpuThread(); - void FlushOnGpuThread(int32_t put_offset, uint32_t order_num); + void FlushOnGpuThread(int32_t put_offset); void ScheduleDelayedWorkOnGpuThread(); bool MakeCurrent(); base::Closure WrapCallback(const base::Closure& callback); State GetStateFast(); - void QueueTask(const base::Closure& task) { service_->ScheduleTask(task); } + void QueueTask(bool out_of_order, const base::Closure& task); + void ProcessTasksOnGpuThread(); void CheckSequencedThread(); void FenceSyncReleaseOnGpuThread(uint64_t release); bool WaitFenceSyncOnGpuThread(gpu::CommandBufferNamespace namespace_id, gpu::CommandBufferId command_buffer_id, uint64_t release); + void OnWaitFenceSyncCompleted(CommandBufferNamespace namespace_id, + CommandBufferId command_buffer_id, + uint64_t release); void DescheduleUntilFinishedOnGpuThread(); void RescheduleAfterFinishedOnGpuThread(); void SignalSyncTokenOnGpuThread(const SyncToken& sync_token, @@ -216,7 +254,7 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, const gfx::Size& size, gfx::BufferFormat format, uint32_t internalformat, - uint32_t order_num, + // uint32_t order_num, uint64_t fence_sync); void DestroyImageOnGpuThread(int32_t id); void SetGetBufferOnGpuThread(int32_t shm_id, base::WaitableEvent* completion); @@ -232,6 +270,8 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // Members accessed on the gpu thread (possibly with the exception of // creation): + bool waiting_for_sync_point_ = false; + scoped_refptr origin_task_runner_; scoped_refptr transfer_buffer_manager_; std::unique_ptr executor_; @@ -265,6 +305,10 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, scoped_refptr service_; State state_after_last_flush_; base::Lock state_after_last_flush_lock_; + + // The group of contexts that share namespaces with this context. + scoped_refptr context_group_; + scoped_refptr gl_share_group_; base::WaitableEvent fence_sync_wait_event_; @@ -272,6 +316,18 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, // the client thread. std::unique_ptr sequence_checker_; + base::Lock task_queue_lock_; + struct GpuTask { + GpuTask(const base::Closure& callback, uint32_t order_number); + ~GpuTask(); + base::Closure callback; + uint32_t order_number; + }; + std::queue> task_queue_; + + SwapBuffersCompletionCallback swap_buffers_completion_callback_; + UpdateVSyncParametersCallback update_vsync_parameters_completion_callback_; + base::WeakPtr client_thread_weak_ptr_; base::WeakPtr gpu_thread_weak_ptr_; base::WeakPtrFactory client_thread_weak_ptr_factory_; @@ -280,36 +336,6 @@ class GPU_EXPORT InProcessCommandBuffer : public CommandBuffer, DISALLOW_COPY_AND_ASSIGN(InProcessCommandBuffer); }; -// Default Service class when a null service is used. -class GPU_EXPORT GpuInProcessThread - : public base::Thread, - public NON_EXPORTED_BASE(InProcessCommandBuffer::Service), - public base::RefCountedThreadSafe { - public: - explicit GpuInProcessThread(SyncPointManager* sync_point_manager); - - void AddRef() const override; - void Release() const override; - void ScheduleTask(const base::Closure& task) override; - void ScheduleDelayedWork(const base::Closure& callback) override; - bool UseVirtualizedGLContexts() override; - scoped_refptr shader_translator_cache() - override; - scoped_refptr - framebuffer_completeness_cache() override; - SyncPointManager* sync_point_manager() override; - - private: - ~GpuInProcessThread() override; - friend class base::RefCountedThreadSafe; - - SyncPointManager* sync_point_manager_; // Non-owning. - scoped_refptr shader_translator_cache_; - scoped_refptr - framebuffer_completeness_cache_; - DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread); -}; - } // namespace gpu #endif // GPU_IPC_IN_PROCESS_COMMAND_BUFFER_H_ diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h index a71ca9b41a55de..797dad1039489e 100644 --- a/gpu/ipc/service/gpu_channel_manager.h +++ b/gpu/ipc/service/gpu_channel_manager.h @@ -133,6 +133,12 @@ class GPU_EXPORT GpuChannelManager { return exiting_for_lost_context_; } + gles2::MailboxManager* mailbox_manager() const { + return mailbox_manager_.get(); + } + + gl::GLShareGroup* share_group() const { return share_group_.get(); } + protected: virtual std::unique_ptr CreateGpuChannel( int client_id, @@ -145,13 +151,7 @@ class GPU_EXPORT GpuChannelManager { return sync_point_manager_; } - gl::GLShareGroup* share_group() const { return share_group_.get(); } - gles2::MailboxManager* mailbox_manager() const { - return mailbox_manager_.get(); - } - PreemptionFlag* preemption_flag() const { - return preemption_flag_.get(); - } + PreemptionFlag* preemption_flag() const { return preemption_flag_.get(); } scoped_refptr task_runner_; scoped_refptr io_task_runner_; diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 42dd8b51c350b8..a6a88a24109429 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc @@ -32,6 +32,10 @@ #include "ui/gl/gl_implementation.h" #include "ui/gl/test/gl_surface_test_support.h" +#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) +#include "gpu/ipc/common/gpu_surface_tracker.h" +#endif + namespace ui { namespace { @@ -113,6 +117,11 @@ class DirectOutputSurface : public cc::OutputSurface { } // namespace +struct InProcessContextFactory::PerCompositorData { + gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; + std::unique_ptr display; +}; + InProcessContextFactory::InProcessContextFactory( bool context_factory_for_test, cc::SurfaceManager* surface_manager) @@ -166,10 +175,14 @@ void InProcessContextFactory::CreateCompositorFrameSink( attribs.sample_buffers = 0; attribs.fail_if_major_perf_caveat = false; attribs.bind_generates_resource = false; + PerCompositorData* data = per_compositor_data_[compositor.get()].get(); + if (!data) + data = CreatePerCompositorData(compositor.get()); + scoped_refptr context_provider = InProcessContextProvider::Create( attribs, shared_worker_context_provider_.get(), - &gpu_memory_buffer_manager_, &image_factory_, compositor->widget(), + &gpu_memory_buffer_manager_, &image_factory_, data->surface_handle, "UICompositor"); std::unique_ptr display_output_surface; @@ -189,14 +202,15 @@ void InProcessContextFactory::CreateCompositorFrameSink( std::unique_ptr scheduler(new cc::DisplayScheduler( begin_frame_source.get(), compositor->task_runner().get(), display_output_surface->capabilities().max_frames_pending)); - per_compositor_data_[compositor.get()] = base::MakeUnique( + + data->display = base::MakeUnique( &shared_bitmap_manager_, &gpu_memory_buffer_manager_, compositor->GetRendererSettings(), compositor->frame_sink_id(), std::move(begin_frame_source), std::move(display_output_surface), std::move(scheduler), base::MakeUnique( compositor->task_runner().get())); - auto* display = per_compositor_data_[compositor.get()].get(); + auto* display = per_compositor_data_[compositor.get()]->display.get(); auto compositor_frame_sink = base::MakeUnique( compositor->frame_sink_id(), surface_manager_, display, context_provider, shared_worker_context_provider_, &gpu_memory_buffer_manager_, @@ -230,9 +244,16 @@ InProcessContextFactory::SharedMainThreadContextProvider() { } void InProcessContextFactory::RemoveCompositor(Compositor* compositor) { - if (!per_compositor_data_.count(compositor)) + PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor); + if (it == per_compositor_data_.end()) return; - per_compositor_data_.erase(compositor); + PerCompositorData* data = it->second.get(); + DCHECK(data); +#if !defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) + if (data->surface_handle) + gpu::GpuSurfaceTracker::Get()->RemoveSurface(data->surface_handle); +#endif + per_compositor_data_.erase(it); } bool InProcessContextFactory::DoesCreateTestContexts() { @@ -266,14 +287,14 @@ void InProcessContextFactory::SetDisplayVisible(ui::Compositor* compositor, bool visible) { if (!per_compositor_data_.count(compositor)) return; - per_compositor_data_[compositor]->SetVisible(visible); + per_compositor_data_[compositor]->display->SetVisible(visible); } void InProcessContextFactory::ResizeDisplay(ui::Compositor* compositor, const gfx::Size& size) { if (!per_compositor_data_.count(compositor)) return; - per_compositor_data_[compositor]->Resize(size); + per_compositor_data_[compositor]->display->Resize(size); } void InProcessContextFactory::AddObserver(ContextFactoryObserver* observer) { @@ -284,4 +305,27 @@ void InProcessContextFactory::RemoveObserver(ContextFactoryObserver* observer) { observer_list_.RemoveObserver(observer); } +InProcessContextFactory::PerCompositorData* +InProcessContextFactory::CreatePerCompositorData(ui::Compositor* compositor) { + DCHECK(!per_compositor_data_[compositor]); + + gfx::AcceleratedWidget widget = compositor->widget(); + + auto data = base::MakeUnique(); + if (widget == gfx::kNullAcceleratedWidget) { + data->surface_handle = gpu::kNullSurfaceHandle; + } else { +#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW) + data->surface_handle = widget; +#else + gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get(); + data->surface_handle = tracker->AddSurfaceForNativeWidget(widget); +#endif + } + + PerCompositorData* return_ptr = data.get(); + per_compositor_data_[compositor] = std::move(data); + return return_ptr; +} + } // namespace ui diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 54266ba4e226ec..68914332747fe2 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h @@ -14,6 +14,7 @@ #include "cc/test/test_image_factory.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_task_graph_runner.h" +#include "gpu/ipc/common/surface_handle.h" #include "ui/compositor/compositor.h" namespace cc { @@ -72,6 +73,10 @@ class InProcessContextFactory : public ContextFactory { void RemoveObserver(ContextFactoryObserver* observer) override; private: + struct PerCompositorData; + + PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor); + scoped_refptr shared_main_thread_contexts_; scoped_refptr shared_worker_context_provider_; cc::TestSharedBitmapManager shared_bitmap_manager_; @@ -84,8 +89,9 @@ class InProcessContextFactory : public ContextFactory { cc::SurfaceManager* surface_manager_; base::ObserverList observer_list_; - base::hash_map> - per_compositor_data_; + using PerCompositorDataMap = + base::hash_map>; + PerCompositorDataMap per_compositor_data_; DISALLOW_COPY_AND_ASSIGN(InProcessContextFactory); }; diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc index 3483d3139cae49..c442ce06882efd 100644 --- a/ui/compositor/test/in_process_context_provider.cc +++ b/ui/compositor/test/in_process_context_provider.cc @@ -29,7 +29,7 @@ scoped_refptr InProcessContextProvider::Create( InProcessContextProvider* shared_context, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, - gfx::AcceleratedWidget window, + gpu::SurfaceHandle window, const std::string& debug_name) { return new InProcessContextProvider(attribs, shared_context, gpu_memory_buffer_manager, image_factory, @@ -55,7 +55,7 @@ InProcessContextProvider::CreateOffscreen( attribs.bind_generates_resource = false; return new InProcessContextProvider(attribs, shared_context, gpu_memory_buffer_manager, image_factory, - gfx::kNullAcceleratedWidget, "Offscreen"); + gpu::kNullSurfaceHandle, "Offscreen"); } InProcessContextProvider::InProcessContextProvider( @@ -63,7 +63,7 @@ InProcessContextProvider::InProcessContextProvider( InProcessContextProvider* shared_context, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, - gfx::AcceleratedWidget window, + gpu::SurfaceHandle window, const std::string& debug_name) : attribs_(attribs), shared_context_(shared_context), diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h index d61a77db0ccb8d..2d2501f46fbfb6 100644 --- a/ui/compositor/test/in_process_context_provider.h +++ b/ui/compositor/test/in_process_context_provider.h @@ -15,6 +15,7 @@ #include "base/threading/thread_checker.h" #include "cc/output/context_provider.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/ipc/common/surface_handle.h" #include "ui/gfx/native_widget_types.h" namespace gpu { @@ -36,7 +37,7 @@ class InProcessContextProvider : public cc::ContextProvider { InProcessContextProvider* shared_context, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, - gfx::AcceleratedWidget window, + gpu::SurfaceHandle window, const std::string& debug_name); // Uses default attributes for creating an offscreen context. @@ -68,7 +69,7 @@ class InProcessContextProvider : public cc::ContextProvider { InProcessContextProvider* shared_context, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, gpu::ImageFactory* image_factory, - gfx::AcceleratedWidget window, + gpu::SurfaceHandle window, const std::string& debug_name); ~InProcessContextProvider() override; @@ -83,7 +84,7 @@ class InProcessContextProvider : public cc::ContextProvider { InProcessContextProvider* shared_context_; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; gpu::ImageFactory* image_factory_; - gfx::AcceleratedWidget window_; + gpu::SurfaceHandle window_; std::string debug_name_; base::Lock context_lock_; diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index ca4e7a193509dc..a8bfb194c8c787 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn @@ -718,6 +718,7 @@ static_library("test_support_internal") { deps = [ "//base", "//base/test:test_support", + "//gpu/ipc/service", "//ipc:test_support", "//skia", "//testing/gtest", diff --git a/ui/views/DEPS b/ui/views/DEPS index d5541eea7396eb..a2f14198c2f108 100644 --- a/ui/views/DEPS +++ b/ui/views/DEPS @@ -28,4 +28,7 @@ specific_include_rules = { "view_unittest\.cc": [ "+cc/playback" ], + "views_test_suite\.cc": [ + "+gpu/ipc/service", + ] } diff --git a/ui/views/views_test_suite.cc b/ui/views/views_test_suite.cc index e837e5ffdcb4df..bd08ea3a791057 100644 --- a/ui/views/views_test_suite.cc +++ b/ui/views/views_test_suite.cc @@ -10,6 +10,7 @@ #include "base/path_service.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "gpu/ipc/service/image_transport_surface.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" @@ -41,6 +42,11 @@ int ViewsTestSuite::RunTestsSerially() { void ViewsTestSuite::Initialize() { base::TestSuite::Initialize(); gl::GLSurfaceTestSupport::InitializeOneOff(); + +#if defined(OS_MACOSX) + gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true); +#endif + ui::RegisterPathProvider(); base::FilePath ui_test_pak_path;