Expose RENDERMODE_CONTINUOUSLY and RENDERMODE_WHEN_DIRTY (#2801)

This commit is contained in:
alasram
2024-09-17 12:59:58 -07:00
committed by GitHub
parent 0e0c8da72a
commit 77a464d335
11 changed files with 157 additions and 59 deletions

View File

@@ -140,10 +140,10 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
// add accessibility support
setContentDescription(context.getString(R.string.maplibre_mapActionDescription));
setWillNotDraw(false);
initialiseDrawingSurface(options);
initializeDrawingSurface(options);
}
private void initialiseMap() {
private void initializeMap() {
Context context = getContext();
// callback for focal point invalidation
@@ -305,7 +305,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
}
}
private void initialiseDrawingSurface(MapLibreMapOptions options) {
private void initializeDrawingSurface(MapLibreMapOptions options) {
mapRenderer = MapRenderer.create(options, getContext(), () -> MapView.this.onSurfaceCreated());
renderView = mapRenderer.getView();
@@ -321,9 +321,9 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
post(new Runnable() {
@Override
public void run() {
// Initialise only when not destroyed and only once
// Initialize only when not destroyed and only once
if (!destroyed && maplibreMap == null) {
MapView.this.initialiseMap();
MapView.this.initializeMap();
maplibreMap.onStart();
}
}
@@ -465,6 +465,34 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
}
}
/**
* Set the rendering refresh mode and wake up the render thread if it is sleeping.
*
* @param mode can be:
* {@link MapRenderer.RenderingRefreshMode#CONTINUOUS} or {@link MapRenderer.RenderingRefreshMode#WHEN_DIRTY}
* default is {@link MapRenderer.RenderingRefreshMode#WHEN_DIRTY}
*/
public void setRenderingRefreshMode(MapRenderer.RenderingRefreshMode mode) {
if (mapRenderer != null) {
mapRenderer.setRenderingRefreshMode(mode);
} else {
throw new IllegalStateException("Calling MapView#setRenderingRefreshMode before mapRenderer is created.");
}
}
/**
* Get the rendering refresh mode
*
* @return one of the MapRenderer.RenderingRefreshMode modes
* @see #setRenderingRefreshMode
*/
public MapRenderer.RenderingRefreshMode getRenderingRefreshMode() {
if (mapRenderer == null) {
throw new IllegalStateException("Calling MapView#getRenderingRefreshMode before mapRenderer is created.");
}
return mapRenderer.getRenderingRefreshMode();
}
/**
* Returns if the map has been destroyed.
* <p>

View File

@@ -30,7 +30,24 @@ public abstract class MapRenderer implements MapRendererScheduler {
private static final String TAG = "Mbgl-MapRenderer";
// Holds the pointer to the native peer after initialisation
/**
* Rendering presentation refresh mode.
*/
public enum RenderingRefreshMode {
/**
* The map is rendered only in response to an event that affects the rendering of the map.
* This mode is preferred to improve battery life and overall system performance
*/
WHEN_DIRTY,
/**
* The map is repeatedly re-rendered at the refresh rate of the display.
* This mode is preferred when benchmarking the rendering
*/
CONTINUOUS,
}
// Holds the pointer to the native peer after initialization
private long nativePtr = 0;
private double expectedRenderTime = 0;
private MapLibreMap.OnFpsChangedListener onFpsChangedListener;
@@ -57,7 +74,7 @@ public abstract class MapRenderer implements MapRendererScheduler {
public MapRenderer(@NonNull Context context, String localIdeographFontFamily) {
float pixelRatio = context.getResources().getDisplayMetrics().density;
// Initialise native peer
// Initialize native peer
nativeInitialize(this, pixelRatio, localIdeographFontFamily);
}
@@ -83,6 +100,10 @@ public abstract class MapRenderer implements MapRendererScheduler {
// Implement if needed
}
public abstract void setRenderingRefreshMode(RenderingRefreshMode mode);
public abstract RenderingRefreshMode getRenderingRefreshMode();
public void setOnFpsChangedListener(MapLibreMap.OnFpsChangedListener listener) {
onFpsChangedListener = listener;
}

View File

@@ -5,6 +5,7 @@ import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import org.maplibre.android.maps.renderer.MapRenderer;
import androidx.annotation.NonNull;
@@ -21,24 +22,6 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
protected boolean detached;
/**
* The renderer only renders
* when the surface is created, or when {@link #requestRender} is called.
*
* @see #getRenderMode()
* @see #setRenderMode(int)
* @see #requestRender()
*/
public static final int RENDERMODE_WHEN_DIRTY = 0;
/**
* The renderer is called
* continuously to re-render the scene.
*
* @see #getRenderMode()
* @see #setRenderMode(int)
*/
public static final int RENDERMODE_CONTINUOUSLY = 1;
/**
* Standard View constructor. In order to render something, you
* must call {@link #setRenderer} to register a renderer.
@@ -104,7 +87,7 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
* <li>{@link #onResume()}
* <li>{@link #queueEvent(Runnable)}
* <li>{@link #requestRender()}
* <li>{@link #setRenderMode(int)}
* <li>{@link #setRenderingRefreshMode(MapRenderer.RenderingRefreshMode)}
* </ul>
*
* @param renderer the renderer to use to perform drawing.
@@ -118,21 +101,20 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
}
/**
* Set the rendering mode. When renderMode is
* RENDERMODE_CONTINUOUSLY, the renderer is called
* repeatedly to re-render the scene. When renderMode
* is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface
* is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY.
* Set the rendering refresh mode to CONTINUOUS or WHEN_DIRTY.
* Defaults to MapRenderer.RenderingRefreshMode.WHEN_DIRTY.
* The renderer is called repeatedly to re-render the scene in continuous mode otherwise
* the renderer is called when the surface is created, or when {@link #requestRender} is called.
* <p>
* Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance
* Using WHEN_DIRTY can improve battery life and overall system performance
* by allowing the GPU and CPU to idle when the view does not need to be updated.
* <p>
* This method can only be called after {@link #setRenderer(SurfaceViewMapRenderer)}
*
* @param renderMode one of the RENDERMODE_X constants
* @param mode one of the MapRenderer.RenderingRefreshMode constants
*/
public void setRenderMode(int renderMode) {
renderThread.setRenderMode(renderMode);
public void setRenderingRefreshMode(MapRenderer.RenderingRefreshMode mode) {
renderThread.setRenderingRefreshMode(mode);
}
/**
@@ -141,14 +123,14 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
*
* @return the current rendering mode.
*/
public int getRenderMode() {
return renderThread.getRenderMode();
public MapRenderer.RenderingRefreshMode getRenderingRefreshMode() {
return renderThread.getRenderingRefreshMode();
}
/**
* Request that the renderer render a frame.
* This method is typically used when the render mode has been set to
* RENDERMODE_WHEN_DIRTY, so that frames are only rendered on demand.
* MapRenderer.RenderingRefreshMode.WHEN_DIRTY, so that frames are only rendered on demand.
* May be called
* from any thread. Must not be called before a renderer has been set.
*/
@@ -249,13 +231,13 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (detached && (renderer != null)) {
int renderMode = RENDERMODE_CONTINUOUSLY;
MapRenderer.RenderingRefreshMode renderMode = MapRenderer.RenderingRefreshMode.WHEN_DIRTY;
if (renderThread != null) {
renderMode = renderThread.getRenderMode();
renderMode = renderThread.getRenderingRefreshMode();
}
createRenderThread();
if (renderMode != RENDERMODE_CONTINUOUSLY) {
renderThread.setRenderMode(renderMode);
if (renderMode != MapRenderer.RenderingRefreshMode.WHEN_DIRTY) {
renderThread.setRenderingRefreshMode(renderMode);
}
renderThread.start();
}
@@ -289,7 +271,7 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
width = 0;
height = 0;
requestRender = true;
renderMode = RENDERMODE_CONTINUOUSLY;
renderMode = MapRenderer.RenderingRefreshMode.WHEN_DIRTY;
wantRenderNotification = false;
}
@@ -311,24 +293,21 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
protected boolean readyToDraw() {
return (!paused) && hasSurface
&& (width > 0) && (height > 0)
&& (requestRender || (renderMode == RENDERMODE_CONTINUOUSLY));
&& (requestRender || (renderMode == MapRenderer.RenderingRefreshMode.CONTINUOUS));
}
public boolean ableToDraw() {
return readyToDraw();
}
public void setRenderMode(int renderMode) {
if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
throw new IllegalArgumentException("renderMode");
}
public void setRenderingRefreshMode(MapRenderer.RenderingRefreshMode mode) {
synchronized (renderThreadManager) {
this.renderMode = renderMode;
this.renderMode = mode;
renderThreadManager.notifyAll();
}
}
public int getRenderMode() {
public MapRenderer.RenderingRefreshMode getRenderingRefreshMode() {
synchronized (renderThreadManager) {
return renderMode;
}
@@ -503,7 +482,7 @@ public abstract class MapLibreSurfaceView extends SurfaceView implements Surface
protected boolean waitingForSurface;
protected int width;
protected int height;
protected int renderMode;
protected MapRenderer.RenderingRefreshMode renderMode;
protected boolean requestRender;
protected boolean wantRenderNotification;
protected boolean renderComplete;

View File

@@ -112,4 +112,20 @@ public class SurfaceViewMapRenderer extends MapRenderer {
public void waitForEmpty() {
surfaceView.waitForEmpty();
}
/**
* {@inheritDoc}
*/
@Override
public void setRenderingRefreshMode(MapRenderer.RenderingRefreshMode mode) {
surfaceView.setRenderingRefreshMode(mode);
}
/**
* {@inheritDoc}
*/
@Override
public MapRenderer.RenderingRefreshMode getRenderingRefreshMode() {
return surfaceView.getRenderingRefreshMode();
}
}

View File

@@ -132,4 +132,22 @@ public class TextureViewMapRenderer extends MapRenderer {
public boolean isTranslucentSurface() {
return translucentSurface;
}
/**
* {@inheritDoc}
*/
@Override
public void setRenderingRefreshMode(MapRenderer.RenderingRefreshMode mode) {
throw new RuntimeException("setRenderingRefreshMode is not supported for TextureViewMapRenderer. "
+ "Use SurfaceViewMapRenderer to set the rendering refresh mode.");
}
/**
* {@inheritDoc}
*/
@Override
public MapRenderer.RenderingRefreshMode getRenderingRefreshMode() {
throw new RuntimeException("getRenderingRefreshMode is not supported for TextureViewMapRenderer. "
+ "Use SurfaceViewMapRenderer to set the rendering refresh mode.");
}
}