Different types of surface in applications correspond to different layer classes in the surfaceflinger of the local layer of frameworks. This article mainly discusses the implementation and differences of these layers.
Before reading this article, you 'd better understand surfaceflinger, a system service. For more information, see my following two articles:
- Sharedclient in Android surfaceflinger -- display buffer management between the client (surface) and the server (layer)
- Working thread in Android surfaceflinger: threadloop ()
Visual Effects
The following pictures show the visual effects of different layers:
- Layer corresponds to normal window
- Layerdim will make the window behind him become a dark transparent Effect
- Based on layerdim, layerblur may blur the background.
Create Layer
By default, a normal window surface is created. A layer class is created in surfaceflinger. To create a layerdim or layerblur, the application needs to set the flag of the window before binding the View:
Create a layerdim effect:
@ Override <br/> protected void oncreate (bundle icicle) {<br/> // be sure to call the super class. <br/> super. oncreate (icicle); </P> <p> // have the system blur any windows behind this one. <br/> getwindow (). setflags (windowmanager. layoutparams. flag_dim_behind, <br/> windowmanager. layoutparams. flag_dim_behind); <br/> ...... <br/> setcontentview (......); <br/>}
Effect of creating layerblur:
@ Override <br/> protected void oncreate (bundle icicle) {<br/> // be sure to call the super class. <br/> super. oncreate (icicle); </P> <p> // have the system blur any windows behind this one. <br/> getwindow (). setflags (windowmanager. layoutparams. flag_blur_behind, <br/> windowmanager. layoutparams. flag_blur_behind); <br/> ...... <br/> setcontentview (......); <br/>}
Correspondingly, in sufaceflinger, different layers are created based on the flag passed in by the Java layer:
Sp <isurface> surfaceflinger: createsurface (clientid, int PID, <br/> const string8 & name, isurfaceflingerclient: surface_data_t * Params, <br/> displayid D, uint32_t W, uint32_t H, pixelformat format, <br/> uint32_t flags) <br/>{< br/> sp <layerbaseclient> layer; <br/> sp <layerbaseclient :: surface> surfacehandle; <br/> ...... <br/> switch (flags & efxsurfacemask) {<br/> case efxsurfacenormal: <Br/> If (unlikely (flags & epushbuffers) {<br/> layer = createpushbufferssurfacelocked (client, D, ID, <br/> W, H, flags ); <br/>} else {<br/> layer = createnormalsurfacelocked (client, D, ID, <br/> W, H, flags, format ); <br/>}< br/> break; <br/> case efxsurfaceblur: <br/> layer = createblursurfacelocked (client, D, ID, W, H, flags ); <br/> break; <br/> case efxsurfacedim: <br/> layer = createdim Surfacelocked (client, D, ID, W, H, flags); <br/> break; <br/>}</P> <p> If (layer! = 0) {<br/> layer-> setname (name); <br/> settransactionflags (etransactionneeded); <br/> surfacehandle = Layer-> getsurface (); <br/> ........ <br/>}</P> <p> return surfacehandle; <br/>}< br/>
Static structure of layer class
The following figure shows the inheritance relationships between layer classes:
- All layers inherit the layerbaseclient, and surfaceflinger accesses other derived layer classes through the layerbaseclient class.
- The embedded surface class of layerbaseclient inherits the isurface interface, which is used to interact with the surfaceflinger client.
- Both layer and layerbuffer have their own embedded classes: surfacelayer and surfacelayerbuffer, which inherit the embedded class surface of layerbaseclient.
- Layerbuffer has another embedded class: source, and two embedded classes are derived: buffersource and overlaysource.
Isurface Interface
The isurface interface is actually very simple. There are only a few functions:
- Used by the requestbuffer () // layer class to apply for frontbuffer and backbuffer, called during initialization or size change
- Registerbuffers () // used by the layerbuffer class to register the imemoryheap Interface
- Unregisterbuffers () // used by the layerbuffer class to cancel the imemoryheap Interface
- Postbuffer () // post the image data to be refreshed
- Createoverlay () // used to create an overlay Surface
In the derived class of layerbaseclient, an embedded class inherits layerbaseclient: surface, and then implements the corresponding functions of this interface as needed.
Layer class
The layer class is the most commonly used one. Common application Windows correspond to one layer class. The layer class embedded class surfacelayer inherits the isurface interface. When creating a layer class, an isurface interface is returned to the Creator. In addition, the layer class will create two graphicbuffer objects at the time of creation. These two buffers are used as frontbuffer and backbuffer at different times. frontbuffer is used for drawing operations in this window, backbuffer is used for mixed operations on all windows. However, the two graphicbuffer objects do not really allocate memory when they are created. Instead, they formally apply for memory using the requestbuffer method of the isurface interface at the first lockbuffer. When the window size changes, you also need to re-allocate memory suitable for the window size. The main member functions of the layer class are as follows:
- Createsurface () returns the isurface Interface
- Setbuffers () creates two graphicbuffer objects and creates an isurface interface implementation class surfacelayer
- Ondraw () uses OpenGL to mix the image data in frontbuffer into the main surface of OpenGL.
- Dotransaction () detects and processes window size changes
- Lockpageflip () gets the frontbuffer and generates the OpenGL texture of the frontbuffer.
- Finishpageflip () Unlock frontbuffer. After that, the buffer will be queue to the idle list and can be used as the backbuffer next time.
Layerdim and layerblur
Layerdim and layerblur, their display content is fixed (transparent black), so there is no need to allocate two graphicbuffer objects, so they do not inherit from layerbaseclient: surface embedded class, instead, the layerbaseclient: Surface class is directly used as their isurface interface. Take layerdim as an example to trace its draw process:
- When creating layerdim, generate a pure black OpenGL texture in layerdim. initdimmer ()
Void layerdim: initdimmer (surfaceflinger * flinger, uint32_t W, uint32_t h) <br/>{< br/> stexid =-1; <br/> simage = egl_no_image_khr; <br/> ...... <br/> If (likely (flags & displayhardware: direct_texture )) {<br/>/* apply for graphicbuffer */<br/> sp <graphicbuffer> buffer = new graphicbuffer (W, H, pixel_format_rgb_565, <br/> graphicbuffer :: usage_sw_write_often | <br/> graphicbuffer: usage_hw_texture); </P> <p> android_native_buffer_t * clientbuf = buffer-> getnativebuffer (); <br/>/* apply for OpenGL textures */<br/> glgentextures (1, & stexid); <br/> glbindtexture (gl_texture_2d, stexid ); </P> <p> egldisplay dpy = eglgetcurrentdisplay (); <br/> simage = eglcreateimagekhr (dpy, egl_no_context, <br/> principal, (eglclientbuffer) clientbuf, 0 ); <br/> gleglimagetargettexture2does (gl_texture_2d, (gleglimageoes) simage); <br/> ...... <br/> // initialize the texture with zeros <br/> gglsurface t; <br/> buffer-> lock (& T, gralloc_usage_sw_write_often ); <br/> memset (T. data, 0, T. stride * t. height * 2); <br/> buffer-> unlock (); <br/> susetexture = true; <br/>}< br/>
- In ondraw (), mix the texture generated in the first step to the main surface of OpenGL.
Void layerdim: ondraw (const region & clip) const <br/>{< br/> const State & S (drawingstate (); <br/> region :: const_iterator it = clip. begin (); <br/> region: const_iterator const end = clip. end (); <br/> If (S. alpha> 0 & (it! = END) {<br/> const displayhardware & HW (graphicplane (0 ). displayhardware (); <br/> ...... <br/>/* set the transparency value */<br/> glcolor4x (0, 0, 0, alpha); </P> <p> # If defined (dim_with_texture) & defined (egl_android_image_native_buffer) <br/> If (susetexture) {<br/> glbindtexture (gl_texture_2d, stexid); <br/> glable (gl_texture_2d ); <br/> gltexenvx (gl_texture_env, gl_texture_env_mode, gl_replace); <br/> const g Lshort texcoords [4] [2] = {<br/> {0, 0}, <br/> {0, 1}, <br/> {1, 1 }, <br/> {1, 0 }< br/>}; <br/> glmatrixmode (gl_texture); <br/> glloadidentity (); <br/> glableclientstate (gl_texture_coord_array); <br/> gltexcoordpointer (2, gl_short, 0, texcoords ); <br/>} else <br/> # endif <br/> {<br/> gldisable (gl_texture_2d ); <br/>}</P> <p> glshort W = swidth; <br/> glshort H = sheight; <br/> const Gls Hort vertices [4] [2] = {<br/> {0, 0}, <br/> {0, h}, <br/> {W, h }, <br/> {W, 0 }< br/>}; <br/> glvertexpointer (2, gl_short, 0, vertices ); </P> <p> while (it! = END) {<br/> const rect & R = * It ++; <br/> const glint Sy = fbheight-(R. top + R. height (); <br/> glscissor (R. left, Sy, R. width (), R. height (); <br/> gldrawarrays (gl_triangle_fan, 0, 4); <br/>}< br/> gldisableclientstate (gl_texture_coord_array ); <br/>}< br/>
Layerbuffer
Pending