Surfaceflinger the output of the image after it is synthesized. In the image output, there are some differences between the hardware synthesizer and the non-existent situation. The software is synthesized using the image buffer producer and consumer model. First, take a look at the initialization of the image buffers.
void Surfaceflinger::init () {alogi ("Surfaceflinger ' s main thread ready to run.") "Initializing graphics h/w ..."); ...//Initialize our non-virtual displays for (size_t i=0; i<displaydevice::num_builtin_display_types; i++) {displaydevice::D isplaytype Type ((displaydevice::D isplaytype) i); Set-up the displays that is already connected if (mhwc->isconnected (i) | | type==displaydevice::D isplay_prima RY) {//All non-virtual displays is currently considered secure. bool Issecure = true; createbuiltindisplaylocked (type); Wp<ibinder> token = mbuiltindisplays[i]; Sp<igraphicbufferproducer> producer; Sp<igraphicbufferconsumer> consumer; Bufferqueue::createbufferqueue (&producer, &consumer, New Graphicbufferalloc ()); Sp<framebuffersurface> FBS = new Framebuffersurface (*MHWC, I, conSumer); int32_t hwcid = Allocatehwcdisplayid (type); sp<displaydevice> HW = new Displaydevice (this, type, Hwcid, Mhwc->getformat (hwcid), Issecure, Token, FBS, producer, Mrenderengine->geteglconfig ()); if (i > Displaydevice::D isplay_primary) {//fixme:currently we don ' t get Blank/unblank requests For displays and than the main display, so we all//assume a connected display is Unblank Ed. ALOGD ("Marking display%zu as acquired/unblanked", I); Hw->setpowermode (Hwc_power_mode_normal); } mdisplays.add (token, HW); } } ......}
The
- calls Bufferqueue::createbufferqueue to create an image buffer and get its producer and consumer interfaces
- to create framebuffersurface using the consumer consumer interface obtained above
- Create Displaydevice
- displaydevice software synthesized images using the resulting producer producer interface to consume processing in framebuffersurface
Displaydevice::D isplaydevice (const sp<surfaceflinger>& Flinger, DisplayType type, int32_t hwcid, int format, bool issecure, const wp<ibinder>& Displaytoken, const SP<DISPL aysurface>& Displaysurface, const sp<igraphicbufferproducer>& producer, EGLConfig config) : Lastcompositionhadvisiblelayers (False), Mflinger (Flinger), Mtype (type), Mhwcdisplayid (hwcid), Mdisplayt Oken (Displaytoken), Mdisplaysurface (Displaysurface), Mdisplay (Egl_no_display), Msurface (Egl_no_surface), Mdisplaywidth (), Mdisplayheight (), Mformat (), Mflags (), Mpageflipcount (), Missecure (issecure), MSec Urelayervisible (False), Mlayerstack (No_layer_stack), Morientation (), Mpowermode (Hwc_power_mode_off), M Activeconfig (0) {Mnativewindow = new Surface (producer, false); anativewindow* Const window = Mnativewindow.get (); /* * Create our DISPlay ' surface */eglsurface surface; Egldisplay display = Eglgetdisplay (egl_default_display); if (config = = egl_no_config) {config = renderengine::chooseeglconfig (display, format); Surface = Eglcreatewindowsurface (Display, config, window, NULL); Eglquerysurface (display, surface, egl_width, &mdisplaywidth); Eglquerysurface (display, surface, egl_height, &mdisplayheight); Make sure this composition can never be stalled by a virtual display//consumer that isn ' t processing buffers fast Enough. We have a to does this//in the Places://* Here, in case the display was composed entirely by HWC. * in Makecurrent (), using Eglswapinterval. Some EGL Drivers set the//window ' s swap interval in eglmakecurrent, so they ' ll override the//interval we set Here. if (mtype >= displaydevice::D isplay_virtual) window->setswapinterval (window, 0); mconfig = config; Mdisplay = display; Msurface = surface; Mformat = format; Mpageflipcount = 0; Mviewport.makeinvalid (); Mframe.makeinvalid (); Virtual displays is always considered enabled Mpowermode = (mtype >= displaydevice::D isplay_virtual)? Hwc_power_mode_normal:hwc_power_mode_off; Name the display. The name would be replaced shortly if the display//is created with Createdisplay (). Switch (mtype) {case display_primary:mdisplayname = ' built-in screen '; Break Case display_external:mdisplayname = "HDMI screen"; Break Default:mdisplayname = "Virtual screen"; e.g. Overlay #n break; }//Initialize the display orientation transform. Setprojection (Displaystate::eorientationdefault, Mviewport, mframe);}
- Initializing the EGL graphics library using the producer interface
- The EGL graphics library is called when the software draws the layer, and the producer interface is called indirectly
In Surfaceflinger: Call the Docomposesurfaces function composition layer in the:d odisplaycomposition function, and then call Hw->swapbuffers. For no hwcomper exists, the direct commit is displayed. When Hwcomper is present, the layer of the software composition is referred to hwcomper for processing.
void Displaydevice::swapbuffers (hwcomposer& hwc) const {//We need to call Eglswapbuffers () if: (1) We don ' t have a hardware composer, or//(2) We do GLES composition this frame, and either (a) We have framebuffer target support (not present on legacy//devices, where hwcomposer::commit () h Andles things); or//(b) This is a virtual display if (Hwc.initcheck ()! = No_error | | (Hwc.hasglescomposition (Mhwcdisplayid) && (hwc.supportsframebuffertarget () | | | mtype >= DISPL ay_virtual)) {Eglboolean success = Eglswapbuffers (Mdisplay, msurface); if (!success) {Eglint error = Eglgeterror (); if (Error = = Egl_context_lost | | Mtype = = Displaydevice::D isplay_primary) {log_always_fatal ("eglswapbuffers (%p,%p) failed W ITH 0x%08x ", Mdisplay, Msurface, error); } else {Aloge ("eglswapbuffers (%p,%p) failed with 0x%08x", Mdisp Lay, Msurface, error); }}} status_t result = Mdisplaysurface->advanceframe (); if (Result! = No_error) {aloge ("[%s] failed pushing new frame to HWC:%d", mdisplayname.string () , result); } }
- Call Eglswapbuffers commit gles composition buffer when no hwcomposer exists or hwcomposer is present but gles composition is used
- Other conditions do not handle layer layers
Eglswapbuffers submits the buffer of the gles synthesis to the layer consumer to deal with, the previous article mentions that the consumer is framebuffersurface. Look at its handler function:
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) { sp<GraphicBuffer> buf; sp<Fence> acquireFence; status_t err = nextBuffer(buf, acquireFence); if (err != NO_ERROR) { ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)", strerror(-err), err); return; } err = mHwc.fbPost(mDisplayType, acquireFence, buf); if (err != NO_ERROR) { ALOGE("error posting framebuffer: %d", err); }}
- Call Mhwc.fbpost commit buffer to Hwcomposer function
int HWComposer::fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) { if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { return setFramebufferTarget(id, acquireFence, buffer); } else { acquireFence->waitForever("HWComposer::fbPost"); return mFbDev->post(mFbDev, buffer->handle); }}
- When a hardware synthesizer is present, call the Setframebuffertarget function to submit the results of the software composition to the hardware synthesizer to blend the layer output
- When there is no hardware synthesizer, call Mfbdev->post directly to submit the results of the software synthesis to framebuffer in the output
When you finish dodisplaycomposition in Surfaceflinger, the layer is processed and the Postframebuffer submission layer is called to Hwcomposer.
void SurfaceFlinger::postFramebuffer(){ ATRACE_CALL(); ...... HWComposer& hwc(getHwComposer()); if (hwc.initCheck() == NO_ERROR) { if (!hwc.supportsFramebufferTarget()) { // EGL spec says: // "surface must be bound to the calling thread‘s current context, // for the current rendering API." getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); } hwc.commit(); } ......}
- Call Hwc.commit () to submit the layer when there is hwcomposer.
status_t Hwcomposer::commit () {int err = No_error; if (MHWC) {if (!hwchasapiversion (MHWC, hwc_device_api_version_1_1)) {//On VERSION 1.0, the Ope NGL ES Target surface is communicated//by the (Dpy, Sur) fields and we were guaranteed to has only A single display. Mlists[0]->dpy = Eglgetcurrentdisplay (); Mlists[0]->sur = Eglgetcurrentsurface (Egl_draw); } for (size_t i=virtual_display_id_base; i<mnumdisplays; i++) {displaydata& disp (mdisplaydat A[i]); if (disp.outbufhandle) {mlists[i]->outbuf = Disp.outbufhandle; MLISTS[I]->OUTBUFACQUIREFENCEFD = Disp.outbufacquirefence->dup (); }} Err = Mhwc->set (MHWC, Mnumdisplays, mlists); for (size_t i=0; i<mnumdisplays; i++) {displaydata& disp (mDiSplaydata[i]); Disp.lastdisplayfence = disp.lastretirefence; Disp.lastretirefence = fence::no_fence; if (disp.list) {if (disp.list->retirefencefd! =-1) {disp.lastretirefence = New Fence (DISP.LIST->RETIREFENCEFD); DISP.LIST->RETIREFENCEFD =-1; } disp.list->flags &= ~hwc_geometry_changed; }}} "return (status_t) err;}
- Call Mhwc->set to compose and output the layer graph to the display device using hardware
Android Surfaceflinger Service (eight) output of-----image