From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../org/mozilla/gecko/gfx/SurfaceAllocator.java | 139 +++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java') diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java new file mode 100644 index 0000000000..f3cca81a81 --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java @@ -0,0 +1,139 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.gfx; + +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; +import android.util.LongSparseArray; +import org.mozilla.gecko.GeckoAppShell; +import org.mozilla.gecko.annotation.WrapForJNI; +import org.mozilla.gecko.process.GeckoProcessManager; +import org.mozilla.gecko.process.GeckoServiceChildProcess; + +/* package */ final class SurfaceAllocator { + private static final String LOGTAG = "SurfaceAllocator"; + + private static ISurfaceAllocator sAllocator; + + // Keep a reference to all allocated Surfaces, so that we can release them if we lose the + // connection to the allocator service. + private static final LongSparseArray sSurfaces = + new LongSparseArray(); + + private static synchronized void ensureConnection() { + if (sAllocator != null) { + return; + } + + 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 + .asBinder() + .linkToDeath( + new IBinder.DeathRecipient() { + @Override + public void binderDied() { + Log.w(LOGTAG, "RemoteSurfaceAllocator died"); + synchronized (SurfaceAllocator.class) { + // Our connection to the remote allocator has died, so all our surfaces are + // invalid. Release them all now. When their owners attempt to render in to + // them they can detect they have been released and allocate new ones instead. + for (int i = 0; i < sSurfaces.size(); i++) { + sSurfaces.valueAt(i).release(); + } + sSurfaces.clear(); + sAllocator = null; + } + } + }, + 0); + } catch (final RemoteException e) { + Log.w(LOGTAG, "Failed to connect to RemoteSurfaceAllocator", e); + sAllocator = null; + } + } + + @WrapForJNI + 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; + } + + final GeckoSurface surface = sAllocator.acquireSurface(width, height, singleBufferMode); + if (surface == null) { + Log.w(LOGTAG, "Failed to acquire GeckoSurface: RemoteSurfaceAllocator returned null"); + return null; + } + sSurfaces.put(surface.getHandle(), surface); + + if (!surface.inProcess()) { + final SyncConfig config = surface.initSyncSurface(width, height); + if (config != null) { + sAllocator.configureSync(config); + } + } + return surface; + } catch (final RemoteException e) { + Log.w(LOGTAG, "Failed to acquire GeckoSurface", e); + return null; + } + } + + @WrapForJNI + public static synchronized void disposeSurface(final GeckoSurface surface) { + // If the surface has already been released (probably due to losing connection to the remote + // allocator) then there is nothing to do here. + if (surface.isReleased()) { + return; + } + + sSurfaces.remove(surface.getHandle()); + + // Release our Surface + surface.release(); + + if (sAllocator == null) { + return; + } + + // Release the SurfaceTexture on the other side. If we have lost connection then do nothing, as + // there is nothing on the other side to release. + try { + if (sAllocator != null) { + sAllocator.releaseSurface(surface.getHandle()); + } + } catch (final RemoteException e) { + Log.w(LOGTAG, "Failed to release surface texture", e); + } + } + + public static synchronized void sync(final long upstream) { + // Sync from the SurfaceTexture on the other side. If we have lost connection then do nothing, + // as there is nothing on the other side to sync from. + try { + if (sAllocator != null) { + sAllocator.sync(upstream); + } + } catch (final RemoteException e) { + Log.w(LOGTAG, "Failed to sync texture", e); + } + } +} -- cgit v1.2.3