blob: e9a229e26d3105f3db431170a2744d1a5a2ffc97 [file] [log] [blame]
// Copyright 2015 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 "android_webview/browser/aw_render_thread_context_provider.h"
#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/gpu/context_cache_controller.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_trace_implementation.h"
#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/config/gpu_feature_info.h"
#include "gpu/ipc/gl_in_process_context.h"
#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace android_webview {
// static
scoped_refptr<AwRenderThreadContextProvider>
AwRenderThreadContextProvider::Create(
scoped_refptr<gl::GLSurface> surface,
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor) {
return new AwRenderThreadContextProvider(surface, std::move(task_executor));
}
AwRenderThreadContextProvider::AwRenderThreadContextProvider(
scoped_refptr<gl::GLSurface> surface,
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor) {
DCHECK(main_thread_checker_.CalledOnValidThread());
// This is an onscreen context, wrapping the GLSurface given to us from
// the Android OS. The widget we pass here will be ignored since we're
// providing the GLSurface to the context already.
DCHECK(!surface->IsOffscreen());
gpu::ContextCreationAttribs attributes;
// The context is wrapping an already allocated surface, so we can't control
// what buffers it has from these attributes. We do expect an alpha and
// stencil buffer to exist for webview, as the display compositor requires
// having them both in order to integrate its output with the content behind
// it.
attributes.alpha_size = 8;
attributes.stencil_size = 8;
// The depth buffer may exist due to having a stencil buffer, but we don't
// need one, so use -1 for it.
attributes.depth_size = -1;
attributes.samples = 0;
attributes.sample_buffers = 0;
attributes.bind_generates_resource = false;
gpu::SharedMemoryLimits limits;
// This context is only used for the display compositor, and there are no
// uploads done with it at all. We choose a small transfer buffer limit
// here, the minimums match the display compositor context for the android
// browser. We don't set the max since we expect the transfer buffer to be
// relatively unused.
limits.start_transfer_buffer_size = 64 * 1024;
limits.min_transfer_buffer_size = 64 * 1024;
context_ = std::make_unique<gpu::GLInProcessContext>();
context_->Initialize(std::move(task_executor), surface,
surface->IsOffscreen(), gpu::kNullSurfaceHandle,
attributes, limits, nullptr, nullptr, nullptr);
context_->GetImplementation()->SetLostContextCallback(base::BindOnce(
&AwRenderThreadContextProvider::OnLostContext, base::Unretained(this)));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableGpuClientTracing)) {
// This wraps the real GLES2Implementation and we should always use this
// instead when it's present.
trace_impl_ = std::make_unique<gpu::gles2::GLES2TraceImplementation>(
context_->GetImplementation());
}
cache_controller_ = std::make_unique<viz::ContextCacheController>(
context_->GetImplementation(), nullptr);
}
AwRenderThreadContextProvider::~AwRenderThreadContextProvider() {
DCHECK(main_thread_checker_.CalledOnValidThread());
if (gr_context_)
gr_context_->releaseResourcesAndAbandonContext();
}
uint32_t AwRenderThreadContextProvider::GetCopyTextureInternalFormat() {
// The attributes used in the constructor included an alpha channel.
return GL_RGBA;
}
void AwRenderThreadContextProvider::AddRef() const {
base::RefCountedThreadSafe<AwRenderThreadContextProvider>::AddRef();
}
void AwRenderThreadContextProvider::Release() const {
base::RefCountedThreadSafe<AwRenderThreadContextProvider>::Release();
}
gpu::ContextResult AwRenderThreadContextProvider::BindToCurrentThread() {
// This is called on the thread the context will be used.
DCHECK(main_thread_checker_.CalledOnValidThread());
return gpu::ContextResult::kSuccess;
}
const gpu::Capabilities& AwRenderThreadContextProvider::ContextCapabilities()
const {
DCHECK(main_thread_checker_.CalledOnValidThread());
return context_->GetImplementation()->capabilities();
}
const gpu::GpuFeatureInfo& AwRenderThreadContextProvider::GetGpuFeatureInfo()
const {
DCHECK(main_thread_checker_.CalledOnValidThread());
return context_->GetGpuFeatureInfo();
}
gpu::gles2::GLES2Interface* AwRenderThreadContextProvider::ContextGL() {
DCHECK(main_thread_checker_.CalledOnValidThread());
if (trace_impl_)
return trace_impl_.get();
return context_->GetImplementation();
}
gpu::ContextSupport* AwRenderThreadContextProvider::ContextSupport() {
DCHECK(main_thread_checker_.CalledOnValidThread());
return context_->GetImplementation();
}
class GrContext* AwRenderThreadContextProvider::GrContext() {
DCHECK(main_thread_checker_.CalledOnValidThread());
if (gr_context_)
return gr_context_.get();
sk_sp<GrGLInterface> interface(skia_bindings::CreateGLES2InterfaceBindings(
ContextGL(), ContextSupport()));
gr_context_ = GrContext::MakeGL(std::move(interface));
cache_controller_->SetGrContext(gr_context_.get());
return gr_context_.get();
}
viz::ContextCacheController* AwRenderThreadContextProvider::CacheController() {
DCHECK(main_thread_checker_.CalledOnValidThread());
return cache_controller_.get();
}
base::Lock* AwRenderThreadContextProvider::GetLock() {
// This context provider is not used on multiple threads.
NOTREACHED();
return nullptr;
}
void AwRenderThreadContextProvider::AddObserver(viz::ContextLostObserver* obs) {
observers_.AddObserver(obs);
}
void AwRenderThreadContextProvider::RemoveObserver(
viz::ContextLostObserver* obs) {
observers_.RemoveObserver(obs);
}
void AwRenderThreadContextProvider::OnLostContext() {
DCHECK(main_thread_checker_.CalledOnValidThread());
for (auto& observer : observers_)
observer.OnContextLost();
if (gr_context_)
gr_context_->abandonContext();
}
} // namespace android_webview