Android OpenGL Getting Started GLSurfaceView

  • 2021-12-12 09:38:50
  • OfStack

GLSurfaceView use

OpenGL ES is an open source graphics library, so it needs one thing to display the picture. In android, opengl package provides an View called GLSurfaceView, which is defined as follows:

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

Its characteristics are as follows:

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.

It can be seen that the system has packaged an View for rendering pictures and can be set accordingly.

The steps are as follows:

1. Create and define an GLSurfaceView
2. Call setEGLContextClientVersion of GLSurfaceView to set the version number, which can be set to 2
3. onResume and onPause call the corresponding lifecycle methods of GLSurfaceView, respectively
4. Call setRender of GLSurfaceView to set up its own class that implements the GLSurfaceView. Render interface
5. There are three methods of Render interface, which are initialization of SurfaceCreated, adaptation of width and height of SurfaceChange and specific DrawFrame method

onSurfaceCreated(GL10 gl, EGLConfig config); onSurfaceChanged(GL10 gl, int width, int height); onDrawFrame(GL10 gl);

GLSurfaceView detailed analysis:

1. GLSurfaceView calls init () in the constructor to set the three drop-back functions as above


private void init() {
      SurfaceHolder holder = getHolder();
      holder.addCallback(this);
  }

2. setRender will make some default settings, and generate a thread of GLThread to render and draw related operations, and the drawn content is still drawn to Surface provided by SurfaceView by default


  public void setRenderer(Renderer renderer) {
      checkRenderThreadState();
      if (mEGLConfigChooser == null) {
          mEGLConfigChooser = new SimpleEGLConfigChooser(true);
      }
      if (mEGLContextFactory == null) {
          mEGLContextFactory = new DefaultContextFactory();
      }
      if (mEGLWindowSurfaceFactory == null) {
          mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
      }
      mRenderer = renderer;
      mGLThread = new GLThread(mThisWeakRef);
      mGLThread.start();
  }

3. guardedRun () method is called in run () method of GLThread, new is called an EglHelper class in guardedRun method, and start method of EglHelper is called after a logical judgment.

4. In the EglHelper. start () method


 public void start() {
    mEgl = (EGL10) EGLContext.getEGL();
    mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

    if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
       throw new RuntimeException("eglGetDisplay failed");
    }
    int[] version = new int[2];
    if(!mEgl.eglInitialize(mEglDisplay, version)) {
      throw new RuntimeException("eglInitialize failed");
    }
    GLSurfaceView view = mGLSurfaceViewWeakRef.get();
    if (view == null) {
        mEglConfig = null;
        mEglContext = null;
    } else {
        mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
        mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
    }
    ...
}

There are several important methods that will eventually call the C + + layer to initialize the related rendering interface

EGLContext.getEGL() eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY) eglInitialize(mEglDisplay, version) createContext()

5. The EglHelper. createSurface () method is called after the guardedRun () start () call, and eventually the C + + layer is also called.


public boolean createSurface() {
//Check preconditions.
//window size has changed, create a new surface.
	destroySurfaceImp();
//Create an EGL surface we can render into.
    GLSurfaceView view = mGLSurfaceViewWeakRef.get();
    if (view != null) {
       	mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
                        mEglDisplay, mEglConfig, view.getHolder());
    } else {mEglSurface = null;}
    ...
    int error = mEgl.eglGetError();
	...
    if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
     	logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
     	return false;
   	}
    return true;
}
createWindowSurface eglGetError eglMakeCurrent

EGL related knowledge

EGL is used to manage drawing surfaces with the following mechanism

Communicate with the device's native window system Query the available types and configurations of drawing surfaces Create a drawing surface Synchronize rendering between OpenGL ES 3.0 and other graphics rendering API Manage rendering resources such as texture maps

EGLDisplay: Since each window system has different semantics, EGL provides the basic opaque type EGLDisplay, encapsulating all system dependencies for interfacing with native window systems

EGL has the following methods:

EGLDisplay eglGetDisplay(Object native_display);
1. Open Link to EGL Display Server Open Link to EGL Display Server
2. native_display is an displayId that specifies the display link, and the default link is EGL_DEFAULT_DISPLAY

boolean eglInitialize(EGLDisplay display, int[] major_minor)
1. After opening the link, you need to initialize EGL
2. display: Value returned by getDisplay
3. Primary and minor version numbers

boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config);
1. Let EGL select a matching EGLConfig
2. Specifically, call the selection configuration, and the configuration details will not be described for the time being

EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
1. Create a rendering context
2. display: Specified display link
3. config: Specified configuration
4. share_context: Allows multiple EGL contexts to share specific types of data; Use EGL_NO_CONTEXT to indicate no sharing
5. attrib_list: Specifies the list of attributes used by the creation context; There is only one acceptable attribute: EGL_CONTEXT_CLIENT_VERSION for specifying the version of OpenGL ES that you are using
6. When eglCreateContext succeeds, it returns a handle to the newly created context.

EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
1. With an EGLConfig that meets the rendering requirements, you can call this function to create a window
2. The attributes are the same as above

int eglGetError();
1. The EGL function returns EGL_TRUE on success or EGL_FALSE otherwise. If you need to query the cause of the failure, call eglGetError () and get the error code returned.

boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);
1. Because a single application can create multiple EGLContext for different purposes, you need to associate a specific EGLContext with a rendering surface: Specify the current context

The whole approximate process is called as mentioned above.

The above is Android OpenGL Getting Started GLSurfaceView details, more information about Android GLSurfaceView please pay attention to other related articles on this site!


Related articles: