Android4.2.2 creation of Layer and Bufferqueue of SurfaceFlinger

Source: Internet
Author: User

This article is a summary of the source code. Please specify the source for the transfer. Thank you.

Welcome to your discussion. Qq: 1037701636 email: gzzaigcn2012@gmail.com

Android source code Version: 4.2.2; hardware platform A31

Based on BootAnimation, the previous blog post came to the SurfaceFlinger Surface creation process. The specific implementation was completed by the createSurface of the Client. In fact, the Surface on the client exists in the server with the name of the Layer.

Sp
 
  
Client: createSurface (ISurfaceComposerClient: surface_data_t * params, const String8 & name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {/** createSurface must be called from the GL thread so that it can * have access to the GL context. */class MessageCreateLayer: public MessageBase {sp
  
   
Result; SurfaceFlinger * flinger; ISurfaceComposerClient: surface_data_t * params; Client * client; const String8 & name; uint32_t w, h; PixelFormat format; uint32_t flags; public: response (SurfaceFlinger * flinger, response: response * params, const String8 & name, Client * client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags): flinger (flinger ), params (params), client (client), name (name), w (w), h (h), format (format), flags (flags) {} sp
   
    
GetResult () const {return result;} virtual bool handler () {result = flinger-> createLayer (params, name, client, w, h, format, flags ); // create a layer return true during message processing;}; sp
    
     
Msg = new MessageCreateLayer (mFlinger. get (), params, name, this, w, h, format, flags); // create a MessageCreateLayer object and assign it to the base class mFlinger-> postMessageSync (msg ); // The message for creating a layer is sent by SF to return static_cast.
     
      
(Msg. get ()-> getResult ();}
     
    
   
  
 

The implementation of this function seems to be somewhat complicated. First, create a Layer-Layer message class for inheritance and MessageBase. Let's start step by step from the constructor analysis.

Step 1: Let's talk about the message processing mechanism on the SurfaceFlinger side. We can use the article "events and message processing mechanisms" on the previous blog post Android4.2.2 SurfaceFlinger, do you know that all messages are finally submitted to SF for message processing. Look at this function mFlinger-> postMessageSync (msg) and you will know that a synchronous message is sent.

status_t SurfaceFlinger::postMessageSync(const sp
 
  & msg,        nsecs_t reltime, uint32_t flags) {    status_t res = mEventQueue.postMessage(msg, reltime);    if (res == NO_ERROR) {        msg->wait();    }    return res;}
 

The member variable MessageQueue mEventQueue of SF is used to send messages.

Status_t MessageQueue: postMessage (const sp
 
  
& MessageHandler, nsecs_t relTime) {const Message dummyMessage; if (relTime> 0) {mLooper-> callback (relTime, messageHandler, dummyMessage);} else {mLooper-> sendMessage (messageHandler, dummyMessage); // use logoff to send a message to the Message Queue} return NO_ERROR ;}
 
Void Logoff: sendMessage (const sp
 
  
& Handler, const Message & message) {nsecs_t now = systemTime (SYSTEM_TIME_MONOTONIC); sendMessageAtTime (now, handler, message); // send messages in time}
 

The focus of input here is that the messageHanler variable is understood as the message handle. According to this call process, it is actually the MessageCreateLayer object.

Here it is basically similar to the RefreshEvent of the previous SF message processing mechanism. You can view the diagram I have summarized on the SF message and event processing mechanism, and finally return

Handler-> handleMessage (message); // handle processing of MessageHandler messages. What is the corresponding handle here and how to call handleMessage? We found it here:

Void MessageBase: handleMessage (const Message &) {this-> handler (); // call the multi-state handle of the inheritance class. this points to the original object, when a base class pointer accesses a derived class object, the barrier of the derived class is called. open ();};

The above msg input is converted into MessageBase, and the input is converted into MessageHandle. However, we know that the member function MessageHandle of MessageBase is not inherited and overloaded. Therefore, the MessageCreateLayer object msg actually calls the handleMessage of MessageBase, the implementation of this function internally calls this-> handle, and it is easy to know that this handleMessage is actually inherited to the msg object of the MessageCreateLayer class. Therefore, it is returned to the handle of MessageCreateLayer.

Step2. with so many detours, call createSurface on the Client side to send a message again so that SurfaceFlinger can process the message and return to the handle of MessageCreateLayer, in handle processing, we found that the processing was actually submitted to SurfaceFlinger.

Virtual bool handler () {result = flinger-> createLayer (params, name, client, w, h, format, flags); // create a layer return true during message processing ;}

Next, let's look at the createLayer function of SurfaceFlinger:

Sp
 
  
SurfaceFlinger: createLayer (ISurfaceComposerClient: surface_data_t * params, const String8 & name, const sp
  
   
& Client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {sp
   
    
Layer; sp
    
     
SurfaceHandle; if (int32_t (w | h) <0) {ALOGE ("createLayer () failed, w or h is negative (w = % d, h = % d )", int (w), int (h); return surfaceHandle;} // ALOGD ("createLayer for (% d x % d), name = % s", w, h, name. string (); switch (flags & ISurfaceComposerClient: eFXSurfaceMask) {case ISurfaceComposerClient: eFXSurfaceNormal: layer = createNormalLayer (client, w, h, flags, format ); // create a new layer pointing to the layer break; Case when: eFXSurfaceBlur: case ISurfaceComposerClient: eFXSurfaceDim: layer = createDimLayer (client, w, h, flags); break; case when: When: layer = createScreenshotLayer (client, w, h, flags); break;} if (layer! = 0) {layer-> initStates (w, h, flags); layer-> setName (name); ssize_t token = addClientLayer (client, layer ); // Add this layer to the client and add the Z axis surfaceHandle = layer-> getSurface (); // use Layer if (surfaceHandle! = 0) {params-> token = token; params-> identity = layer-> getIdentity (); // layer id} setTransactionFlags (eTransactionNeeded);} return surfaceHandle ;}
    
   
  
 


Step 3: process the createNormalLayer function. The actual Layer object is created.

The member function onFirstRef () of Layer ():

Void Layer: onFirstRef () {LayerBaseClient: onFirstRef (); // The base class LayerBaseClient struct FrameQueuedListener: public SurfaceTexture :: frameAvailableListener {// internal class inherits FrameAvailableListener FrameQueuedListener (Layer * layer): mLayer (layer) {} private: wp
 
  
MLayer; virtual void onFrameAvailable () {sp
  
   
That (mLayer. promote (); if (that! = 0) {that-> onFrameQueued (); // call the onFrameQueued of the Layer }}; // Creates a custom BufferQueue for SurfaceTexture to use sp
   
    
Bq = new SurfaceTextureLayer (); // create a new SurfaceTextureLayer, I .e. BufferQueue mSurfaceTexture = new SurfaceTexture (mTextureName, true, GL_TEXTURE_EXTERNAL_OES, false, bq ); mSurfaceTexture-> Merge (getinclutiveusage (0); mSurfaceTexture-> merge (new FrameQueuedListener (this); // create a new frame queue to listen to mSurfaceTexture-> setSynchronousMode (true ); // synchronization mode supported # ifdef resume # warning "disabling triple buffering" mSurfaceTexture-> setdefamaxmaxbuffercount (2); # else mSurfaceTexture-> setDefaultMaxBufferCount (3); # endif const sp
    
     
Hw (mFlinger-> getdefadisplaydisplaydevice (); updateTransformHint (hw );}
    
   
  
 

In this function, there is an internal struct FrameQueuedListener, which listens to frame queues. The SurfaceTextureLayer and SurfaceTexture class objects represent the BufferQueue and ConsumerBase objects respectively. Here, we will directly propose the Layer-related UML diagram to help the following analysis.

Step 4: Let's take a look at the construction process of SurfaceTextureLayer:

The SurfaceTextureLayer construction actually serves BufferQueue. Let's continue to look at the construction process of BufferQueue's core class.

BufferQueue: BufferQueue (bool allowSynchronousMode, const sp
 
  
& Allocator ):....... mdefabuffbufferformat (PIXEL_FORMAT_RGBA_8888), mConsumerUsageBits (0), mTransformHint (0) {// Choose a name using the PID and a process-unique ID. mConsumerName = String8: format ("unnamed-% d", getpid (), createProcessUniqueId (); ST_LOGV ("BufferQueue"); if (allocator = NULL) {sp
  
   
Composer (ComposerService: getComposerService (); mGraphicBufferAlloc = composer-> aggregate (); // create GraphicBuffer if (mGraphicBufferAlloc = 0) {ST_LOGE ("aggregate () failed in BufferQueue () ") ;}} else {mGraphicBufferAlloc = allocator ;}}
  
 

The BufferQueue cache queue is created by calling SF (ComposerService: getComposerService is a familiar BpSurfaceComposer, that is, the SF agent on the client) to apply for and allocate the graphic buffer, graphicBufferAllocation on the SF side. The implementation is as follows:

Sp
 
  
SurfaceFlinger: createGraphicBufferAlloc () {sp
  
   
Gba (new GraphicBufferAlloc (); // request for image cache return gba ;}
  
 

Image caches created by SF are stored in the member variables of BufferQueue.

Step 5: Go to the SurfaceTexture class, that is, the so-called surface texture. This class inherits the ConsumerBase. The so-called consumer mode mainly refers to rendering the image cache.

ConsumerBase: ConsumerBase (const sp
 
  
& BufferQueue): mAbandoned (false), mBufferQueue (bufferQueue) {// Choose a name using the PID and a process-unique ID. mName = String8: format ("unnamed-% d", getpid (), createProcessUniqueId ()); // Note that we can't create an sp <...> (this) in a ctor that will not keep a // reference once the ctor ends, as that wocould cause the refcount of 'eas' // dropping to 0 at the end of the ctor. since all we need is a wp <...> // that's what we create. wp
  
   
Listener; sp
   
    
Proxy; listener = static_cast
    
     
(This); proxy = new BufferQueue: ProxyConsumerListener (listener); // create a listener agent status_t err = mBufferQueue-> consumerConnect (proxy ); // create a ConsumerListener proxy if (err! = NO_ERROR) {CB_LOGE ("SurfaceTexture: error connecting to BufferQueue: % s (% d)", strerror (-err), err );} else {mBufferQueue-> setConsumerName (mName );}}
    
   
  
 

The listener and proxy variables are displayed here. The listener is directly converted from the previously created Bufferqueue, and the proxy creates a remote proxy for the listener and stores it in the mConsumerListener variable of BufferQueue.

Next, let's look at the constructor of the SurfaceTexture class:

SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,        GLenum texTarget, bool useFenceSync, const sp
 
   &bufferQueue) :    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),    mCurrentTransform(0),    mCurrentTimestamp(0),    mFilteringEnabled(true),    mTexName(tex),#ifdef USE_FENCE_SYNC    mUseFenceSync(useFenceSync),#else    mUseFenceSync(false),#endif    mTexTarget(texTarget),    mEglDisplay(EGL_NO_DISPLAY),    mEglContext(EGL_NO_CONTEXT),    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),    mAttached(true){    ST_LOGV("SurfaceTexture");    memcpy(mCurrentTransformMatrix, mtxIdentity,            sizeof(mCurrentTransformMatrix));    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);}
 

Return to the Layer class constructor, mSurfaceTexture-> setFrameAvailableListener (new FrameQueuedListener (this) to analyze the processing process and create a new frame queue listener to save it to the mFrameAvailableListener of the Layer object.

Step 6: After completing the Layer object initialization, call this status_t err = layer-> setBuffers (w, h, format, flags); and SET related Buffer information. Return to SurfaceFlinger: createLayer, the initial Layer call function, and analyze the following functions:

Ssize_t token = addClientLayer (client, layer); // Add the layer to the client and add the Z axis surfaceHandle = Layer-> getSurface (); // use layer

Associate the Layer object created above with the Client currently interacting with the Client. This surfaceHandle is the Surface object that is finally returned to the client request. It should be noted that the layer object of getSurface is a Layer-derived class and inherits LayerBaseClient. If getSuface is not overloaded, the following call is performed:

Sp
 
  
LayerBaseClient: getSurface () {sp
  
   
S; Mutex: Autolock _ l (mLock); LOG_ALWAYS_FATAL_IF (mHasSurface, "LayerBaseClient: getSurface () has already been called"); mHasSurface = true; s = createSurface (); // call the createSurface function of the derived class mClientSurfaceBinder = s-> asBinder (); // BBinder return s ;}
  
 

The createSurface here is actually this-> createSurface. Therefore, when the base class function is reloaded, The createSurface function of the derived class is called when the member function is called.

Sp
 
  
Layer: createSurface () {class BSurface: public BnSurface, public LayerCleaner {wp
  
   
MOwner; virtual sp
   
    
GetSurfaceTexture () const {sp
    
     
Res; sp
     
      
That (mOwner. promote (); if (that! = NULL) {res = that-> mSurfaceTexture-> getBufferQueue (); // call the base class ConsumerBase} return res of SurfaceTexture; // mBufferQueue is returned, class is SurfaceTexturelayer} public: BSurface (const sp
      
        & Flinger, const sp
       
         & Layer): LayerCleaner (flinger, layer), mOwner (layer) {}}; sp
        
          Sur (new BSurface (mFlinger, this); return sur ;}
        
       
      
     
    
   
  
 

The final returned result is an internal class BSurface that inherits BnSurface, so it is also a local BBinder. Later, he will be used for communication between the Binder.

Step 7: here, the readyToRun function of BootAnimation is returned:

Sp
 
  
Surface = mClient-> createSurface (& data, name, w, h, format, flags); // the corresponding volume lient on the SF side is used. BpSurface
 

The final returned result shows a BpSurface class object, which echoes the preceding Binder communication. The surface object is finally created and submitted to SurfaceControl for further interface operations.


Step 8: Go to sp. S = control-> getSurface (); obtain the Surface through the sufacecontrol class object created above

sp
 
   SurfaceControl::getSurface() const{    Mutex::Autolock _l(mLock);    if (mSurfaceData == 0) {        sp
  
    surface_control(const_cast
   
    (this));        mSurfaceData = new Surface(surface_control);    }    return mSurfaceData;}
   
  
 

So what did this Surface class do? Look at the constructor:

Surface: Surface (const sp
 
  
& Surface): SurfaceTextureClient (), // The parent class calls SurfaceTextureClient: init (); finishes ANativeWindow initialization mSurface (surface-> mSurface), mIdentity (surface-> mIdentity) {sp
  
   
St; if (mSurface! = NULL) {st = mSurface-> getSurfaceTexture (); // call BpSurface to obtain BpSurfaceTexture} init (st) after remote Bnsurface processing; // Surface initialization}
  
 

Check whether this SurfaceTexture is familiar. Indeed, in step 5, we mentioned that the creation of Layer objects on the SF side will create relevant surface texture objects. This should be an operation class object on the client side, let's take a look at its initialization process:

class SurfaceTextureClient    : public ANativeObjectBase{public:    SurfaceTextureClient(const sp
 
  & surfaceTexture);
 

This class inherits an ANativeWindow, which is understood as a local window, that is, the client side will directly perform related operations on it.

SurfaceTextureClient::SurfaceTextureClient() {    SurfaceTextureClient::init();}
Void SurfaceTextureClient: init () {// Initialize the ANativeWindow function pointers. ANativeWindow: setSwapInterval = interval; ANativeWindow: queue = queue; ANativeWindow: cancelBuffer = queue; ANativeWindow: queueBuffer = queue; ANativeWindow: query = hook_query; ANativeWindow :: perform = hook_perform; ANativeWindow: queue = queue; ANativeWindow: cancelBuffer_DEPRECATED = queue; ANativeWindow: lockBuffer_DEPRECATED = queue; ANativeWindow: queue = queue; // initialize the callback of the ANativeWindow function in the local window ......}

The above is the entire constructor. It only completes the callback initialization of the local window ANativeWindow, and subsequent operations on the buffer are in these functions.

Next, let's take a look at mSurface-> getSurfaceTexture (): Here mSurface was previously called by SurfaceComposerClient: createSurface. Previously, it analyzed a local BSurface anonymous service proxy on the server, therefore, it will be done by BnSurface.

status_t BnSurface::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch(code) {        case GET_SURFACE_TEXTURE: {            CHECK_INTERFACE(ISurface, data, reply);            reply->writeStrongBinder( getSurfaceTexture()->asBinder() );            return NO_ERROR;        }        default:            return BBinder::onTransact(code, data, reply, flags);    }}

It means that BpSurfaceTexture is finally returned, so that the client has its own surface texture object.

Virtual sp
 
  
GetSurfaceTexture () const {sp
  
   
Res; sp
   
    
That (mOwner. promote (); if (that! = NULL) {res = that-> mSurfaceTexture-> getBufferQueue (); // call the base class ConsumerBase} return res of SurfaceTexture; // The returned class is mBufferQueue and the class is SurfaceTexturelayer}
   
  
 

You can see that-> mSurfaceTexture-> getBufferQueue (), that is the Layer object created earlier, and mSUrfaceTexture is in SurfaceTextureLayer (where BufferQueue is located)

    sp
 
   getBufferQueue() const {        return mBufferQueue;    }
 

That is, the final getSurfaceTexture. The so-called surface texture acquisition directly returns BufferQueue. BufferQueue inherits BpSurfaceTexture and returns it to the client of the application as an anonymous Binder object.

BpSurface (const sp
 
  
& Impl): BpInterface
  
   
(Impl) {} virtual sp
   
    
GetSurfaceTexture () const {Parcel data, reply; data. writeInterfaceToken (ISurface: getInterfaceDescriptor (); remote ()-> transact (GET_SURFACE_TEXTURE, data, & reply );
    
     
(Reply. readStrongBinder (); // The value is BpSurfaceTexture on the client and SurfaceTextureLayer on the server }};
    
   
  
 

The returned result is a BpSurfaceTexture, which will be implemented in init (st) and maintained in SurfaceTextureClient:

void Surface::init(const sp
 
  & surfaceTexture){    if (mSurface != NULL || surfaceTexture != NULL) {        ALOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");        if (surfaceTexture != NULL) {            setISurfaceTexture(surfaceTexture);//mSurfaceTexture = surfaceTexture;            setUsage(GraphicBuffer::USAGE_HW_RENDER);        }......}
 

After the above analysis, we can know that this BpSurfaceTexture anonymous Binder client will request BnSurfaceTexture again to complete some tasks, which will actually be the world of BufferQueue.






 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.