blob: 9dc7b516f5f1401cd809f3eb1760254ba5adf698 [file] [log] [blame]
// Copyright 2018 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/command_buffer/service/raster_decoder_context_state.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/service_transfer_cache.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/create_gr_gl_interface.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include "components/viz/common/gpu/vulkan_context_provider.h"
#endif
namespace gpu {
namespace raster {
RasterDecoderContextState::RasterDecoderContextState(
scoped_refptr<gl::GLShareGroup> share_group,
scoped_refptr<gl::GLSurface> surface,
scoped_refptr<gl::GLContext> context,
bool use_virtualized_gl_contexts,
base::OnceClosure context_lost_callback,
viz::VulkanContextProvider* vulkan_context_provider)
: use_virtualized_gl_contexts(use_virtualized_gl_contexts),
context_lost_callback(std::move(context_lost_callback)),
vk_context_provider(vulkan_context_provider),
#if BUILDFLAG(ENABLE_VULKAN)
gr_context(vk_context_provider ? vk_context_provider->GetGrContext()
: nullptr),
#endif
use_vulkan_gr_context(!!gr_context),
share_group_(std::move(share_group)),
context_(context),
real_context_(std::move(context)),
surface_(std::move(surface)),
weak_ptr_factory_(this) {
if (base::ThreadTaskRunnerHandle::IsSet()) {
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "RasterDecoderContextState", base::ThreadTaskRunnerHandle::Get());
}
}
RasterDecoderContextState::~RasterDecoderContextState() {
if (gr_context)
gr_context->abandonContext();
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
this);
}
void RasterDecoderContextState::InitializeGrContext(
const GpuDriverBugWorkarounds& workarounds,
GrContextOptions::PersistentCache* cache,
GpuProcessActivityFlags* activity_flags,
gl::ProgressReporter* progress_reporter) {
if (!use_vulkan_gr_context) {
DCHECK(context_->IsCurrent(surface()));
sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface(
*context_->GetVersionInfo(), workarounds.use_es2_for_oopr,
progress_reporter));
if (!interface) {
LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation "
"failed.";
return;
}
if (activity_flags && cache) {
// |activity_flags| is safe to capture here since it must outlive the
// this context state.
interface->fFunctions.fProgramBinary =
[activity_flags](GrGLuint program, GrGLenum binaryFormat,
void* binary, GrGLsizei length) {
GpuProcessActivityFlags::ScopedSetFlag scoped_set_flag(
activity_flags, ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY);
glProgramBinary(program, binaryFormat, binary, length);
};
}
// If you make any changes to the GrContext::Options here that could
// affect text rendering, make sure to match the capabilities initialized
// in GetCapabilities and ensuring these are also used by the
// PaintOpBufferSerializer.
GrContextOptions options;
options.fDriverBugWorkarounds =
GrDriverBugWorkarounds(workarounds.ToIntSet());
options.fDisableCoverageCountingPaths = true;
size_t max_resource_cache_bytes = 0u;
raster::DetermineGrCacheLimitsFromAvailableMemory(
&max_resource_cache_bytes, &glyph_cache_max_texture_bytes);
options.fGlyphCacheTextureMaximumBytes = glyph_cache_max_texture_bytes;
options.fPersistentCache = cache;
options.fAvoidStencilBuffers = workarounds.avoid_stencil_buffers;
owned_gr_context = GrContext::MakeGL(std::move(interface), options);
gr_context = owned_gr_context.get();
if (!gr_context) {
LOG(ERROR) << "OOP raster support disabled: GrContext creation "
"failed.";
} else {
constexpr int kMaxGaneshResourceCacheCount = 16384;
gr_context->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
max_resource_cache_bytes);
}
}
transfer_cache = std::make_unique<ServiceTransferCache>();
}
bool RasterDecoderContextState::InitializeGL(
const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds,
const GpuFeatureInfo& gpu_feature_info) {
if (use_vulkan_gr_context)
return true;
DCHECK(!context_state_);
feature_info_ = base::MakeRefCounted<gles2::FeatureInfo>(
gpu_driver_bug_workarounds, gpu_feature_info);
feature_info_->Initialize(gpu::CONTEXT_TYPE_OPENGLES2,
false /* is_passthrough_cmd_decoder */,
gles2::DisallowedFeatures());
auto* api = gl::g_current_gl_context;
const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
GLint max_vertex_attribs = 0;
api->glGetIntegervFn(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
if (max_vertex_attribs < kGLES2RequiredMinimumVertexAttribs)
return false;
context_state_ = std::make_unique<gles2::ContextState>(
feature_info_.get(), false /* track_texture_and_sampler_units */);
context_state_->set_api(api);
context_state_->InitGenericAttribs(max_vertex_attribs);
// Set all the default state because some GL drivers get it wrong.
// TODO(backer): Not all of this state needs to be initialized. Reduce the set
// if perf becomes a problem.
context_state_->InitCapabilities(nullptr);
context_state_->InitState(nullptr);
if (use_virtualized_gl_contexts) {
auto virtual_context = base::MakeRefCounted<GLContextVirtual>(
share_group_.get(), real_context_.get(),
weak_ptr_factory_.GetWeakPtr());
if (!virtual_context->Initialize(surface_.get(), gl::GLContextAttribs()))
return false;
context_ = std::move(virtual_context);
MakeCurrent(nullptr);
}
return true;
}
bool RasterDecoderContextState::MakeCurrent(gl::GLSurface* surface) {
if (context_lost_)
return false;
if (!context_->MakeCurrent(surface ? surface : surface_.get())) {
MarkContextLost();
return false;
}
return true;
}
void RasterDecoderContextState::MarkContextLost() {
if (!context_lost_) {
context_lost_ = true;
context_state_->MarkContextLost();
if (gr_context)
gr_context->abandonContext();
std::move(context_lost_callback).Run();
}
// TODO notify gpu channel manager.
}
bool RasterDecoderContextState::IsCurrent(gl::GLSurface* surface) {
return context_->IsCurrent(surface);
}
bool RasterDecoderContextState::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
if (gr_context)
DumpGrMemoryStatistics(gr_context, pmd, base::nullopt);
return true;
}
void RasterDecoderContextState::PurgeMemory(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
if (!gr_context) {
DCHECK(!transfer_cache);
return;
}
// Ensure the context is current before doing any GPU cleanup.
MakeCurrent(nullptr);
switch (memory_pressure_level) {
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
// This function is only called with moderate or critical pressure.
NOTREACHED();
return;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
// With moderate pressure, clear any unlocked resources.
gr_context->purgeUnlockedResources(true /* scratchResourcesOnly */);
break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
// With critical pressure, purge as much as possible.
gr_context->freeGpuResources();
break;
}
transfer_cache->PurgeMemory(memory_pressure_level);
}
void RasterDecoderContextState::PessimisticallyResetGrContext() const {
// Calling GrContext::resetContext() is very cheap, so we do it
// pessimistically. We could dirty less state if skia state setting
// performance becomes an issue.
if (gr_context && !use_vulkan_gr_context)
gr_context->resetContext();
}
bool RasterDecoderContextState::initialized() const {
return true;
}
const gles2::ContextState* RasterDecoderContextState::GetContextState() {
if (need_context_state_reset) {
// Returning nullptr to force full state restoration by the caller. We do
// this because GrContext changes to GL state are untracked in our
// context_state_.
return nullptr;
}
return context_state_.get();
}
void RasterDecoderContextState::RestoreState(
const gles2::ContextState* prev_state) {
PessimisticallyResetGrContext();
context_state_->RestoreState(prev_state);
}
void RasterDecoderContextState::RestoreGlobalState() const {
PessimisticallyResetGrContext();
context_state_->RestoreGlobalState(nullptr);
}
void RasterDecoderContextState::ClearAllAttributes() const {}
void RasterDecoderContextState::RestoreActiveTexture() const {
PessimisticallyResetGrContext();
}
void RasterDecoderContextState::RestoreAllTextureUnitAndSamplerBindings(
const gles2::ContextState* prev_state) const {
PessimisticallyResetGrContext();
}
void RasterDecoderContextState::RestoreActiveTextureUnitBinding(
unsigned int target) const {
PessimisticallyResetGrContext();
}
void RasterDecoderContextState::RestoreBufferBinding(unsigned int target) {
PessimisticallyResetGrContext();
if (target == GL_PIXEL_PACK_BUFFER) {
context_state_->UpdatePackParameters();
} else if (target == GL_PIXEL_UNPACK_BUFFER) {
context_state_->UpdateUnpackParameters();
}
context_state_->api()->glBindBufferFn(target, 0);
}
void RasterDecoderContextState::RestoreBufferBindings() const {
PessimisticallyResetGrContext();
context_state_->RestoreBufferBindings();
}
void RasterDecoderContextState::RestoreFramebufferBindings() const {
PessimisticallyResetGrContext();
context_state_->fbo_binding_for_scissor_workaround_dirty = true;
context_state_->stencil_state_changed_since_validation = true;
}
void RasterDecoderContextState::RestoreRenderbufferBindings() {
PessimisticallyResetGrContext();
context_state_->RestoreRenderbufferBindings();
}
void RasterDecoderContextState::RestoreProgramBindings() const {
PessimisticallyResetGrContext();
context_state_->RestoreProgramSettings(nullptr, false);
}
void RasterDecoderContextState::RestoreTextureUnitBindings(
unsigned unit) const {
PessimisticallyResetGrContext();
}
void RasterDecoderContextState::RestoreVertexAttribArray(unsigned index) {
NOTIMPLEMENTED();
}
void RasterDecoderContextState::RestoreAllExternalTextureBindingsIfNeeded() {
PessimisticallyResetGrContext();
}
QueryManager* RasterDecoderContextState::GetQueryManager() {
return nullptr;
}
} // namespace raster
} // namespace gpu