Bug 1898238 - Make SharedSurface_EGLImage and (Render)EGLImageTextureHost work. r=sotaro,jgilbert

SharedSurface_EGLImage has mostly avoided bitrotting. However, it now
sometimes gets destructed after the GLContext has been lost, resulting
in a crash when attempting to clean up its resources. To avoid this,
we hold a weak reference to the EglDisplay, and use that to clean up
rather than the GLContext.

To support rendering with SWGL, EGLImageTextureHost ensures the
correct preferCompositorSurface, supportsExternalCompositing, and
imageType values are sent to webrender. RenderEGLImageTextureHost now
implements RenderTextureHostSWGL, as well as the new
CreateTextureSource() function, and EGLImageTextureSource is
initialized with a GL context reference so that it may actually work.

Additionally we use eglWaitSync() rather than eglClientWaitSync()
where available for improved performance. And we ensure that we bind
the EGL images' textures to GL_TEXTURE_2D rather than
GL_TEXTURE_EXTERNAL when running on the Android emulator to work
around the buggy implementation in some emulator versions.

Differential Revision: https://phabricator.services.mozilla.com/D211291
This commit is contained in:
Jamie Nicol
2024-07-22 20:23:38 +00:00
parent c5467289a3
commit 4e1b51a92c
11 changed files with 249 additions and 63 deletions

View File

@@ -3578,9 +3578,11 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
#ifdef MOZ_WIDGET_GTK #ifdef MOZ_WIDGET_GTK
return LOCAL_GL_TEXTURE_2D; return LOCAL_GL_TEXTURE_2D;
#else #else
return IsExtensionSupported(OES_EGL_image_external) if (IsExtensionSupported(OES_EGL_image_external) &&
? LOCAL_GL_TEXTURE_EXTERNAL mRenderer != GLRenderer::AndroidEmulator) {
: LOCAL_GL_TEXTURE_2D; return LOCAL_GL_TEXTURE_EXTERNAL;
}
return LOCAL_GL_TEXTURE_2D;
#endif #endif
} }

View File

@@ -69,18 +69,18 @@ SharedSurface_EGLImage::SharedSurface_EGLImage(const SharedSurfaceDesc& desc,
const EGLImage image) const EGLImage image)
: SharedSurface(desc, std::move(fb)), : SharedSurface(desc, std::move(fb)),
mMutex("SharedSurface_EGLImage mutex"), mMutex("SharedSurface_EGLImage mutex"),
mEglDisplay(GLContextEGL::Cast(desc.gl)->mEgl),
mImage(image) {} mImage(image) {}
SharedSurface_EGLImage::~SharedSurface_EGLImage() { SharedSurface_EGLImage::~SharedSurface_EGLImage() {
const auto& gle = GLContextEGL::Cast(mDesc.gl); if (auto display = mEglDisplay.lock()) {
const auto& egl = gle->mEgl; display->fDestroyImage(mImage);
egl->fDestroyImage(mImage);
if (mSync) { if (mSync) {
// We can't call this unless we have the ext, but we will always have // We can't call this unless we have the ext, but we will always have
// the ext if we have something to destroy. // the ext if we have something to destroy.
egl->fDestroySync(mSync); display->fDestroySync(mSync);
mSync = 0; }
} }
} }

View File

