blob: eefaa0d29bc40f53fd671c635120684216fa6c70 [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/shared_image_factory.h"
#include <inttypes.h>
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_dump_manager.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/shared_image_trace_utils.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h"
#include "gpu/command_buffer/service/shared_image_manager.h"
#include "gpu/config/gpu_preferences.h"
#include "ui/gl/trace_util.h"
namespace gpu {
SharedImageFactory::SharedImageFactory(
const GpuPreferences& gpu_preferences,
const GpuDriverBugWorkarounds& workarounds,
const GpuFeatureInfo& gpu_feature_info,
MailboxManager* mailbox_manager,
SharedImageManager* shared_image_manager,
ImageFactory* image_factory,
gles2::MemoryTracker* tracker)
: use_passthrough_(gpu_preferences.use_passthrough_cmd_decoder &&
gles2::PassthroughCommandDecoderSupported()),
mailbox_manager_(mailbox_manager),
shared_image_manager_(shared_image_manager),
backing_factory_(
std::make_unique<SharedImageBackingFactoryGLTexture>(gpu_preferences,
workarounds,
gpu_feature_info,
image_factory,
tracker)) {}
SharedImageFactory::~SharedImageFactory() {
DCHECK(mailboxes_.empty());
}
bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
if (mailboxes_.find(mailbox) != mailboxes_.end()) {
LOG(ERROR) << "CreateSharedImage: mailbox already exists";
return false;
}
auto backing =
backing_factory_->CreateSharedImage(format, size, color_space, usage);
if (!backing) {
LOG(ERROR) << "CreateSharedImage: could not create backing.";
return false;
}
// TODO(ericrk): Handle the non-legacy case.
if (!backing->ProduceLegacyMailbox(mailbox, mailbox_manager_)) {
LOG(ERROR)
<< "CreateSharedImage: could not convert backing to legacy mailbox.";
backing->Destroy(true /* have_context */);
return false;
}
if (!shared_image_manager_->Register(mailbox, std::move(backing))) {
LOG(ERROR) << "CreateSharedImage: Could not register backing with "
"SharedImageManager.";
backing->Destroy(true /* have_context */);
return false;
}
mailboxes_.emplace(mailbox);
return true;
}
bool SharedImageFactory::DestroySharedImage(const Mailbox& mailbox) {
auto it = mailboxes_.find(mailbox);
if (it == mailboxes_.end()) {
LOG(ERROR) << "Could not find shared image mailbox";
return false;
}
shared_image_manager_->Unregister(mailbox, true /* have_context */);
mailboxes_.erase(it);
return true;
}
void SharedImageFactory::DestroyAllSharedImages(bool have_context) {
for (const auto& mailbox : mailboxes_) {
shared_image_manager_->Unregister(mailbox, have_context);
}
mailboxes_.clear();
}
bool SharedImageFactory::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd,
int client_id,
uint64_t client_tracing_id) {
if (use_passthrough_)
return true;
// TODO(ericrk): Move some of this to SharedImageBacking.
for (const auto& mailbox : mailboxes_) {
auto* texture =
static_cast<gles2::Texture*>(mailbox_manager_->ConsumeTexture(mailbox));
DCHECK(texture);
// Unique name in the process.
std::string dump_name =
base::StringPrintf("gpu/shared-images/client_0x%" PRIX32 "/mailbox_%s",
client_id, mailbox.ToDebugString().c_str());
base::trace_event::MemoryAllocatorDump* dump =
pmd->CreateAllocatorDump(dump_name);
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
static_cast<uint64_t>(texture->estimated_size()));
// Add a mailbox guid which expresses shared ownership with the client
// process.
// This must match the client-side.
auto client_guid = GetSharedImageGUIDForTracing(mailbox);
pmd->CreateSharedGlobalAllocatorDump(client_guid);
pmd->AddOwnershipEdge(dump->guid(), client_guid);
// Add a |service_guid| which expresses shared ownership between the
// various GPU dumps.
auto service_guid =
gl::GetGLTextureServiceGUIDForTracing(texture->service_id());
pmd->CreateSharedGlobalAllocatorDump(service_guid);
// TODO(piman): coalesce constant with TextureManager::DumpTextureRef.
int importance = 2; // This client always owns the ref.
pmd->AddOwnershipEdge(client_guid, service_guid, importance);
// Dump all sub-levels held by the texture. They will appear below the
// main gl/textures/client_X/mailbox_Y dump.
texture->DumpLevelMemory(pmd, client_tracing_id, dump_name);
}
return true;
}
} // namespace gpu