// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/compositor/test/in_process_context_factory.h" #include "base/bind.h" #include "base/command_line.h" #include "base/threading/thread.h" #include "cc/output/compositor_frame.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface_client.h" #include "cc/surfaces/onscreen_display_client.h" #include "cc/surfaces/surface_display_output_surface.h" #include "cc/surfaces/surface_id_allocator.h" #include "cc/test/pixel_test_output_surface.h" #include "cc/test/test_shared_bitmap_manager.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "ui/compositor/compositor_switches.h" #include "ui/compositor/reflector.h" #include "ui/compositor/test/in_process_context_provider.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" namespace ui { namespace { class FakeReflector : public Reflector { public: FakeReflector() {} ~FakeReflector() override {} void OnMirroringCompositorResized() override {} }; // An OutputSurface implementation that directly draws and swaps to an actual // GL surface. class DirectOutputSurface : public cc::OutputSurface { public: explicit DirectOutputSurface( const scoped_refptr& context_provider) : cc::OutputSurface(context_provider), weak_ptr_factory_(this) {} ~DirectOutputSurface() override {} // cc::OutputSurface implementation void SwapBuffers(cc::CompositorFrame* frame) override { DCHECK(context_provider_.get()); DCHECK(frame->gl_frame_data); if (frame->gl_frame_data->sub_buffer_rect == gfx::Rect(frame->gl_frame_data->size)) { context_provider_->ContextSupport()->Swap(); } else { context_provider_->ContextSupport()->PartialSwapBuffers( frame->gl_frame_data->sub_buffer_rect); } uint32_t sync_point = context_provider_->ContextGL()->InsertSyncPointCHROMIUM(); context_provider_->ContextSupport()->SignalSyncPoint( sync_point, base::Bind(&OutputSurface::OnSwapBuffersComplete, weak_ptr_factory_.GetWeakPtr())); client_->DidSwapBuffers(); } private: base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DirectOutputSurface); }; } // namespace InProcessContextFactory::InProcessContextFactory( bool context_factory_for_test, cc::SurfaceManager* surface_manager) : next_surface_id_namespace_(1u), use_test_surface_(true), context_factory_for_test_(context_factory_for_test), surface_manager_(surface_manager) { DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone) << "If running tests, ensure that main() is calling " << "gfx::GLSurface::InitializeOneOffForTests()"; } InProcessContextFactory::~InProcessContextFactory() { DCHECK(per_compositor_data_.empty()); } void InProcessContextFactory::CreateOutputSurface( base::WeakPtr compositor) { gpu::gles2::ContextCreationAttribHelper attribs; attribs.alpha_size = 8; attribs.blue_size = 8; attribs.green_size = 8; attribs.red_size = 8; attribs.depth_size = 0; attribs.stencil_size = 0; attribs.samples = 0; attribs.sample_buffers = 0; attribs.fail_if_major_perf_caveat = false; attribs.bind_generates_resource = false; bool lose_context_when_out_of_memory = true; scoped_refptr context_provider = InProcessContextProvider::Create(attribs, lose_context_when_out_of_memory, compositor->widget(), "UICompositor"); scoped_ptr real_output_surface; if (use_test_surface_) { bool flipped_output_surface = false; real_output_surface = make_scoped_ptr(new cc::PixelTestOutputSurface( context_provider, flipped_output_surface)); } else { real_output_surface = make_scoped_ptr(new DirectOutputSurface(context_provider)); } if (surface_manager_) { scoped_ptr display_client( new cc::OnscreenDisplayClient( real_output_surface.Pass(), surface_manager_, GetSharedBitmapManager(), GetGpuMemoryBufferManager(), compositor->GetRendererSettings(), compositor->task_runner())); scoped_ptr surface_output_surface( new cc::SurfaceDisplayOutputSurface(surface_manager_, compositor->surface_id_allocator(), context_provider)); display_client->set_surface_output_surface(surface_output_surface.get()); surface_output_surface->set_display_client(display_client.get()); compositor->SetOutputSurface(surface_output_surface.Pass()); delete per_compositor_data_[compositor.get()]; per_compositor_data_[compositor.get()] = display_client.release(); } else { compositor->SetOutputSurface(real_output_surface.Pass()); } } scoped_ptr InProcessContextFactory::CreateReflector( Compositor* mirrored_compositor, Layer* mirroring_layer) { return make_scoped_ptr(new FakeReflector); } void InProcessContextFactory::RemoveReflector(Reflector* reflector) { } scoped_refptr InProcessContextFactory::SharedMainThreadContextProvider() { if (shared_main_thread_contexts_.get() && !shared_main_thread_contexts_->DestroyedOnMainThread()) return shared_main_thread_contexts_; bool lose_context_when_out_of_memory = false; shared_main_thread_contexts_ = InProcessContextProvider::CreateOffscreen( lose_context_when_out_of_memory); if (shared_main_thread_contexts_.get() && !shared_main_thread_contexts_->BindToCurrentThread()) shared_main_thread_contexts_ = NULL; return shared_main_thread_contexts_; } void InProcessContextFactory::RemoveCompositor(Compositor* compositor) { if (!per_compositor_data_.count(compositor)) return; delete per_compositor_data_[compositor]; per_compositor_data_.erase(compositor); } bool InProcessContextFactory::DoesCreateTestContexts() { return context_factory_for_test_; } uint32 InProcessContextFactory::GetImageTextureTarget() { return GL_TEXTURE_2D; } cc::SharedBitmapManager* InProcessContextFactory::GetSharedBitmapManager() { return &shared_bitmap_manager_; } gpu::GpuMemoryBufferManager* InProcessContextFactory::GetGpuMemoryBufferManager() { return &gpu_memory_buffer_manager_; } cc::TaskGraphRunner* InProcessContextFactory::GetTaskGraphRunner() { return &task_graph_runner_; } scoped_ptr InProcessContextFactory::CreateSurfaceIdAllocator() { return make_scoped_ptr( new cc::SurfaceIdAllocator(next_surface_id_namespace_++)); } void InProcessContextFactory::ResizeDisplay(ui::Compositor* compositor, const gfx::Size& size) { if (!per_compositor_data_.count(compositor)) return; per_compositor_data_[compositor]->display()->Resize(size); } } // namespace ui