@@ -19,6 +19,7 @@
namespace mozilla { namespace mozilla {
namespace gl { namespace gl {
class EglDisplay;
class GLLibraryEGL; class GLLibraryEGL;
// - // -
@@ -27,6 +28,7 @@ class GLLibraryEGL;
class SharedSurface_EGLImage final : public SharedSurface { class SharedSurface_EGLImage final : public SharedSurface {
mutable Mutex mMutex MOZ_UNANNOTATED; mutable Mutex mMutex MOZ_UNANNOTATED;
EGLSync mSync = 0; EGLSync mSync = 0;
const std::weak_ptr<EglDisplay> mEglDisplay;
public: public:
const EGLImage mImage; const EGLImage mImage;

View File

@@ -927,7 +927,9 @@ EGLImageTextureSource::EGLImageTextureSource(TextureSourceProvider* aProvider,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
GLenum aTarget, GLenum aWrapMode, GLenum aTarget, GLenum aWrapMode,
gfx::IntSize aSize) gfx::IntSize aSize)
: mImage(aImage), : mGL(aProvider->GetGLContext()),
mCompositor(aProvider->AsCompositorOGL()),
mImage(aImage),
mFormat(aFormat), mFormat(aFormat),
mTextureTarget(aTarget), mTextureTarget(aTarget),
mWrapMode(aWrapMode), mWrapMode(aWrapMode),
@@ -989,9 +991,8 @@ EGLImageTextureHost::~EGLImageTextureHost() = default;
gl::GLContext* EGLImageTextureHost::gl() const { return nullptr; } gl::GLContext* EGLImageTextureHost::gl() const { return nullptr; }
gfx::SurfaceFormat EGLImageTextureHost::GetFormat() const { gfx::SurfaceFormat EGLImageTextureHost::GetFormat() const {
MOZ_ASSERT(mTextureSource); return mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::R8G8B8X8;
: gfx::SurfaceFormat::UNKNOWN;
} }
void EGLImageTextureHost::CreateRenderTexture( void EGLImageTextureHost::CreateRenderTexture(
@@ -999,7 +1000,7 @@ void EGLImageTextureHost::CreateRenderTexture(
MOZ_ASSERT(mExternalImageId.isSome()); MOZ_ASSERT(mExternalImageId.isSome());
RefPtr<wr::RenderTextureHost> texture = RefPtr<wr::RenderTextureHost> texture =
new wr::RenderEGLImageTextureHost(mImage, mSync, mSize); new wr::RenderEGLImageTextureHost(mImage, mSync, mSize, GetFormat());
wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId, wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId,
texture.forget()); texture.forget());
} }
@@ -1010,11 +1011,18 @@ void EGLImageTextureHost::PushResourceUpdates(
auto method = aOp == TextureHost::ADD_IMAGE auto method = aOp == TextureHost::ADD_IMAGE
? &wr::TransactionBuilder::AddExternalImage ? &wr::TransactionBuilder::AddExternalImage
: &wr::TransactionBuilder::UpdateExternalImage; : &wr::TransactionBuilder::UpdateExternalImage;
auto imageType = wr::ExternalImageType::TextureHandle(
wr::ImageBufferKind::TextureExternal);
gfx::SurfaceFormat format = // Prefer TextureExternal unless the backend requires TextureRect.
mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8; TextureHost::NativeTexturePolicy policy =
TextureHost::BackendNativeTexturePolicy(aResources.GetBackendType(),
GetSize());
auto imageType = policy == TextureHost::NativeTexturePolicy::REQUIRE
? wr::ExternalImageType::TextureHandle(
wr::ImageBufferKind::TextureRect)
: wr::ExternalImageType::TextureHandle(
wr::ImageBufferKind::TextureExternal);
gfx::SurfaceFormat format = GetFormat();
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
// XXX Add RGBA handling. Temporary hack to avoid crash // XXX Add RGBA handling. Temporary hack to avoid crash
@@ -1030,12 +1038,21 @@ void EGLImageTextureHost::PushDisplayItems(
wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds, wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, wr::ImageRendering aFilter, const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
const Range<wr::ImageKey>& aImageKeys, PushDisplayItemFlagSet aFlags) { const Range<wr::ImageKey>& aImageKeys, PushDisplayItemFlagSet aFlags) {
bool preferCompositorSurface =
aFlags.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE);
bool supportsExternalCompositing =
SupportsExternalCompositing(aBuilder.GetBackendType());
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
aBuilder.PushImage( aBuilder.PushImage(aBounds, aClip, true, false, aFilter, aImageKeys[0],
aBounds, aClip, true, false, aFilter, aImageKeys[0], !(mFlags & TextureFlags::NON_PREMULTIPLIED),
!(mFlags & TextureFlags::NON_PREMULTIPLIED), wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f},
wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f}, preferCompositorSurface, supportsExternalCompositing);
aFlags.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE)); }
bool EGLImageTextureHost::SupportsExternalCompositing(
WebRenderBackend aBackend) {
return aBackend == WebRenderBackend::SOFTWARE;
} }
// //

