Commit f405a5e6 authored by Peng Huang's avatar Peng Huang Committed by Chromium LUCI CQ

SharedImageBackingEglImage: support passthrough decoder.

Bug: 1168584
Change-Id: I7eb840feafb2ba0c734713f88d48bcd822004472
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2640933
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845410}
parent e6584c33
......@@ -20,50 +20,59 @@ namespace gpu {
class SharedImageBackingEglImage::TextureHolder
: public base::RefCounted<TextureHolder> {
public:
TextureHolder(gles2::Texture* texture) : texture_(texture) {}
void MarkContextLost() { context_lost_ = true; }
explicit TextureHolder(gles2::Texture* texture) : texture_(texture) {}
explicit TextureHolder(
scoped_refptr<gles2::TexturePassthrough> texture_passthrough)
: texture_passthrough_(std::move(texture_passthrough)) {}
void MarkContextLost() {
context_lost_ = true;
if (texture_passthrough_)
texture_passthrough_->MarkContextLost();
}
gles2::Texture* texture() { return texture_; }
const scoped_refptr<gles2::TexturePassthrough>& texture_passthrough() const {
return texture_passthrough_;
}
private:
friend class base::RefCounted<TextureHolder>;
~TextureHolder() { texture_->RemoveLightweightRef(!context_lost_); }
~TextureHolder() {
if (texture_)
texture_->RemoveLightweightRef(!context_lost_);
}
gles2::Texture* const texture_;
gles2::Texture* const texture_ = nullptr;
const scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
bool context_lost_ = false;
};
// Implementation of SharedImageRepresentationGLTexture which uses GL texture
// which is an EGLImage sibling.
class SharedImageRepresentationEglImageGLTexture
: public SharedImageRepresentationGLTexture {
class SharedImageBackingEglImage::RepresentationGLShared {
public:
using TextureHolder = SharedImageBackingEglImage::TextureHolder;
SharedImageRepresentationEglImageGLTexture(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker,
RepresentationGLShared(SharedImageBackingEglImage* backing,
scoped_refptr<TextureHolder> texture_holder)
: SharedImageRepresentationGLTexture(manager, backing, tracker),
texture_holder_(std::move(texture_holder)) {}
: backing_(backing), texture_holder_(std::move(texture_holder)) {}
~SharedImageRepresentationEglImageGLTexture() override {
~RepresentationGLShared() {
EndAccess();
if (!has_context())
if (!backing_->have_context())
texture_holder_->MarkContextLost();
texture_holder_.reset();
}
bool BeginAccess(GLenum mode) override {
bool BeginAccess(GLenum mode) {
if (mode == GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM ||
mode == GL_SHARED_IMAGE_ACCESS_MODE_OVERLAY_CHROMIUM) {
if (!egl_backing()->BeginRead(this))
if (!backing_->BeginRead(this))
return false;
mode_ = RepresentationAccessMode::kRead;
} else if (mode == GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM) {
if (!egl_backing()->BeginWrite())
if (!backing_->BeginWrite())
return false;
mode_ = RepresentationAccessMode::kWrite;
} else {
......@@ -72,33 +81,88 @@ class SharedImageRepresentationEglImageGLTexture
return true;
}
void EndAccess() override {
void EndAccess() {
if (mode_ == RepresentationAccessMode::kNone)
return;
// Pass this fence to its backing.
if (mode_ == RepresentationAccessMode::kRead) {
egl_backing()->EndRead(this);
backing_->EndRead(this);
} else if (mode_ == RepresentationAccessMode::kWrite) {
egl_backing()->EndWrite();
backing_->EndWrite();
} else {
NOTREACHED();
}
mode_ = RepresentationAccessMode::kNone;
}
gles2::Texture* GetTexture() override { return texture_holder_->texture(); }
const scoped_refptr<TextureHolder>& texture_holder() const {
return texture_holder_;
}
private:
SharedImageBackingEglImage* const backing_;
scoped_refptr<TextureHolder> texture_holder_;
RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
DISALLOW_COPY_AND_ASSIGN(RepresentationGLShared);
};
class SharedImageBackingEglImage::RepresentationGLTexture
: public SharedImageRepresentationGLTexture {
public:
RepresentationGLTexture(SharedImageManager* manager,
SharedImageBackingEglImage* backing,
MemoryTypeTracker* tracker,
scoped_refptr<TextureHolder> texture_holder)
: SharedImageRepresentationGLTexture(manager, backing, tracker),
shared_(backing, std::move(texture_holder)) {}
~RepresentationGLTexture() override = default;
bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
void EndAccess() override { shared_.EndAccess(); }
gles2::Texture* GetTexture() override {
return shared_.texture_holder()->texture();
}
bool SupportsMultipleConcurrentReadAccess() override { return true; }
private:
SharedImageBackingEglImage* egl_backing() {
return static_cast<SharedImageBackingEglImage*>(backing());
RepresentationGLShared shared_;
DISALLOW_COPY_AND_ASSIGN(RepresentationGLTexture);
};
class SharedImageBackingEglImage::RepresentationGLTexturePassthrough
: public SharedImageRepresentationGLTexturePassthrough {
public:
RepresentationGLTexturePassthrough(
SharedImageManager* manager,
SharedImageBackingEglImage* backing,
MemoryTypeTracker* tracker,
scoped_refptr<TextureHolder> texture_holder)
: SharedImageRepresentationGLTexturePassthrough(manager,
backing,
tracker),
shared_(backing, std::move(texture_holder)) {}
~RepresentationGLTexturePassthrough() override = default;
bool BeginAccess(GLenum mode) override { return shared_.BeginAccess(mode); }
void EndAccess() override { shared_.EndAccess(); }
const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
override {
return shared_.texture_holder()->texture_passthrough();
}
scoped_refptr<TextureHolder> texture_holder_;
RepresentationAccessMode mode_ = RepresentationAccessMode::kNone;
DISALLOW_COPY_AND_ASSIGN(SharedImageRepresentationEglImageGLTexture);
bool SupportsMultipleConcurrentReadAccess() override { return true; }
private:
RepresentationGLShared shared_;
DISALLOW_COPY_AND_ASSIGN(RepresentationGLTexturePassthrough);
};
SharedImageBackingEglImage::SharedImageBackingEglImage(
......@@ -113,7 +177,8 @@ SharedImageBackingEglImage::SharedImageBackingEglImage(
GLuint gl_format,
GLuint gl_type,
SharedImageBatchAccessManager* batch_access_manager,
const GpuDriverBugWorkarounds& workarounds)
const GpuDriverBugWorkarounds& workarounds,
bool use_passthrough)
: ClearTrackingSharedImageBacking(mailbox,
format,
size,
......@@ -125,15 +190,14 @@ SharedImageBackingEglImage::SharedImageBackingEglImage(
true /*is_thread_safe*/),
gl_format_(gl_format),
gl_type_(gl_type),
batch_access_manager_(batch_access_manager) {
batch_access_manager_(batch_access_manager),
use_passthrough_(use_passthrough) {
DCHECK(batch_access_manager_);
created_on_context_ = gl::g_current_gl_context;
// On some GPUs (NVidia) keeping reference to egl image itself is not enough,
// we must keep reference to at least one sibling.
if (workarounds.dont_delete_source_texture_for_egl_image) {
auto* texture = GenEGLImageSibling();
if (texture)
source_texture_holder_ = base::MakeRefCounted<TextureHolder>(texture);
source_texture_holder_ = GenEGLImageSibling();
}
}
......@@ -154,8 +218,9 @@ bool SharedImageBackingEglImage::ProduceLegacyMailbox(
return false;
}
std::unique_ptr<SharedImageRepresentationGLTexture>
SharedImageBackingEglImage::ProduceGLTexture(SharedImageManager* manager,
template <class T>
std::unique_ptr<T> SharedImageBackingEglImage::ProduceGLTextureInternal(
SharedImageManager* manager,
MemoryTypeTracker* tracker) {
// On some GPUs (Mali, mostly Android 9, like J7) glTexSubImage fails on egl
// image sibling. So we use the original texture if we're on the same gl
......@@ -165,16 +230,25 @@ SharedImageBackingEglImage::ProduceGLTexture(SharedImageManager* manager,
// doesn't need lock.
if (created_on_context_ == gl::g_current_gl_context &&
source_texture_holder_) {
return std::make_unique<SharedImageRepresentationEglImageGLTexture>(
manager, this, tracker, source_texture_holder_);
return std::make_unique<T>(manager, this, tracker, source_texture_holder_);
}
auto* texture = GenEGLImageSibling();
if (!texture)
return nullptr;
auto texture_holder = base::MakeRefCounted<TextureHolder>(texture);
return std::make_unique<SharedImageRepresentationEglImageGLTexture>(
manager, this, tracker, std::move(texture_holder));
auto texture_holder = GenEGLImageSibling();
return std::make_unique<T>(manager, this, tracker, std::move(texture_holder));
}
std::unique_ptr<SharedImageRepresentationGLTexture>
SharedImageBackingEglImage::ProduceGLTexture(SharedImageManager* manager,
MemoryTypeTracker* tracker) {
return ProduceGLTextureInternal<RepresentationGLTexture>(manager, tracker);
}
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
SharedImageBackingEglImage::ProduceGLTexturePassthrough(
SharedImageManager* manager,
MemoryTypeTracker* tracker) {
return ProduceGLTextureInternal<RepresentationGLTexturePassthrough>(manager,
tracker);
}
std::unique_ptr<SharedImageRepresentationSkia>
......@@ -182,12 +256,21 @@ SharedImageBackingEglImage::ProduceSkia(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
scoped_refptr<SharedContextState> context_state) {
if (use_passthrough_) {
auto gl_representation = ProduceGLTexturePassthrough(manager, tracker);
if (!gl_representation)
return nullptr;
return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation),
std::move(context_state),
manager, this, tracker);
} else {
auto gl_representation = ProduceGLTexture(manager, tracker);
if (!gl_representation)
return nullptr;
return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation),
std::move(context_state),
manager, this, tracker);
}
}
bool SharedImageBackingEglImage::BeginWrite() {
......@@ -232,7 +315,7 @@ void SharedImageBackingEglImage::EndWrite() {
}
bool SharedImageBackingEglImage::BeginRead(
const SharedImageRepresentation* reader) {
const RepresentationGLShared* reader) {
AutoLock auto_lock(this);
if (is_writing_) {
......@@ -251,8 +334,7 @@ bool SharedImageBackingEglImage::BeginRead(
return true;
}
void SharedImageBackingEglImage::EndRead(
const SharedImageRepresentation* reader) {
void SharedImageBackingEglImage::EndRead(const RepresentationGLShared* reader) {
{
AutoLock auto_lock(this);
......@@ -279,7 +361,8 @@ void SharedImageBackingEglImage::EndRead(
base::MakeRefCounted<gl::SharedGLFenceEGL>();
}
gles2::Texture* SharedImageBackingEglImage::GenEGLImageSibling() {
scoped_refptr<SharedImageBackingEglImage::TextureHolder>
SharedImageBackingEglImage::GenEGLImageSibling() {
// Create a gles2::texture.
GLenum target = GL_TEXTURE_2D;
gl::GLApi* api = gl::g_current_gl_context;
......@@ -293,23 +376,6 @@ gles2::Texture* SharedImageBackingEglImage::GenEGLImageSibling() {
api->glTexParameteriFn(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
api->glTexParameteriFn(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
auto* texture = new gles2::Texture(service_id);
texture->SetLightweightRef();
texture->SetTarget(target, 1 /*max_levels*/);
texture->set_min_filter(GL_LINEAR);
texture->set_mag_filter(GL_LINEAR);
texture->set_wrap_t(GL_CLAMP_TO_EDGE);
texture->set_wrap_s(GL_CLAMP_TO_EDGE);
// If the backing is already cleared, no need to clear it again.
gfx::Rect cleared_rect;
if (IsCleared())
cleared_rect = gfx::Rect(size());
// Set the level info.
texture->SetLevelInfo(target, 0, gl_format_, size().width(), size().height(),
1, 0, gl_format_, gl_type_, cleared_rect);
// Note that we needed to use |bind_egl_image| flag and add some additional
// logic to handle it in order to make the locks
// more granular since BindToTexture() do not need to be behind the lock.
......@@ -328,8 +394,8 @@ gles2::Texture* SharedImageBackingEglImage::GenEGLImageSibling() {
// Use service id of the texture as a source to create the native buffer.
egl_image_buffer_ = gles2::NativeImageBuffer::Create(service_id);
if (!egl_image_buffer_) {
texture->RemoveLightweightRef(have_context());
return nullptr;
api->glDeleteTexturesFn(1, &service_id);
return {};
}
bind_egl_image = false;
}
......@@ -341,8 +407,35 @@ gles2::Texture* SharedImageBackingEglImage::GenEGLImageSibling() {
buffer->BindToTexture(target);
}
if (use_passthrough_) {
auto texture_passthrough =
base::MakeRefCounted<gpu::gles2::TexturePassthrough>(
service_id, GL_TEXTURE_2D, gl_format_, size().width(),
size().height(),
/*depth=*/1, /*border=*/0, gl_format_, gl_type_);
return base::MakeRefCounted<TextureHolder>(std::move(texture_passthrough));
}
auto* texture = new gles2::Texture(service_id);
texture->SetLightweightRef();
texture->SetTarget(GL_TEXTURE_2D, 1 /*max_levels*/);
texture->set_min_filter(GL_LINEAR);
texture->set_mag_filter(GL_LINEAR);
texture->set_wrap_t(GL_CLAMP_TO_EDGE);
texture->set_wrap_s(GL_CLAMP_TO_EDGE);
// If the backing is already cleared, no need to clear it again.
gfx::Rect cleared_rect;
if (IsCleared())
cleared_rect = gfx::Rect(size());
// Set the level info.
texture->SetLevelInfo(GL_TEXTURE_2D, 0, gl_format_, size().width(),
size().height(), 1, 0, gl_format_, gl_type_,
cleared_rect);
texture->SetImmutable(true /*immutable*/, false /*immutable_storage*/);
return texture;
return base::MakeRefCounted<TextureHolder>(std::move(texture));
}
void SharedImageBackingEglImage::SetEndReadFence(
......
......@@ -25,7 +25,6 @@ struct Mailbox;
namespace gles2 {
class NativeImageBuffer;
class Texture;
} // namespace gles2
// Implementation of SharedImageBacking that is used to create EGLImage targets
......@@ -47,7 +46,8 @@ class SharedImageBackingEglImage : public ClearTrackingSharedImageBacking {
GLuint gl_format,
GLuint gl_type,
SharedImageBatchAccessManager* batch_access_manager,
const GpuDriverBugWorkarounds& workarounds);
const GpuDriverBugWorkarounds& workarounds,
bool use_passthrough);
~SharedImageBackingEglImage() override;
......@@ -55,16 +55,15 @@ class SharedImageBackingEglImage : public ClearTrackingSharedImageBacking {
bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
void MarkForDestruction() override;
bool BeginWrite();
void EndWrite();
bool BeginRead(const SharedImageRepresentation* reader);
void EndRead(const SharedImageRepresentation* reader);
protected:
std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
ProduceGLTexturePassthrough(SharedImageManager* manager,
MemoryTypeTracker* tracker) override;
std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
SharedImageManager* manager,
MemoryTypeTracker* tracker,
......@@ -72,11 +71,22 @@ class SharedImageBackingEglImage : public ClearTrackingSharedImageBacking {
private:
friend class SharedImageBatchAccessManager;
friend class SharedImageRepresentationEglImageGLTexture;
class TextureHolder;
class RepresentationGLShared;
class RepresentationGLTexture;
class RepresentationGLTexturePassthrough;
template <class T>
std::unique_ptr<T> ProduceGLTextureInternal(SharedImageManager* manager,
MemoryTypeTracker* tracker);
bool BeginWrite();
void EndWrite();
bool BeginRead(const RepresentationGLShared* reader);
void EndRead(const RepresentationGLShared* reader);
// Use to create EGLImage texture target from the same EGLImage object.
gles2::Texture* GenEGLImageSibling();
scoped_refptr<TextureHolder> GenEGLImageSibling();
void SetEndReadFence(scoped_refptr<gl::SharedGLFenceEGL> shared_egl_fence);
......@@ -101,10 +111,12 @@ class SharedImageBackingEglImage : public ClearTrackingSharedImageBacking {
// signalled.
base::flat_map<gl::GLApi*, scoped_refptr<gl::SharedGLFenceEGL>> read_fences_
GUARDED_BY(lock_);
base::flat_set<const SharedImageRepresentation*> active_readers_
base::flat_set<const RepresentationGLShared*> active_readers_
GUARDED_BY(lock_);
SharedImageBatchAccessManager* batch_access_manager_ = nullptr;
const bool use_passthrough_;
DISALLOW_COPY_AND_ASSIGN(SharedImageBackingEglImage);
};
......
......@@ -398,7 +398,7 @@ SharedImageBackingFactoryGLTexture::MakeEglImageBacking(
return std::make_unique<SharedImageBackingEglImage>(
mailbox, format, size, color_space, surface_origin, alpha_type, usage,
estimated_size, format_info.gl_format, format_info.gl_type,
batch_access_manager_, workarounds_);
batch_access_manager_, workarounds_, use_passthrough_);
#else
return nullptr;
#endif
......
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