Expose getSurfaceTransformHint API

The transform hint can be used by a buffer producer to pre-rotate
the rendering such that the final transformation in the system
composer is identity. This can be very useful when used in
conjunction with the h/w composer HAL in situations where it cannot
handle rotations or handle them with an additional power cost.

Bug: 196167822
Test: atest AttachedSurfaceControlTest
Change-Id: Idb7fcf58ecbcc22cd43c226ee4faad958c265e72
This commit is contained in:
Vishnu Nair
2021-09-20 08:52:50 -07:00
parent bc617435cf
commit 1f19e1141e
3 changed files with 116 additions and 1 deletions

View File

@@ -46890,8 +46890,15 @@ package android.view {
}
@UiThread public interface AttachedSurfaceControl {
method public default void addOnSurfaceTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnSurfaceTransformHintChangedListener);
method public boolean applyTransactionOnDraw(@NonNull android.view.SurfaceControl.Transaction);
method @Nullable public android.view.SurfaceControl.Transaction buildReparentTransaction(@NonNull android.view.SurfaceControl);
method public default int getSurfaceTransformHint();
method public default void removeOnSurfaceTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnSurfaceTransformHintChangedListener);
}
@UiThread public static interface AttachedSurfaceControl.OnSurfaceTransformHintChangedListener {
method public void onSurfaceTransformHintChanged(int);
}
public final class Choreographer {

View File

@@ -53,4 +53,72 @@ public interface AttachedSurfaceControl {
* to the View hierarchy you may need to call {@link android.view.View#invalidate}
*/
boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t);
/**
* The transform hint can be used by a buffer producer to pre-rotate the rendering such that the
* final transformation in the system composer is identity. This can be very useful when used in
* conjunction with the h/w composer HAL in situations where it cannot handle rotations or
* handle them with an additional power cost.
*
* The transform hint should be used with ASurfaceControl APIs when submitting buffers.
* Example usage:
*
* 1. After a configuration change, before dequeuing a buffer, the buffer producer queries the
* function for the transform hint.
*
* 2. The desired buffer width and height is rotated by the transform hint.
*
* 3. The producer dequeues a buffer of the new pre-rotated size.
*
* 4. The producer renders to the buffer such that the image is already transformed, that is
* applying the transform hint to the rendering.
*
* 5. The producer applies the inverse transform hint to the buffer it just rendered.
*
* 6. The producer queues the pre-transformed buffer with the buffer transform.
*
* 7. The composer combines the buffer transform with the display transform. If the buffer
* transform happens to cancel out the display transform then no rotation is needed and there
* will be no performance penalties.
*
* Note, when using ANativeWindow APIs in conjunction with a NativeActivity Surface or
* SurfaceView Surface, the buffer producer will already have access to the transform hint and
* no additional work is needed.
*/
default @Surface.Rotation int getSurfaceTransformHint() {
return Surface.ROTATION_0;
}
/**
* Surface transform hint change listener.
* @see #getSurfaceTransformHint
*/
@UiThread
interface OnSurfaceTransformHintChangedListener {
/**
* @param hint new surface transform hint
* @see #getSurfaceTransformHint
*/
void onSurfaceTransformHintChanged(@Surface.Rotation int hint);
}
/**
* Registers a surface transform hint changed listener to receive notifications about when
* the transform hint changes.
*
* @see #getSurfaceTransformHint
* @see #removeOnSurfaceTransformHintChangedListener
*/
default void addOnSurfaceTransformHintChangedListener(
@NonNull OnSurfaceTransformHintChangedListener listener) {
}
/**
* Unregisters a surface transform hint changed listener.
*
* @see #addOnSurfaceTransformHintChangedListener
*/
default void removeOnSurfaceTransformHintChangedListener(
@NonNull OnSurfaceTransformHintChangedListener listener) {
}
}

View File

@@ -312,6 +312,9 @@ public final class ViewRootImpl implements ViewParent,
static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<>();
static boolean sFirstDrawComplete = false;
private ArrayList<OnSurfaceTransformHintChangedListener> mTransformHintListeners =
new ArrayList<>();
private @Surface.Rotation int mPreviousTransformHint = Surface.ROTATION_0;
/**
* Callback for notifying about global configuration changes.
*/
@@ -7824,6 +7827,11 @@ public final class ViewRootImpl implements ViewParent,
}
mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl);
}
int transformHint = mSurfaceControl.getTransformHint();
if (mPreviousTransformHint != transformHint) {
mPreviousTransformHint = transformHint;
dispatchTransformHintChanged(transformHint);
}
} else {
destroySurface();
}
@@ -10447,7 +10455,39 @@ public final class ViewRootImpl implements ViewParent,
return true;
}
int getSurfaceTransformHint() {
@Override
public @Surface.Rotation int getSurfaceTransformHint() {
return mSurfaceControl.getTransformHint();
}
@Override
public void addOnSurfaceTransformHintChangedListener(
OnSurfaceTransformHintChangedListener listener) {
Objects.requireNonNull(listener);
if (mTransformHintListeners.contains(listener)) {
throw new IllegalArgumentException(
"attempt to call addOnSurfaceTransformHintChangedListener() "
+ "with a previously registered listener");
}
mTransformHintListeners.add(listener);
}
@Override
public void removeOnSurfaceTransformHintChangedListener(
OnSurfaceTransformHintChangedListener listener) {
Objects.requireNonNull(listener);
mTransformHintListeners.remove(listener);
}
private void dispatchTransformHintChanged(@Surface.Rotation int hint) {
if (mTransformHintListeners.isEmpty()) {
return;
}
ArrayList<OnSurfaceTransformHintChangedListener> listeners =
(ArrayList<OnSurfaceTransformHintChangedListener>) mTransformHintListeners.clone();
for (int i = 0; i < listeners.size(); i++) {
OnSurfaceTransformHintChangedListener listener = listeners.get(i);
listener.onSurfaceTransformHintChanged(hint);
}
}
}