Bug 1762424 - Provide SurfaceControl to compositor and render in to child Surface. r=agi,gfx-reviewers,geckoview-reviewers,jrmuizel,owlish

This adds new version of the GeckoView API
GeckoDisplay.surfaceChanged(), which takes a single argument of a new
type GeckoDisplay.SurfaceInfo. As well as containing fields for each
the the existing surfaceChanged() arguments, this has an additional
SurfaceControl field. This must be provided when rendering in to a
SurfaceView on SDK level 29 or greater. On earlier SDK levels, or when
rendering in to a TextureView or SurfaceTexture, this can be
null. SurfaceViewWrapper and GeckoView classes are updated to handle
this correctly. The old surfaceChanged() methods have been deprecated,
and tests have been updated to use the new version.

When provided, the SurfaceControl is passed along with the Surface
through to the widget and, when enabled, over to the GPU process. The
compositor widget then creates a child Surface from that
SurfaceControl, and renders in to that child Surface rather than the
parent one.

This works around a bug on Android 12 where following the GPU process
dying the Surface was left in an unusable state, meaning subsequent
attempts to initialize a compositor would fail. Because the Surface is
now created by the GPU process it gets destroyed when the process
dies, therefore a new Surface can successfully be created when we
reinitialize the compositor.

Differential Revision: https://phabricator.services.mozilla.com/D143485
This commit is contained in:
Jamie Nicol
2022-04-18 18:11:07 +00:00
parent ead3d232db
commit 8894f23f51
20 changed files with 303 additions and 66 deletions

View File

@@ -889,6 +889,7 @@ class LayerViewSupport final
GeckoSession::Compositor::WeakRef mCompositor;
Atomic<bool, ReleaseAcquire> mCompositorPaused;
java::sdk::Surface::GlobalRef mSurface;
java::sdk::SurfaceControl::GlobalRef mSurfaceControl;
// Used to communicate with the gecko compositor from the UI thread.
// Set in NotifyCompositorCreated and cleared in NotifyCompositorSessionLost.
RefPtr<UiCompositorControllerChild> mUiCompositorControllerChild;
@@ -1013,7 +1014,7 @@ class LayerViewSupport final
nsWindow* gkWindow = window->GetNsWindow();
if (gkWindow) {
mUiCompositorControllerChild->OnCompositorSurfaceChanged(
gkWindow->mWidgetId, mSurface);
gkWindow->mWidgetId, mSurface, mSurfaceControl);
}
}
@@ -1047,6 +1048,9 @@ class LayerViewSupport final
}
java::sdk::Surface::Param GetSurface() { return mSurface; }
java::sdk::SurfaceControl::Param GetSurfaceControl() {
return mSurfaceControl;
}
private:
already_AddRefed<DataSourceSurface> FlipScreenPixels(
@@ -1193,10 +1197,20 @@ class LayerViewSupport final
void SyncResumeResizeCompositor(
const GeckoSession::Compositor::LocalRef& aObj, int32_t aX, int32_t aY,
int32_t aWidth, int32_t aHeight, jni::Object::Param aSurface) {
int32_t aWidth, int32_t aHeight, jni::Object::Param aSurface,
jni::Object::Param aSurfaceControl) {
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
mSurface = java::sdk::Surface::GlobalRef::From(aSurface);
mSurfaceControl =
java::sdk::SurfaceControl::GlobalRef::From(aSurfaceControl);
if (mSurfaceControl) {
// Setting the SurfaceControl's buffer size here ensures child Surfaces
// created by the compositor have the correct size.
java::sdk::SurfaceControl::Transaction::LocalRef transaction =
java::sdk::SurfaceControl::Transaction::New();
transaction->SetBufferSize(mSurfaceControl, aWidth, aHeight)->Apply();
}
if (mUiCompositorControllerChild) {
if (auto window = mWindow.Access()) {
@@ -1204,7 +1218,7 @@ class LayerViewSupport final
if (gkWindow) {
// Send new Surface to GPU process, if one exists.
mUiCompositorControllerChild->OnCompositorSurfaceChanged(
gkWindow->mWidgetId, mSurface);
gkWindow->mWidgetId, mSurface, mSurfaceControl);
}
}
@@ -2386,6 +2400,13 @@ void* nsWindow::GetNativeData(uint32_t aDataType) {
return lvs->GetSurface().Get();
}
return nullptr;
case NS_JAVA_SURFACE_CONTROL:
if (::mozilla::jni::NativeWeakPtr<LayerViewSupport>::Accessor lvs{
mLayerViewSupport.Access()}) {
return lvs->GetSurfaceControl().Get();
}
return nullptr;
}
return nullptr;