1628 lines
62 KiB
Java
1628 lines
62 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2018 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 android.graphics;
|
||
|
|
||
|
import android.annotation.FloatRange;
|
||
|
import android.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.app.Activity;
|
||
|
import android.app.ActivityManager;
|
||
|
import android.content.Context;
|
||
|
import android.content.pm.ActivityInfo;
|
||
|
import android.content.res.Configuration;
|
||
|
import android.hardware.DataSpace;
|
||
|
import android.hardware.HardwareBuffer;
|
||
|
import android.hardware.OverlayProperties;
|
||
|
import android.hardware.display.DisplayManager;
|
||
|
import android.os.IBinder;
|
||
|
import android.os.ParcelFileDescriptor;
|
||
|
import android.os.RemoteException;
|
||
|
import android.os.ServiceManager;
|
||
|
import android.util.Log;
|
||
|
import android.util.TimeUtils;
|
||
|
import android.view.Display;
|
||
|
import android.view.Display.Mode;
|
||
|
import android.view.IGraphicsStats;
|
||
|
import android.view.IGraphicsStatsCallback;
|
||
|
import android.view.NativeVectorDrawableAnimator;
|
||
|
import android.view.PixelCopy;
|
||
|
import android.view.Surface;
|
||
|
import android.view.SurfaceControl;
|
||
|
import android.view.SurfaceHolder;
|
||
|
import android.view.animation.AnimationUtils;
|
||
|
|
||
|
import java.io.File;
|
||
|
import java.io.FileDescriptor;
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
import java.util.concurrent.Executor;
|
||
|
|
||
|
import sun.misc.Cleaner;
|
||
|
|
||
|
/**
|
||
|
* <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
|
||
|
* from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
|
||
|
* HardwareRenderer instances as desired.</p>
|
||
|
*
|
||
|
* <h3>Resources & lifecycle</h3>
|
||
|
*
|
||
|
* <p>All HardwareRenderer instances share a common render thread. The render thread contains
|
||
|
* the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
|
||
|
* HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
|
||
|
* however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
|
||
|
* is to have a HardwareRenderer instance for every active {@link Surface}. For example
|
||
|
* when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
|
||
|
* of which may be drawing at the same time.</p>
|
||
|
*
|
||
|
* <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
|
||
|
* any {@link Surface} used must have a prompt, reliable consuming side. System-provided
|
||
|
* consumers such as {@link android.view.SurfaceView},
|
||
|
* {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
|
||
|
* or {@link android.view.TextureView} all fit this requirement. However if custom consumers
|
||
|
* are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
|
||
|
* it is the app's responsibility to ensure that they consume updates promptly and rapidly.
|
||
|
* Failure to do so will cause the render thread to stall on that surface, blocking all
|
||
|
* HardwareRenderer instances.</p>
|
||
|
*/
|
||
|
public class HardwareRenderer {
|
||
|
private static final String LOG_TAG = "HardwareRenderer";
|
||
|
|
||
|
// Keep in sync with DrawFrameTask.h SYNC_* flags
|
||
|
/**
|
||
|
* Nothing interesting to report. Sync & draw kicked off
|
||
|
*/
|
||
|
public static final int SYNC_OK = 0;
|
||
|
|
||
|
/**
|
||
|
* The renderer is requesting a redraw. This can occur if there's an animation that's running
|
||
|
* in the RenderNode tree and the hardware renderer is unable to self-animate.
|
||
|
*
|
||
|
* <p>If this is returned from syncAndDraw the expectation is that syncAndDraw
|
||
|
* will be called again on the next vsync signal.
|
||
|
*/
|
||
|
public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
|
||
|
|
||
|
/**
|
||
|
* The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
|
||
|
* This can happen if {@link Surface#release()} was called. The user should no longer
|
||
|
* attempt to call syncAndDraw until a new surface has been provided by calling
|
||
|
* setSurface.
|
||
|
*
|
||
|
* <p>Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
|
||
|
*/
|
||
|
public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
|
||
|
|
||
|
/**
|
||
|
* The hardware renderer has been set to a "stopped" state. If this is returned then the
|
||
|
* rendering content has been synced, however a frame was not produced.
|
||
|
*/
|
||
|
public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
|
||
|
|
||
|
/**
|
||
|
* The content was synced but the renderer has declined to produce a frame in this vsync
|
||
|
* interval. This can happen if a frame was already drawn in this vsync or if the renderer
|
||
|
* is outrunning the frame consumer. The renderer will internally re-schedule itself
|
||
|
* to render a frame in the next vsync signal, so the caller does not need to do anything
|
||
|
* in response to this signal.
|
||
|
*/
|
||
|
public static final int SYNC_FRAME_DROPPED = 1 << 3;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(value = {
|
||
|
SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
|
||
|
SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface SyncAndDrawResult {
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
|
||
|
/** @hide */
|
||
|
public static final int FLAG_DUMP_RESET = 1 << 1;
|
||
|
/** @hide */
|
||
|
public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
|
||
|
FLAG_DUMP_FRAMESTATS,
|
||
|
FLAG_DUMP_RESET
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface DumpFlags {
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Trims all Skia caches.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int CACHE_TRIM_ALL = 0;
|
||
|
/**
|
||
|
* Trims Skia font caches.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int CACHE_TRIM_FONT = 1;
|
||
|
/**
|
||
|
* Trims Skia resource caches.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final int CACHE_TRIM_RESOURCES = 2;
|
||
|
|
||
|
/** @hide */
|
||
|
@IntDef(prefix = {"CACHE_TRIM_"}, value = {
|
||
|
CACHE_TRIM_ALL,
|
||
|
CACHE_TRIM_FONT,
|
||
|
CACHE_TRIM_RESOURCES
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface CacheTrimLevel {}
|
||
|
|
||
|
/**
|
||
|
* Name of the file that holds the shaders cache.
|
||
|
*/
|
||
|
private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
|
||
|
private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
|
||
|
|
||
|
private static int sDensityDpi = 0;
|
||
|
|
||
|
private final long mNativeProxy;
|
||
|
/** @hide */
|
||
|
protected RenderNode mRootNode;
|
||
|
private boolean mOpaque = true;
|
||
|
private int mForceDark = ForceDarkType.NONE;
|
||
|
private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT;
|
||
|
private float mDesiredSdrHdrRatio = 1f;
|
||
|
|
||
|
/**
|
||
|
* Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
|
||
|
* to opaque with no light source configured.
|
||
|
*/
|
||
|
public HardwareRenderer() {
|
||
|
ProcessInitializer.sInstance.initUsingContext();
|
||
|
mRootNode = RenderNode.adopt(nCreateRootRenderNode());
|
||
|
mRootNode.setClipToBounds(false);
|
||
|
mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
|
||
|
if (mNativeProxy == 0) {
|
||
|
throw new OutOfMemoryError("Unable to create hardware renderer");
|
||
|
}
|
||
|
Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
|
||
|
ProcessInitializer.sInstance.init(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destroys the rendering context of this HardwareRenderer. This destroys the resources
|
||
|
* associated with this renderer and releases the currently set {@link Surface}. This must
|
||
|
* be called when this HardwareRenderer is no longer needed.
|
||
|
*
|
||
|
* <p>The renderer may be restored from this state by setting a new {@link Surface}, setting
|
||
|
* new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
|
||
|
* rendering by issuing a new {@link FrameRenderRequest}.
|
||
|
*
|
||
|
* <p>It is recommended to call this in response to callbacks such as
|
||
|
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
|
||
|
*
|
||
|
* <p>Note that if there are any outstanding frame commit callbacks they may never being
|
||
|
* invoked if the frame was deferred to a later vsync.
|
||
|
*/
|
||
|
public void destroy() {
|
||
|
nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets a name for this renderer. This is used to identify this renderer instance
|
||
|
* when reporting debug information such as the per-window frame time metrics
|
||
|
* reported by 'adb shell dumpsys gfxinfo [package] framestats'
|
||
|
*
|
||
|
* @param name The debug name to use for this HardwareRenderer instance
|
||
|
*/
|
||
|
public void setName(@NonNull String name) {
|
||
|
nSetName(mNativeProxy, name);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the center of the light source. The light source point controls the directionality
|
||
|
* and shape of shadows rendered by RenderNode Z & elevation.
|
||
|
*
|
||
|
* <p>The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
|
||
|
* lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
|
||
|
*
|
||
|
* <p>The light source should be setup both as part of initial configuration, and whenever
|
||
|
* the window moves to ensure the light source stays anchored in display space instead
|
||
|
* of in window space.
|
||
|
*
|
||
|
* <p>This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
|
||
|
* before shadows will work.
|
||
|
*
|
||
|
* @param lightX The X position of the light source
|
||
|
* @param lightY The Y position of the light source
|
||
|
* @param lightZ The Z position of the light source. Must be >= 0.
|
||
|
* @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
|
||
|
* larger radius will have softer shadows.
|
||
|
*/
|
||
|
public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
|
||
|
float lightRadius) {
|
||
|
validateFinite(lightX, "lightX");
|
||
|
validateFinite(lightY, "lightY");
|
||
|
validatePositive(lightZ, "lightZ");
|
||
|
validatePositive(lightRadius, "lightRadius");
|
||
|
nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
|
||
|
* has max alpha, and ramps down from the values provided to zero.
|
||
|
*
|
||
|
* <p>These values are typically provided by the current theme, see
|
||
|
* {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
|
||
|
*
|
||
|
* <p>This must be set at least once along with
|
||
|
* {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
|
||
|
*
|
||
|
* @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
|
||
|
* is 0.039f.
|
||
|
* @param spotShadowAlpha The alpha for the spot shadow. If unsure, a reasonable default is
|
||
|
* 0.19f.
|
||
|
*/
|
||
|
public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
|
||
|
@FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
|
||
|
validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
|
||
|
validateAlpha(spotShadowAlpha, "spotShadowAlpha");
|
||
|
nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the content root to render. It is not necessary to call this whenever the content
|
||
|
* recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
|
||
|
* contained within the content node, will be applied whenever a new {@link FrameRenderRequest}
|
||
|
* is issued via {@link #createRenderRequest()} and {@link FrameRenderRequest#syncAndDraw()}.
|
||
|
*
|
||
|
* @param content The content to set as the root RenderNode. If null the content root is removed
|
||
|
* and the renderer will draw nothing.
|
||
|
*/
|
||
|
public void setContentRoot(@Nullable RenderNode content) {
|
||
|
RecordingCanvas canvas = mRootNode.beginRecording();
|
||
|
if (content != null) {
|
||
|
canvas.drawRenderNode(content);
|
||
|
}
|
||
|
mRootNode.endRecording();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* <p>The surface to render into. The surface is assumed to be associated with the display and
|
||
|
* as such is still driven by vsync signals such as those from
|
||
|
* {@link android.view.Choreographer} and that it has a native refresh rate matching that of
|
||
|
* the display's (typically 60hz).</p>
|
||
|
*
|
||
|
* <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
|
||
|
* any {@link Surface} used must have a prompt, reliable consuming side. System-provided
|
||
|
* consumers such as {@link android.view.SurfaceView},
|
||
|
* {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
|
||
|
* or {@link android.view.TextureView} all fit this requirement. However if custom consumers
|
||
|
* are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
|
||
|
* it is the app's responsibility to ensure that they consume updates promptly and rapidly.
|
||
|
* Failure to do so will cause the render thread to stall on that surface, blocking all
|
||
|
* HardwareRenderer instances.</p>
|
||
|
*
|
||
|
* @param surface The surface to render into. If null then rendering will be stopped. If
|
||
|
* non-null then {@link Surface#isValid()} must be true.
|
||
|
*/
|
||
|
public void setSurface(@Nullable Surface surface) {
|
||
|
setSurface(surface, false);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* See {@link #setSurface(Surface)}
|
||
|
*
|
||
|
* @hide
|
||
|
* @param discardBuffer determines whether the surface will attempt to preserve its contents
|
||
|
* between frames. If set to true the renderer will attempt to preserve
|
||
|
* the contents of the buffer between frames if the implementation allows
|
||
|
* it. If set to false no attempt will be made to preserve the buffer's
|
||
|
* contents between frames.
|
||
|
*/
|
||
|
public void setSurface(@Nullable Surface surface, boolean discardBuffer) {
|
||
|
if (surface != null && !surface.isValid()) {
|
||
|
throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
|
||
|
}
|
||
|
nSetSurface(mNativeProxy, surface, discardBuffer);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the SurfaceControl to be used internally inside render thread
|
||
|
* @hide
|
||
|
* @param surfaceControl The surface control to pass to render thread in hwui.
|
||
|
* If null, any previous references held in render thread will be discarded.
|
||
|
*/
|
||
|
public void setSurfaceControl(@Nullable SurfaceControl surfaceControl,
|
||
|
@Nullable BLASTBufferQueue blastBufferQueue) {
|
||
|
nSetSurfaceControl(mNativeProxy, surfaceControl != null ? surfaceControl.mNativeObject : 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the parameters that can be used to control a render request for a
|
||
|
* {@link HardwareRenderer}. This is not thread-safe and must not be held on to for longer
|
||
|
* than a single frame request.
|
||
|
*/
|
||
|
public final class FrameRenderRequest {
|
||
|
private FrameInfo mFrameInfo = new FrameInfo();
|
||
|
private boolean mWaitForPresent;
|
||
|
|
||
|
private FrameRenderRequest() { }
|
||
|
|
||
|
private void reset() {
|
||
|
mWaitForPresent = false;
|
||
|
// Default to the animation time which, if choreographer is in play, will default to the
|
||
|
// current vsync time. Otherwise it will be 'now'.
|
||
|
mRenderRequest.setVsyncTime(
|
||
|
AnimationUtils.currentAnimationTimeMillis() * TimeUtils.NANOS_PER_MS);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setFrameInfo(FrameInfo info) {
|
||
|
System.arraycopy(info.frameInfo, 0, mFrameInfo.frameInfo, 0, info.frameInfo.length);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the vsync time that represents the start point of this frame. Typically this
|
||
|
* comes from {@link android.view.Choreographer.FrameCallback}. Other compatible time
|
||
|
* sources include {@link System#nanoTime()}, however if the result is being displayed
|
||
|
* on-screen then using {@link android.view.Choreographer} is strongly recommended to
|
||
|
* ensure smooth animations.
|
||
|
*
|
||
|
* <p>If the clock source is not from a CLOCK_MONOTONIC source then any animations driven
|
||
|
* directly by RenderThread will not be synchronized properly with the current frame.
|
||
|
*
|
||
|
* @param vsyncTime The vsync timestamp for this frame. The timestamp is in nanoseconds
|
||
|
* and should come from a CLOCK_MONOTONIC source.
|
||
|
*
|
||
|
* @return this instance
|
||
|
*/
|
||
|
public @NonNull FrameRenderRequest setVsyncTime(long vsyncTime) {
|
||
|
// TODO(b/168552873): populate vsync Id once available to Choreographer public API
|
||
|
mFrameInfo.setVsync(vsyncTime, vsyncTime, FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE,
|
||
|
vsyncTime, -1);
|
||
|
mFrameInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a frame commit callback. This callback will be invoked when the current rendering
|
||
|
* content has been rendered into a frame and submitted to the swap chain. The frame may
|
||
|
* not currently be visible on the display when this is invoked, but it has been submitted.
|
||
|
* This callback is useful in combination with {@link PixelCopy} to capture the current
|
||
|
* rendered content of the UI reliably.
|
||
|
*
|
||
|
* @param executor The executor to run the callback on. It is strongly recommended that
|
||
|
* this executor post to a different thread, as the calling thread is
|
||
|
* highly sensitive to being blocked.
|
||
|
* @param frameCommitCallback The callback to invoke when the frame content has been drawn.
|
||
|
* Will be invoked on the given {@link Executor}.
|
||
|
*
|
||
|
* @return this instance
|
||
|
*/
|
||
|
public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
|
||
|
@NonNull Runnable frameCommitCallback) {
|
||
|
nSetFrameCommitCallback(mNativeProxy,
|
||
|
didProduceBuffer -> executor.execute(frameCommitCallback));
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets whether or not {@link #syncAndDraw()} should block until the frame has been
|
||
|
* presented. If this is true and {@link #syncAndDraw()} does not return
|
||
|
* {@link #SYNC_FRAME_DROPPED} or an error then when {@link #syncAndDraw()} has returned
|
||
|
* the frame has been submitted to the {@link Surface}. The default and typically
|
||
|
* recommended value is false, as blocking for present will prevent pipelining from
|
||
|
* happening, reducing overall throughput. This is useful for situations such as
|
||
|
* {@link SurfaceHolder.Callback2#surfaceRedrawNeeded(SurfaceHolder)} where it is desired
|
||
|
* to block until a frame has been presented to ensure first-frame consistency with
|
||
|
* other Surfaces.
|
||
|
*
|
||
|
* @param shouldWait If true the next call to {@link #syncAndDraw()} will block until
|
||
|
* completion.
|
||
|
* @return this instance
|
||
|
*/
|
||
|
public @NonNull FrameRenderRequest setWaitForPresent(boolean shouldWait) {
|
||
|
mWaitForPresent = shouldWait;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Syncs the RenderNode tree to the render thread and requests a frame to be drawn. This
|
||
|
* {@link FrameRenderRequest} instance should no longer be used after calling this method.
|
||
|
* The system internally may reuse instances of {@link FrameRenderRequest} to reduce
|
||
|
* allocation churn.
|
||
|
*
|
||
|
* @return The result of the sync operation.
|
||
|
*/
|
||
|
@SyncAndDrawResult
|
||
|
public int syncAndDraw() {
|
||
|
int syncResult = syncAndDrawFrame(mFrameInfo);
|
||
|
if (mWaitForPresent && (syncResult & SYNC_FRAME_DROPPED) == 0) {
|
||
|
fence();
|
||
|
}
|
||
|
return syncResult;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private FrameRenderRequest mRenderRequest = new FrameRenderRequest();
|
||
|
|
||
|
/**
|
||
|
* Returns a {@link FrameRenderRequest} that can be used to render a new frame. This is used
|
||
|
* to synchronize the RenderNode content provided by {@link #setContentRoot(RenderNode)} with
|
||
|
* the RenderThread and then renders a single frame to the Surface set with
|
||
|
* {@link #setSurface(Surface)}.
|
||
|
*
|
||
|
* @return An instance of {@link FrameRenderRequest}. The instance may be reused for every
|
||
|
* frame, so the caller should not hold onto it for longer than a single render request.
|
||
|
*/
|
||
|
public @NonNull FrameRenderRequest createRenderRequest() {
|
||
|
mRenderRequest.reset();
|
||
|
return mRenderRequest;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SyncAndDrawResult
|
||
|
public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
|
||
|
return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Suspends any current rendering into the surface but do not do any destruction. This
|
||
|
* is useful to temporarily suspend using the active Surface in order to do any Surface
|
||
|
* mutations necessary.
|
||
|
*
|
||
|
* <p>Any subsequent draws will override the pause, resuming normal operation.
|
||
|
*
|
||
|
* @return true if there was an outstanding render request, false otherwise. If this is true
|
||
|
* the caller should ensure that {@link #createRenderRequest()}
|
||
|
* and {@link FrameRenderRequest#syncAndDraw()} is called at the soonest
|
||
|
* possible time to resume normal operation.
|
||
|
*
|
||
|
* TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
|
||
|
* Surface before getting a new one. However things like SurfaceView will ensure that
|
||
|
* the old surface remains un-destroyed until after a new frame has been produced with
|
||
|
* the new surface.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean pause() {
|
||
|
return nPause(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hard stops rendering into the surface. If the renderer is stopped it will
|
||
|
* block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
|
||
|
* still sync over the latest rendering content, however they will not render and instead
|
||
|
* {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
|
||
|
*
|
||
|
* <p>If false is passed then rendering will resume as normal. Any pending rendering requests
|
||
|
* will produce a new frame at the next vsync signal.
|
||
|
*
|
||
|
* <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}
|
||
|
* and {@link Activity#onStart()}.
|
||
|
*
|
||
|
* @param stopped true to stop all rendering, false to resume
|
||
|
* @hide
|
||
|
*/
|
||
|
public void setStopped(boolean stopped) {
|
||
|
nSetStopped(mNativeProxy, stopped);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hard stops rendering into the surface. If the renderer is stopped it will
|
||
|
* block any attempt to render. Calls to {@link FrameRenderRequest#syncAndDraw()} will
|
||
|
* still sync over the latest rendering content, however they will not render and instead
|
||
|
* {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
|
||
|
*
|
||
|
* <p>This is useful in combination with lifecycle events such as {@link Activity#onStop()}.
|
||
|
* See {@link #start()} for resuming rendering.
|
||
|
*/
|
||
|
public void stop() {
|
||
|
nSetStopped(mNativeProxy, true);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Resumes rendering into the surface. Any pending rendering requests
|
||
|
* will produce a new frame at the next vsync signal.
|
||
|
*
|
||
|
* <p>This is useful in combination with lifecycle events such as {@link Activity#onStart()}.
|
||
|
* See {@link #stop()} for stopping rendering.
|
||
|
*/
|
||
|
public void start() {
|
||
|
nSetStopped(mNativeProxy, false);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destroys all the display lists associated with the current rendering content.
|
||
|
* This includes releasing a reference to the current content root RenderNode. It will
|
||
|
* therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
|
||
|
* rendering after calling this, along with re-recording the display lists for the
|
||
|
* RenderNode tree.
|
||
|
*
|
||
|
* <p>It is recommended, but not necessary, to use this in combination with lifecycle events
|
||
|
* such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
|
||
|
* {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
|
||
|
* {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
|
||
|
*
|
||
|
* See also {@link #stop()}.
|
||
|
*/
|
||
|
public void clearContent() {
|
||
|
nDestroyHardwareResources(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Whether or not the force-dark feature should be used for this renderer.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean setForceDark(@ForceDarkType.ForceDarkTypeDef int type) {
|
||
|
if (mForceDark != type) {
|
||
|
mForceDark = type;
|
||
|
nSetForceDark(mNativeProxy, type);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Allocate buffers ahead of time to avoid allocation delays during rendering.
|
||
|
*
|
||
|
* <p>Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
|
||
|
* memory usage of Surfaces that render rarely or never hit triple buffering. However
|
||
|
* for UI it can result in a slight bit of jank on first launch. This hint will
|
||
|
* tell the HardwareRenderer that now is a good time to allocate the 3 buffers
|
||
|
* necessary for typical rendering.
|
||
|
*
|
||
|
* <p>Must be called after a {@link Surface} has been set.
|
||
|
*
|
||
|
* TODO: Figure out if we even need/want this. Should HWUI just be doing this in response
|
||
|
* to setSurface anyway? Vulkan swapchain makes this murky, so delay making it public
|
||
|
* @hide
|
||
|
*/
|
||
|
public void allocateBuffers() {
|
||
|
nAllocateBuffers(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Notifies the hardware renderer that a call to {@link FrameRenderRequest#syncAndDraw()} will
|
||
|
* be coming soon. This is used to help schedule when RenderThread-driven animations will
|
||
|
* happen as the renderer wants to avoid producing more than one frame per vsync signal.
|
||
|
*/
|
||
|
public void notifyFramePending() {
|
||
|
nNotifyFramePending(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
|
||
|
*
|
||
|
* <p>If the renderer is set to opaque it is the app's responsibility to ensure that the
|
||
|
* content renders to every pixel of the Surface, otherwise corruption may result. Note that
|
||
|
* this includes ensuring that the first draw of any given pixel does not attempt to blend
|
||
|
* against the destination. If this is false then the hardware renderer will clear to
|
||
|
* transparent at the start of every frame.
|
||
|
*
|
||
|
* @param opaque true if the content rendered is opaque, false if the renderer should clear
|
||
|
* to transparent before rendering
|
||
|
*/
|
||
|
public void setOpaque(boolean opaque) {
|
||
|
if (mOpaque != opaque) {
|
||
|
mOpaque = opaque;
|
||
|
nSetOpaque(mNativeProxy, mOpaque);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
|
||
|
*
|
||
|
* @return true if the renderer is opaque, false otherwise
|
||
|
*/
|
||
|
public boolean isOpaque() {
|
||
|
return mOpaque;
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setFrameCommitCallback(FrameCommitCallback callback) {
|
||
|
nSetFrameCommitCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setFrameCompleteCallback(FrameCompleteCallback callback) {
|
||
|
nSetFrameCompleteCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* TODO: Public API this?
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void addObserver(HardwareRendererObserver observer) {
|
||
|
nAddObserver(mNativeProxy, observer.getNativeInstance());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* TODO: Public API this?
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void removeObserver(HardwareRendererObserver observer) {
|
||
|
nRemoveObserver(mNativeProxy, observer.getNativeInstance());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the desired color mode on this renderer. Whether or not the actual rendering
|
||
|
* will use the requested colorMode depends on the hardware support for such rendering.
|
||
|
*
|
||
|
* @param colorMode The @{@link ActivityInfo.ColorMode} to request
|
||
|
* @hide
|
||
|
*/
|
||
|
public float setColorMode(@ActivityInfo.ColorMode int colorMode) {
|
||
|
if (mColorMode != colorMode) {
|
||
|
mColorMode = colorMode;
|
||
|
mDesiredSdrHdrRatio = nSetColorMode(mNativeProxy, colorMode);
|
||
|
}
|
||
|
return mDesiredSdrHdrRatio;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the colormode with the desired SDR white point.
|
||
|
*
|
||
|
* The white point only applies if the color mode is an HDR mode
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void setColorMode(@ActivityInfo.ColorMode int colorMode, float whitePoint) {
|
||
|
nSetSdrWhitePoint(mNativeProxy, whitePoint);
|
||
|
mColorMode = colorMode;
|
||
|
nSetColorMode(mNativeProxy, colorMode);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setTargetHdrSdrRatio(float ratio) {
|
||
|
if (ratio < 1.f || !Float.isFinite(ratio)) ratio = 1.f;
|
||
|
nSetTargetSdrHdrRatio(mNativeProxy, ratio);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Blocks until all previously queued work has completed.
|
||
|
*
|
||
|
* TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
|
||
|
* better
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void fence() {
|
||
|
nFence(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void registerAnimatingRenderNode(RenderNode animator) {
|
||
|
nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
|
||
|
nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
|
||
|
animator.getAnimatorNativePtr());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Prevents any further drawing until {@link FrameRenderRequest#syncAndDraw()} is called.
|
||
|
* This is a signal that the contents of the RenderNode tree are no longer safe to play back.
|
||
|
* In practice this usually means that there are Functor pointers in the
|
||
|
* display list that are no longer valid.
|
||
|
*
|
||
|
* TODO: Can we get webview off of this?
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void stopDrawing() {
|
||
|
nStopDrawing(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new hardware layer. A hardware layer built by calling this
|
||
|
* method will be treated as a texture layer, instead of as a render target.
|
||
|
*
|
||
|
* @return A hardware layer
|
||
|
* @hide
|
||
|
*/
|
||
|
public TextureLayer createTextureLayer() {
|
||
|
long layer = nCreateTextureLayer(mNativeProxy);
|
||
|
return TextureLayer.adoptTextureLayer(this, layer);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Detaches the layer's surface texture from the GL context and releases
|
||
|
* the texture id
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void detachSurfaceTexture(long hardwareLayer) {
|
||
|
nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
|
||
|
}
|
||
|
|
||
|
|
||
|
/** @hide */
|
||
|
public void buildLayer(RenderNode node) {
|
||
|
if (node.hasDisplayList()) {
|
||
|
nBuildLayer(mNativeProxy, node.mNativeRenderNode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
|
||
|
return nCopyLayerInto(mNativeProxy, layer.getDeferredLayerUpdater(),
|
||
|
bitmap.getNativeInstance());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates that the specified hardware layer needs to be updated
|
||
|
* as soon as possible.
|
||
|
*
|
||
|
* @param layer The hardware layer that needs an update
|
||
|
* @hide
|
||
|
*/
|
||
|
public void pushLayerUpdate(TextureLayer layer) {
|
||
|
nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Tells the HardwareRenderer that the layer is destroyed. The renderer
|
||
|
* should remove the layer from any update queues.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void onLayerDestroyed(TextureLayer layer) {
|
||
|
nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
protected void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) {
|
||
|
nSetASurfaceTransactionCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
protected void setPrepareSurfaceControlForWebviewCallback(
|
||
|
PrepareSurfaceControlForWebviewCallback callback) {
|
||
|
nSetPrepareSurfaceControlForWebviewCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setFrameCallback(FrameDrawingCallback callback) {
|
||
|
nSetFrameCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
|
||
|
* rendernode of the UI thread.
|
||
|
*
|
||
|
* @param node The node to add.
|
||
|
* @param placeFront If true, the render node will be placed in front of the content node,
|
||
|
* otherwise behind the content node.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void addRenderNode(RenderNode node, boolean placeFront) {
|
||
|
nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Only especially added render nodes can be removed.
|
||
|
*
|
||
|
* @param node The node which was added via addRenderNode which should get removed again.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void removeRenderNode(RenderNode node) {
|
||
|
nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Draws a particular render node. If the node is not the content node, only the additional
|
||
|
* nodes will get drawn and the content remains untouched.
|
||
|
*
|
||
|
* @param node The node to be drawn.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void drawRenderNode(RenderNode node) {
|
||
|
nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Loads system properties used by the renderer. This method is invoked
|
||
|
* whenever system properties are modified. Implementations can use this
|
||
|
* to trigger live updates of the renderer based on properties.
|
||
|
*
|
||
|
* @return True if a property has changed.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean loadSystemProperties() {
|
||
|
return nLoadSystemProperties(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void dumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
|
||
|
nDumpGlobalProfileInfo(fd, dumpFlags);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
|
||
|
nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* To avoid unnecessary overdrawing of the main content all additionally passed render nodes
|
||
|
* will be prevented to overdraw this area. It will be synchronized with the draw call.
|
||
|
* This should be updated in the content view's draw call.
|
||
|
*
|
||
|
* @param left The left side of the protected bounds.
|
||
|
* @param top The top side of the protected bounds.
|
||
|
* @param right The right side of the protected bounds.
|
||
|
* @param bottom The bottom side of the protected bounds.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void setContentDrawBounds(int left, int top, int right, int bottom) {
|
||
|
nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Force the new frame to draw, ensuring the UI draw request will attempt a draw this vsync.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void forceDrawNextFrame() {
|
||
|
nForceDrawNextFrame(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public void setPictureCaptureCallback(@Nullable PictureCapturedCallback callback) {
|
||
|
nSetPictureCaptureCallback(mNativeProxy, callback);
|
||
|
}
|
||
|
|
||
|
/** called by native */
|
||
|
static void invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback) {
|
||
|
Picture picture = new Picture(picturePtr);
|
||
|
callback.onPictureCaptured(picture);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface used to receive callbacks when Webview requests a surface control.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface PrepareSurfaceControlForWebviewCallback {
|
||
|
/**
|
||
|
* Invoked when Webview calls to get a surface control.
|
||
|
*
|
||
|
*/
|
||
|
void prepare();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface used to receive callbacks when a transaction needs to be merged.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface ASurfaceTransactionCallback {
|
||
|
/**
|
||
|
* Invoked during a frame drawing.
|
||
|
*
|
||
|
* @param aSurfaceTranactionNativeObj the ASurfaceTransaction native object handle
|
||
|
* @param aSurfaceControlNativeObj ASurfaceControl native object handle
|
||
|
* @param frame The id of the frame being drawn.
|
||
|
*/
|
||
|
boolean onMergeTransaction(long aSurfaceTranactionNativeObj,
|
||
|
long aSurfaceControlNativeObj, long frame);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface used to receive callbacks when a frame is being drawn.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface FrameDrawingCallback {
|
||
|
/**
|
||
|
* Invoked during a frame drawing.
|
||
|
*
|
||
|
* @param frame The id of the frame being drawn.
|
||
|
*/
|
||
|
void onFrameDraw(long frame);
|
||
|
|
||
|
/**
|
||
|
* Invoked during a frame drawing.
|
||
|
*
|
||
|
* @param syncResult The result of the draw. Should be a value or a combination of values
|
||
|
* from {@link SyncAndDrawResult}
|
||
|
* @param frame The id of the frame being drawn.
|
||
|
*
|
||
|
* @return A {@link FrameCommitCallback} that will report back if the current vsync draws.
|
||
|
*/
|
||
|
default FrameCommitCallback onFrameDraw(@SyncAndDrawResult int syncResult, long frame) {
|
||
|
onFrameDraw(frame);
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface used to be notified when a frame has finished rendering
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface FrameCommitCallback {
|
||
|
/**
|
||
|
* Invoked after a new frame was drawn
|
||
|
*
|
||
|
* @param didProduceBuffer The draw successfully produced a new buffer.
|
||
|
*/
|
||
|
void onFrameCommit(boolean didProduceBuffer);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't
|
||
|
* mean a new frame has drawn, specifically if there's nothing new to draw, but only that
|
||
|
* RenderThread had a chance to draw a frame.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface FrameCompleteCallback {
|
||
|
/**
|
||
|
* Invoked after a frame draw was attempted.
|
||
|
*/
|
||
|
void onFrameComplete();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Interface for listening to picture captures
|
||
|
* @hide
|
||
|
*/
|
||
|
public interface PictureCapturedCallback {
|
||
|
/** @hide */
|
||
|
void onPictureCaptured(Picture picture);
|
||
|
}
|
||
|
|
||
|
private static void validateAlpha(float alpha, String argumentName) {
|
||
|
if (!(alpha >= 0.0f && alpha <= 1.0f)) {
|
||
|
throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
|
||
|
+ alpha + " is not in the range of 0.0f to 1.0f");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void validatePositive(float f, String argumentName) {
|
||
|
if (!(Float.isFinite(f) && f >= 0.0f)) {
|
||
|
throw new IllegalArgumentException(argumentName
|
||
|
+ " must be a finite positive, given=" + f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void validateFinite(float f, String argumentName) {
|
||
|
if (!Float.isFinite(f)) {
|
||
|
throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Notifies the hardware renderer about pending choreographer callbacks.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void notifyCallbackPending() {
|
||
|
nNotifyCallbackPending(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Notifies the hardware renderer about upcoming expensive frames.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public void notifyExpensiveFrame() {
|
||
|
nNotifyExpensiveFrame(mNativeProxy);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* b/68769804, b/66945974: For low FPS experiments.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setFPSDivisor(int divisor) {
|
||
|
nSetRtAnimationsEnabled(divisor <= 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
|
||
|
* called before any OpenGL context is created.
|
||
|
*
|
||
|
* @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setContextPriority(int priority) {
|
||
|
nSetContextPriority(priority);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets whether or not high contrast text rendering is enabled. The setting is global
|
||
|
* but only affects content rendered after the change is made.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setHighContrastText(boolean highContrastText) {
|
||
|
nSetHighContrastText(highContrastText);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setIsolatedProcess(boolean isIsolated) {
|
||
|
nSetIsolatedProcess(isIsolated);
|
||
|
ProcessInitializer.sInstance.setIsolated(isIsolated);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sends device configuration changes to the render thread, for rendering profiling views.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void sendDeviceConfigurationForDebugging(Configuration config) {
|
||
|
if (config.densityDpi != Configuration.DENSITY_DPI_UNDEFINED
|
||
|
&& config.densityDpi != sDensityDpi) {
|
||
|
sDensityDpi = config.densityDpi;
|
||
|
nSetDisplayDensityDpi(config.densityDpi);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* If set extra graphics debugging abilities will be enabled such as dumping skp
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setDebuggingEnabled(boolean enable) {
|
||
|
nSetDebuggingEnabled(enable);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public abstract static class CopyRequest {
|
||
|
protected Bitmap mDestinationBitmap;
|
||
|
final Rect mSrcRect;
|
||
|
|
||
|
protected CopyRequest(Rect srcRect, Bitmap destinationBitmap) {
|
||
|
mDestinationBitmap = destinationBitmap;
|
||
|
if (srcRect != null) {
|
||
|
mSrcRect = srcRect;
|
||
|
} else {
|
||
|
mSrcRect = new Rect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve the bitmap in which to store the result of the copy request
|
||
|
*/
|
||
|
public long getDestinationBitmap(int srcWidth, int srcHeight) {
|
||
|
if (mDestinationBitmap == null) {
|
||
|
mDestinationBitmap =
|
||
|
Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
|
||
|
}
|
||
|
return mDestinationBitmap.getNativeInstance();
|
||
|
}
|
||
|
|
||
|
/** Called when the copy is completed */
|
||
|
public abstract void onCopyFinished(int result);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public static void copySurfaceInto(Surface surface, CopyRequest copyRequest) {
|
||
|
final Rect srcRect = copyRequest.mSrcRect;
|
||
|
nCopySurfaceInto(surface, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
|
||
|
copyRequest);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
|
||
|
* RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
|
||
|
* not the RenderNode from a View.
|
||
|
*
|
||
|
* @hide
|
||
|
**/
|
||
|
public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
|
||
|
return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Invoke this method when the system is running out of memory. This
|
||
|
* method will attempt to recover as much memory as possible, based on
|
||
|
* the specified hint.
|
||
|
*
|
||
|
* @param level Hint about the amount of memory that should be trimmed,
|
||
|
* see {@link android.content.ComponentCallbacks}
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void trimMemory(int level) {
|
||
|
nTrimMemory(level);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Invoke this when all font caches should be flushed. This can cause jank on next render
|
||
|
* commands so use it only after expensive font allocation operations which would
|
||
|
* allocate large amount of temporary memory.
|
||
|
*
|
||
|
* @param level Hint about which caches to trim. See {@link #CACHE_TRIM_ALL},
|
||
|
* {@link #CACHE_TRIM_FONT}, {@link #CACHE_TRIM_RESOURCES}
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void trimCaches(@CacheTrimLevel int level) {
|
||
|
nTrimCaches(level);
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public static void overrideProperty(@NonNull String name, @NonNull String value) {
|
||
|
if (name == null || value == null) {
|
||
|
throw new IllegalArgumentException("name and value must be non-null");
|
||
|
}
|
||
|
nOverrideProperty(name, value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the directory to use as a persistent storage for threaded rendering
|
||
|
* resources.
|
||
|
*
|
||
|
* @param cacheDir A directory the current process can write to
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setupDiskCache(File cacheDir) {
|
||
|
setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
|
||
|
new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
public static void setPackageName(String packageName) {
|
||
|
ProcessInitializer.sInstance.setPackageName(packageName);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets a context for process initialization
|
||
|
*
|
||
|
* TODO: Remove this once there is a static method for retrieving an application's context.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setContextForInit(Context context) {
|
||
|
ProcessInitializer.sInstance.setContext(context);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets whether or not the current process is a system or persistent process. Used to influence
|
||
|
* the chosen memory usage policy.
|
||
|
*
|
||
|
* @hide
|
||
|
**/
|
||
|
public static void setIsSystemOrPersistent() {
|
||
|
nSetIsSystemOrPersistent(true);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if HardwareRender will produce output.
|
||
|
*
|
||
|
* This value is global to the process and affects all uses of HardwareRenderer,
|
||
|
* including
|
||
|
* those created by the system such as those used by the View tree when using hardware
|
||
|
* accelerated rendering.
|
||
|
*
|
||
|
* Default is true in all production environments, but may be false in testing-focused
|
||
|
* emulators or if {@link #setDrawingEnabled(boolean)} is used.
|
||
|
*/
|
||
|
public static boolean isDrawingEnabled() {
|
||
|
return nIsDrawingEnabled();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Toggles whether or not HardwareRenderer will produce drawing output globally in the current
|
||
|
* process.
|
||
|
*
|
||
|
* This applies to all HardwareRenderer instances, including those created by the platform such
|
||
|
* as those used by the system for hardware accelerated View rendering.
|
||
|
*
|
||
|
* The capability to disable drawing output is intended for test environments, primarily
|
||
|
* headless ones. By setting this to false, tests that launch activities or interact with Views
|
||
|
* can be quicker with less RAM usage by skipping the final step of View drawing. All View
|
||
|
* lifecycle events will occur as normal, only the final step of rendering on the GPU to the
|
||
|
* display will be skipped.
|
||
|
*
|
||
|
* This can be toggled on and off at will, so screenshot tests can also run in this same
|
||
|
* environment by toggling drawing back on and forcing a frame to be drawn such as by calling
|
||
|
* view#invalidate(). Once drawn and the screenshot captured, this can then be turned back off.
|
||
|
*/
|
||
|
// TODO(b/194195794): Add link to androidx's Screenshot library for help with this
|
||
|
public static void setDrawingEnabled(boolean drawingEnabled) {
|
||
|
nSetDrawingEnabled(drawingEnabled);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Disable RenderThread animations that schedule draws directly from RenderThread. This is used
|
||
|
* when we don't want to de-schedule draw requests that come from the UI thread.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static void setRtAnimationsEnabled(boolean enabled) {
|
||
|
nSetRtAnimationsEnabled(enabled);
|
||
|
}
|
||
|
|
||
|
private static final class DestroyContextRunnable implements Runnable {
|
||
|
private final long mNativeInstance;
|
||
|
|
||
|
DestroyContextRunnable(long nativeInstance) {
|
||
|
mNativeInstance = nativeInstance;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void run() {
|
||
|
nDeleteProxy(mNativeInstance);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static class ProcessInitializer {
|
||
|
static ProcessInitializer sInstance = new ProcessInitializer();
|
||
|
|
||
|
private boolean mInitialized = false;
|
||
|
private boolean mDisplayInitialized = false;
|
||
|
|
||
|
private boolean mIsolated = false;
|
||
|
private Context mContext;
|
||
|
private String mPackageName;
|
||
|
private IGraphicsStats mGraphicsStatsService;
|
||
|
private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
|
||
|
@Override
|
||
|
public void onRotateGraphicsStatsBuffer() throws RemoteException {
|
||
|
rotateBuffer();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
private ProcessInitializer() {
|
||
|
}
|
||
|
|
||
|
synchronized void setPackageName(String name) {
|
||
|
if (mInitialized) return;
|
||
|
mPackageName = name;
|
||
|
}
|
||
|
|
||
|
synchronized void setIsolated(boolean isolated) {
|
||
|
if (mInitialized) return;
|
||
|
mIsolated = isolated;
|
||
|
}
|
||
|
|
||
|
synchronized void setContext(Context context) {
|
||
|
if (mInitialized) return;
|
||
|
mContext = context;
|
||
|
}
|
||
|
|
||
|
synchronized void init(long renderProxy) {
|
||
|
if (mInitialized) return;
|
||
|
mInitialized = true;
|
||
|
|
||
|
initSched(renderProxy);
|
||
|
initGraphicsStats();
|
||
|
}
|
||
|
|
||
|
private void initSched(long renderProxy) {
|
||
|
try {
|
||
|
int tid = nGetRenderThreadTid(renderProxy);
|
||
|
ActivityManager.getService().setRenderThread(tid);
|
||
|
} catch (Throwable t) {
|
||
|
Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void initGraphicsStats() {
|
||
|
if (mPackageName == null) return;
|
||
|
|
||
|
try {
|
||
|
IBinder binder = ServiceManager.getService("graphicsstats");
|
||
|
if (binder == null) return;
|
||
|
mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
|
||
|
requestBuffer();
|
||
|
} catch (Throwable t) {
|
||
|
Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
synchronized void initUsingContext() {
|
||
|
if (mContext == null) return;
|
||
|
|
||
|
initDisplayInfo();
|
||
|
|
||
|
nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
|
||
|
nSetIsLowRam(ActivityManager.isLowRamDeviceStatic());
|
||
|
// Defensively clear out the context in case we were passed a context that can leak
|
||
|
// if we live longer than it, e.g. an activity context.
|
||
|
mContext = null;
|
||
|
}
|
||
|
|
||
|
private void initDisplayInfo() {
|
||
|
if (mDisplayInitialized) return;
|
||
|
if (mIsolated) {
|
||
|
mDisplayInitialized = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
|
||
|
if (dm == null) {
|
||
|
Log.d(LOG_TAG, "Failed to find DisplayManager for display-based configuration");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
|
||
|
if (defaultDisplay == null) {
|
||
|
Log.d(LOG_TAG, "Failed to find default display for display-based configuration");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
final Display[] allDisplays = dm.getDisplays();
|
||
|
if (allDisplays.length == 0) {
|
||
|
Log.d(LOG_TAG, "Failed to query displays");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
final Mode activeMode = defaultDisplay.getMode();
|
||
|
final ColorSpace defaultWideColorSpace =
|
||
|
defaultDisplay.getPreferredWideGamutColorSpace();
|
||
|
int wideColorDataspace = defaultWideColorSpace != null
|
||
|
? defaultWideColorSpace.getDataSpace() : 0;
|
||
|
// largest width & height are used to size the default HWUI cache sizes. So find the
|
||
|
// largest display resolution we could encounter & use that as the guidance. The actual
|
||
|
// memory policy in play will interpret these values differently.
|
||
|
int largestWidth = activeMode.getPhysicalWidth();
|
||
|
int largestHeight = activeMode.getPhysicalHeight();
|
||
|
final OverlayProperties overlayProperties = defaultDisplay.getOverlaySupport();
|
||
|
|
||
|
for (int i = 0; i < allDisplays.length; i++) {
|
||
|
final Display display = allDisplays[i];
|
||
|
// Take the first wide gamut dataspace as the source of truth
|
||
|
// Possibly should do per-HardwareRenderer wide gamut dataspace so we can use the
|
||
|
// target display's ideal instead
|
||
|
if (wideColorDataspace == 0) {
|
||
|
ColorSpace cs = display.getPreferredWideGamutColorSpace();
|
||
|
if (cs != null) {
|
||
|
wideColorDataspace = cs.getDataSpace();
|
||
|
}
|
||
|
}
|
||
|
Mode[] modes = display.getSupportedModes();
|
||
|
for (int j = 0; j < modes.length; j++) {
|
||
|
Mode mode = modes[j];
|
||
|
int width = mode.getPhysicalWidth();
|
||
|
int height = mode.getPhysicalHeight();
|
||
|
if ((width * height) > (largestWidth * largestHeight)) {
|
||
|
largestWidth = width;
|
||
|
largestHeight = height;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nInitDisplayInfo(largestWidth, largestHeight, defaultDisplay.getRefreshRate(),
|
||
|
wideColorDataspace, defaultDisplay.getAppVsyncOffsetNanos(),
|
||
|
defaultDisplay.getPresentationDeadlineNanos(),
|
||
|
overlayProperties.isCombinationSupported(
|
||
|
DataSpace.DATASPACE_SCRGB, HardwareBuffer.RGBA_FP16),
|
||
|
overlayProperties.isCombinationSupported(
|
||
|
DataSpace.pack(
|
||
|
DataSpace.STANDARD_DCI_P3,
|
||
|
DataSpace.TRANSFER_SRGB,
|
||
|
DataSpace.RANGE_EXTENDED),
|
||
|
HardwareBuffer.RGBA_10101010),
|
||
|
overlayProperties.isMixedColorSpacesSupported());
|
||
|
|
||
|
mDisplayInitialized = true;
|
||
|
}
|
||
|
|
||
|
private void rotateBuffer() {
|
||
|
nRotateProcessStatsBuffer();
|
||
|
requestBuffer();
|
||
|
}
|
||
|
|
||
|
private void requestBuffer() {
|
||
|
try {
|
||
|
ParcelFileDescriptor pfd = mGraphicsStatsService
|
||
|
.requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
|
||
|
nSetProcessStatsBuffer(pfd.getFd());
|
||
|
pfd.close();
|
||
|
} catch (Throwable t) {
|
||
|
Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public static native void disableVsync();
|
||
|
|
||
|
/**
|
||
|
* Start render thread and initialize EGL or Vulkan.
|
||
|
*
|
||
|
* Initializing EGL involves loading and initializing the graphics driver. Some drivers take
|
||
|
* several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
|
||
|
* its first frame adds directly to user-visible app launch latency.
|
||
|
*
|
||
|
* Should only be called after GraphicsEnvironment.chooseDriver().
|
||
|
* @hide
|
||
|
*/
|
||
|
public static native void preload();
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
protected static native boolean isWebViewOverlaysEnabled();
|
||
|
|
||
|
/** @hide */
|
||
|
protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
|
||
|
|
||
|
private static native void nRotateProcessStatsBuffer();
|
||
|
|
||
|
private static native void nSetProcessStatsBuffer(int fd);
|
||
|
|
||
|
private static native int nGetRenderThreadTid(long nativeProxy);
|
||
|
|
||
|
private static native long nCreateRootRenderNode();
|
||
|
|
||
|
private static native long nCreateProxy(boolean translucent, long rootRenderNode);
|
||
|
|
||
|
private static native void nDeleteProxy(long nativeProxy);
|
||
|
|
||
|
private static native boolean nLoadSystemProperties(long nativeProxy);
|
||
|
|
||
|
private static native void nSetName(long nativeProxy, String name);
|
||
|
|
||
|
private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer);
|
||
|
|
||
|
private static native void nSetSurfaceControl(long nativeProxy, long nativeSurfaceControl);
|
||
|
|
||
|
private static native boolean nPause(long nativeProxy);
|
||
|
|
||
|
private static native void nSetStopped(long nativeProxy, boolean stopped);
|
||
|
|
||
|
private static native void nSetLightGeometry(long nativeProxy,
|
||
|
float lightX, float lightY, float lightZ, float lightRadius);
|
||
|
|
||
|
private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
|
||
|
float spotShadowAlpha);
|
||
|
|
||
|
private static native void nSetOpaque(long nativeProxy, boolean opaque);
|
||
|
|
||
|
private static native float nSetColorMode(long nativeProxy, int colorMode);
|
||
|
|
||
|
private static native void nSetTargetSdrHdrRatio(long nativeProxy, float ratio);
|
||
|
|
||
|
private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
|
||
|
|
||
|
private static native void nSetIsHighEndGfx(boolean isHighEndGfx);
|
||
|
|
||
|
private static native void nSetIsLowRam(boolean isLowRam);
|
||
|
|
||
|
private static native void nSetIsSystemOrPersistent(boolean isSystemOrPersistent);
|
||
|
|
||
|
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
|
||
|
|
||
|
private static native void nDestroy(long nativeProxy, long rootRenderNode);
|
||
|
|
||
|
private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
|
||
|
long animatingNode);
|
||
|
|
||
|
private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
|
||
|
|
||
|
private static native long nCreateTextureLayer(long nativeProxy);
|
||
|
|
||
|
private static native void nBuildLayer(long nativeProxy, long node);
|
||
|
|
||
|
private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmapHandle);
|
||
|
|
||
|
private static native void nPushLayerUpdate(long nativeProxy, long layer);
|
||
|
|
||
|
private static native void nCancelLayerUpdate(long nativeProxy, long layer);
|
||
|
|
||
|
private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
|
||
|
|
||
|
private static native void nDestroyHardwareResources(long nativeProxy);
|
||
|
|
||
|
private static native void nTrimMemory(int level);
|
||
|
|
||
|
private static native void nTrimCaches(int level);
|
||
|
|
||
|
private static native void nOverrideProperty(String name, String value);
|
||
|
|
||
|
private static native void nFence(long nativeProxy);
|
||
|
|
||
|
private static native void nStopDrawing(long nativeProxy);
|
||
|
|
||
|
private static native void nNotifyFramePending(long nativeProxy);
|
||
|
|
||
|
private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
|
||
|
@DumpFlags int dumpFlags);
|
||
|
|
||
|
private static native void nDumpGlobalProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags);
|
||
|
|
||
|
private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
|
||
|
boolean placeFront);
|
||
|
|
||
|
private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
|
||
|
|
||
|
private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
|
||
|
|
||
|
private static native void nSetContentDrawBounds(long nativeProxy, int left,
|
||
|
int top, int right, int bottom);
|
||
|
|
||
|
private static native void nForceDrawNextFrame(long nativeProxy);
|
||
|
|
||
|
private static native void nSetPictureCaptureCallback(long nativeProxy,
|
||
|
PictureCapturedCallback callback);
|
||
|
|
||
|
private static native void nSetASurfaceTransactionCallback(long nativeProxy,
|
||
|
ASurfaceTransactionCallback callback);
|
||
|
|
||
|
private static native void nSetPrepareSurfaceControlForWebviewCallback(long nativeProxy,
|
||
|
PrepareSurfaceControlForWebviewCallback callback);
|
||
|
|
||
|
private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
|
||
|
|
||
|
private static native void nSetFrameCommitCallback(long nativeProxy,
|
||
|
FrameCommitCallback callback);
|
||
|
|
||
|
private static native void nSetFrameCompleteCallback(long nativeProxy,
|
||
|
FrameCompleteCallback callback);
|
||
|
|
||
|
private static native void nAddObserver(long nativeProxy, long nativeObserver);
|
||
|
|
||
|
private static native void nRemoveObserver(long nativeProxy, long nativeObserver);
|
||
|
|
||
|
private static native void nCopySurfaceInto(Surface surface,
|
||
|
int srcLeft, int srcTop, int srcRight, int srcBottom, CopyRequest request);
|
||
|
|
||
|
private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
|
||
|
|
||
|
private static native void nSetHighContrastText(boolean enabled);
|
||
|
|
||
|
private static native void nSetDebuggingEnabled(boolean enabled);
|
||
|
|
||
|
private static native void nSetIsolatedProcess(boolean enabled);
|
||
|
|
||
|
private static native void nSetContextPriority(int priority);
|
||
|
|
||
|
private static native void nAllocateBuffers(long nativeProxy);
|
||
|
|
||
|
private static native void nSetForceDark(long nativeProxy, int type);
|
||
|
|
||
|
private static native void nSetDisplayDensityDpi(int densityDpi);
|
||
|
|
||
|
private static native void nInitDisplayInfo(int width, int height, float refreshRate,
|
||
|
int wideColorDataspace, long appVsyncOffsetNanos, long presentationDeadlineNanos,
|
||
|
boolean supportsFp16ForHdr, boolean isRgba10101010SupportedForHdr,
|
||
|
boolean nSupportMixedColorSpaces);
|
||
|
|
||
|
private static native void nSetDrawingEnabled(boolean drawingEnabled);
|
||
|
|
||
|
private static native boolean nIsDrawingEnabled();
|
||
|
|
||
|
private static native void nSetRtAnimationsEnabled(boolean rtAnimationsEnabled);
|
||
|
|
||
|
private static native void nNotifyCallbackPending(long nativeProxy);
|
||
|
|
||
|
private static native void nNotifyExpensiveFrame(long nativeProxy);
|
||
|
}
|