View File

@@ -643,6 +643,8 @@ class EGLImageTextureHost final : public TextureHost {
const Range<wr::ImageKey>& aImageKeys, const Range<wr::ImageKey>& aImageKeys,
PushDisplayItemFlagSet aFlags) override; PushDisplayItemFlagSet aFlags) override;
bool SupportsExternalCompositing(WebRenderBackend aBackend) override;
protected: protected:
const EGLImage mImage; const EGLImage mImage;
const EGLSync mSync; const EGLSync mSync;

View File

@@ -283,7 +283,8 @@ void RenderCompositorLayersSWGL::AttachExternalImage(
image->AsRenderDXGIYCbCrTextureHost()); image->AsRenderDXGIYCbCrTextureHost());
#elif defined(ANDROID) #elif defined(ANDROID)
MOZ_RELEASE_ASSERT(image->AsRenderAndroidHardwareBufferTextureHost() || MOZ_RELEASE_ASSERT(image->AsRenderAndroidHardwareBufferTextureHost() ||
image->AsRenderAndroidSurfaceTextureHost()); image->AsRenderAndroidSurfaceTextureHost() ||
image->AsRenderEGLImageTextureHost());
#endif #endif
auto surfaceCursor = mSurfaces.find(aId); auto surfaceCursor = mSurfaces.find(aId);

View File

