android graphic(8)—surface申请GraphicBuffer过程

http://blog.csdn.net/lewif/article/details/50703679

目录(?)[+]


本节分析surfaceBuffer Queue申请GraphicBuffer的过程(这里的surfacenativesurface,不是Java中的),在此过程中还会涉及利用Flattenable协议对对象序列化,binder传递文件描述符等概念。

surfacedequeueBuffer函数

Surface调用hook_dequeueBuffer()去申请图形缓冲区,

intSurface::hook_dequeueBuffer(ANativeWindow* window,

       ANativeWindowBuffer** buffer, int* fenceFd) {

   Surface* c = getSelf(window);

   return c->dequeueBuffer(buffer, fenceFd);

}

其中,

typedefstruct android_native_base_t

{

   /* a magic value defined by the actual EGL native type */

   int magic;

 

   /* the sizeof() of the actual EGL native type */

   intversion;

 

   void* reserved[4];

 

   /* reference-counting interface */

   void (*incRef)(struct android_native_base_t* base);

   void (*decRef)(struct android_native_base_t* base);

} android_native_base_t;

 

typedefstruct native_handle

{

   intversion;        /*sizeof(native_handle_t) */

   int numFds;         /* number offile-descriptors at &data[0] */

   int numInts;        /* number of intsat &data[numFds] */

   int data[0];        /* numFds + numIntsints */

} native_handle_t;

 

typedefconst native_handle_t* buffer_handle_t;

 

 

typedefstruct ANativeWindowBuffer

{

   struct android_native_base_t common;

 

   int width;

   int height;

   int stride;

   int format;

   int usage;

 

   void* reserved[2];

   //图形缓冲区

   buffer_handle_t handle;

 

   void* reserved_proc[8];

} ANativeWindowBuffer_t;

