Which compositor exists?
Aura makes browser process also use compositor. Let's classify which class is used in which case.
In renderer process
- RenderWidget owns RenderWidgetCompositor that is created by initializeLayerTreeView()
- RenderWidgetCompositor owns cc::LayerTreeHost
In browser process when Aura is turned on
- [Desktop]RootWindowHost owns aura::RootWindow
- aura::RootWindow owns ui::Compositor
- ui::Compositor owns cc::LayerTreeHost
Overview
- render process: RenderWidget -> RenderWidgetCompositor : LayerTreeHostClient -> LayerTreeHost
- browser process: RootWindow -> Compositor : LayerTreeHostClient -> LayerTreeHost
- important relationship
- LayerTreeHost -> ThreadProxy : LayerTreeHostImplClient -> LayerTreeHostImpl
- LayerTreeHost -> ThreadProxy : SchedulerClient -> Scheduler
OutputSurface lifecycle
Make accelerated surface or disable accelerated compositing
- WebViewImpl try to create compositor or disable accelerated compositing
void WebViewImpl::setIsAcceleratedCompositingActive(bool active) { ... m_client->initializeLayerTreeView(); m_layerTreeView = m_client->layerTreeView(); if (m_layerTreeView) { m_layerTreeView->setRootLayer(*m_rootLayer); ... } else { m_isAcceleratedCompositingActive = false; m_client->didDeactivateCompositor(); m_compositorCreationFailed = true; } ... }
- RenderWidget::initializeLayerTreeView() fails if creating OutputSurface fails.
void RenderWidget::initializeLayerTreeView() { compositor_ = RenderWidgetCompositor::Create( this, is_threaded_compositing_enabled_); if (!compositor_) return; compositor_->setViewportSize(size_, physical_backing_size_); if (init_complete_) compositor_->setSurfaceReady(); } scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( RenderWidget* widget, bool threaded) { scoped_ptr<RenderWidgetCompositor> compositor( new RenderWidgetCompositor(widget, threaded)); CommandLine* cmd = CommandLine::ForCurrentProcess(); cc::LayerTreeSettings settings; settings.throttle_frame_production = !cmd->HasSwitch(switches::kDisableGpuVsync); // settings... if (!compositor->initialize(settings)) return scoped_ptr<RenderWidgetCompositor>(); return compositor.Pass(); } bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) { scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy = RenderThreadImpl::current()->compositor_message_loop_proxy(); layer_tree_host_ = cc::LayerTreeHost::Create( this, NULL, settings, compositor_message_loop_proxy); return layer_tree_host_; } bool LayerTreeHost::Initialize( scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { if (impl_task_runner.get()) return InitializeProxy(ThreadProxy::Create(this, impl_task_runner)); else return InitializeProxy(SingleThreadProxy::Create(this)); } bool LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) { TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal"); scoped_ptr<OutputSurface> output_surface(CreateOutputSurface()); if (!output_surface) return false; // HERE!!! CAN FAIL!!!! proxy_ = proxy.Pass(); proxy_->Start(output_surface.Pass()); return true; } void ThreadProxy::Start(scoped_ptr<OutputSurface> first_output_surface) { DCHECK(IsMainThread()); DCHECK(Proxy::HasImplThread()); DCHECK(first_output_surface); // Create LayerTreeHostImpl. DebugScopedSetMainThreadBlocked main_thread_blocked(this); CompletionEvent completion; Proxy::ImplThreadTaskRunner()->PostTask( FROM_HERE, base::Bind(&ThreadProxy::InitializeImplOnImplThread, base::Unretained(this), &completion)); completion.Wait(); main_thread_weak_ptr_ = weak_factory_.GetWeakPtr(); first_output_surface_ = first_output_surface.Pass(); started_ = true; } void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread"); DCHECK(IsImplThread()); layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); const LayerTreeSettings& settings = layer_tree_host_->settings(); SchedulerSettings scheduler_settings; scheduler_settings.deadline_scheduling_enabled = settings.deadline_scheduling_enabled; scheduler_settings.impl_side_painting = settings.impl_side_painting; scheduler_settings.timeout_and_draw_when_animation_checkerboards = settings.timeout_and_draw_when_animation_checkerboards; scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = settings.maximum_number_of_failed_draws_before_draw_is_forced_; scheduler_settings.using_synchronous_renderer_compositor = settings.using_synchronous_renderer_compositor; scheduler_settings.throttle_frame_production = settings.throttle_frame_production; scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings); scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr(); completion->Signal(); }
What's happen when creating OutputSurface
what is OutputSurface
- It is something like GraphicsContext3D for LayerTreeHost
- OutputSurface own ContextProvider that owns WebGraphicsContext3D
in render process
- LayerTreeHost::CreateOutputSurface() -> RenderWidgetCompositor::CreateOutputSurface() -> RenderWidget::CreateOutputSurface()
scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { ... // 1. Create ContextProvider scoped_refptr<ContextProviderCommandBuffer> context_provider; context_provider = ContextProviderCommandBuffer::Create( CreateGraphicsContext3D(attributes), "RenderCompositor"); uint32 output_surface_id = next_output_surface_id_++; if (!context_provider.get()) { /// CAN FAIL!!!! ONLY Renderer can fail. if (!command_line.HasSwitch(switches::kEnableSoftwareCompositing)) return scoped_ptr<cc::OutputSurface>(); // 2. Software fallback return scoped_ptr<cc::OutputSurface>(new CompositorOutputSurface(... } // 3. Create OutputSurface if (command_line.HasSwitch(switches::kEnableDelegatedRenderer) && !command_line.HasSwitch(switches::kDisableDelegatedRenderer)) { DCHECK(is_threaded_compositing_enabled_); return scoped_ptr<cc::OutputSurface>( new DelegatedCompositorOutputSurface( routing_id(), output_surface_id, context_provider, scoped_ptr<cc::SoftwareOutputDevice>())); } if (command_line.HasSwitch(cc::switches::kCompositeToMailbox)) { return scoped_ptr<cc::OutputSurface>( new MailboxOutputSurface( routing_id(), output_surface_id, context_provider, scoped_ptr<cc::SoftwareOutputDevice>(), format)); } bool use_swap_compositor_frame_message = false; return scoped_ptr<cc::OutputSurface>( new CompositorOutputSurface( routing_id(), output_surface_id, context_provider, scoped_ptr<cc::SoftwareOutputDevice>(), use_swap_compositor_frame_message)); }
In browser process
- LayerTreeHost::CreateOutputSurface() -> Compositor::CreateOutputSurface() -> GpuProcessTransportFactory::CreateOutputSurface()
scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface( ui::Compositor* compositor) { ... scoped_refptr<ContextProviderCommandBuffer> context_provider; ... CommandLine* command_line = CommandLine::ForCurrentProcess(); if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) { context_provider = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateContextCommon( swap_client_weak_ptr, data->surface_id), "Compositor"); } // Software surface if (!context_provider.get()) { scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface = SoftwareBrowserCompositorOutputSurface::Create( CreateSoftwareOutputDevice(compositor)); return surface.PassAs<cc::OutputSurface>(); } ... scoped_ptr<BrowserCompositorOutputSurface> surface( new BrowserCompositorOutputSurface( context_provider, per_compositor_data_[compositor]->surface_id, &output_surface_map_, base::MessageLoopProxy::current().get(), compositor->AsWeakPtr())); ... return surface.PassAs<cc::OutputSurface>(); }
NOTE: Failure of OutputSurface creation.
- If Browser process fails, it creates SoftwareBrowserCompositorOutputSurface.
- If Render process fails and !kEnableSoftwareCompositing, it does not create OutputSurface.
- and Render process does not do accelerated compositing.
What's happen when creating ContextProviderCommandBuffer
- OutputSurface -> ContextProviderCommandBuffer -> WebGraphicsContext3DCommandBufferImpl -> GLES2Implementation
- Under WebGraphicsContext3D, refer to How GPU Process work in multi process
scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
...
scoped_refptr<ContextProviderCommandBuffer> context_provider;
if (!fallback) {
context_provider = ContextProviderCommandBuffer::Create(
CreateGraphicsContext3D(attributes),
"RenderCompositor");
}
...
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
RenderWidget::CreateGraphicsContext3D(
const WebKit::WebGraphicsContext3D::Attributes& attributes) {
...
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
new WebGraphicsContext3DCommandBufferImpl(
surface_id(),
GetURLForGraphicsContext3D(),
gpu_channel_host.get(),
swap_client,
attributes,
false /* bind generates resources */,
limits));
return context.Pass();
}
How impl thread get ownership of gl context.
// in impl thread
void Scheduler::ProcessScheduledActions() {
...
action = state_machine_.NextAction();
...
switch (action) {
...
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
client_->ScheduledActionBeginOutputSurfaceCreation();
break;
...
}
void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
...
Proxy::MainThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
main_thread_weak_ptr_));
}
in main thread
void ThreadProxy::CreateAndInitializeOutputSurface() {
...
layer_tree_host_->DidLoseOutputSurface();
output_surface_creation_callback_.Reset(base::Bind(
&ThreadProxy::DoCreateAndInitializeOutputSurface,
base::Unretained(this)));
output_surface_creation_callback_.callback().Run();
}
void ThreadProxy::DoCreateAndInitializeOutputSurface() {
...
scoped_ptr<OutputSurface> output_surface = first_output_surface_.Pass();
if (!output_surface)
// when reusing compositor
output_surface = layer_tree_host_->CreateOutputSurface();
RendererCapabilities capabilities;
bool success = !!output_surface;
if (!success) {
OnOutputSurfaceInitializeAttempted(false, capabilities);
return;
}
scoped_refptr<ContextProvider> offscreen_context_provider;
// if filter exists,
if (created_offscreen_context_provider_) {
offscreen_context_provider =
layer_tree_host_->client()->OffscreenContextProvider();
success = !!offscreen_context_provider.get();
if (!success) {
OnOutputSurfaceInitializeAttempted(false, capabilities);
return;
}
}
success = false;
{
// Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
// of that call are pushed into the success and capabilities local
// variables.
CompletionEvent completion;
DebugScopedSetMainThreadBlocked main_thread_blocked(this);
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
impl_thread_weak_ptr_,
&completion,
base::Passed(&output_surface),
offscreen_context_provider,
&success,
&capabilities));
// Main thread waits for impl thread done.
completion.Wait();
}
OnOutputSurfaceInitializeAttempted(success, capabilities);
}
in impl thread
void ThreadProxy::InitializeOutputSurfaceOnImplThread(
CompletionEvent* completion,
scoped_ptr<OutputSurface> output_surface,
scoped_refptr<ContextProvider> offscreen_context_provider,
bool* success,
RendererCapabilities* capabilities) {
...
*success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
...
}
bool LayerTreeHostImpl::InitializeRenderer(
scoped_ptr<OutputSurface> output_surface) {
...
// Note: order is important here.
renderer_.reset();
tile_manager_.reset();
resource_provider_.reset();
output_surface_.reset();
// Create or Own above important instances in reverse order
if (!output_surface->BindToClient(this))
return false;
scoped_ptr<ResourceProvider> resource_provider =
ResourceProvider::Create(output_surface.get(),
shared_bitmap_manager_,
settings_.highp_threshold_min,
settings_.use_rgba_4444_textures,
settings_.texture_id_allocation_chunk_size);
if (!resource_provider)
return false;
if (output_surface->capabilities().deferred_gl_initialization)
EnforceZeroBudget(true);
bool skip_gl_renderer = false;
CreateAndSetRenderer(
output_surface.get(), resource_provider.get(), skip_gl_renderer);
if (!renderer_)
return false;
if (settings_.impl_side_painting) {
CreateAndSetTileManager(resource_provider.get(),
output_surface->context_provider().get(),
GetRendererCapabilities().using_map_image);
}
// Setup BeginImplFrameEmulation if it's not supported natively
if (!settings_.begin_impl_frame_scheduling_enabled) {
const base::TimeDelta display_refresh_interval =
base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond /
settings_.refresh_rate);
output_surface->InitializeBeginImplFrameEmulation(
proxy_->ImplThreadTaskRunner(),
settings_.throttle_frame_production,
display_refresh_interval);
}
int max_frames_pending =
output_surface->capabilities().max_frames_pending;
if (max_frames_pending <= 0)
max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING;
output_surface->SetMaxFramesPending(max_frames_pending);
resource_provider_ = resource_provider.Pass();
output_surface_ = output_surface.Pass();
client_->OnCanDrawStateChanged(CanDraw());
return true;
}
- Q: Why this complex ownership transfer of OutputSurface is needed?
- A: unfortunately, connecting GPU Process IPC is possible in only main thread.
- Note
- TileManager in LayerTreeHostImpl is created if impl-side painting.
- LayerTreeHost owns PrioritizedResourceManager if not impl-side painting.
- ResourceProvider in LayerTreeHostImpl is null if software rendering mode.
- Renderer consists of GLRenderer, SoftwareRenderer and DelegatingRenderer
- Important relationship
- LayerTreeHostImpl : RendererClient -> Renderer
- LayerTreeHostImpl : TileManagerClient -> TileManager
- LayerTreeHostImpl : OutputSurfaceClient -> OutputSurface
Complexity originated by Android SynchronousCompositor
LayerTreeHostImpl, OutputSurface and etc.. has special methods only for Android. Ignore it when reading code.
- How to go through this fxxx code. When SynchronousCompositorFactory::GetInstance() exists,
- AwContents -> InProcessViewRenderer -...-> SynchronousCompositor -> SynchronousCompositorOutputSurface
scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
SynchronousCompositorFactory::GetInstance()) {
return factory->CreateOutputSurface(routing_id());
}
#endif
...
}
scoped_refptr<cc::ContextProvider>
RenderThreadImpl::SharedMainThreadContextProvider() {
DCHECK(IsMainThread());
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
SynchronousCompositorFactory::GetInstance())
return factory->GetOffscreenContextProviderForMainThread();
#endif
...
}
- What kind of methods exists
// Use ContextProviderInProcess instead of ContextProviderCommandBuffer
// Call OutputSurface::InitializeAndSetContext3d()
bool SynchronousCompositorOutputSurface::InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface,
scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
DCHECK(!context_provider_);
DCHECK(surface);
scoped_refptr<cc::ContextProvider> onscreen_context_provider =
webkit::gpu::ContextProviderInProcess::Create(
CreateWebGraphicsContext3D(surface), "SynchronousCompositor");
return InitializeAndSetContext3d(onscreen_context_provider,
offscreen_context_provider);
}
// Only here use LayerTreeHostImpl::DeferredInitialize(). Time to blame.
bool OutputSurface::InitializeAndSetContext3d(
..
if (client_->DeferredInitialize(offscreen_context_provider))
..
}
// Only here use LayerTreeHostImpl::ReleaseGL(). Time to blame.
void SynchronousCompositorOutputSurface::ReleaseHwDraw() {
cc::OutputSurface::ReleaseGL();
}
TINN GOLD LLC - ITALIAN Art | TINN GOLD LLC
ReplyDeleteTINN ford edge titanium GOLD LLC. $2.00 CAD (tax) ion titanium hair color / 0.10%. FREE titanium curling iron shipping babyliss nano titanium at TINN GOLD LLC. TINN GOLD LLC. titanium block