blob: c5bf15bef21a26e1d39797332cb71d76409e26a6 [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_backing_factory_gl_texture.h"
#include <algorithm>
#include <list>
#include <string>
#include <utility>
#include "base/feature_list.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.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/context_state.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_context_state.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/shared_image_backing_gl_image.h"
#include "gpu/command_buffer/service/shared_image_backing_gl_texture.h"
#include "gpu/command_buffer/service/shared_image_factory.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
#include "gpu/command_buffer/service/skia_utils.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_preferences.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/buffer_format_utils.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_image_native_pixmap.h"
#include "ui/gl/gl_image_shared_memory.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/scoped_binders.h"
#include "ui/gl/shared_gl_fence_egl.h"
#include "ui/gl/trace_util.h"
#if defined(OS_ANDROID)
#include "gpu/command_buffer/service/shared_image_backing_egl_image.h"
#include "gpu/command_buffer/service/shared_image_batch_access_manager.h"
#endif
#if defined(OS_MAC)
#include "gpu/command_buffer/service/shared_image_backing_factory_iosurface.h"
#endif
namespace gpu {
namespace {
size_t EstimatedSize(viz::ResourceFormat format, const gfx::Size& size) {
size_t estimated_size = 0;
viz::ResourceSizes::MaybeSizeInBytes(size, format, &estimated_size);
return estimated_size;
}
using InitializeGLTextureParams =
SharedImageBackingGLCommon::InitializeGLTextureParams;
} // anonymous namespace
///////////////////////////////////////////////////////////////////////////////
// SharedImageBackingGLTexture
SharedImageBackingGLTexture::SharedImageBackingGLTexture(
const Mailbox& mailbox,
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
GrSurfaceOrigin surface_origin,
SkAlphaType alpha_type,
uint32_t usage,
bool is_passthrough)
: SharedImageBacking(mailbox,
format,
size,
color_space,
surface_origin,
alpha_type,
usage,
EstimatedSize(format, size),
false /* is_thread_safe */),
is_passthrough_(is_passthrough) {}
SharedImageBackingGLTexture::~SharedImageBackingGLTexture() {
if (IsPassthrough()) {
if (passthrough_texture_) {
if (!have_context())
passthrough_texture_->MarkContextLost();
passthrough_texture_.reset();
}
} else {
if (texture_) {
texture_->RemoveLightweightRef(have_context());
texture_ = nullptr;
}
}
}
GLenum SharedImageBackingGLTexture::GetGLTarget() const {
return texture_ ? texture_->target() : passthrough_texture_->target();
}
GLuint SharedImageBackingGLTexture::GetGLServiceId() const {
return texture_ ? texture_->service_id() : passthrough_texture_->service_id();
}
void SharedImageBackingGLTexture::OnMemoryDump(
const std::string& dump_name,
base::trace_event::MemoryAllocatorDump* dump,
base::trace_event::ProcessMemoryDump* pmd,
uint64_t client_tracing_id) {
const auto client_guid = GetSharedImageGUIDForTracing(mailbox());
if (!IsPassthrough()) {
const auto service_guid =
gl::GetGLTextureServiceGUIDForTracing(texture_->service_id());
pmd->CreateSharedGlobalAllocatorDump(service_guid);
pmd->AddOwnershipEdge(client_guid, service_guid, /* importance */ 2);
texture_->DumpLevelMemory(pmd, client_tracing_id, dump_name);
}
}
gfx::Rect SharedImageBackingGLTexture::ClearedRect() const {
if (IsPassthrough()) {
// This backing is used exclusively with ANGLE which handles clear tracking
// internally. Act as though the texture is always cleared.
return gfx::Rect(size());
} else {
return texture_->GetLevelClearedRect(texture_->target(), 0);
}
}
void SharedImageBackingGLTexture::SetClearedRect(
const gfx::Rect& cleared_rect) {
if (!IsPassthrough())
texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
}
bool SharedImageBackingGLTexture::ProduceLegacyMailbox(
MailboxManager* mailbox_manager) {
if (IsPassthrough())
mailbox_manager->ProduceTexture(mailbox(), passthrough_texture_.get());
else
mailbox_manager->ProduceTexture(mailbox(), texture_);
return true;
}
std::unique_ptr<SharedImageRepresentationGLTexture>
SharedImageBackingGLTexture::ProduceGLTexture(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
DCHECK(texture_);
return std::make_unique<SharedImageRepresentationGLTextureImpl>(
manager, this, nullptr, tracker, texture_);
}
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
SharedImageBackingGLTexture::ProduceGLTexturePassthrough(
SharedImageManager* manager,
MemoryTypeTracker* tracker) {
DCHECK(passthrough_texture_);
return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
manager, this, nullptr, tracker, passthrough_texture_);
}
std::unique_ptr<SharedImageRepresentationDawn>
SharedImageBackingGLTexture::ProduceDawn(SharedImageManager* manager,
MemoryTypeTracker* tracker,
WGPUDevice device) {
if (!factory()) {
DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
return nullptr;
}
return SharedImageBackingGLCommon::ProduceDawnCommon(
factory(), manager, tracker, device, this, IsPassthrough());
}
std::unique_ptr<SharedImageRepresentationSkia>
SharedImageBackingGLTexture::ProduceSkia(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) {
if (!cached_promise_texture_) {
GrBackendTexture backend_texture;
GetGrBackendTexture(context_state->feature_info(), GetGLTarget(), size(),
GetGLServiceId(), format(), &backend_texture);
cached_promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
}
return std::make_unique<SharedImageRepresentationSkiaImpl>(
manager, this, nullptr, std::move(context_state), cached_promise_texture_,
tracker);
}
void SharedImageBackingGLTexture::Update(
std::unique_ptr<gfx::GpuFence> in_fence) {}
void SharedImageBackingGLTexture::InitializeGLTexture(
GLuint service_id,
const InitializeGLTextureParams& params) {
SharedImageBackingGLCommon::MakeTextureAndSetParameters(
params.target, service_id, params.framebuffer_attachment_angle,
IsPassthrough() ? &passthrough_texture_ : nullptr,
IsPassthrough() ? nullptr : &texture_);
if (IsPassthrough()) {
passthrough_texture_->SetEstimatedSize(EstimatedSize(format(), size()));
} else {
texture_->SetLevelInfo(params.target, 0, params.internal_format,
size().width(), size().height(), 1, 0, params.format,
params.type,
params.is_cleared ? gfx::Rect(size()) : gfx::Rect());
texture_->SetImmutable(true, params.has_immutable_storage);
}
}
void SharedImageBackingGLTexture::SetCompatibilitySwizzle(
const gles2::Texture::CompatibilitySwizzle* swizzle) {
if (!IsPassthrough())
texture_->SetCompatibilitySwizzle(swizzle);
}
} // namespace gpu