图形的buffer其实核心就是buffer_handle_t handle;这个handle,上节分析过,就是通过mmap返回的fdsizemap到进程中内存的起始地址。

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {

   ATRACE_CALL();

   ALOGV("Surface::dequeueBuffer");

   Mutex::Autolock lock(mMutex);

   int buf = -1;

   int reqW = mReqWidth ? mReqWidth :mUserWidth;

   int reqH = mReqHeight ? mReqHeight :mUserHeight;

   sp<Fence> fence;

   //申请buffer

   // mGraphicBufferProducerBufferQueueBp对象

   status_t result = mGraphicBufferProducer->dequeueBuffer(&buf,&fence, mSwapIntervalZero,

            reqW, reqH, mReqFormat, mReqUsage);

   if (result < 0) {

       ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"

             "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,

             result);

       return result;

   }

   sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);

 

   // this should never happen

   ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received nullFence! buf=%d", buf);

 

   if (result &IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {

       freeAllBuffers();

   }

 

   if ((result &IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {

       //

       //由于申请的内存是在surfaceflinger进程中,BufferQueue中的图形缓冲区也是通过

       // 匿名共享内存和binder传递描述符映射过去的,Surface通过调用

       // requestBuffer将图形缓冲区映射到Surface所在进程

        result =mGraphicBufferProducer->requestBuffer(buf, &gbuf);

       if (result != NO_ERROR) {

            ALOGE("dequeueBuffer:IGraphicBufferProducer::requestBuffer failed: %d", result);

            return result;

       }

   }

 

   if (fence->isValid()) {

       *fenceFd = fence->dup();

       if (*fenceFd == -1) {

            ALOGE("dequeueBuffer:error duping fence: %d", errno);

            // dup() should never fail; something is badly wrong. Soldier on

            // and hope for the best; the worst that should happenis some

            // visible corruption that lasts until the next frame.

       }

   } else {

       *fenceFd = -1;

   }

   //sp<>智能指针的get返回真是对象的指针

   *buffer = gbuf.get();

   return OK;

}

上面dequeueBuffer()主要包括2部分: 
1.
BufferQueue申请缓冲区; 
2.
由于BufferQueueSurface不在同一进程,需要用requestBuffer将映射在BufferQueue进程的图形缓冲区同时映射到surface所在的进程(匿名共享内存)

BufferQueue申请内存

Surface类中,有个成员mSlots数组,即有32BufferSlot

//NUM_BUFFER_SLOTS32

BufferSlot mSlots[NUM_BUFFER_SLOTS];

BufferSlot结构如下,保存申请到的图形缓冲区。

   struct BufferSlot {

       //保存缓冲区

       sp<GraphicBuffer> buffer;

       Region dirtyRegion;

   };

   //int buf = -1;

   // buf是个int值,是上面mSlots数组的下标

   status_t result =mGraphicBufferProducer->dequeueBuffer(&buf, &fence,mSwapIntervalZero,

            reqW, reqH, mReqFormat, mReqUsage);

mGraphicBufferProducer->dequeueBuffer进而会去调用BpGraphicBufferProducerdequeueBuffer函数,

classBpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>

{

    virtualstatus_t dequeueBuffer(int *buf, sp<Fence>* fence, boolasync,

            uint32_tw, uint32_th, uint32_tformat, uint32_tusage) {

        Parcel data, reply;

        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());

       data.writeInt32(async);

       data.writeInt32(w);

       data.writeInt32(h);

       data.writeInt32(format);

       data.writeInt32(usage);

        //通过BpBinder将要什么的buffer的相关参数保存到data,发送给BBinder

        status_tresult = remote()->transact(DEQUEUE_BUFFER, data, &reply);

        if (result != NO_ERROR) {

            returnresult;

        }

        //BBinderBpBinder返回了一个int,并不是缓冲区的内存,例如前面介绍的handle啥的

        *buf =reply.readInt32();

        boolnonNull = reply.readInt32();

        if (nonNull) {

            *fence= new Fence();

           reply.read(**fence);

        }

        result =reply.readInt32();

        returnresult;

    }

}

client侧,也就是BpGraphicBufferProducer侧,通过DEQUEUE_BUFFER后核心只返回了一个*buf =reply.readInt32();(先不管fence),也就是数组mSlots的下标。看来,BufferQueue中应该也有个和mSlots对应的数组,也是32个,一一对应,继续分析server侧,即Bn侧,

status_tBnGraphicBufferProducer::onTransact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

     caseDEQUEUE_BUFFER: {

            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);

            bool async      = data.readInt32();

            uint32_t w      = data.readInt32();

            uint32_t h      = data.readInt32();

            uint32_t format = data.readInt32();

            uint32_t usage  = data.readInt32();

            int buf;

            sp<Fence> fence;

            //调用BufferQueuedequeueBuffer

            //也返回一个intbuf

            int result =dequeueBuffer(&buf, &fence, async, w, h, format, usage);

            //buffence写入parcel,通过binder传给client

            reply->writeInt32(buf);

            reply->writeInt32(fence != NULL);

            if (fence != NULL) {

                reply->write(*fence);

            }

            reply->writeInt32(result);

            return NO_ERROR;

}

BufferQueue中果然也有个mSlots数组,32BufferSlot

BufferSlotmSlots[NUM_BUFFER_SLOTS];

