summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java')
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java
new file mode 100644
index 0000000000..7cf891aa59
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurface.java
@@ -0,0 +1,152 @@
+/* -*- 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 static org.mozilla.geckoview.BuildConfig.DEBUG_BUILD;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Surface;
+import org.mozilla.gecko.annotation.WrapForJNI;
+
+public final class GeckoSurface implements Parcelable {
+ private static final String LOGTAG = "GeckoSurface";
+
+ private Surface mSurface;
+ private long mHandle;
+ private boolean mIsSingleBuffer;
+ private volatile boolean mIsAvailable;
+ private boolean mOwned = true;
+ private volatile boolean mIsReleased = false;
+
+ private int mMyPid;
+ // Locally allocated surface/texture. Do not pass it over IPC.
+ private GeckoSurface mSyncSurface;
+
+ @WrapForJNI(exceptionMode = "nsresult")
+ public GeckoSurface(final GeckoSurfaceTexture gst) {
+ mSurface = new Surface(gst);
+ mHandle = gst.getHandle();
+ mIsSingleBuffer = gst.isSingleBuffer();
+ mIsAvailable = true;
+ mMyPid = android.os.Process.myPid();
+ }
+
+ public GeckoSurface(final Parcel p) {
+ mSurface = Surface.CREATOR.createFromParcel(p);
+ mHandle = p.readLong();
+ mIsSingleBuffer = p.readByte() == 1 ? true : false;
+ mIsAvailable = (p.readByte() == 1 ? true : false);
+ mMyPid = p.readInt();
+ }
+
+ public static final Parcelable.Creator<GeckoSurface> CREATOR =
+ new Parcelable.Creator<GeckoSurface>() {
+ public GeckoSurface createFromParcel(final Parcel p) {
+ return new GeckoSurface(p);
+ }
+
+ public GeckoSurface[] newArray(final int size) {
+ return new GeckoSurface[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(final Parcel out, final int flags) {
+ mSurface.writeToParcel(out, flags);
+ if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) == 0) {
+ // GeckoSurface can be passed across processes as a return value or
+ // an argument, and should always tranfers its ownership (move) to
+ // the receiver of parcel. On the other hand, Surface is moved only
+ // when passed as a return value and releases itself when corresponding
+ // write flags is provided. (See Surface.writeToParcel().)
+ // The superclass method must be called here to ensure the local instance
+ // is truely forgotten.
+ mSurface.release();
+ }
+ mOwned = false;
+
+ out.writeLong(mHandle);
+ out.writeByte((byte) (mIsSingleBuffer ? 1 : 0));
+ out.writeByte((byte) (mIsAvailable ? 1 : 0));
+ out.writeInt(mMyPid);
+ }
+
+ public void release() {
+ if (mIsReleased) {
+ return;
+ }
+ mIsReleased = true;
+
+ if (mSyncSurface != null) {
+ mSyncSurface.release();
+ final GeckoSurfaceTexture gst = GeckoSurfaceTexture.lookup(mSyncSurface.getHandle());
+ if (gst != null) {
+ gst.decrementUse();
+ }
+ mSyncSurface = null;
+ }
+
+ if (mOwned) {
+ mSurface.release();
+ }
+ }
+
+ @WrapForJNI
+ public long getHandle() {
+ return mHandle;
+ }
+
+ @WrapForJNI
+ public Surface getSurface() {
+ return mSurface;
+ }
+
+ @WrapForJNI
+ public boolean getAvailable() {
+ return mIsAvailable;
+ }
+
+ @WrapForJNI
+ public boolean isReleased() {
+ return mIsReleased;
+ }
+
+ @WrapForJNI
+ public void setAvailable(final boolean available) {
+ mIsAvailable = available;
+ }
+
+ /* package */ boolean inProcess() {
+ return android.os.Process.myPid() == mMyPid;
+ }
+
+ /* package */ SyncConfig initSyncSurface(final int width, final int height) {
+ if (DEBUG_BUILD) {
+ if (inProcess()) {
+ throw new AssertionError("no need for sync when allocated in process");
+ }
+ }
+ if (GeckoSurfaceTexture.lookup(mHandle) != null) {
+ throw new AssertionError("texture#" + mHandle + " already in use.");
+ }
+ final GeckoSurfaceTexture texture =
+ GeckoSurfaceTexture.acquire(GeckoSurfaceTexture.isSingleBufferSupported(), mHandle);
+ if (texture != null) {
+ texture.setDefaultBufferSize(width, height);
+ texture.track(mHandle);
+ mSyncSurface = new GeckoSurface(texture);
+ return new SyncConfig(mHandle, mSyncSurface, width, height);
+ }
+
+ return null;
+ }
+}