FixedSizeSurfaceTexture.java
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.camera.core;
import android.graphics.SurfaceTexture;
import android.os.Build.VERSION_CODES;
import android.util.Size;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
/**
* An implementation of {@link SurfaceTexture} with a fixed default buffer size.
*
* <p>The fixed default buffer size used at construction time cannot be changed through the {@link
* #setDefaultBufferSize(int, int)} method.
*/
final class FixedSizeSurfaceTexture extends SurfaceTexture {
private final Owner mOwner;
// For testing purpose, cannot find a better way to verify super.release() is called.
// SurfaceTexture.isRelease() is not a good way to check since it is not supported in some
// api levels.
@VisibleForTesting
boolean mIsSuperReleased = false;
private static final Owner SELF_OWNER = new Owner() {
@Override
public boolean requestRelease() {
return true;
}
};
/**
* Construct a new SurfaceTexture to stream images to a given OpenGL texture.
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
* @param fixedSize the fixed default buffer size
* @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
FixedSizeSurfaceTexture(int texName, Size fixedSize) {
this(texName, fixedSize, SELF_OWNER);
}
/**
* Construct a new SurfaceTexture to stream images to a given OpenGL texture.
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
* @param fixedSize the fixed default buffer size
* @param owner the {@link Owner} which owns this instance.
* @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
FixedSizeSurfaceTexture(int texName, Size fixedSize, Owner owner) {
super(texName);
super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
mOwner = owner;
}
/**
* Construct a new SurfaceTexture to stream images to a given OpenGL texture.
*
* <p>In single buffered mode the application is responsible for serializing access to the image
* content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
* method must be called before the image content producer takes ownership of the buffer. For
* example, when producing image content with the NDK ANativeWindow_lock and
* ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
* ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
* {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
* frame.
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
* @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
* @param fixedSize the fixed default buffer size
* @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
FixedSizeSurfaceTexture(int texName, boolean singleBufferMode, Size fixedSize) {
super(texName, singleBufferMode);
super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
mOwner = SELF_OWNER;
}
/**
* Construct a new SurfaceTexture to stream images to a given OpenGL texture.
*
* <p>In single buffered mode the application is responsible for serializing access to the image
* content buffer. Each time the image content is to be updated, the {@link #releaseTexImage()}
* method must be called before the image content producer takes ownership of the buffer. For
* example, when producing image content with the NDK ANativeWindow_lock and
* ANativeWindow_unlockAndPost functions, {@link #releaseTexImage()} must be called before each
* ANativeWindow_lock, or that call will fail. When producing image content with OpenGL ES,
* {@link #releaseTexImage()} must be called before the first OpenGL ES function call each
* frame.
*
* <p>Unlike {@link SurfaceTexture(int, boolean)}, which takes an OpenGL texture object name,
* this constructor creates the SurfaceTexture in detached mode. A texture name must be passed
* in using {@link #attachToGLContext} before calling {@link #releaseTexImage()} and producing
* image content using OpenGL ES.
*
* @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
* @param fixedSize the fixed default buffer size
* @throws android.view.Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
@RequiresApi(api = VERSION_CODES.O)
FixedSizeSurfaceTexture(boolean singleBufferMode, Size fixedSize) {
super(singleBufferMode);
super.setDefaultBufferSize(fixedSize.getWidth(), fixedSize.getHeight());
mOwner = SELF_OWNER;
}
/**
* This method has no effect.
*
* <p>Unlike {@link SurfaceTexture}, this method does not affect the default buffer size. The
* default buffer size will remain what it was set to during construction.
*
* @param width ignored width
* @param height ignored height
*/
@Override
public void setDefaultBufferSize(int width, int height) {
// No-op
}
/*
* Overrides the release() to request Owner's permission before releasing it.
*/
@Override
public void release() {
if (mOwner.requestRelease()) {
super.release();
mIsSuperReleased = true;
}
}
/**
* An interface for specifying the ownership of a resource.
*
* It is used in condition that some resource cannot be released by itself and would like to be
* controlled by a OWNER. The resource can only be release()'d when Owner's requestRelease
* returns
* true.
*/
interface Owner {
/** request release permission from owner */
boolean requestRelease();
}
}