但是BufferSlot 结构不同于Surface中的,由于BufferQueue的核心职责就是管理图形缓冲区,需要记录每个缓冲区的状态(FREEDEQUEUEDQUEUEDACQUIRED)等,关于生产者消费者这里不细述了,

  struct BufferSlot {

 

       BufferSlot()

       : mEglDisplay(EGL_NO_DISPLAY),

         mBufferState(BufferSlot::FREE),

         mRequestBufferCalled(false),

         mFrameNumber(0),

         mEglFence(EGL_NO_SYNC_KHR),

         mAcquireCalled(false),

         mNeedsCleanupOnRelease(false) {

       }

 

       // mGraphicBuffer points to the buffer allocated for this slot oris NULL

       // if no buffer has been allocated.

       sp<GraphicBuffer> mGraphicBuffer;

 

       // mEglDisplay is the EGLDisplayused to create EGLSyncKHR objects.

       EGLDisplay mEglDisplay;

 

       // BufferState represents the different states in which a buffer slot

       // can be. All slots are initially FREE.

       enum BufferState {

            // FREE indicates that the buffer is available to be dequeued

            // by the producer.  The buffer may bein use by the consumer for

           // a finite time, so thebuffer must notbe modified until the

            // associated fence is signaled.

            //

            // The slot is "owned" byBufferQueue.  It transitions to DEQUEUED

            // when dequeueBuffer is called.

            FREE = 0,

 

            // DEQUEUED indicates that the buffer has been dequeued by the

            // producer, but has not yet been queued or canceled.  The

            // producer may modify the buffer'scontents as soon as the

            // associated ready fence is signaled.

            //

            // The slot is "owned" by theproducer.  It can transition to

            // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).

            DEQUEUED = 1,

 

            // QUEUED indicates that the buffer has been filled by the

            // producer and queued for use by the consumer.  The buffer

            // contents may continue to be modified for a finite time,so

            // the contents must notbe accessed until the associated fence

            // is signaled.

            //

            // The slot is "owned" byBufferQueue.  It can transition to

            // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is

            // queued in asynchronous mode).

           QUEUED = 2,

 

            // ACQUIRED indicates that the buffer has been acquired by the

            // consumer.  As with QUEUED, the contents must notbe accessed

            // by the consumer until the fence is signaled.

            //

            // The slot is "owned" by theconsumer.  It transitions to FREE

            // when releaseBuffer is called.

            ACQUIRED = 3

       };

 

       // mBufferState is the currentstate of this buffer slot.

       BufferState mBufferState;

 

       // mRequestBufferCalled is used for validating that the producerdid

       // call requestBuffer() when told to do so. Technically this isnot

       // needed but useful for debugging and catchingproducer bugs.

       bool mRequestBufferCalled;

 

       // mFrameNumber is the number of the queuedframe for this slot.  This

       // is used to dequeue buffers in LRU order (useful because buffers

       // may be released before their release fence is signaled).

       uint64_t mFrameNumber;

 

       // mEglFence is the EGL sync object that must signal before the buffer

       // associated with this buffer slot may be dequeued. It is initialized

       // to EGL_NO_SYNC_KHR when the buffer is created and may beset to a

       // new sync object inreleaseBuffer.  (This is deprecated in favor of

       // mFence, below.)

       EGLSyncKHR mEglFence;

 

       // mFence is a fence whichwill signal when work initiated by the

       // previous owner of the buffer is finished. When the buffer is FREE,

       // the fence indicates when the consumer has finished reading

       // from the buffer, or when the producer has finished writing if it

       // called cancelBuffer after queueing some writes. When the buffer is

       // QUEUED, it indicates when the producer has finished filling the

       // buffer. When the buffer is DEQUEUED or ACQUIRED, thefence has been

       // passed to the consumer or producer alongwith ownership of the

       // buffer, and mFence isset to NO_FENCE.

       sp<Fence> mFence;

 

       // Indicates whether this buffer has been seen by a consumer yet

       bool mAcquireCalled;

 

       // Indicates whether this buffer needs to be cleaned up by the

       // consumer.  This isset when a buffer in ACQUIRED state is freed.

       // It causes releaseBuffer to return STALE_BUFFER_SLOT.

       bool mNeedsCleanupOnRelease;

   };

BufferQueuedequeueBuffer函数,

