Class InterlacedSurfaceView

  • All Implemented Interfaces:
    Drawable.Callback, AccessibilityEventSource, KeyEvent.Callback, SurfaceHolder.Callback, SurfaceHolder.Callback2, InterlacedView

    public class InterlacedSurfaceView
    extends SurfaceView
    implements InterlacedView
    InterlacedSurfaceView interlaces InputViewsAsset for Leia Display.

    Moving and Resizing an InterlacedSurfaceView

    Since interlacing depends on the precise location on the screen of the image, we need to keep the InterlacedSurfaceView up-to-date with its position and size. Currently, the rendering of InterlacedSurfaceView and its presentation on the screen is asynchronous. So animating position and size generally not supported.
    Scaling animations
    There is no way to support them at the moment. Avoid them at all costs.

    Usually, there are scaling animations on over-scroll. They can be entirely disabled by calling View.setOverScrollMode(int) with View.OVER_SCROLL_NEVER.

    Move animations
    Currently, move animations can be supported by forcing a view to move over a predefined pixels grid, i.e. move it with a non-unit step. We call this grid the interlace pattern grid. The grid step depends on the display. For the 9V display, X-step is 3px, and Y-step is 9px. This behavior is disabled by default because InterlacedSurfaceView can be rendered at any location on the screen. There are problems only when location is constantly changing. There are currently two ways to align a view to the grid: manual and automatic. The automatic approach covers most of the use cases. The known use-cases where the automatic approach is enough - androidx.recyclerview.widget.RecyclerView, androidx.viewpager2.widget.ViewPager2, and com.google.android.material.appbar.AppBarLayout. The manual approach requires the user to call updatePosition(boolean, boolean) when the view is moved. The manual approach is the only known way to handle ScrollView and HorizontalScrollView.

    To activate the automatic grid alignment either call setAutoAlign(boolean, boolean) or add autoAlignX or/and autoAlignY attributes to the XML. If your view is expected to be moving horizontally, it should be aligned over the X-axis. And the same applies to vertical movement and the Y-axis.

    Manual position update with a ScrollView can be done this way:

     interlacedSurfaceView.setManualPositionUpdate(true); // Not necessary but preferably to specify your intentions explicitly
     verticalScrollView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
         interlacedSurfaceView.updatePosition(false, true);
     });

    Transparency

    InterlacedSurfaceView supports transparency. It should be explicitly enabled on initialization. This can be done in two ways: either specify supportsTransparency=true attribute or use InterlacedSurfaceView(Context, boolean, boolean).
    • Method Detail

      • setRenderMode

        public void setRenderMode​(int renderMode)
        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 requestRender() is called. Defaults to RENDERMODE_CONTINUOUSLY.

        Using RENDERMODE_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.

        This method can only be called after setRenderer(Renderer)

        Parameters:
        renderMode - one of the RENDERMODE_X constants
        See Also:
        RENDERMODE_CONTINUOUSLY, RENDERMODE_WHEN_DIRTY
      • setFrameRate

        public void setFrameRate​(long period,
                                 TimeUnit unit)
      • setFrameRate

        public void setFrameRate​(float fps)
      • releaseInputViewsAsset

        public void releaseInputViewsAsset()
      • surfaceCreated

        public void surfaceCreated​(SurfaceHolder holder)
        This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients of LeiaGLSurfaceView.
        Specified by:
        surfaceCreated in interface SurfaceHolder.Callback
      • surfaceDestroyed

        public void surfaceDestroyed​(SurfaceHolder holder)
        This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients of LeiaGLSurfaceView.
        Specified by:
        surfaceDestroyed in interface SurfaceHolder.Callback
      • setAutoAlign

        public void setAutoAlign​(boolean x,
                                 boolean y)
        Configures InterlacedSurfaceView to automatically align to work around move animation limitations. Set both arguments to false to disable any alignment (default).
        Specified by:
        setAutoAlign in interface InterlacedView
        Parameters:
        x - align in the X-axis
        y - align in the Y-axis
      • setManualPositionUpdate

        public void setManualPositionUpdate​(boolean manualPositionUpdate)
        Configures whether InterlacedSurfaceView should rely on the user to keep its position synchronized.
        See Also:
        updatePosition(boolean, boolean)
      • updatePosition

        public void updatePosition​(boolean alignX,
                                   boolean alignY)
        Notify InterlacedSurfaceView that its position has been changed. Optionally, allows to align the view to work around move animation limitations.
      • getRectMatrix

        public float[] getRectMatrix()
        Get the rect matrix
        Specified by:
        getRectMatrix in interface InterlacedView
        Returns:
        the rect matrix if available or an identity matrix
      • getZonePlateResults

        public ZonePlateResults getZonePlateResults()
        Get zonePlate results.
      • setSupportCirclePhase

        public void setSupportCirclePhase​(float phase)
        Set zonePlate parameter.
      • writeZonePlateResultsToInterlacer

        public boolean writeZonePlateResultsToInterlacer​(float slant,
                                                         float pitch,
                                                         float phc,
                                                         float dOverN,
                                                         float n)
        Write zoneplate results to interlacer
      • setCameraRectificationParameters

        public void setCameraRectificationParameters​(boolean isFront,
                                                     float deltaThetaX,
                                                     float deltaThetaY,
                                                     float deltaThetaZ,
                                                     float calibrationTargetDistanceMm)
      • setCameraAngles

        public void setCameraAngles​(boolean isLeft,
                                    float thetaXFpc,
                                    float thetaYFpc,
                                    float thetaZFpc)
      • getActCoef

        public float getActCoef()
      • getScaleTypeMatrix

        public Matrix getScaleTypeMatrix()
        Get the scale type matrix
        Specified by:
        getScaleTypeMatrix in interface InterlacedView
        Returns:
        the scale type matrix if available or an identity matrix
      • isAGSL

        public boolean isAGSL()
        Description copied from interface: InterlacedView
        Is the view drawn by an AGSL RuntimeShader?
        Specified by:
        isAGSL in interface InterlacedView
        Returns:
        true if view is drawn with AGSL
      • clearAllInterlacers

        public static void clearAllInterlacers()
      • setGLWrapper

        public void setGLWrapper​(com.leia.sdk.views.LeiaGLSurfaceView.GLWrapper glWrapper)
        Set the glWrapper. If the glWrapper is not null, its LeiaGLSurfaceView.GLWrapper.wrap(GL) method is called whenever a surface is created. A GLWrapper can be used to wrap the GL object that's passed to the renderer. Wrapping a GL object enables examining and modifying the behavior of the GL calls made by the renderer.

        Wrapping is typically used for debugging purposes.

        The default value is null.

        Parameters:
        glWrapper - the new GLWrapper
      • setDebugFlags

        public void setDebugFlags​(int debugFlags)
        Set the debug flags to a new value. The value is constructed by OR-together zero or more of the DEBUG_CHECK_* constants. The debug flags take effect whenever a surface is created. The default value is zero.
        Parameters:
        debugFlags - the new debug flags
        See Also:
        DEBUG_CHECK_GL_ERROR, DEBUG_LOG_GL_CALLS
      • getDebugFlags

        public int getDebugFlags()
        Get the current value of the debug flags.
        Returns:
        the current value of the debug flags.
      • setPreserveEGLContextOnPause

        public void setPreserveEGLContextOnPause​(boolean preserveOnPause)
        Control whether the EGL context is preserved when the LeiaGLSurfaceView is paused and resumed.

        If set to true, then the EGL context may be preserved when the LeiaGLSurfaceView is paused.

        Prior to API level 11, whether the EGL context is actually preserved or not depends upon whether the Android device can support an arbitrary number of EGL contexts or not. Devices that can only support a limited number of EGL contexts must release the EGL context in order to allow multiple applications to share the GPU.

        If set to false, the EGL context will be released when the LeiaGLSurfaceView is paused, and recreated when the LeiaGLSurfaceView is resumed.

        The default is false.

        Parameters:
        preserveOnPause - preserve the EGL context when paused
      • getPreserveEGLContextOnPause

        public boolean getPreserveEGLContextOnPause()
        Returns:
        true if the EGL context will be preserved when paused
      • setEGLContextFactory

        public void setEGLContextFactory​(com.leia.sdk.views.LeiaGLSurfaceView.EGLContextFactory factory)
        Install a custom EGLContextFactory.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        If this method is not called, then by default a context will be created with no shared context and with a null attribute list.

      • setEGLWindowSurfaceFactory

        public void setEGLWindowSurfaceFactory​(com.leia.sdk.views.LeiaGLSurfaceView.EGLWindowSurfaceFactory factory)
        Install a custom EGLWindowSurfaceFactory.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        If this method is not called, then by default a window surface will be created with a null attribute list.

      • setEGLConfigChooser

        public void setEGLConfigChooser​(com.leia.sdk.views.LeiaGLSurfaceView.EGLConfigChooser configChooser)
        Install a custom EGLConfigChooser.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        If no setEGLConfigChooser method is called, then by default the view will choose an EGLConfig that is compatible with the current android.view.Surface, with a depth buffer depth of at least 16 bits.

        Parameters:
        configChooser -
      • setEGLConfigChooser

        public void setEGLConfigChooser​(boolean needDepth)
        Install a config chooser which will choose a config as close to 16-bit RGB as possible, with or without an optional depth buffer as close to 16-bits as possible.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        If no setEGLConfigChooser method is called, then by default the view will choose an RGB_888 surface with a depth buffer depth of at least 16 bits.

        Parameters:
        needDepth -
      • setEGLConfigChooser

        public void setEGLConfigChooser​(int redSize,
                                        int greenSize,
                                        int blueSize,
                                        int alphaSize,
                                        int depthSize,
                                        int stencilSize)
        Install a config chooser which will choose a config with at least the specified depthSize and stencilSize, and exactly the specified redSize, greenSize, blueSize and alphaSize.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        If no setEGLConfigChooser method is called, then by default the view will choose an RGB_888 surface with a depth buffer depth of at least 16 bits.

      • setEGLContextClientVersion

        public void setEGLContextClientVersion​(int version)
        Inform the default EGLContextFactory and default EGLConfigChooser which EGLContext client version to pick.

        Use this method to create an OpenGL ES 2.0-compatible context. Example:

             public MyView(Context context) {
                 super(context);
                 setEGLContextClientVersion(2); // Pick an OpenGL ES 2.0 context.
                 setRenderer(new MyRenderer());
             }
         

        Note: Activities which require OpenGL ES 2.0 should indicate this by setting @lt;uses-feature android:glEsVersion="0x00020000" /> in the activity's AndroidManifest.xml file.

        If this method is called, it must be called before setRenderer(Renderer) is called.

        This method only affects the behavior of the default EGLContexFactory and the default EGLConfigChooser. If setEGLContextFactory(EGLContextFactory) has been called, then the supplied EGLContextFactory is responsible for creating an OpenGL ES 2.0-compatible context. If setEGLConfigChooser(EGLConfigChooser) has been called, then the supplied EGLConfigChooser is responsible for choosing an OpenGL ES 2.0-compatible config.

        Parameters:
        version - The EGLContext client version to choose. Use 2 for OpenGL ES 2.0
      • getRenderMode

        public int getRenderMode()
        Get the current rendering mode. May be called from any thread. Must not be called before a renderer has been set.
        Returns:
        the current rendering mode.
        See Also:
        RENDERMODE_CONTINUOUSLY, RENDERMODE_WHEN_DIRTY
      • requestRender

        public void requestRender()
        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. May be called from any thread. Must not be called before a renderer has been set.
      • surfaceChanged

        public void surfaceChanged​(SurfaceHolder holder,
                                   int format,
                                   int w,
                                   int h)
        This method is part of the SurfaceHolder.Callback interface, and is not normally called or subclassed by clients of LeiaGLSurfaceView.
        Specified by:
        surfaceChanged in interface SurfaceHolder.Callback
      • onPause

        public void onPause()
        Pause the rendering thread, optionally tearing down the EGL context depending upon the value of setPreserveEGLContextOnPause(boolean). This method should be called when it is no longer desirable for the LeiaGLSurfaceView to continue rendering, such as in response to Activity.onStop. Must not be called before a renderer has been set.
      • onResume

        public void onResume()
        Resumes the rendering thread, re-creating the OpenGL context if necessary. It is the counterpart to onPause(). This method should typically be called in Activity.onStart. Must not be called before a renderer has been set.
      • queueEvent

        public void queueEvent​(Runnable r)
        Queue a runnable to be run on the GL rendering thread. This can be used to communicate with the Renderer on the rendering thread. Must not be called before a renderer has been set.
        Parameters:
        r - the runnable to be run on the GL rendering thread.
      • onAttachedToWindow

        protected void onAttachedToWindow()
        This method is used as part of the View class and is not normally called or subclassed by clients of LeiaGLSurfaceView.
        Overrides:
        onAttachedToWindow in class SurfaceView