Sunday, March 10, 2019

Surface Flinger


<ZT> SurfaceFlinger

Original posted at http://tjc411.wordpress.com/android/surfaceflinger/
 
SurfaceFlinger is not what draws your window. It allocates a frame buffer for your window, which the framework running in your application draws directly to without interacting with SurfaceFlinger. The only interaction SurfaceFlinger is involved with when you draw your window is to composite the final new frame buffer to the screen once you are done drawing a frame.

1. What is SurfaceFlinger
SurfaceFlinger is one of Android native servers.
It just composes all the surfaces for different applications and send the final composed surface to the framebuffer.
Following is what SurfaceFlinger does:
a. Provide system-wide surface “composer”, handling all surface rendering to framebuffer device.
b. Can combine 2D and 3D surfaces and surfaces from multiple applications
c. Surfaces passed as buffers via Binder IPC calls
d. Can use OpenGL ES and 2D hardware accelerator for its compositions
e. Double-buffering using page-flip
2. SurfaceFlinger Initialization
If you look at SurfaceFlinger.cpp, SurfaceFlinger class is inherited from Thread class. It means when it’s created,it will stay in a loop waiting for events.
Before it waits for events in threadLoop(), readyToRun() gets called for initialization. (refer to Thread::_threadLoop())
status_t SurfaceFlinger::readyToRun()
{
LOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");

// we only support one display currently
int dpy = 0;

{
// initialize the main display
GraphicPlane& plane(graphicPlane(dpy));
DisplayHardware* const hw = new DisplayHardware(this, dpy);
plane.setDisplayHardware(hw);
}
...
// Initialize OpenGL|ES
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_SCISSOR_TEST);
glShadeModel(GL_FLAT);
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
...
}
/*
* Initialize the display to the specified values.
*
*/
DisplayHardware::DisplayHardware(
const sp<SurfaceFlinger>& flinger,
uint32_t dpy)
: DisplayHardwareBase(flinger, dpy),
mFlags(0)
{
init(dpy);
}
void DisplayHardware::init(uint32_t dpy)
{
...
// initialize EGL
EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE, 0,
EGL_NONE
};
...
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, NULL, NULL);
eglGetConfigs(display, NULL, 0, &numConfigs);
....

/*
* Create our main surface
*/
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
}
Following is what init() does:
1. EGL initialization
ESL is needed in order to support OpenGL ES by making connection to Native Window system.
2. Create a surface
EGL’s three types of surface:
windows: used for onscreen rendering (framebuffer)
pbuffers: used for offscreen rendering
pixmaps: used for offscreen rendering through native API
static int mapFrameBuffer(struct private_module_t* module)//hardware/*
-> open fb device
-> obtain FSCREEN_INFO and VSSCREEN_INFO
-> get buffer pointer that you can use to access fb device through mmap()
3. Create OpenGL ES Context
4. Gather OpenGL ES
5. Initialize HW Modules(copybit, overlay)
- copybit supports bitblt and stretchbitblt.
it is basically used for frequent operations when drawing such as copying and scaling.

0 Comments:

Post a Comment