@@ -9,16 +9,20 @@
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
#include "GLContextEGL.h" #include "GLContextEGL.h"
#include "GLLibraryEGL.h" #include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "OGLShaderConfig.h"
namespace mozilla { namespace mozilla {
namespace wr { namespace wr {
RenderEGLImageTextureHost::RenderEGLImageTextureHost(EGLImage aImage, RenderEGLImageTextureHost::RenderEGLImageTextureHost(EGLImage aImage,
EGLSync aSync, EGLSync aSync,
gfx::IntSize aSize) gfx::IntSize aSize,
gfx::SurfaceFormat aFormat)
: mImage(aImage), : mImage(aImage),
mSync(aSync), mSync(aSync),
mSize(aSize), mSize(aSize),
mFormat(aFormat),
mTextureTarget(LOCAL_GL_TEXTURE_2D), mTextureTarget(LOCAL_GL_TEXTURE_2D),
mTextureHandle(0) { mTextureHandle(0) {
MOZ_COUNT_CTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHost); MOZ_COUNT_CTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHost);
@@ -35,8 +39,7 @@ wr::WrExternalImage RenderEGLImageTextureHost::Lock(uint8_t aChannelIndex,
if (mGL.get() != aGL) { if (mGL.get() != aGL) {
if (mGL) { if (mGL) {
// This should not happen. SharedSurface_EGLImage is created only in // This should not happen. On android, SingletonGL is used.
// parent process.
MOZ_ASSERT_UNREACHABLE("Unexpected GL context"); MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
return InvalidToWrExternalImage(); return InvalidToWrExternalImage();
} }
@@ -47,35 +50,10 @@ wr::WrExternalImage RenderEGLImageTextureHost::Lock(uint8_t aChannelIndex,
return InvalidToWrExternalImage(); return InvalidToWrExternalImage();
} }
EGLint status = LOCAL_EGL_CONDITION_SATISFIED; if (!WaitSync() || !CreateTextureHandle()) {
if (mSync) {
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
MOZ_ASSERT(egl->IsExtensionSupported(gl::EGLExtension::KHR_fence_sync));
status = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
// We do not need to delete sync here. It is deleted by
// SharedSurface_EGLImage.
mSync = 0;
}
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
MOZ_ASSERT(
status != 0,
"ClientWaitSync generated an error. Has mSync already been destroyed?");
return InvalidToWrExternalImage(); return InvalidToWrExternalImage();
} }
if (!mTextureHandle) {
mTextureTarget = mGL->GetPreferredEGLImageTextureTarget();
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
mGL->fGenTextures(1, &mTextureHandle);
ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget,
mTextureHandle);
mGL->fEGLImageTargetTexture2D(mTextureTarget, mImage);
}
const auto uvs = GetUvCoords(mSize); const auto uvs = GetUvCoords(mSize);
return NativeTextureToWrExternalImage( return NativeTextureToWrExternalImage(
mTextureHandle, uvs.first.x, uvs.first.y, uvs.second.x, uvs.second.y); mTextureHandle, uvs.first.x, uvs.first.y, uvs.second.x, uvs.second.y);
@@ -83,14 +61,162 @@ wr::WrExternalImage RenderEGLImageTextureHost::Lock(uint8_t aChannelIndex,
void RenderEGLImageTextureHost::Unlock() {} void RenderEGLImageTextureHost::Unlock() {}
RefPtr<layers::TextureSource> RenderEGLImageTextureHost::CreateTextureSource(
layers::TextureSourceProvider* aProvider) {
gl::GLContext* gl = aProvider->GetGLContext();
if (mGL.get() != gl) {
if (mGL) {
// This should not happen. On android, SingletonGL is used.
MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
return nullptr;
}
mGL = gl;
}
if (!WaitSync()) {
return nullptr;
}
return new layers::EGLImageTextureSource(
aProvider, mImage, mFormat, gl->GetPreferredEGLImageTextureTarget(),
LOCAL_GL_CLAMP_TO_EDGE, mSize);
}
gfx::SurfaceFormat RenderEGLImageTextureHost::GetFormat() const {
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::R8G8B8A8 ||
mFormat == gfx::SurfaceFormat::R8G8B8X8);
// SWGL does not support RGBA/RGBX so we must provide data in BGRA/BGRX
// format. ReadTexImage() called by MapPlane() will ensure that data gets
// converted correctly.
if (mFormat == gfx::SurfaceFormat::R8G8B8A8) {
return gfx::SurfaceFormat::B8G8R8A8;
}
if (mFormat == gfx::SurfaceFormat::R8G8B8X8) {
return gfx::SurfaceFormat::B8G8R8X8;
}
gfxCriticalNoteOnce << "Unexpected color format of RenderEGLImageTextureHost";
return gfx::SurfaceFormat::UNKNOWN;
}
bool RenderEGLImageTextureHost::MapPlane(RenderCompositor* aCompositor,
uint8_t aChannelIndex,
PlaneInfo& aPlaneInfo) {
RefPtr<gfx::DataSourceSurface> readback = ReadTexImage();
if (!readback) {
return false;
}
gfx::DataSourceSurface::MappedSurface map;
if (!readback->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
return false;
}
mReadback = readback;
aPlaneInfo.mSize = mSize;
aPlaneInfo.mStride = map.mStride;
aPlaneInfo.mData = map.mData;
return true;
}
void RenderEGLImageTextureHost::UnmapPlanes() {
if (mReadback) {
mReadback->Unmap();
mReadback = nullptr;
}
}
bool RenderEGLImageTextureHost::CreateTextureHandle() {
if (mTextureHandle) {
return true;
}
mTextureTarget = mGL->GetPreferredEGLImageTextureTarget();
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
mGL->fGenTextures(1, &mTextureHandle);
ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget,
mTextureHandle);
mGL->fEGLImageTargetTexture2D(mTextureTarget, mImage);
return true;
}
void RenderEGLImageTextureHost::DeleteTextureHandle() { void RenderEGLImageTextureHost::DeleteTextureHandle() {
if (mTextureHandle) { if (mTextureHandle) {
// XXX recycle gl texture, since SharedSurface_EGLImage and if (mGL && mGL->MakeCurrent()) {
// RenderEGLImageTextureHost is not recycled. // XXX recycle gl texture, since SharedSurface_EGLImage and
mGL->fDeleteTextures(1, &mTextureHandle); // RenderEGLImageTextureHost is not recycled.
mGL->fDeleteTextures(1, &mTextureHandle);
}
mTextureHandle = 0; mTextureHandle = 0;
} }
} }
bool RenderEGLImageTextureHost::WaitSync() {
bool syncSucceeded = true;
if (mSync) {
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
MOZ_ASSERT(egl->IsExtensionSupported(gl::EGLExtension::KHR_fence_sync));
if (egl->IsExtensionSupported(gl::EGLExtension::KHR_wait_sync)) {
syncSucceeded = egl->fWaitSync(mSync, 0) == LOCAL_EGL_TRUE;
} else {
syncSucceeded = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER) ==
LOCAL_EGL_CONDITION_SATISFIED;
}
// We do not need to delete sync here. It is deleted by
// SharedSurface_EGLImage.
mSync = 0;
}
MOZ_ASSERT(
syncSucceeded,
"(Client)WaitSync generated an error. Has mSync already been destroyed?");
return syncSucceeded;
}
already_AddRefed<gfx::DataSourceSurface>
RenderEGLImageTextureHost::ReadTexImage() {
if (!mGL) {
mGL = RenderThread::Get()->SingletonGL();
if (!mGL) {
return nullptr;
}
}
if (!WaitSync() || !CreateTextureHandle()) {
return nullptr;
}
// Allocate resulting image surface.
// Use GetFormat() rather than mFormat for the DataSourceSurface. eg BGRA
// rather than RGBA, as the latter is not supported by swgl.
// ReadTexImageHelper will take care of converting the data for us.
const gfx::SurfaceFormat surfFormat = GetFormat();
int32_t stride = mSize.width * BytesPerPixel(surfFormat);
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateDataSourceSurfaceWithStride(mSize, surfFormat,
stride);
if (!surf) {
return nullptr;
}
layers::ShaderConfigOGL config =
layers::ShaderConfigFromTargetAndFormat(mTextureTarget, mFormat);
int shaderConfig = config.mFeatures;
bool ret = mGL->ReadTexImageHelper()->ReadTexImage(
surf, mTextureHandle, mTextureTarget, mSize, shaderConfig,
/* aYInvert */ false);
if (!ret) {
return nullptr;
}
return surf.forget();
}
} // namespace wr } // namespace wr
} // namespace mozilla } // namespace mozilla