status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, boolasync,

       uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {

   ATRACE_CALL();

   ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);

 

 

   status_t returnFlags(OK);

   EGLDisplay dpy = EGL_NO_DISPLAY;

   EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;

 

   { // Scope for the lock

       Mutex::Autolock lock(mMutex);

 

       if (format == 0) {

            format = mDefaultBufferFormat;

       }

        // turn on usage bits the consumerrequested

       usage |= mConsumerUsageBits;

 

       int found = -1;

       bool tryAgain = true;

       while (tryAgain) {

            if (mAbandoned) {

                ST_LOGE("dequeueBuffer:BufferQueue has been abandoned!");

                return NO_INIT;

            }

 

            constint maxBufferCount =getMaxBufferCountLocked(async);

            if (async && mOverrideMaxBufferCount) {

                // FIXME: somedrivers are manually setting the buffer-count (which they

                // shouldn't), sowe do this extra test here to handle that case.

                // This isTEMPORARY, until we get this fixed.

                if (mOverrideMaxBufferCount < maxBufferCount) {

                    ST_LOGE("dequeueBuffer:async mode is invalid with buffercount override");

                    return BAD_VALUE;

                }

            }

 

            // Free up anybuffers that are in slots beyond the max buffer

            // count.

            for (int i = maxBufferCount; i <NUM_BUFFER_SLOTS; i++) {

                assert(mSlots[i].mBufferState== BufferSlot::FREE);

                if (mSlots[i].mGraphicBuffer != NULL) {

                    freeBufferLocked(i);

                    returnFlags |=IGraphicBufferProducer::RELEASE_ALL_BUFFERS;

                }

            }

 

            // look for a freebuffer to give to the client

            found = INVALID_BUFFER_SLOT;

            int dequeuedCount = 0;

            int acquiredCount = 0;

            //mSlots中状态是FREE的,而且同时要选择mFrameNumber值最小的那个

            for (int i = 0; i < maxBufferCount; i++) {

                constint state = mSlots[i].mBufferState;

                switch (state) {

                    case BufferSlot::DEQUEUED:

                        dequeuedCount++;

                        break;

                    case BufferSlot::ACQUIRED:

                        acquiredCount++;

                        break;

                    case BufferSlot::FREE:

                        /* We return the oldest of the freebuffers to avoid

                        * stalling the producer if possible. This is because

                        * the consumer may still have pending reads of the

                        * buffers in flight.

                        */

                        if ((found < 0) ||

                               mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {

                            found = i;

                        }

                        break;

                }

            }

 

            // clients are notallowed to dequeue more than one buffer

            // if they didn'tset a buffer count.

            if (!mOverrideMaxBufferCount && dequeuedCount) {

                ST_LOGE("dequeueBuffer:can't dequeue multiple buffers without "

                        "settingthe buffer count");

                return -EINVAL;

            }

 

            // See whether abuffer has been queued since the last

            // setBufferCountso we know whether to perform the min undequeued

            // buffers checkbelow.

            if (mBufferHasBeenQueued) {

                // make sure theclient is not trying to dequeue more buffers

                // than allowed.

                constint newUndequeuedCount = maxBufferCount -(dequeuedCount+1);

                constint minUndequeuedCount =getMinUndequeuedBufferCount(async);

                if (newUndequeuedCount < minUndequeuedCount) {

                    ST_LOGE("dequeueBuffer:min undequeued buffer count (%d) "

                            "exceeded(dequeued=%d undequeudCount=%d)",

                            minUndequeuedCount,dequeuedCount,

                           newUndequeuedCount);

                    return -EBUSY;

                }

            }

 

            // If no buffer isfound, wait for a buffer to be released or for

            // the max buffercount to change.

            tryAgain = found ==INVALID_BUFFER_SLOT;

            //如果所有的buffer都不是free的,则等待

            if (tryAgain) {

                // return an errorif we're in "cannot block" mode (producer and consumer

                // are controlledby the application) -- however, the consumer is allowed

                // to acquirebriefly an extra buffer (which could cause us to have to wait here)

                // and that's okaybecause we know the wait will be brief (it happens

                // if we dequeue abuffer while the consumer has acquired one but not released

                // the old one yet-- for e.g.: see GLConsumer::updateTexImage()).

                if (mDequeueBufferCannotBlock && (acquiredCount <=mMaxAcquiredBufferCount)) {

                    ST_LOGE("dequeueBuffer:would block! returning an error instead.");

                   return WOULD_BLOCK;

                }

                mDequeueCondition.wait(mMutex);

            }

       }

 

 

       if (found == INVALID_BUFFER_SLOT) {

            // This should nothappen.

            ST_LOGE("dequeueBuffer:no available buffer slots");

            return -EBUSY;

       }

 

       constint buf = found;

       *outBuf = found;

 

       ATRACE_BUFFER_INDEX(buf);

 

       constbool useDefaultSize = !w && !h;

       if (useDefaultSize) {

           // use the defaultsize

            w = mDefaultWidth;

            h = mDefaultHeight;

       }

 

   //将找到的buf所对应的状态修改为DEQUEUED

       mSlots[buf].mBufferState = BufferSlot::DEQUEUED;

 

       const sp<GraphicBuffer>&buffer(mSlots[buf].mGraphicBuffer);

       //如果buffer为空,或者非空,但是buffer的尺寸有变化,

       //returnFlags添加BUFFER_NEEDS_REALLOCATION重新申请标志

       if ((buffer == NULL) ||

            (uint32_t(buffer->width)  != w) ||

            (uint32_t(buffer->height) != h)||

            (uint32_t(buffer->format) !=format) ||

            ((uint32_t(buffer->usage) &usage) != usage))

       {

            mSlots[buf].mAcquireCalled = false;

            mSlots[buf].mGraphicBuffer = NULL;

            mSlots[buf].mRequestBufferCalled = false;

            mSlots[buf].mEglFence =EGL_NO_SYNC_KHR;

            mSlots[buf].mFence =Fence::NO_FENCE;

            mSlots[buf].mEglDisplay =EGL_NO_DISPLAY;

 

            returnFlags |=IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;

       }

 

 

       if (CC_UNLIKELY(mSlots[buf].mFence == NULL)) {

            ST_LOGE("dequeueBuffer:about to return a NULL fence from mSlot. "

                    "buf=%d, w=%d,h=%d, format=%d",

                    buf, buffer->width,buffer->height, buffer->format);

       }

 

       dpy = mSlots[buf].mEglDisplay;

       eglFence = mSlots[buf].mEglFence;

       *outFence = mSlots[buf].mFence;

       mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;

       mSlots[buf].mFence = Fence::NO_FENCE;

   }  // end lock scope

 

   // buffer需要重新申请,则调用mGraphicBufferAlloc去创建buffer

   if (returnFlags &IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {

       status_t error;

       sp<GraphicBuffer> graphicBuffer(

                mGraphicBufferAlloc->createGraphicBuffer(w,h, format, usage, &error));

       if (graphicBuffer == 0) {

            ST_LOGE("dequeueBuffer:SurfaceComposer::createGraphicBuffer failed");

            return error;

       }

 

       { // Scope for the lock

            Mutex::Autolock lock(mMutex);

 

            if (mAbandoned) {

                ST_LOGE("dequeueBuffer:BufferQueue has been abandoned!");

                return NO_INIT;

            }

 

            mSlots[*outBuf].mFrameNumber = ~0;

            mSlots[*outBuf].mGraphicBuffer =graphicBuffer;

       }

   }

 

   if (eglFence != EGL_NO_SYNC_KHR) {

       EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);

       // If something goes wrong, log the error, but return the buffer without

       // synchronizing access to it.  It'stoo late at this point to abort the

       // dequeue operation.

       if (result == EGL_FALSE) {

            ST_LOGE("dequeueBuffer:error waiting for fence: %#x",eglGetError());

       } elseif (result == EGL_TIMEOUT_EXPIRED_KHR) {

            ST_LOGE("dequeueBuffer:timeout waiting for fence");

       }

       eglDestroySyncKHR(dpy, eglFence);

   }

 

   ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%pflags=%#x", *outBuf,

            mSlots[*outBuf].mFrameNumber,

           mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);

 

   return returnFlags;

}

上面函数主要包括5部分: 
1.
首先找空闲的buffer,在mSlots中状态是FREE的,而且同时要选择mFrameNumber值最小的那个; 
2.
如果所有的buffer都不是free的,则等待; 
3.
将找到的buf所对应的状态修改为DEQUEUED 
4.
const sp<GraphicBuffer>&buffer(mSlots[buf].mGraphicBuffer),取找到的buf中的mGraphicBuffer,如果buffer为空,或者非空,但是buffer的尺寸有变化,将returnFlags添加BUFFER_NEEDS_REALLOCATION重新申请标志; 
5.
如果buffer需要重新申请,则调用mGraphicBufferAlloc去创建buffer,关于mGraphicBufferAlloc的创建在前面的android—匿名binder中有介绍,继续分析mGraphicBufferAlloc去创建缓冲区的过程,

       sp<GraphicBuffer> graphicBuffer(

               mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));

BpGraphicBufferAlloc

classBpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>

{

    virtual sp<GraphicBuffer>createGraphicBuffer(uint32_tw, uint32_th,

            PixelFormatformat, uint32_tusage, status_t* error) {

        Parcel data, reply;

       data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());

       data.writeInt32(w);

       data.writeInt32(h);

       data.writeInt32(format);

       data.writeInt32(usage);

        remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);

        sp<GraphicBuffer>graphicBuffer;

        status_tresult = reply.readInt32();

        if (result == NO_ERROR) {

           //clientreplay中反序列化出surfaceflinger中创建的GraphicBuffer对象

           graphicBuffer = new GraphicBuffer();

            result= reply.read(*graphicBuffer);

            //reply.readStrongBinder();

            // herewe don't even have to read the BufferReference from

            // theparcel, it'll die with the parcel.

        }

        *error =result;

        returngraphicBuffer;

    }

}

BnGraphicBufferAlloc

status_tBnGraphicBufferAlloc::onTransact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

  caseCREATE_GRAPHIC_BUFFER: {

            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);

            uint32_t w = data.readInt32();

            uint32_t h = data.readInt32();

           PixelFormat format = data.readInt32();

            uint32_t usage = data.readInt32();

            status_t error;

            //调用GraphicBufferAlloccreateGraphicBuffer函数,

            sp<GraphicBuffer> result =

                    createGraphicBuffer(w, h,format, usage, &error);

            reply->writeInt32(error);

            if (result != 0) {

                //GraphicBuffer进行序列化,传给client

                reply->write(*result);

                // We add a BufferReference to this parcel to make sure the

                // buffer stays alive until theGraphicBuffer object on

                // the other side has beencreated.

                // This is needed so that the buffer handle can be

                // registered before the bufferis destroyed on implementations

                // that do not use file-descriptors to track their buffers.

                reply->writeStrongBinder(new BufferReference(result) );

            }

            return NO_ERROR;

       } break;

sp<GraphicBuffer>GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,

       PixelFormat format, uint32_t usage, status_t* error) {

   sp<GraphicBuffer> graphicBuffer(newGraphicBuffer(w, h, format, usage));

   status_t err = graphicBuffer->initCheck();

   *error = err;

   if (err !=0|| graphicBuffer->handle==0) {

       if (err == NO_MEMORY) {

            GraphicBuffer::dumpAllocationsToSystemLog();

       }

       ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "

             "failed (%s),handle=%p",

                w, h, strerror(-err), graphicBuffer->handle);

       return0;

   }

   return graphicBuffer;

}

GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,

       PixelFormat reqFormat, uint32_t reqUsage)

   : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),

     mInitCheck(NO_ERROR)

{

   width  =

   height =

   stride =

   format =

   usage  =0;

   handle=NULL;

   mInitCheck = initSize(w, h,reqFormat, reqUsage);

}

上面的函数主要就是利用GraphicBufferAlloc去分配图形缓冲区的过程,中间会用到gralloc模块,以及GraphicBuffer的序列化和反序列化,反序列化unflatten()时还会调用grallocBufferQueue所在的进程将在surfaceflinger中申请的内存map注册过来(匿名共享内存)。 
到此,BufferQueue中已经申请到了内存,返回给Surface一个int的数组下标,看来这时候Surface还没有获取到任何图形缓冲区相关的东西。 
由于申请的内存是在BufferQueue所在的进程,接下来需要调用requestBufferbuffer映射到Surface所在的进程

    result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

SurfacerequestBuffer

int Surface::dequeueBuffer(android_native_buffer_t**buffer, int* fenceFd) {

   ..........

   sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);

 

   if ((result &IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {

       //传入数组下标,返回从BufferQueue中映射的GraphicBuffer

       result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

       if (result != NO_ERROR) {

            ALOGE("dequeueBuffer:IGraphicBufferProducer::requestBuffer failed: %d", result);

            return result;

       }

   }

    ......

}

上面调用了mGraphicBufferProducer->requestBuffer(buf, &gbuf), 
BpGraphicBufferProducer

classBpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>

{

 

 

    virtualstatus_t requestBuffer(intbufferIdx, sp<GraphicBuffer>* buf) {

        Parcel data, reply;

       data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());

       data.writeInt32(bufferIdx);

        //传入数组下标

        status_tresult =remote()->transact(REQUEST_BUFFER, data, &reply);

        if (result != NO_ERROR) {

            returnresult;

        }

        boolnonNull = reply.readInt32();

        if (nonNull) {

        //GraphicBuffer的反序列化,在Surface所在进程map映射真实的图形缓冲区

            *buf =new GraphicBuffer();

           reply.read(**buf);

        }

        result =reply.readInt32();

        returnresult;

    }

}

从上面的代码能够看出,requestBuffer的核心就是:Surface传一个数组下标,然后去将BufferQueue中对应的数组下标中的GraphicBuffer对象映射到Surface中,然后保存在对应的数组中,这两个数组一一对应。 
综上,真正申请图形缓冲区是在surface flinger进程中,因为GraphicBufferAlloc对象是在surface flingernew出来的,然后BufferQueueSurface中的图形缓冲区都是通过GraphicBuffer的序列化和反序列化新映射出来的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值