Look at the Surface

Surface’s official introduction: Handle onto a raw buffer that is being managed by the screen Compositor, the Surface is a Handle to the raw buffer, You can get a Canvas with Surface.

Canvas canvas = mSurface.lockCanvas(null);
mSurface.unlockCanvasAndPost(canvas);
Copy the code

SurfaceView

SurfaceView encapsulates the Surface, and inside it helps us manage a Surface. We use SurfaceView to get the Surface to draw, please refer to the official explanation:

Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen

The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.

The transparent region that makes the surface visible is based on the layout positions in the view hierarchy. If the post-layout transform properties are used to draw a sibling view on top of the SurfaceView, the view may not be properly composited with the surface.

Access to the underlying surface is provided via the SurfaceHolder interface, which can be retrieved by calling getHolder().

The Surface will be created for you while the SurfaceView’s window is visible; you should implement SurfaceHolder.Callback#surfaceCreated and SurfaceHolder.Callback#surfaceDestroyed to discover when the Surface is created and destroyed as the window is shown and hidden.

One of the purposes of this class is to provide a surface in which a secondary thread can render into the screen. If you are going to use it this way, you need to be aware of some threading semantics:

  • All SurfaceView and SurfaceHolder.Callback methods will be called from the thread running the SurfaceView’s window (typically the main thread of the application). They thus need to correctly synchronize with any state that is also touched by the drawing thread.
  • You must ensure that the drawing thread only touches the underlying Surface while it is valid — between SurfaceHolder.Callback.surfaceCreated() and SurfaceHolder.Callback.surfaceDestroyed().

Drawing process:

  • GetSurface from surfaceholder. getSurface;
  • You can get the Canvas of the Surface by using surface. lockCanvas.
  • Draw images using Canvas;
  • Using Surface. UnlockCanvasAndPost can release the Canvas.

GLSurfaceView

GLSurfaceView inherits from SurfaceView, and encapsulates SurfaceView again, which is convenient for us to use OpenGL in Android.

GLSurfaceView provides the following features:

  • Provide and manage a separate Surface;
  • Provides and manages an EGL display that allows OpengL to render content on the Surface above;
  • Support user custom Renderer (Render), set a custom Renderer through setRenderer;
  • Let the renderer run in a separate GLThread thread from the UI thread;
  • Support both on-demand and continuous rendering modes;
  • GPU acceleration: The efficiency of GLSurfaceView is more than 30 times that of SurfaceView. SurfaceView uses canvas to draw, and GLSurfaceView uses GPU acceleration to improve the drawing efficiency.
  • View’s onDraw(Canvas Canvas) is rendered using the Skia rendering engine, while GLSurfaceView’s Renderer’s onDrawFrame(GL10 GL) is rendered using the OpengL rendering engine.

See official explanation:

An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering.

A GLSurfaceView provides the following features:

  • Manages a surface, which is a special piece of memory that can be composited into the Android view system.
  • Manages an EGL display, which enables OpenGL to render into a surface.
  • Accepts a user-provided Renderer object that does the actual rendering.
  • Renders on a dedicated thread to decouple rendering performance from the UI thread.
  • Supports both on-demand and continuous rendering.
  • Optionally wraps, traces, and/or error-checks the renderer’s OpenGL calls.

conclusion

In addition to the above differences, SurfaceView is more universal, GLSurfaceView rendering is more delicate, if you want to make the ordinary SurfaceView rendering effect is better, you can add anti-aliasing effect, but anti-aliasing effect will have a certain performance consumption, hard decoding set surface mode, Just use the regular SurfaceView.

The player with good general compatibility supports both SurfaceView and GLSurfaceView modes for users to choose according to actual scenarios. Take the RTSP and RTMP players of Android platform of Daniu Live SDK(Github) as an example:

    /* Create rendering */
    private boolean CreateView(a) {

        if (sSurfaceView == null) {

            Log.i(TAG, "CreateView..");

            String manufacturer = Build.MANUFACTURER;
            Log.i(TAG, "CreateView, current manufacturer: " + manufacturer);

            if (is_enable_hardware_render_mode) {
                // Hardware Render mode with the second parameter set to false
                sSurfaceView = NTRenderer.CreateRenderer(this.false);
            } else {
                // You can define this character string by yourself. For example, if huawei is selected, enter Huawei and Meizu
                if ("huawei".equalsIgnoreCase(manufacturer)) {
                    sSurfaceView = NTRenderer.CreateRenderer(this.true);
                } else {
                    /* * useOpenGLES2: If with true: Check if system supports openGLES, if * supported, it will choose openGLES. If with false: it will set * with default surfaceView; * /
                    sSurfaceView = NTRenderer.CreateRenderer(this.true); }}}if (sSurfaceView == null) {
            Log.i(TAG, "Create render failed..");
            return false;
        }

        if (is_enable_hardware_render_mode) {
            SurfaceHolder surfaceHolder = sSurfaceView.getHolder();
            if (surfaceHolder == null) {
                Log.e(TAG, "CreateView, surfaceHolder with null..");
            }
            surfaceHolder.addCallback(this);
        }

        return true;
    }
Copy the code

Interested developers can refer to the official documentation.