blob: 9f270d9b1c7078b8b9dbcf71849a6bcca8b963ea [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/test/test_in_process_context_provider.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/task/single_thread_task_runner.h"
#include "base/types/optional_util.h"
#include "components/viz/common/gpu/context_cache_controller.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "components/viz/test/test_gpu_service_holder.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/raster_implementation_gles.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/common/context_creation_attribs.h"
#include "gpu/config/skia_limits.h"
#include "gpu/ipc/gl_in_process_context.h"
#include "gpu/ipc/raster_in_process_context.h"
#include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
namespace viz {
TestInProcessContextProvider::TestInProcessContextProvider(
TestContextType type,
bool support_locking,
gpu::raster::GrShaderCache* gr_shader_cache,
gpu::GpuProcessActivityFlags* activity_flags)
: type_(type), activity_flags_(activity_flags) {
DCHECK(main_thread_checker_.CalledOnValidThread());
context_thread_checker_.DetachFromThread();
if (support_locking) {
context_lock_.emplace();
}
}
TestInProcessContextProvider::~TestInProcessContextProvider() {
DCHECK(main_thread_checker_.CalledOnValidThread() ||
context_thread_checker_.CalledOnValidThread());
}
void TestInProcessContextProvider::AddRef() const {
base::RefCountedThreadSafe<TestInProcessContextProvider>::AddRef();
}
void TestInProcessContextProvider::Release() const {
base::RefCountedThreadSafe<TestInProcessContextProvider>::Release();
}
gpu::ContextResult TestInProcessContextProvider::BindToCurrentSequence() {
DCHECK(context_thread_checker_.CalledOnValidThread());
auto* holder = TestGpuServiceHolder::GetInstance();
gpu::ContextCreationAttribs attribs;
attribs.alpha_size = 8;
attribs.blue_size = 8;
attribs.green_size = 8;
attribs.red_size = 8;
attribs.depth_size = 0;
attribs.stencil_size = 8;
attribs.samples = 0;
attribs.sample_buffers = 0;
attribs.bind_generates_resource = false;
if (type_ == TestContextType::kGLES2) {
attribs.enable_gles2_interface = true;
attribs.enable_raster_interface = false;
attribs.enable_oop_rasterization = false;
gles2_context_ = std::make_unique<gpu::GLInProcessContext>();
auto result = gles2_context_->Initialize(
TestGpuServiceHolder::GetInstance()->task_executor(), attribs,
gpu::SharedMemoryLimits());
DCHECK_EQ(result, gpu::ContextResult::kSuccess);
caps_ = gles2_context_->GetCapabilities();
} else {
bool is_gpu_raster = type_ == TestContextType::kGpuRaster;
attribs.enable_gles2_interface = false;
attribs.enable_raster_interface = true;
attribs.enable_oop_rasterization = is_gpu_raster;
raster_context_ = std::make_unique<gpu::RasterInProcessContext>();
auto result = raster_context_->Initialize(
holder->task_executor(), attribs, gpu::SharedMemoryLimits(),
holder->gpu_service()->gr_shader_cache(), activity_flags_);
DCHECK_EQ(result, gpu::ContextResult::kSuccess);
caps_ = raster_context_->GetCapabilities();
// We don't have a good way for tests to change what the in process gpu
// service will return for this capability. But we want to use gpu
// rasterization if and only if the test requests it.
caps_.gpu_rasterization = is_gpu_raster;
}
cache_controller_ = std::make_unique<ContextCacheController>(
ContextSupport(), base::SingleThreadTaskRunner::GetCurrentDefault());
cache_controller_->SetLock(GetLock());
return gpu::ContextResult::kSuccess;
}
gpu::gles2::GLES2Interface* TestInProcessContextProvider::ContextGL() {
CheckValidThreadOrLockAcquired();
DCHECK_EQ(type_, TestContextType::kGLES2);
return gles2_context_->GetImplementation();
}
gpu::raster::RasterInterface* TestInProcessContextProvider::RasterInterface() {
CheckValidThreadOrLockAcquired();
DCHECK_NE(type_, TestContextType::kGLES2);
return raster_context_->GetImplementation();
}
gpu::ContextSupport* TestInProcessContextProvider::ContextSupport() {
if (gles2_context_) {
return gles2_context_->GetImplementation();
} else {
return raster_context_->GetContextSupport();
}
}
class GrDirectContext* TestInProcessContextProvider::GrContext() {
CheckValidThreadOrLockAcquired();
if (gr_context_)
return gr_context_->get();
if (!gles2_context_) {
return nullptr;
}
size_t max_resource_cache_bytes;
size_t max_glyph_cache_texture_bytes;
gpu::DefaultGrCacheLimitsForTests(&max_resource_cache_bytes,
&max_glyph_cache_texture_bytes);
gr_context_ = std::make_unique<skia_bindings::GrContextForGLES2Interface>(
ContextGL(), ContextSupport(), ContextCapabilities(),
max_resource_cache_bytes, max_glyph_cache_texture_bytes);
cache_controller_->SetGrContext(gr_context_->get());
return gr_context_->get();
}
gpu::SharedImageInterface*
TestInProcessContextProvider::SharedImageInterface() {
if (gles2_context_) {
return gles2_context_->GetSharedImageInterface();
} else {
return raster_context_->GetSharedImageInterface();
}
}
ContextCacheController* TestInProcessContextProvider::CacheController() {
CheckValidThreadOrLockAcquired();
return cache_controller_.get();
}
base::Lock* TestInProcessContextProvider::GetLock() {
return base::OptionalToPtr(context_lock_);
}
const gpu::Capabilities& TestInProcessContextProvider::ContextCapabilities()
const {
CheckValidThreadOrLockAcquired();
return caps_;
}
const gpu::GpuFeatureInfo& TestInProcessContextProvider::GetGpuFeatureInfo()
const {
CheckValidThreadOrLockAcquired();
return gpu_feature_info_;
}
void TestInProcessContextProvider::AddObserver(ContextLostObserver* obs) {
observers_.AddObserver(obs);
}
void TestInProcessContextProvider::RemoveObserver(ContextLostObserver* obs) {
observers_.RemoveObserver(obs);
}
void TestInProcessContextProvider::SendOnContextLost() {
for (auto& observer : observers_) {
observer.OnContextLost();
}
}
void TestInProcessContextProvider::ExecuteOnGpuThread(base::OnceClosure task) {
DCHECK(raster_context_);
raster_context_->GetCommandBufferForTest()
->service_for_testing()
->ScheduleOutOfOrderTask(std::move(task));
}
void TestInProcessContextProvider::CheckValidThreadOrLockAcquired() const {
#if DCHECK_IS_ON()
if (context_lock_) {
context_lock_->AssertAcquired();
} else {
DCHECK(context_thread_checker_.CalledOnValidThread());
}
#endif
}
} // namespace viz