зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1453501 - Allow GLContextEGL to be used without a surface r=jgilbert
Right now GLContextProviderEGL requires the widget to have a valid EGLSurface when creating a non-offscreen GLContext. This patch falls back to a dummy pbuffer surface or EGL_NO_SURFACE if supported, allowing the GLContext creation to succeed. This will give us some more flexibility on Android where the widget surface is not always readily available. Additinally, we use the fallback surface any time MakeCurrent() is called without a valid surface. This is needed to allow things like Compositor shutdown when there is no widget surface available. MozReview-Commit-ID: 1kbLIGNiOkV
This commit is contained in:
Родитель
2079f15ee0
Коммит
5c6878f58e
|
@ -117,6 +117,7 @@ public:
|
|||
const EGLConfig mConfig;
|
||||
protected:
|
||||
EGLSurface mSurface;
|
||||
const EGLSurface mFallbackSurface;
|
||||
public:
|
||||
const EGLContext mContext;
|
||||
protected:
|
||||
|
|
|
@ -131,10 +131,35 @@ DestroySurface(EGLSurface oldSurface) {
|
|||
}
|
||||
|
||||
static EGLSurface
|
||||
CreateSurfaceFromNativeWindow(EGLNativeWindowType window, const EGLConfig& config) {
|
||||
EGLSurface newSurface = nullptr;
|
||||
CreateFallbackSurface(const EGLConfig& config)
|
||||
{
|
||||
if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_surfaceless_context)) {
|
||||
// We don't need a PBuffer surface in this case
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
std::vector<EGLint> pbattrs;
|
||||
pbattrs.push_back(LOCAL_EGL_WIDTH); pbattrs.push_back(1);
|
||||
pbattrs.push_back(LOCAL_EGL_HEIGHT); pbattrs.push_back(1);
|
||||
|
||||
for (const auto& cur : kTerminationAttribs) {
|
||||
pbattrs.push_back(cur);
|
||||
}
|
||||
|
||||
EGLSurface surface = sEGLLibrary.fCreatePbufferSurface(EGL_DISPLAY(), config, pbattrs.data());
|
||||
if (!surface) {
|
||||
MOZ_CRASH("Failed to create fallback EGLSurface");
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static EGLSurface
|
||||
CreateSurfaceFromNativeWindow(EGLNativeWindowType window, const EGLConfig& config)
|
||||
{
|
||||
MOZ_ASSERT(window);
|
||||
EGLSurface newSurface = EGL_NO_SURFACE;
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
JNIEnv* const env = jni::GetEnvForThread();
|
||||
ANativeWindow* const nativeWindow = ANativeWindow_fromSurface(
|
||||
|
@ -168,7 +193,6 @@ already_AddRefed<GLContext>
|
|||
GLContextEGLFactory::Create(EGLNativeWindowType aWindow,
|
||||
bool aWebRender)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
nsCString discardFailureId;
|
||||
if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
|
||||
gfxCriticalNote << "Failed to load EGL library 3!";
|
||||
|
@ -193,11 +217,9 @@ GLContextEGLFactory::Create(EGLNativeWindowType aWindow,
|
|||
}
|
||||
}
|
||||
|
||||
EGLSurface surface = mozilla::gl::CreateSurfaceFromNativeWindow(aWindow, config);
|
||||
|
||||
if (!surface) {
|
||||
gfxCriticalNote << "Failed to create EGLSurface!";
|
||||
return nullptr;
|
||||
EGLSurface surface = EGL_NO_SURFACE;
|
||||
if (aWindow) {
|
||||
surface = mozilla::gl::CreateSurfaceFromNativeWindow(aWindow, config);
|
||||
}
|
||||
|
||||
CreateContextFlags flags = CreateContextFlags::NONE;
|
||||
|
@ -228,6 +250,7 @@ GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
|||
: GLContext(flags, caps, nullptr, isOffscreen, false)
|
||||
, mConfig(config)
|
||||
, mSurface(surface)
|
||||
, mFallbackSurface(CreateFallbackSurface(config))
|
||||
, mContext(context)
|
||||
, mSurfaceOverride(EGL_NO_SURFACE)
|
||||
, mThebesSurface(nullptr)
|
||||
|
@ -259,6 +282,7 @@ GLContextEGL::~GLContextEGL()
|
|||
sEGLLibrary.fDestroyContext(EGL_DISPLAY(), mContext);
|
||||
|
||||
mozilla::gl::DestroySurface(mSurface);
|
||||
mozilla::gl::DestroySurface(mFallbackSurface);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -356,8 +380,12 @@ GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
|
|||
bool
|
||||
GLContextEGL::MakeCurrentImpl() const
|
||||
{
|
||||
const EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
|
||||
: mSurface;
|
||||
EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
|
||||
: mSurface;
|
||||
if (!surface) {
|
||||
surface = mFallbackSurface;
|
||||
}
|
||||
|
||||
const bool succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), surface, surface,
|
||||
mContext);
|
||||
if (!succeeded) {
|
||||
|
@ -391,10 +419,16 @@ GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
|
|||
// If we get here, then by definition we know that we want to get a new surface.
|
||||
ReleaseSurface();
|
||||
MOZ_ASSERT(aWidget);
|
||||
mSurface = mozilla::gl::CreateSurfaceFromNativeWindow(GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget), mConfig);
|
||||
if (!mSurface) {
|
||||
return false;
|
||||
|
||||
void* nativeWindow = GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget);
|
||||
if (nativeWindow) {
|
||||
mSurface = mozilla::gl::CreateSurfaceFromNativeWindow(nativeWindow, mConfig);
|
||||
if (!mSurface) {
|
||||
NS_WARNING("Failed to create EGLSurface from native window");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return MakeCurrent(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ static const char* sEGLExtensionNames[] = {
|
|||
"EGL_ANGLE_stream_producer_d3d_texture",
|
||||
"EGL_ANGLE_device_creation",
|
||||
"EGL_ANGLE_device_creation_d3d11",
|
||||
"EGL_KHR_surfaceless_context"
|
||||
};
|
||||
|
||||
#if defined(ANDROID)
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
* IsExtensionSupported. The results of this are cached, and as
|
||||
* such it's safe to use this even in performance critical code.
|
||||
* If you add to this array, remember to add to the string names
|
||||
* in GLContext.cpp.
|
||||
* in GLLibraryEGL.cpp.
|
||||
*/
|
||||
enum EGLExtensions {
|
||||
KHR_image_base,
|
||||
|
@ -99,6 +99,7 @@ public:
|
|||
ANGLE_stream_producer_d3d_texture,
|
||||
ANGLE_device_creation,
|
||||
ANGLE_device_creation_d3d11,
|
||||
KHR_surfaceless_context,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче