зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1755381 - Manually connect surface allocators when rendering is (re)initialized. r=agi,aosmond
Rather than lazily attempting to connect the SurfaceAllocator if required whenever the content process tries to allocate a surface, instead give control over the connection to the parent process. Make it connect after the content process has been created, and additionally after rendering has being reinitialized following a GPU process loss. This aligns with how we reconnect various IPDL protocols between content processes and the compositor. This avoids content processes attempting to connect to the GPU process' surface allocator before it has been started, which is important for the next patch in this series where we want to delay restarting the GPU process if the app is in the background. If the content process attempts to allocate a surface inbetween the old connection dying and the new connection being made then it will gracefully fail. If the GPU process dies again whilst the connection is being made then that is okay, a new connection will be made shortly afterwards. Differential Revision: https://phabricator.services.mozilla.com/D139041
This commit is contained in:
Родитель
1b7cfb0901
Коммит
b78abc197a
|
@ -48,6 +48,7 @@
|
|||
#include "SandboxHal.h"
|
||||
#include "SourceSurfaceRawData.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxPlatformFontList.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
|
@ -3053,6 +3054,8 @@ bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
|
|||
std::move(vrBridge), std::move(videoManager),
|
||||
namespaces);
|
||||
|
||||
InitSurfaceAllocator();
|
||||
|
||||
gpm->AddListener(this);
|
||||
|
||||
nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
|
||||
|
@ -3225,6 +3228,28 @@ void ContentParent::OnCompositorUnexpectedShutdown() {
|
|||
Unused << SendReinitRendering(std::move(compositor), std::move(imageBridge),
|
||||
std::move(vrBridge), std::move(videoManager),
|
||||
namespaces);
|
||||
|
||||
InitSurfaceAllocator();
|
||||
}
|
||||
|
||||
void ContentParent::InitSurfaceAllocator() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
nsCOMPtr<nsIEventTarget> launcherThread(GetIPCLauncher());
|
||||
MOZ_ASSERT(launcherThread);
|
||||
|
||||
auto selector = java::GeckoProcessManager::Selector::New(
|
||||
java::GeckoProcessType::CONTENT(), OtherPid());
|
||||
|
||||
bool gpuProcessEnabled = gfx::gfxConfig::IsEnabled(gfx::Feature::GPU_PROCESS);
|
||||
|
||||
launcherThread->Dispatch(NS_NewRunnableFunction(
|
||||
"ContentParent::InitSurfaceAllocator()",
|
||||
[selector = java::GeckoProcessManager::Selector::GlobalRef(selector),
|
||||
gpuProcessEnabled]() {
|
||||
java::GeckoProcessManager::SetChildProcessSurfaceAllocator(
|
||||
selector, gpuProcessEnabled);
|
||||
}));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ContentParent::OnCompositorDeviceReset() {
|
||||
|
|
|
@ -722,6 +722,11 @@ class ContentParent final
|
|||
void OnVarChanged(const GfxVarUpdate& aVar) override;
|
||||
void OnCompositorUnexpectedShutdown() override;
|
||||
|
||||
// Sets the SurfaceAllocator the content process should use to allocate
|
||||
// Surfaces on Android. Ideally this should be done in (Re)InitRendering,
|
||||
// but unfortunately we must go via Java and AIDL rather than IPDL.
|
||||
void InitSurfaceAllocator();
|
||||
|
||||
private:
|
||||
/**
|
||||
* A map of the remote content process type to a list of content parents
|
||||
|
|
|
@ -42,5 +42,12 @@ interface IChildProcess {
|
|||
* Returns the interface that other processes should use to allocate Surfaces to be
|
||||
* consumed by the GPU process. Must only be called for a GPU child process type.
|
||||
*/
|
||||
ISurfaceAllocator getSurfaceAllocator();
|
||||
ISurfaceAllocator getSurfaceAllocatorFromGpuProcess();
|
||||
|
||||
/**
|
||||
* Connects the child process' SurfaceAllocator to the specified RemoteSurfaceAllocator.
|
||||
* Must be called after creating the child process and after rendering has been reinitialized
|
||||
* following the GPU process being killed, to allow the child process to allocate Surfaces.
|
||||
*/
|
||||
oneway void setSurfaceAllocator(in ISurfaceAllocator surfaceAllocator);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,4 @@ import org.mozilla.gecko.gfx.ISurfaceAllocator;
|
|||
|
||||
interface IProcessManager {
|
||||
void getEditableParent(in IGeckoEditableChild child, long contentId, long tabId);
|
||||
// Returns the interface that child processes should use to allocate Surfaces.
|
||||
ISurfaceAllocator getSurfaceAllocator();
|
||||
}
|
||||
|
|
|
@ -9,12 +9,10 @@ import android.os.IBinder;
|
|||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import androidx.annotation.NonNull;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.process.GeckoProcessManager;
|
||||
import org.mozilla.gecko.process.GeckoServiceChildProcess;
|
||||
|
||||
/* package */ final class SurfaceAllocator {
|
||||
public final class SurfaceAllocator {
|
||||
private static final String LOGTAG = "SurfaceAllocator";
|
||||
|
||||
private static ISurfaceAllocator sAllocator;
|
||||
|
@ -23,23 +21,13 @@ import org.mozilla.gecko.process.GeckoServiceChildProcess;
|
|||
// connection to the allocator service.
|
||||
private static final SparseArray<GeckoSurface> sSurfaces = new SparseArray<GeckoSurface>();
|
||||
|
||||
private static synchronized void ensureConnection() {
|
||||
if (sAllocator != null) {
|
||||
return;
|
||||
public static synchronized void connect(final @NonNull ISurfaceAllocator allocator) {
|
||||
if (allocator == null) {
|
||||
throw new IllegalArgumentException("SurfaceAllocator.connect() allocator must be non-null");
|
||||
}
|
||||
|
||||
try {
|
||||
if (GeckoAppShell.isParentProcess()) {
|
||||
sAllocator = GeckoProcessManager.getInstance().getSurfaceAllocator();
|
||||
} else {
|
||||
sAllocator = GeckoServiceChildProcess.getSurfaceAllocator();
|
||||
}
|
||||
|
||||
if (sAllocator == null) {
|
||||
Log.w(LOGTAG, "Failed to connect to RemoteSurfaceAllocator");
|
||||
return;
|
||||
}
|
||||
sAllocator
|
||||
allocator
|
||||
.asBinder()
|
||||
.linkToDeath(
|
||||
new IBinder.DeathRecipient() {
|
||||
|
@ -59,6 +47,7 @@ import org.mozilla.gecko.process.GeckoServiceChildProcess;
|
|||
}
|
||||
},
|
||||
0);
|
||||
sAllocator = allocator;
|
||||
} catch (final RemoteException e) {
|
||||
Log.w(LOGTAG, "Failed to connect to RemoteSurfaceAllocator", e);
|
||||
sAllocator = null;
|
||||
|
@ -69,8 +58,6 @@ import org.mozilla.gecko.process.GeckoServiceChildProcess;
|
|||
public static synchronized GeckoSurface acquireSurface(
|
||||
final int width, final int height, final boolean singleBufferMode) {
|
||||
try {
|
||||
ensureConnection();
|
||||
|
||||
if (sAllocator == null) {
|
||||
Log.w(LOGTAG, "Failed to acquire GeckoSurface: not connected");
|
||||
return null;
|
||||
|
|
|
@ -66,37 +66,6 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
nativeGetEditableParent(child, contentId, tabId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the surface allocator interface to be used by child processes to allocate Surfaces. The
|
||||
* service bound to the returned interface may live in either the GPU process or parent process.
|
||||
*/
|
||||
@Override // IProcessManager
|
||||
public ISurfaceAllocator getSurfaceAllocator() {
|
||||
final GeckoResult<Boolean> gpuReady = GeckoAppShell.ensureGpuProcessReady();
|
||||
|
||||
try {
|
||||
final GeckoResult<ISurfaceAllocator> allocator = new GeckoResult<>();
|
||||
if (gpuReady.poll(1000)) {
|
||||
// The GPU process is enabled and ready, so ask it for its surface allocator.
|
||||
XPCOMEventTarget.runOnLauncherThread(
|
||||
() -> {
|
||||
final Selector selector = new Selector(GeckoProcessType.GPU);
|
||||
final GpuProcessConnection conn =
|
||||
(GpuProcessConnection) INSTANCE.mConnections.getExistingConnection(selector);
|
||||
|
||||
allocator.complete(conn.getSurfaceAllocator());
|
||||
});
|
||||
} else {
|
||||
// The GPU process is disabled, so return the parent process allocator instance.
|
||||
allocator.complete(RemoteSurfaceAllocator.getInstance());
|
||||
}
|
||||
return allocator.poll(100);
|
||||
} catch (final Throwable e) {
|
||||
Log.e(LOGTAG, "Error in getSurfaceAllocator", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static CompositorSurfaceManager getCompositorSurfaceManager() {
|
||||
final Selector selector = new Selector(GeckoProcessType.GPU);
|
||||
|
@ -105,6 +74,43 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
return conn.getCompositorSurfaceManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the specified child process' SurfaceAllocator. Should be called after creating the
|
||||
* child process, and after rendering has been reinitialized following the a GPU process loss, to
|
||||
* allow the child process to allocate Surfaces.
|
||||
*
|
||||
* @param selector Selector identifying the child process to connect.
|
||||
* @param gpuProcessEnabled Whether the GPU process is enabled.
|
||||
*/
|
||||
@WrapForJNI
|
||||
public static void setChildProcessSurfaceAllocator(
|
||||
final Selector selector, final boolean gpuProcessEnabled) {
|
||||
XPCOMEventTarget.assertOnLauncherThread();
|
||||
final ChildConnection conn = INSTANCE.mConnections.getExistingConnection(selector);
|
||||
if (conn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpuProcessEnabled) {
|
||||
// If the GPU process is enabled then attempt to connect the child process to the GPU process'
|
||||
// surface allocator. If the GPU process has died then we may be unable to find the
|
||||
// connection, in which case do nothing - this function will be called again once rendering
|
||||
// has been reinitialized.
|
||||
final Selector gpuSelector = new Selector(GeckoProcessType.GPU);
|
||||
final GpuProcessConnection gpuConn =
|
||||
(GpuProcessConnection) INSTANCE.mConnections.getExistingConnection(gpuSelector);
|
||||
if (gpuConn != null) {
|
||||
conn.setSurfaceAllocator(gpuConn.getSurfaceAllocator());
|
||||
} else {
|
||||
Log.w(LOGTAG, "setSurfaceAllocator called with GPU process enabled but not running");
|
||||
}
|
||||
} else {
|
||||
// If the GPU process is disabled then connect the child process to the parent process'
|
||||
// surface allocator
|
||||
conn.setSurfaceAllocator(RemoteSurfaceAllocator.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
/** Gecko uses this class to uniquely identify a process managed by GeckoProcessManager. */
|
||||
public static final class Selector {
|
||||
private final GeckoProcessType mType;
|
||||
|
@ -245,6 +251,14 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
return GeckoResult.fromValue(null);
|
||||
}
|
||||
|
||||
public void setSurfaceAllocator(final ISurfaceAllocator surfaceAllocator) {
|
||||
try {
|
||||
mChild.setSurfaceAllocator(surfaceAllocator);
|
||||
} catch (final RemoteException e) {
|
||||
Log.w(LOGTAG, "Error calling IChildProcess.setSurfaceAllocator()", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBinderConnected(final IBinder service) {
|
||||
XPCOMEventTarget.assertOnLauncherThread();
|
||||
|
@ -322,7 +336,7 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
@Override
|
||||
protected void onBinderConnected(@NonNull final IChildProcess child) throws RemoteException {
|
||||
mCompositorSurfaceManager = new CompositorSurfaceManager(child.getCompositorSurfaceManager());
|
||||
mSurfaceAllocator = child.getSurfaceAllocator();
|
||||
mSurfaceAllocator = child.getSurfaceAllocatorFromGpuProcess();
|
||||
}
|
||||
|
||||
public CompositorSurfaceManager getCompositorSurfaceManager() {
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.os.ParcelFileDescriptor;
|
|||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.GeckoThread.FileDescriptors;
|
||||
|
@ -22,6 +23,7 @@ import org.mozilla.gecko.IGeckoEditableChild;
|
|||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.gfx.ICompositorSurfaceManager;
|
||||
import org.mozilla.gecko.gfx.ISurfaceAllocator;
|
||||
import org.mozilla.gecko.gfx.SurfaceAllocator;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
public class GeckoServiceChildProcess extends Service {
|
||||
|
@ -163,10 +165,17 @@ public class GeckoServiceChildProcess extends Service {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ISurfaceAllocator getSurfaceAllocator() {
|
||||
Log.e(LOGTAG, "Invalid call to IChildProcess.getSurfaceAllocator for non-GPU process");
|
||||
public ISurfaceAllocator getSurfaceAllocatorFromGpuProcess() {
|
||||
Log.e(
|
||||
LOGTAG,
|
||||
"Invalid call to IChildProcess.getSurfaceAllocatorFromGpuProcess for non-GPU process");
|
||||
throw new AssertionError(
|
||||
"Invalid call to IChildProcess.getSurfaceAllocator for non-GPU process.");
|
||||
"Invalid call to IChildProcess.getSurfaceAllocatorFromGpuProcess for non-GPU process.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSurfaceAllocator(final @NonNull ISurfaceAllocator surfaceAllocator) {
|
||||
SurfaceAllocator.connect(surfaceAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,12 +211,4 @@ public class GeckoServiceChildProcess extends Service {
|
|||
mMemoryController.onLowMemory();
|
||||
super.onLowMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the surface allocator interface that should be used by this process to allocate
|
||||
* Surfaces, for consumption in either the GPU process or parent process.
|
||||
*/
|
||||
public static ISurfaceAllocator getSurfaceAllocator() throws RemoteException {
|
||||
return sProcessManager.getSurfaceAllocator();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class GeckoServiceGpuProcess extends GeckoServiceChildProcess {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ISurfaceAllocator getSurfaceAllocator() {
|
||||
public ISurfaceAllocator getSurfaceAllocatorFromGpuProcess() {
|
||||
return RemoteSurfaceAllocator.getInstance();
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче