android graphic (8) - surface 신청 GraphicBuffer 과정

48778 단어 android-graphic
  • surface 의 dequeue Buffer 함수
  • BufferQueue 에 메모리 신청
  • Surface RequestBuffer 제거
  • 이 절 에 서 는 surface 가 Buffer Queue 에 Graphic Buffer 를 신청 하 는 과정 (이곳 의 surface 는 native surface 이지 자바 의 surface 가 아 닙 니 다) 을 분석 하고 이 과정 에서 Flattenable 프로 토 콜 을 이용 하여 대상 을 직렬 화, binder 전달 파일 설명자 등 개념 도 언급 합 니 다.
    surface 의 dequeue Buffer 함수
    Surface 호출 hookdequeueBuffer () 는 그래 픽 버퍼 를 신청 합 니 다.
    int Surface::hook_dequeueBuffer(ANativeWindow* window,
            ANativeWindowBuffer** buffer, int* fenceFd) {
        Surface* c = getSelf(window);
        return c->dequeueBuffer(buffer, fenceFd);
    }

    그 중
    typedef struct android_native_base_t
    {
        /* a magic value defined by the actual EGL native type */
        int magic;
    
        /* the sizeof() of the actual EGL native type */
        int version;
    
        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;
    
    typedef struct native_handle
    {
        int version;        /* sizeof(native_handle_t) */
        int numFds;         /* number of file-descriptors at &data[0] */
        int numInts;        /* number of ints at &data[numFds] */
        int data[0];        /* numFds + numInts ints */
    } native_handle_t;
    
    typedef const native_handle_t* buffer_handle_t;
    
    
    typedef struct 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 를 통 해 돌아 온 fd, size, map 에서 프로 세 스 메모리 의 시작 주소 입 니 다.
    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;
        //①   buffer
        // mGraphicBufferProducer BufferQueue Bp  
        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& gbuf(mSlots[buf].buffer);
    
        // this should never happen
        ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! 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 happen is some
                // visible corruption that lasts until the next frame.
            }
        } else {
            *fenceFd = -1;
        }
        //sp<>     get         
        *buffer = gbuf.get();
        return OK;
    }

    위의 dequeue Buffer () 는 주로 2 부분 을 포함한다. 1. Buffer Queue 에 버퍼 를 신청 합 니 다.2. Buffer Queue 와 Surface 가 같은 프로 세 스 에 있 지 않 기 때문에 request Buffer 로 Buffer Queue 프로 세 스 의 그래 픽 버퍼 를 surface 가 있 는 프로 세 스 (익명 공유 메모리) 에 동시에 표시 해 야 합 니 다.
    Buffer Queue 에 메모리 신청
    Surface 클래스 에는 32 개의 Buffer Slot 가 있 는 mSlots 배열 이 있 습 니 다.
    //NUM_BUFFER_SLOTS 32
    BufferSlot mSlots[NUM_BUFFER_SLOTS];

    BufferSlot 구 조 는 다음 과 같 습 니 다. 신청 한 그래 픽 버퍼 를 저장 합 니 다.
        struct BufferSlot {
            //     
            sp buffer;
            Region dirtyRegion;
        };
        //int buf = -1; 
        // buf  int ,   mSlots     
        status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
                reqW, reqH, mReqFormat, mReqUsage);
    mGraphicBufferProducer->dequeueBuffer 더 나 아가 BpGraphicBufferProducerdequeueBuffer 함 수 를 호출 합 니 다.
    class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
    {
        virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
                uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
            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_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
            if (result != NO_ERROR) {
                return result;
            }
            //BBinder BpBinder     int,         ,       handle  
            *buf = reply.readInt32();
            bool nonNull = reply.readInt32();
            if (nonNull) {
                *fence = new Fence();
                reply.read(**fence);
            }
            result = reply.readInt32();
            return result;
        }
    }

    client 측, 즉 BpGraphic Buffer Producer 측 을 통 해 DEQUEUEBUFFER 이후 핵심 은 하나 *buf = reply.readInt32(); 만 되 돌 아 왔 다.보아하니 BufferQueue 에 도 mSlots 와 대응 하 는 배열 이 있 을 것 입 니 다. 32 개 입 니 다. 일일이 대응 하고 server 측, 즉 Bn 측 을 계속 분석 하 겠 습 니 다.
    status_t BnGraphicBufferProducer::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
          case DEQUEUE_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;
                //  BufferQueue dequeueBuffer
                //     int buf
                int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
                // buf fence  parcel,  binder  client
                reply->writeInt32(buf);
                reply->writeInt32(fence != NULL);
                if (fence != NULL) {
                    reply->write(*fence);
                }
                reply->writeInt32(result);
                return NO_ERROR;
    }

    Buffer Queue 에 도 역시 mSlots 배열 이 있 습 니 다. 32 개의 Buffer Slot 가 있 습 니 다.
    BufferSlot mSlots[NUM_BUFFER_SLOTS];

    그러나 BufferSlot 구 조 는 Surface 와 다 릅 니 다. BufferQueue 의 핵심 직책 은 그래 픽 버퍼 를 관리 하 는 것 이기 때문에 모든 버퍼 의 상태 (FREE, DEQUEUED, QUEUED, ACQUIRED) 등 을 기록 해 야 합 니 다. 생산자 소비자 에 대해 서 는 자세히 설명 하지 않 습 니 다.
       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 or is NULL
            // if no buffer has been allocated.
            sp mGraphicBuffer;
    
            // mEglDisplay is the EGLDisplay used 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 be in use by the consumer for
                // a finite time, so the buffer must not be modified until the
                // associated fence is signaled.
                //
                // The slot is "owned" by BufferQueue.  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's contents as soon as the
                // associated ready fence is signaled.
                //
                // The slot is "owned" by the producer.  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 not be accessed until the associated fence
                // is signaled.
                //
                // The slot is "owned" by BufferQueue.  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 not be accessed
                // by the consumer until the fence is signaled.
                //
                // The slot is "owned" by the consumer.  It transitions to FREE
                // when releaseBuffer is called.
                ACQUIRED = 3
            };
    
            // mBufferState is the current state of this buffer slot.
            BufferState mBufferState;
    
            // mRequestBufferCalled is used for validating that the producer did
            // call requestBuffer() when told to do so. Technically this is not
            // needed but useful for debugging and catching producer bugs.
            bool mRequestBufferCalled;
    
            // mFrameNumber is the number of the queued frame 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 be set to a
            // new sync object in releaseBuffer.  (This is deprecated in favor of
            // mFence, below.)
            EGLSyncKHR mEglFence;
    
            // mFence is a fence which will 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, the fence has been
            // passed to the consumer or producer along with ownership of the
            // buffer, and mFence is set to NO_FENCE.
            sp 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 is set when a buffer in ACQUIRED state is freed.
            // It causes releaseBuffer to return STALE_BUFFER_SLOT.
            bool mNeedsCleanupOnRelease;
        };

    Buffer Queue 의 dequeue Buffer 함수,
    status_t BufferQueue::dequeueBuffer(int *outBuf, sp* outFence, bool async,
            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 consumer requested
            usage |= mConsumerUsageBits;
    
            int found = -1;
            bool tryAgain = true;
            while (tryAgain) {
                if (mAbandoned) {
                    ST_LOGE("dequeueBuffer: BufferQueue has been abandoned!");
                    return NO_INIT;
                }
    
                const int maxBufferCount = getMaxBufferCountLocked(async);
                if (async && mOverrideMaxBufferCount) {
                    // FIXME: some drivers are manually setting the buffer-count (which they
                    // shouldn't), so we do this extra test here to handle that case.
                    // This is TEMPORARY, until we get this fixed.
                    if (mOverrideMaxBufferCount < maxBufferCount) {
                        ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
                        return BAD_VALUE;
                    }
                }
    
                // Free up any buffers 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 free buffer 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++) {
                    const int 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 free buffers 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 not allowed to dequeue more than one buffer
                // if they didn't set a buffer count.
                if (!mOverrideMaxBufferCount && dequeuedCount) {
                    ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
                            "setting the buffer count");
                    return -EINVAL;
                }
    
                // See whether a buffer has been queued since the last
                // setBufferCount so we know whether to perform the min undequeued
                // buffers check below.
                if (mBufferHasBeenQueued) {
                    // make sure the client is not trying to dequeue more buffers
                    // than allowed.
                    const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
                    const int 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 is found, wait for a buffer to be released or for
                // the max buffer count to change.
                tryAgain = found == INVALID_BUFFER_SLOT;
                //②      buffer   free ,   
                if (tryAgain) {
                    // return an error if we're in "cannot block" mode (producer and consumer
                    // are controlled by the application) -- however, the consumer is allowed
                    // to acquire briefly an extra buffer (which could cause us to have to wait here)
                    // and that's okay because we know the wait will be brief (it happens
                    // if we dequeue a buffer 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 not happen.
                ST_LOGE("dequeueBuffer: no available buffer slots");
                return -EBUSY;
            }
    
            const int buf = found;
            *outBuf = found;
    
            ATRACE_BUFFER_INDEX(buf);
    
            const bool useDefaultSize = !w && !h;
            if (useDefaultSize) {
                // use the default size
                w = mDefaultWidth;
                h = mDefaultHeight;
            }
    
        //③     buf         DEQUEUED
            mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
    
            const sp& 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(
                    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's too late at this point to abort the
            // dequeue operation.
            if (result == EGL_FALSE) {
                ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
                ST_LOGE("dequeueBuffer: timeout waiting for fence");
            }
            eglDestroySyncKHR(dpy, eglFence);
        }
    
        ST_LOGV("dequeueBuffer: returning slot=%d/%llu buf=%p flags=%#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& buffer(mSlots[buf].mGraphicBuffer) 찾 은 buf 의 mGraphic Buffer 를 가 져 옵 니 다. buffer 가 비어 있 거나 비어 있 지 않 지만 buffer 의 크기 가 변 하면 returnFlags 에 BUFFER 를 추가 합 니 다.NEEDS_REALLCATION 재 신청 표지;5. buffer 가 다시 신청 해 야 한다 면 mGraphicBufferAlloc 를 호출 하여 buffer 를 만 듭 니 다. mGraphicBufferAlloc 의 생 성 은 앞의 에 소개 되 어 있 습 니 다. mGraphicBufferAlloc 가 버퍼 를 만 드 는 과정 을 계속 분석 합 니 다.
            sp graphicBuffer(
                    mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage, &error));

    BpGraphicBufferAlloc ,
    class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
    {
        virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
                PixelFormat format, uint32_t usage, 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_t result = reply.readInt32();
            if (result == NO_ERROR) {
                //client replay      surfaceflinger    GraphicBuffer  
                graphicBuffer = new GraphicBuffer();
                result = reply.read(*graphicBuffer);
                // reply.readStrongBinder();
                // here we don't even have to read the BufferReference from
                // the parcel, it'll die with the parcel.
            }
            *error = result;
            return graphicBuffer;
        }
    }

    BnGraphicBufferAlloc,
    status_t BnGraphicBufferAlloc::onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)case CREATE_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;
                //  GraphicBufferAlloc createGraphicBuffer  ,
                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 the GraphicBuffer object on
                    // the other side has been created.
                    // This is needed so that the buffer handle can be
                    // registered before the buffer is 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(new GraphicBuffer(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);
            return 0;
        }
        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);
    }

    위의 함 수 는 주로 Graphic Buffer Alloc 를 이용 하여 그래 픽 버퍼 를 분배 하 는 과정 입 니 다. 중간 에 gralloc 모듈 과 Graphic Buffer 의 직렬 화 와 반 직렬 화, 반 직렬 화 unflatten () 을 사용 할 때 gralloc 를 사용 하여 Buffer Queue 가 있 는 프로 세 스 를 surfaceflinger 에서 신청 한 메모리 map 에 등록 합 니 다 (익명 공유 메모리).여기 서 BufferQueue 에 메모리 가 신청 되 었 습 니 다. Surface 에 int 배열 아래 표 시 를 되 돌려 주 었 습 니 다. 이때 Surface 는 도형 버퍼 와 관련 된 것 을 얻 지 못 한 것 같 습 니 다.신청 한 메모 리 는 BufferQueue 가 있 는 프로 세 스 이기 때문에 다음 에 request Buffer 를 호출 하여 buffer 를 Surface 가 있 는 프로 세 스 에 표시 해 야 합 니 다.
        result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);

    Surface RequestBuffer
    int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
        ..........
        sp& 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), BpGraphic Buffer Producer,
    class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
    {
    
    
        virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
            Parcel data, reply;
            data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
            data.writeInt32(bufferIdx);
            //      
            status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
            if (result != NO_ERROR) {
                return result;
            }
            bool nonNull = reply.readInt32();
            if (nonNull) {
            //GraphicBufferSurface    map          
                *buf = new GraphicBuffer();
                reply.read(**buf);
            }
            result = reply.readInt32();
            return result;
        }
    }

    위의 코드 를 통 해 알 수 있 듯 이 requestBuffer 의 핵심 은 Surface 가 하나의 배열 아래 표 시 를 전달 한 다음 에 BufferQueue 에 대응 하 는 배열 아래 표 시 된 Graphic Buffer 대상 을 Surface 에 투사 한 다음 에 해당 하 는 배열 에 저장 하 는 것 입 니 다. 이 두 배열 은 일일이 대응 합 니 다.다시 말 하면 진정 으로 그래 픽 버퍼 를 신청 하 는 것 은 surface flinger 프로 세 스 입 니 다. Graphic BufferAlloc 대상 은 surface flinger 에서 new 로 나 온 다음 에 BufferQueue 와 Surface 의 그래 픽 버퍼 는 모두 Graphic Buffer 의 직렬 화 와 반 직렬 화 를 통 해 새로 매 핑 되 었 기 때 문 입 니 다.

    좋은 웹페이지 즐겨찾기