天天看點

Android播放器之SurfaceView與GLSurfaceView

先看Surface

Surface的官方介紹:Handle onto a raw buffer that is being managed by the screen compositor,Surface是一個raw buffer的句柄,通過它在raw buffer上進行繪制,可以通過Surface獲得一個Canvas。

Canvas canvas = mSurface.lockCanvas(null);
mSurface.unlockCanvasAndPost(canvas);           

SurfaceView

SurfaceView對Surface進行了一次封裝,它内部幫我們管理了一個Surface。我們使用SurfaceView其實最終都是擷取到這個Surface去繪制,可參看官方解釋:

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()

    SurfaceHolder.Callback.surfaceDestroyed()

繪制過程:

  • 通過SurfaceHolder.getSurface可以擷取到Surface;
  • 通過Surface.lockCanvas可以擷取到Surface的Canvas;
  • 使用Canvas繪制圖像;
  • 使用Surface.unlockCanvasAndPost可以釋放Canvas。

GLSurfaceView

GLSurfaceView繼承自SurfaceView,對SurfaceView又做了一次封裝,友善我們在安卓中使用OpenGL。

GLSurfaceView提供了以下特性:

  • 提供并且管理一個獨立的Surface;
  • 提供并且管理一個EGL display,它能讓opengl把内容渲染到上述的Surface上;
  • 支援使用者自定義渲染器(Render),通過setRenderer設定一個自定義的Renderer;
  • 讓渲染器在獨立的GLThread線程裡運作,和UI線程分離;
  • 支援按需渲染(on-demand)和連續渲染(continuous)兩種模式;
  • GPU加速:GLSurfaceView的效率是SurfaceView的30倍以上,SurfaceView使用畫布進行繪制,GLSurfaceView利用GPU加速提高了繪制效率;
  • View的繪制onDraw(Canvas canvas)使用Skia渲染引擎渲染,而GLSurfaceView的渲染器Renderer的onDrawFrame(GL10 gl)使用opengl繪制引擎進行渲染。

參看官方解釋:

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.

總結

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

        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模式,第二個參數設定為false
                sSurfaceView = NTRenderer.CreateRenderer(this, false);
            } else {
                //這個字元串可以自己定義,例如判斷華為就填寫huawei,魅族就填寫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;
    }           

繼續閱讀