View File

@@ -8,7 +8,7 @@
#define MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOST_H #define MOZILLA_GFX_RENDEREGLIMAGETEXTUREHOST_H
#include "mozilla/layers/TextureHostOGL.h" #include "mozilla/layers/TextureHostOGL.h"
#include "RenderTextureHost.h" #include "RenderTextureHostSWGL.h"
namespace mozilla { namespace mozilla {
@@ -16,28 +16,50 @@ namespace wr {
// RenderEGLImageTextureHost is created only for SharedSurface_EGLImage that is // RenderEGLImageTextureHost is created only for SharedSurface_EGLImage that is
// created in parent process. // created in parent process.
class RenderEGLImageTextureHost final : public RenderTextureHost { class RenderEGLImageTextureHost final : public RenderTextureHostSWGL {
public: public:
RenderEGLImageTextureHost(EGLImage aImage, EGLSync aSync, gfx::IntSize aSize); RenderEGLImageTextureHost(EGLImage aImage, EGLSync aSync, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override; wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL) override;
void Unlock() override; void Unlock() override;
size_t Bytes() override { size_t Bytes() override {
// XXX: we don't have a format so we can't get bpp. return mSize.width * mSize.height * BytesPerPixel(mFormat);
return mSize.width * mSize.height;
} }
RenderEGLImageTextureHost* AsRenderEGLImageTextureHost() override {
return this;
}
RefPtr<layers::TextureSource> CreateTextureSource(
layers::TextureSourceProvider* aProvider) override;
// RenderTextureHostSWGL
gfx::SurfaceFormat GetFormat() const override;
gfx::ColorDepth GetColorDepth() const override {
return gfx::ColorDepth::COLOR_8;
}
size_t GetPlaneCount() const override { return 1; };
bool MapPlane(RenderCompositor* aCompositor, uint8_t aChannelIndex,
PlaneInfo& aPlaneInfo) override;
void UnmapPlanes() override;
private: private:
virtual ~RenderEGLImageTextureHost(); virtual ~RenderEGLImageTextureHost();
bool CreateTextureHandle();
void DeleteTextureHandle(); void DeleteTextureHandle();
bool WaitSync();
already_AddRefed<gfx::DataSourceSurface> ReadTexImage();
const EGLImage mImage; const EGLImage mImage;
EGLSync mSync; EGLSync mSync;
const gfx::IntSize mSize; const gfx::IntSize mSize;
const gfx::SurfaceFormat mFormat;
RefPtr<gl::GLContext> mGL; RefPtr<gl::GLContext> mGL;
GLenum mTextureTarget; GLenum mTextureTarget;
GLuint mTextureHandle; GLuint mTextureHandle;
RefPtr<gfx::DataSourceSurface> mReadback;
}; };
} // namespace wr } // namespace wr

View File

@@ -28,6 +28,7 @@ class TextureSourceProvider;
namespace wr { namespace wr {
class RenderEGLImageTextureHost;
class RenderAndroidHardwareBufferTextureHost; class RenderAndroidHardwareBufferTextureHost;
class RenderAndroidSurfaceTextureHost; class RenderAndroidSurfaceTextureHost;
class RenderCompositor; class RenderCompositor;
@@ -104,6 +105,10 @@ class RenderTextureHost {
return nullptr; return nullptr;
} }
virtual RenderEGLImageTextureHost* AsRenderEGLImageTextureHost() {
return nullptr;
}
virtual RenderAndroidHardwareBufferTextureHost* virtual RenderAndroidHardwareBufferTextureHost*
AsRenderAndroidHardwareBufferTextureHost() { AsRenderAndroidHardwareBufferTextureHost() {
return nullptr; return nullptr;

View File

@@ -151,6 +151,14 @@ RenderTextureHostWrapper::AsRenderAndroidSurfaceTextureHost() {
return mTextureHost->AsRenderAndroidSurfaceTextureHost(); return mTextureHost->AsRenderAndroidSurfaceTextureHost();
} }
RenderEGLImageTextureHost*
RenderTextureHostWrapper::AsRenderEGLImageTextureHost() {
if (!mTextureHost) {
return nullptr;
}
return mTextureHost->AsRenderEGLImageTextureHost();
}
RenderTextureHostSWGL* RenderTextureHostWrapper::EnsureRenderTextureHostSWGL() RenderTextureHostSWGL* RenderTextureHostWrapper::EnsureRenderTextureHostSWGL()
const { const {
if (!mTextureHost) { if (!mTextureHost) {

View File

@@ -45,6 +45,7 @@ class RenderTextureHostWrapper final : public RenderTextureHostSWGL {
RenderAndroidHardwareBufferTextureHost* RenderAndroidHardwareBufferTextureHost*
AsRenderAndroidHardwareBufferTextureHost() override; AsRenderAndroidHardwareBufferTextureHost() override;
RenderAndroidSurfaceTextureHost* AsRenderAndroidSurfaceTextureHost() override; RenderAndroidSurfaceTextureHost* AsRenderAndroidSurfaceTextureHost() override;
RenderEGLImageTextureHost* AsRenderEGLImageTextureHost() override;
RenderTextureHostSWGL* AsRenderTextureHostSWGL() override; RenderTextureHostSWGL* AsRenderTextureHostSWGL() override;
void SetIsSoftwareDecodedVideo() override; void SetIsSoftwareDecodedVideo() override;
bool IsSoftwareDecodedVideo() override; bool IsSoftwareDecodedVideo() override;