Commit b5229e3d authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

SharedImageBackingGLImage: Use Retain/Release to scope GL texture

Change SharedImageBackingGLImage to not allocate a GL texture until
it is going to be used, and also delete the GL texture when it is
no longer in use. This is needed for Metal-only SkiaRenderer, where
we really don't want to be using GL (and actually can't, because
there isn't a context hanging around at all times).

TBR=geofflang

Bug: 1092155
Change-Id: I6c14d03b50f40bd96de1c0c7355c03493c22865d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2298723Reviewed-by: default avatarGeoff Lang <geofflang@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789707}
parent 241ef1f3
...@@ -311,6 +311,13 @@ SharedImageRepresentationGLTextureImpl::SharedImageRepresentationGLTextureImpl( ...@@ -311,6 +311,13 @@ SharedImageRepresentationGLTextureImpl::SharedImageRepresentationGLTextureImpl(
client_(client), client_(client),
texture_(texture) {} texture_(texture) {}
SharedImageRepresentationGLTextureImpl::
~SharedImageRepresentationGLTextureImpl() {
texture_ = nullptr;
if (client_)
client_->SharedImageRepresentationGLTextureRelease(has_context());
}
gles2::Texture* SharedImageRepresentationGLTextureImpl::GetTexture() { gles2::Texture* SharedImageRepresentationGLTextureImpl::GetTexture() {
return texture_; return texture_;
} }
...@@ -341,7 +348,11 @@ SharedImageRepresentationGLTexturePassthroughImpl:: ...@@ -341,7 +348,11 @@ SharedImageRepresentationGLTexturePassthroughImpl::
texture_passthrough_(std::move(texture_passthrough)) {} texture_passthrough_(std::move(texture_passthrough)) {}
SharedImageRepresentationGLTexturePassthroughImpl:: SharedImageRepresentationGLTexturePassthroughImpl::
~SharedImageRepresentationGLTexturePassthroughImpl() = default; ~SharedImageRepresentationGLTexturePassthroughImpl() {
texture_passthrough_.reset();
if (client_)
client_->SharedImageRepresentationGLTextureRelease(has_context());
}
const scoped_refptr<gles2::TexturePassthrough>& const scoped_refptr<gles2::TexturePassthrough>&
SharedImageRepresentationGLTexturePassthroughImpl::GetTexturePassthrough() { SharedImageRepresentationGLTexturePassthroughImpl::GetTexturePassthrough() {
...@@ -426,6 +437,11 @@ SharedImageRepresentationSkiaImpl::~SharedImageRepresentationSkiaImpl() { ...@@ -426,6 +437,11 @@ SharedImageRepresentationSkiaImpl::~SharedImageRepresentationSkiaImpl() {
DLOG(ERROR) << "SharedImageRepresentationSkia was destroyed while still " DLOG(ERROR) << "SharedImageRepresentationSkia was destroyed while still "
<< "open for write access."; << "open for write access.";
} }
promise_texture_.reset();
if (client_) {
DCHECK(context_state_->GrContextIsGL());
client_->SharedImageRepresentationGLTextureRelease(has_context());
}
} }
sk_sp<SkSurface> SharedImageRepresentationSkiaImpl::BeginWriteAccess( sk_sp<SkSurface> SharedImageRepresentationSkiaImpl::BeginWriteAccess(
...@@ -700,8 +716,21 @@ SharedImageBackingGLImage::SharedImageBackingGLImage( ...@@ -700,8 +716,21 @@ SharedImageBackingGLImage::SharedImageBackingGLImage(
gl_params_(params), gl_params_(params),
gl_unpack_attribs_(attribs), gl_unpack_attribs_(attribs),
is_passthrough_(is_passthrough), is_passthrough_(is_passthrough),
cleared_rect_(params.is_cleared ? gfx::Rect(size) : gfx::Rect()),
weak_factory_(this) { weak_factory_(this) {
DCHECK(image_); DCHECK(image_);
}
SharedImageBackingGLImage::~SharedImageBackingGLImage() {
if (gl_texture_retained_for_legacy_mailbox_)
ReleaseGLTexture(have_context());
DCHECK_EQ(gl_texture_retain_count_, 0u);
}
void SharedImageBackingGLImage::RetainGLTexture() {
gl_texture_retain_count_ += 1;
if (gl_texture_retain_count_ > 1)
return;
// Allocate the GL texture. // Allocate the GL texture.
SharedImageBackingGLCommon::MakeTextureAndSetParameters( SharedImageBackingGLCommon::MakeTextureAndSetParameters(
...@@ -711,35 +740,50 @@ SharedImageBackingGLImage::SharedImageBackingGLImage( ...@@ -711,35 +740,50 @@ SharedImageBackingGLImage::SharedImageBackingGLImage(
is_passthrough_ ? nullptr : &texture_); is_passthrough_ ? nullptr : &texture_);
// Set the GLImage to be initially unbound from the GL texture. // Set the GLImage to be initially unbound from the GL texture.
image_bind_or_copy_needed_ = true;
if (is_passthrough_) { if (is_passthrough_) {
passthrough_texture_->SetEstimatedSize(EstimatedSize(format, size)); passthrough_texture_->SetEstimatedSize(EstimatedSize(format(), size()));
passthrough_texture_->SetLevelImage(gl_params_.target, 0, image_.get()); passthrough_texture_->SetLevelImage(gl_params_.target, 0, image_.get());
passthrough_texture_->set_is_bind_pending(true); passthrough_texture_->set_is_bind_pending(true);
} else { } else {
texture_->SetLevelInfo( texture_->SetLevelInfo(gl_params_.target, 0, gl_params_.internal_format,
gl_params_.target, 0, gl_params_.internal_format, size.width(), size().width(), size().height(), 1, 0,
size.height(), 1, 0, gl_params_.format, gl_params_.type, gl_params_.format, gl_params_.type, cleared_rect_);
gl_params_.is_cleared ? gfx::Rect(size) : gfx::Rect());
texture_->SetLevelImage(gl_params_.target, 0, image_.get(), texture_->SetLevelImage(gl_params_.target, 0, image_.get(),
gles2::Texture::UNBOUND); gles2::Texture::UNBOUND);
texture_->SetImmutable(true, false /* has_immutable_storage */); texture_->SetImmutable(true, false /* has_immutable_storage */);
} }
} }
SharedImageBackingGLImage::~SharedImageBackingGLImage() { void SharedImageBackingGLImage::ReleaseGLTexture(bool have_context) {
DCHECK_GT(gl_texture_retain_count_, 0u);
gl_texture_retain_count_ -= 1;
if (gl_texture_retain_count_ > 0)
return;
// If the cached promise texture is referencing the GL texture, then it needs
// to be deleted, too.
if (cached_promise_texture_) {
if (cached_promise_texture_->backendTexture().backend() ==
GrBackendApi::kOpenGL) {
cached_promise_texture_.reset();
}
}
if (rgb_emulation_texture_) { if (rgb_emulation_texture_) {
rgb_emulation_texture_->RemoveLightweightRef(have_context()); rgb_emulation_texture_->RemoveLightweightRef(have_context);
rgb_emulation_texture_ = nullptr; rgb_emulation_texture_ = nullptr;
} }
if (IsPassthrough()) { if (IsPassthrough()) {
if (passthrough_texture_) { if (passthrough_texture_) {
if (!have_context()) if (!have_context)
passthrough_texture_->MarkContextLost(); passthrough_texture_->MarkContextLost();
passthrough_texture_.reset(); passthrough_texture_.reset();
} }
} else { } else {
if (texture_) { if (texture_) {
texture_->RemoveLightweightRef(have_context()); cleared_rect_ = texture_->GetLevelClearedRect(texture_->target(), 0);
texture_->RemoveLightweightRef(have_context);
texture_ = nullptr; texture_ = nullptr;
} }
} }
...@@ -750,7 +794,11 @@ GLenum SharedImageBackingGLImage::GetGLTarget() const { ...@@ -750,7 +794,11 @@ GLenum SharedImageBackingGLImage::GetGLTarget() const {
} }
GLuint SharedImageBackingGLImage::GetGLServiceId() const { GLuint SharedImageBackingGLImage::GetGLServiceId() const {
return texture_ ? texture_->service_id() : passthrough_texture_->service_id(); if (texture_)
return texture_->service_id();
if (passthrough_texture_)
return passthrough_texture_->service_id();
return 0;
} }
scoped_refptr<gfx::NativePixmap> SharedImageBackingGLImage::GetNativePixmap() { scoped_refptr<gfx::NativePixmap> SharedImageBackingGLImage::GetNativePixmap() {
...@@ -768,39 +816,36 @@ void SharedImageBackingGLImage::OnMemoryDump( ...@@ -768,39 +816,36 @@ void SharedImageBackingGLImage::OnMemoryDump(
// Add a |service_guid| which expresses shared ownership between the // Add a |service_guid| which expresses shared ownership between the
// various GPU dumps. // various GPU dumps.
auto client_guid = GetSharedImageGUIDForTracing(mailbox()); auto client_guid = GetSharedImageGUIDForTracing(mailbox());
auto service_guid = gl::GetGLTextureServiceGUIDForTracing(GetGLServiceId()); if (auto service_id = GetGLServiceId()) {
pmd->CreateSharedGlobalAllocatorDump(service_guid); auto service_guid = gl::GetGLTextureServiceGUIDForTracing(GetGLServiceId());
// TODO(piman): coalesce constant with TextureManager::DumpTextureRef. pmd->CreateSharedGlobalAllocatorDump(service_guid);
int importance = 2; // This client always owns the ref. // TODO(piman): coalesce constant with TextureManager::DumpTextureRef.
int importance = 2; // This client always owns the ref.
pmd->AddOwnershipEdge(client_guid, service_guid, importance); pmd->AddOwnershipEdge(client_guid, service_guid, importance);
if (IsPassthrough()) {
auto* gl_image = passthrough_texture_->GetLevelImage(GetGLTarget(), 0);
if (gl_image)
gl_image->OnMemoryDump(pmd, client_tracing_id, dump_name);
} else {
// 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);
} }
image_->OnMemoryDump(pmd, client_tracing_id, dump_name);
} }
gfx::Rect SharedImageBackingGLImage::ClearedRect() const { gfx::Rect SharedImageBackingGLImage::ClearedRect() const {
if (IsPassthrough()) { if (texture_)
// 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); return texture_->GetLevelClearedRect(texture_->target(), 0);
} return cleared_rect_;
} }
void SharedImageBackingGLImage::SetClearedRect(const gfx::Rect& cleared_rect) { void SharedImageBackingGLImage::SetClearedRect(const gfx::Rect& cleared_rect) {
if (!IsPassthrough()) if (texture_)
texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect); texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
else
cleared_rect_ = cleared_rect;
} }
bool SharedImageBackingGLImage::ProduceLegacyMailbox( bool SharedImageBackingGLImage::ProduceLegacyMailbox(
MailboxManager* mailbox_manager) { MailboxManager* mailbox_manager) {
if (!gl_texture_retained_for_legacy_mailbox_) {
RetainGLTexture();
gl_texture_retained_for_legacy_mailbox_ = true;
}
if (IsPassthrough()) if (IsPassthrough())
mailbox_manager->ProduceTexture(mailbox(), passthrough_texture_.get()); mailbox_manager->ProduceTexture(mailbox(), passthrough_texture_.get());
else else
...@@ -811,6 +856,9 @@ bool SharedImageBackingGLImage::ProduceLegacyMailbox( ...@@ -811,6 +856,9 @@ bool SharedImageBackingGLImage::ProduceLegacyMailbox(
std::unique_ptr<SharedImageRepresentationGLTexture> std::unique_ptr<SharedImageRepresentationGLTexture>
SharedImageBackingGLImage::ProduceGLTexture(SharedImageManager* manager, SharedImageBackingGLImage::ProduceGLTexture(SharedImageManager* manager,
MemoryTypeTracker* tracker) { MemoryTypeTracker* tracker) {
// The corresponding release will be done when the returned representation is
// destroyed, in SharedImageRepresentationGLTextureRelease.
RetainGLTexture();
DCHECK(texture_); DCHECK(texture_);
return std::make_unique<SharedImageRepresentationGLTextureImpl>( return std::make_unique<SharedImageRepresentationGLTextureImpl>(
manager, this, this, tracker, texture_); manager, this, this, tracker, texture_);
...@@ -819,6 +867,9 @@ std::unique_ptr<SharedImageRepresentationGLTexturePassthrough> ...@@ -819,6 +867,9 @@ std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
SharedImageBackingGLImage::ProduceGLTexturePassthrough( SharedImageBackingGLImage::ProduceGLTexturePassthrough(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTypeTracker* tracker) { MemoryTypeTracker* tracker) {
// The corresponding release will be done when the returned representation is
// destroyed, in SharedImageRepresentationGLTextureRelease.
RetainGLTexture();
DCHECK(passthrough_texture_); DCHECK(passthrough_texture_);
return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>( return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
manager, this, this, tracker, passthrough_texture_); manager, this, this, tracker, passthrough_texture_);
...@@ -859,6 +910,14 @@ SharedImageBackingGLImage::ProduceSkia( ...@@ -859,6 +910,14 @@ SharedImageBackingGLImage::ProduceSkia(
SharedImageManager* manager, SharedImageManager* manager,
MemoryTypeTracker* tracker, MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) { scoped_refptr<SharedContextState> context_state) {
SharedImageRepresentationGLTextureClient* gl_client = nullptr;
if (context_state->GrContextIsGL()) {
// The corresponding release will be done when the returned representation
// is destroyed, in SharedImageRepresentationGLTextureRelease.
RetainGLTexture();
gl_client = this;
}
if (!cached_promise_texture_) { if (!cached_promise_texture_) {
if (context_state->GrContextIsMetal()) { if (context_state->GrContextIsMetal()) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
...@@ -875,8 +934,8 @@ SharedImageBackingGLImage::ProduceSkia( ...@@ -875,8 +934,8 @@ SharedImageBackingGLImage::ProduceSkia(
} }
} }
return std::make_unique<SharedImageRepresentationSkiaImpl>( return std::make_unique<SharedImageRepresentationSkiaImpl>(
manager, this, context_state->GrContextIsGL() ? this : nullptr, manager, this, gl_client, std::move(context_state),
std::move(context_state), cached_promise_texture_, tracker); cached_promise_texture_, tracker);
} }
std::unique_ptr<SharedImageRepresentationGLTexture> std::unique_ptr<SharedImageRepresentationGLTexture>
...@@ -886,6 +945,7 @@ SharedImageBackingGLImage::ProduceRGBEmulationGLTexture( ...@@ -886,6 +945,7 @@ SharedImageBackingGLImage::ProduceRGBEmulationGLTexture(
if (IsPassthrough()) if (IsPassthrough())
return nullptr; return nullptr;
RetainGLTexture();
if (!rgb_emulation_texture_) { if (!rgb_emulation_texture_) {
const GLenum target = GetGLTarget(); const GLenum target = GetGLTarget();
gl::GLApi* api = gl::g_current_gl_context; gl::GLApi* api = gl::g_current_gl_context;
...@@ -908,6 +968,7 @@ SharedImageBackingGLImage::ProduceRGBEmulationGLTexture( ...@@ -908,6 +968,7 @@ SharedImageBackingGLImage::ProduceRGBEmulationGLTexture(
LOG(ERROR) << "Failed to bind image to rgb texture."; LOG(ERROR) << "Failed to bind image to rgb texture.";
rgb_emulation_texture_->RemoveLightweightRef(true /* have_context */); rgb_emulation_texture_->RemoveLightweightRef(true /* have_context */);
rgb_emulation_texture_ = nullptr; rgb_emulation_texture_ = nullptr;
ReleaseGLTexture(true /* has_context */);
return nullptr; return nullptr;
} }
GLenum format = GLenum format =
...@@ -958,7 +1019,14 @@ void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess() { ...@@ -958,7 +1019,14 @@ void SharedImageBackingGLImage::SharedImageRepresentationGLTextureEndAccess() {
#endif #endif
} }
void SharedImageBackingGLImage::SharedImageRepresentationGLTextureRelease(
bool has_context) {
ReleaseGLTexture(has_context);
}
bool SharedImageBackingGLImage::BindOrCopyImageIfNeeded() { bool SharedImageBackingGLImage::BindOrCopyImageIfNeeded() {
// This is called by code that has retained the GL texture.
DCHECK(texture_ || passthrough_texture_);
if (!image_bind_or_copy_needed_) if (!image_bind_or_copy_needed_)
return true; return true;
...@@ -1025,6 +1093,7 @@ void SharedImageBackingGLImage::InitializePixels(GLenum format, ...@@ -1025,6 +1093,7 @@ void SharedImageBackingGLImage::InitializePixels(GLenum format,
if (SharedImageBackingFactoryIOSurface::InitializePixels(this, image_, data)) if (SharedImageBackingFactoryIOSurface::InitializePixels(this, image_, data))
return; return;
#else #else
RetainGLTexture();
BindOrCopyImageIfNeeded(); BindOrCopyImageIfNeeded();
const GLenum target = GetGLTarget(); const GLenum target = GetGLTarget();
...@@ -1035,6 +1104,7 @@ void SharedImageBackingGLImage::InitializePixels(GLenum format, ...@@ -1035,6 +1104,7 @@ void SharedImageBackingGLImage::InitializePixels(GLenum format,
api, gl_unpack_attribs_, true /* uploading_data */); api, gl_unpack_attribs_, true /* uploading_data */);
api->glTexSubImage2DFn(target, 0, 0, 0, size().width(), size().height(), api->glTexSubImage2DFn(target, 0, 0, 0, size().width(), size().height(),
format, type, data); format, type, data);
ReleaseGLTexture(true /* have_context */);
#endif #endif
} }
......
...@@ -17,6 +17,7 @@ class SharedImageRepresentationGLTextureClient { ...@@ -17,6 +17,7 @@ class SharedImageRepresentationGLTextureClient {
public: public:
virtual bool SharedImageRepresentationGLTextureBeginAccess() = 0; virtual bool SharedImageRepresentationGLTextureBeginAccess() = 0;
virtual void SharedImageRepresentationGLTextureEndAccess() = 0; virtual void SharedImageRepresentationGLTextureEndAccess() = 0;
virtual void SharedImageRepresentationGLTextureRelease(bool have_context) = 0;
}; };
// Representation of a SharedImageBackingGLTexture or SharedImageBackingGLImage // Representation of a SharedImageBackingGLTexture or SharedImageBackingGLImage
...@@ -30,6 +31,7 @@ class SharedImageRepresentationGLTextureImpl ...@@ -30,6 +31,7 @@ class SharedImageRepresentationGLTextureImpl
SharedImageRepresentationGLTextureClient* client, SharedImageRepresentationGLTextureClient* client,
MemoryTypeTracker* tracker, MemoryTypeTracker* tracker,
gles2::Texture* texture); gles2::Texture* texture);
~SharedImageRepresentationGLTextureImpl() override;
private: private:
// SharedImageRepresentationGLTexture: // SharedImageRepresentationGLTexture:
...@@ -283,6 +285,7 @@ class SharedImageBackingGLImage ...@@ -283,6 +285,7 @@ class SharedImageBackingGLImage
// SharedImageRepresentationGLTextureClient: // SharedImageRepresentationGLTextureClient:
bool SharedImageRepresentationGLTextureBeginAccess() override; bool SharedImageRepresentationGLTextureBeginAccess() override;
void SharedImageRepresentationGLTextureEndAccess() override; void SharedImageRepresentationGLTextureEndAccess() override;
void SharedImageRepresentationGLTextureRelease(bool have_context) override;
bool IsPassthrough() const { return is_passthrough_; } bool IsPassthrough() const { return is_passthrough_; }
...@@ -293,11 +296,20 @@ class SharedImageBackingGLImage ...@@ -293,11 +296,20 @@ class SharedImageBackingGLImage
bool BindOrCopyImageIfNeeded(); bool BindOrCopyImageIfNeeded();
bool image_bind_or_copy_needed_ = true; bool image_bind_or_copy_needed_ = true;
void RetainGLTexture();
void ReleaseGLTexture(bool have_context);
size_t gl_texture_retain_count_ = 0;
bool gl_texture_retained_for_legacy_mailbox_ = false;
const SharedImageBackingGLCommon::InitializeGLTextureParams gl_params_; const SharedImageBackingGLCommon::InitializeGLTextureParams gl_params_;
const SharedImageBackingFactoryGLTexture::UnpackStateAttribs const SharedImageBackingFactoryGLTexture::UnpackStateAttribs
gl_unpack_attribs_; gl_unpack_attribs_;
const bool is_passthrough_; const bool is_passthrough_;
// This is the cleared rect used by ClearedRect and SetClearedRect when
// |texture_| is nullptr.
gfx::Rect cleared_rect_;
gles2::Texture* rgb_emulation_texture_ = nullptr; gles2::Texture* rgb_emulation_texture_ = nullptr;
gles2::Texture* texture_ = nullptr; gles2::Texture* texture_ = nullptr;
scoped_refptr<gles2::TexturePassthrough> passthrough_texture_; scoped_refptr<gles2::TexturePassthrough> passthrough_texture_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment